diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 17:47:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 17:47:50 +0000 |
commit | bbe35a6e1b54ef5cd7c1c471886c30ba85c0804e (patch) | |
tree | 985a31e8c860c690d9f20e6621ce5fcc05ccd244 /testenv | |
parent | Initial commit. (diff) | |
download | wget-bbe35a6e1b54ef5cd7c1c471886c30ba85c0804e.tar.xz wget-bbe35a6e1b54ef5cd7c1c471886c30ba85c0804e.zip |
Adding upstream version 1.21.upstream/1.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testenv')
124 files changed, 12626 insertions, 0 deletions
diff --git a/testenv/Makefile.am b/testenv/Makefile.am new file mode 100644 index 0000000..685e511 --- /dev/null +++ b/testenv/Makefile.am @@ -0,0 +1,128 @@ +# Makefile for `wget' utility +# Copyright (C) 2013, 2015, 2018-2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Wget. If not, see <http://www.gnu.org/licenses/>. + +# Additional permission under GNU GPL version 3 section 7 + +# If you modify this program, or any covered work, by linking or +# combining it with the OpenSSL project's OpenSSL library (or a +# modified version of that library), containing parts covered by the +# terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +# grants you additional permission to convey the resulting work. +# Corresponding Source for a non-source form of such a combination +# shall include the source code for the parts of OpenSSL used as well +# as that of the covered work. + + +if METALINK_IS_ENABLED + METALINK_TESTS = Test-metalink-http.py \ + Test-metalink-http-quoted.py \ + Test-metalink-http-baddigest.py \ + Test-metalink-http-xml.py \ + Test-metalink-http-xml-trust.py \ + Test-metalink-http-xml-trust-name.py \ + Test-metalink-http-xml-type.py \ + Test-metalink-http-xml-type-trust.py \ + Test-metalink-http-xml-type-content.py \ + Test-metalink-http-xml-type-trust-content.py \ + Test-metalink-xml.py \ + Test-metalink-xml-continue.py \ + Test-metalink-xml-relpath.py \ + Test-metalink-xml-abspath.py \ + Test-metalink-xml-homepath.py \ + Test-metalink-xml-trust.py \ + Test-metalink-xml-relpath-trust.py \ + Test-metalink-xml-abspath-trust.py \ + Test-metalink-xml-homepath-trust.py \ + Test-metalink-xml-prefix.py \ + Test-metalink-xml-relprefix.py \ + Test-metalink-xml-absprefix.py \ + Test-metalink-xml-homeprefix.py \ + Test-metalink-xml-prefix-trust.py \ + Test-metalink-xml-relprefix-trust.py \ + Test-metalink-xml-absprefix-trust.py \ + Test-metalink-xml-homeprefix-trust.py \ + Test-metalink-xml-emptyprefix-trust.py \ + Test-metalink-xml-size.py \ + Test-metalink-xml-nohash.py \ + Test-metalink-xml-nourls.py \ + Test-metalink-xml-urlbreak.py +else + METALINK_TESTS = +endif + +AUTOMAKE_OPTIONS = parallel-tests +AM_TESTS_ENVIRONMENT = export WGETRC=/dev/null; MAKE_CHECK=True; export MAKE_CHECK;\ + export PYTHONPATH=$$PYTHONPATH:$(srcdir); export VALGRIND_TESTS="@VALGRIND_TESTS@"; + +if WITH_SSL + AM_TESTS_ENVIRONMENT += export SSL_TESTS=1; +endif + +if HAVE_PYTHON3 + TESTS = Test-504.py \ + Test-416.py \ + Test-auth-basic-fail.py \ + Test-auth-basic.py \ + Test-auth-basic-netrc.py \ + Test-auth-basic-netrc-user-given.py \ + Test-auth-basic-netrc-pass-given.py \ + Test-auth-basic-no-netrc-fail.py \ + Test-auth-both.py \ + Test-auth-digest.py \ + Test-auth-no-challenge.py \ + Test-auth-no-challenge-url.py \ + Test-auth-retcode.py \ + Test-auth-with-content-disposition.py \ + Test-c-full.py \ + Test-condget.py \ + Test-Content-disposition-2.py \ + Test-Content-disposition.py \ + Test--convert-links--content-on-error.py \ + Test-cookie-401.py \ + Test-cookie-domain-mismatch.py \ + Test-cookie-expires.py \ + Test-cookie.py \ + Test-Head.py \ + Test-hsts.py \ + Test--https.py \ + Test--https-crl.py \ + Test-missing-scheme-retval.py \ + Test-O.py \ + Test-pinnedpubkey-der-https.py \ + Test-pinnedpubkey-der-no-check-https.py \ + Test-pinnedpubkey-hash-https.py \ + Test-pinnedpubkey-hash-no-check-fail-https.py \ + Test-pinnedpubkey-pem-fail-https.py \ + Test-pinnedpubkey-pem-https.py \ + Test-Post.py \ + Test-recursive-basic.py \ + Test-recursive-include.py \ + Test-recursive-redirect.py \ + Test-redirect.py \ + Test-redirect-crash.py \ + Test--rejected-log.py \ + Test-reserved-chars.py \ + Test--spider-r.py \ + Test-no_proxy-env.py \ + $(METALINK_TESTS) + +endif + +EXTRA_DIST = certs conf exc misc server test README $(TESTS) + +TEST_EXTENSIONS = .py +PY_LOG_COMPILER = python3 +AM_PY_LOG_FLAGS = -O diff --git a/testenv/Makefile.in b/testenv/Makefile.in new file mode 100644 index 0000000..eece604 --- /dev/null +++ b/testenv/Makefile.in @@ -0,0 +1,2194 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for `wget' utility +# Copyright (C) 2013, 2015, 2018-2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with Wget. If not, see <http://www.gnu.org/licenses/>. + +# Additional permission under GNU GPL version 3 section 7 + +# If you modify this program, or any covered work, by linking or +# combining it with the OpenSSL project's OpenSSL library (or a +# modified version of that library), containing parts covered by the +# terms of the OpenSSL or SSLeay licenses, the Free Software Foundation +# grants you additional permission to convey the resulting work. +# Corresponding Source for a non-source form of such a combination +# shall include the source code for the parts of OpenSSL used as well +# as that of the covered work. +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_SSL_TRUE@am__append_1 = export SSL_TESTS=1; +@HAVE_PYTHON3_TRUE@TESTS = Test-504.py Test-416.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-basic-fail.py Test-auth-basic.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-basic-netrc.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-basic-netrc-user-given.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-basic-netrc-pass-given.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-basic-no-netrc-fail.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-both.py Test-auth-digest.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-no-challenge.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-no-challenge-url.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-retcode.py \ +@HAVE_PYTHON3_TRUE@ Test-auth-with-content-disposition.py \ +@HAVE_PYTHON3_TRUE@ Test-c-full.py Test-condget.py \ +@HAVE_PYTHON3_TRUE@ Test-Content-disposition-2.py \ +@HAVE_PYTHON3_TRUE@ Test-Content-disposition.py \ +@HAVE_PYTHON3_TRUE@ Test--convert-links--content-on-error.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie-401.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie-domain-mismatch.py \ +@HAVE_PYTHON3_TRUE@ Test-cookie-expires.py Test-cookie.py \ +@HAVE_PYTHON3_TRUE@ Test-Head.py Test-hsts.py Test--https.py \ +@HAVE_PYTHON3_TRUE@ Test--https-crl.py \ +@HAVE_PYTHON3_TRUE@ Test-missing-scheme-retval.py Test-O.py \ +@HAVE_PYTHON3_TRUE@ Test-pinnedpubkey-der-https.py \ +@HAVE_PYTHON3_TRUE@ Test-pinnedpubkey-der-no-check-https.py \ +@HAVE_PYTHON3_TRUE@ Test-pinnedpubkey-hash-https.py \ +@HAVE_PYTHON3_TRUE@ Test-pinnedpubkey-hash-no-check-fail-https.py \ +@HAVE_PYTHON3_TRUE@ Test-pinnedpubkey-pem-fail-https.py \ +@HAVE_PYTHON3_TRUE@ Test-pinnedpubkey-pem-https.py Test-Post.py \ +@HAVE_PYTHON3_TRUE@ Test-recursive-basic.py \ +@HAVE_PYTHON3_TRUE@ Test-recursive-include.py \ +@HAVE_PYTHON3_TRUE@ Test-recursive-redirect.py Test-redirect.py \ +@HAVE_PYTHON3_TRUE@ Test-redirect-crash.py \ +@HAVE_PYTHON3_TRUE@ Test--rejected-log.py \ +@HAVE_PYTHON3_TRUE@ Test-reserved-chars.py Test--spider-r.py \ +@HAVE_PYTHON3_TRUE@ Test-no_proxy-env.py $(am__EXEEXT_1) +subdir = testenv +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ + $(top_srcdir)/m4/__inline.m4 \ + $(top_srcdir)/m4/absolute-header.m4 $(top_srcdir)/m4/access.m4 \ + $(top_srcdir)/m4/af_alg.m4 $(top_srcdir)/m4/alloca.m4 \ + $(top_srcdir)/m4/arpa_inet_h.m4 \ + $(top_srcdir)/m4/asm-underscore.m4 $(top_srcdir)/m4/base32.m4 \ + $(top_srcdir)/m4/btowc.m4 $(top_srcdir)/m4/builtin-expect.m4 \ + $(top_srcdir)/m4/byteswap.m4 $(top_srcdir)/m4/canonicalize.m4 \ + $(top_srcdir)/m4/chdir-long.m4 $(top_srcdir)/m4/clock_time.m4 \ + $(top_srcdir)/m4/close.m4 $(top_srcdir)/m4/closedir.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/ctype.m4 \ + $(top_srcdir)/m4/d-ino.m4 $(top_srcdir)/m4/dirent_h.m4 \ + $(top_srcdir)/m4/dirfd.m4 \ + $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup.m4 \ + $(top_srcdir)/m4/dup2.m4 $(top_srcdir)/m4/eaccess.m4 \ + $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \ + $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \ + $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 \ + $(top_srcdir)/m4/fatal-signal.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl.m4 \ + $(top_srcdir)/m4/fcntl_h.m4 $(top_srcdir)/m4/fdopendir.m4 \ + $(top_srcdir)/m4/fflush.m4 $(top_srcdir)/m4/filenamecat.m4 \ + $(top_srcdir)/m4/findprog-in.m4 $(top_srcdir)/m4/flexmember.m4 \ + $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/flock.m4 \ + $(top_srcdir)/m4/fnmatch.m4 $(top_srcdir)/m4/fnmatch_h.m4 \ + $(top_srcdir)/m4/fopen.m4 $(top_srcdir)/m4/fpurge.m4 \ + $(top_srcdir)/m4/freading.m4 $(top_srcdir)/m4/free.m4 \ + $(top_srcdir)/m4/fseek.m4 $(top_srcdir)/m4/fseeko.m4 \ + $(top_srcdir)/m4/fstat.m4 $(top_srcdir)/m4/fstatat.m4 \ + $(top_srcdir)/m4/ftell.m4 $(top_srcdir)/m4/ftello.m4 \ + $(top_srcdir)/m4/futimens.m4 $(top_srcdir)/m4/getaddrinfo.m4 \ + $(top_srcdir)/m4/getcwd-abort-bug.m4 \ + $(top_srcdir)/m4/getcwd-path-max.m4 $(top_srcdir)/m4/getcwd.m4 \ + $(top_srcdir)/m4/getdelim.m4 $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getgroups.m4 $(top_srcdir)/m4/getline.m4 \ + $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/getpagesize.m4 \ + $(top_srcdir)/m4/getpass.m4 $(top_srcdir)/m4/getprogname.m4 \ + $(top_srcdir)/m4/getrandom.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \ + $(top_srcdir)/m4/gl-openssl.m4 \ + $(top_srcdir)/m4/gnulib-common.m4 \ + $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/group-member.m4 \ + $(top_srcdir)/m4/host-cpu-c-abi.m4 $(top_srcdir)/m4/hostent.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/iconv_h.m4 \ + $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inet_ntop.m4 \ + $(top_srcdir)/m4/inline.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax_t.m4 $(top_srcdir)/m4/inttypes.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/ioctl.m4 \ + $(top_srcdir)/m4/isblank.m4 $(top_srcdir)/m4/iswblank.m4 \ + $(top_srcdir)/m4/iswdigit.m4 $(top_srcdir)/m4/iswxdigit.m4 \ + $(top_srcdir)/m4/langinfo_h.m4 $(top_srcdir)/m4/largefile.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libunistring-base.m4 \ + $(top_srcdir)/m4/libunistring-optional.m4 \ + $(top_srcdir)/m4/libunistring.m4 $(top_srcdir)/m4/limits-h.m4 \ + $(top_srcdir)/m4/link.m4 $(top_srcdir)/m4/localcharset.m4 \ + $(top_srcdir)/m4/locale-fr.m4 $(top_srcdir)/m4/locale-ja.m4 \ + $(top_srcdir)/m4/locale-zh.m4 $(top_srcdir)/m4/locale_h.m4 \ + $(top_srcdir)/m4/localeconv.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/lseek.m4 $(top_srcdir)/m4/lstat.m4 \ + $(top_srcdir)/m4/malloc.m4 $(top_srcdir)/m4/malloca.m4 \ + $(top_srcdir)/m4/mbchar.m4 $(top_srcdir)/m4/mbiter.m4 \ + $(top_srcdir)/m4/mbrtowc.m4 $(top_srcdir)/m4/mbsinit.m4 \ + $(top_srcdir)/m4/mbsrtowcs.m4 $(top_srcdir)/m4/mbstate_t.m4 \ + $(top_srcdir)/m4/mbtowc.m4 $(top_srcdir)/m4/md4.m4 \ + $(top_srcdir)/m4/md5.m4 $(top_srcdir)/m4/memchr.m4 \ + $(top_srcdir)/m4/mempcpy.m4 $(top_srcdir)/m4/memrchr.m4 \ + $(top_srcdir)/m4/minmax.m4 $(top_srcdir)/m4/mkdir.m4 \ + $(top_srcdir)/m4/mkostemp.m4 $(top_srcdir)/m4/mkstemp.m4 \ + $(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/mmap-anon.m4 \ + $(top_srcdir)/m4/mode_t.m4 $(top_srcdir)/m4/msvc-inval.m4 \ + $(top_srcdir)/m4/msvc-nothrow.m4 $(top_srcdir)/m4/multiarch.m4 \ + $(top_srcdir)/m4/nanosleep.m4 $(top_srcdir)/m4/netdb_h.m4 \ + $(top_srcdir)/m4/netinet_in_h.m4 \ + $(top_srcdir)/m4/nl_langinfo.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/nocrash.m4 $(top_srcdir)/m4/off_t.m4 \ + $(top_srcdir)/m4/open-cloexec.m4 \ + $(top_srcdir)/m4/open-slash.m4 $(top_srcdir)/m4/open.m4 \ + $(top_srcdir)/m4/openat.m4 $(top_srcdir)/m4/opendir.m4 \ + $(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/pipe.m4 \ + $(top_srcdir)/m4/pipe2.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/posix_spawn.m4 \ + $(top_srcdir)/m4/posix_spawn_faction_addchdir.m4 \ + $(top_srcdir)/m4/printf.m4 \ + $(top_srcdir)/m4/pthread_rwlock_rdlock.m4 \ + $(top_srcdir)/m4/quote.m4 $(top_srcdir)/m4/quotearg.m4 \ + $(top_srcdir)/m4/raise.m4 $(top_srcdir)/m4/rawmemchr.m4 \ + $(top_srcdir)/m4/readdir.m4 $(top_srcdir)/m4/readlink.m4 \ + $(top_srcdir)/m4/realloc.m4 $(top_srcdir)/m4/regex.m4 \ + $(top_srcdir)/m4/rewinddir.m4 $(top_srcdir)/m4/save-cwd.m4 \ + $(top_srcdir)/m4/sched_h.m4 $(top_srcdir)/m4/secure_getenv.m4 \ + $(top_srcdir)/m4/select.m4 $(top_srcdir)/m4/servent.m4 \ + $(top_srcdir)/m4/setlocale_null.m4 \ + $(top_srcdir)/m4/sh-filename.m4 $(top_srcdir)/m4/sha1.m4 \ + $(top_srcdir)/m4/sha256.m4 $(top_srcdir)/m4/sha512.m4 \ + $(top_srcdir)/m4/sig_atomic_t.m4 $(top_srcdir)/m4/sigaction.m4 \ + $(top_srcdir)/m4/signal_h.m4 \ + $(top_srcdir)/m4/signalblocking.m4 $(top_srcdir)/m4/sigpipe.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/snprintf.m4 \ + $(top_srcdir)/m4/socketlib.m4 $(top_srcdir)/m4/sockets.m4 \ + $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sockpfaf.m4 \ + $(top_srcdir)/m4/spawn-pipe.m4 $(top_srcdir)/m4/spawn_h.m4 \ + $(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \ + $(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdalign.m4 \ + $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ + $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \ + $(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strcase.m4 \ + $(top_srcdir)/m4/strchrnul.m4 $(top_srcdir)/m4/strdup.m4 \ + $(top_srcdir)/m4/strerror.m4 $(top_srcdir)/m4/strerror_r.m4 \ + $(top_srcdir)/m4/string_h.m4 $(top_srcdir)/m4/strings_h.m4 \ + $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/strnlen.m4 \ + $(top_srcdir)/m4/strpbrk.m4 $(top_srcdir)/m4/strptime.m4 \ + $(top_srcdir)/m4/strtok_r.m4 $(top_srcdir)/m4/strtol.m4 \ + $(top_srcdir)/m4/strtoll.m4 $(top_srcdir)/m4/symlink.m4 \ + $(top_srcdir)/m4/sys_file_h.m4 $(top_srcdir)/m4/sys_ioctl_h.m4 \ + $(top_srcdir)/m4/sys_random_h.m4 \ + $(top_srcdir)/m4/sys_select_h.m4 \ + $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_time_h.m4 \ + $(top_srcdir)/m4/sys_types_h.m4 $(top_srcdir)/m4/sys_uio_h.m4 \ + $(top_srcdir)/m4/sys_wait_h.m4 $(top_srcdir)/m4/tempname.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/time_h.m4 \ + $(top_srcdir)/m4/time_r.m4 $(top_srcdir)/m4/timegm.m4 \ + $(top_srcdir)/m4/timespec.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \ + $(top_srcdir)/m4/tmpdir.m4 $(top_srcdir)/m4/unistd-safer.m4 \ + $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/unlink.m4 \ + $(top_srcdir)/m4/unlocked-io.m4 $(top_srcdir)/m4/utime.m4 \ + $(top_srcdir)/m4/utime_h.m4 $(top_srcdir)/m4/utimens.m4 \ + $(top_srcdir)/m4/utimes.m4 $(top_srcdir)/m4/vasnprintf.m4 \ + $(top_srcdir)/m4/vasprintf.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/wait-process.m4 \ + $(top_srcdir)/m4/waitpid.m4 $(top_srcdir)/m4/warn-on-use.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/m4/wchar_h.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wcrtomb.m4 \ + $(top_srcdir)/m4/wctype_h.m4 $(top_srcdir)/m4/wcwidth.m4 \ + $(top_srcdir)/m4/wget.m4 $(top_srcdir)/m4/wget_manywarnings.m4 \ + $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/wmemchr.m4 \ + $(top_srcdir)/m4/wmempcpy.m4 $(top_srcdir)/m4/write.m4 \ + $(top_srcdir)/m4/xalloc.m4 $(top_srcdir)/m4/xsize.m4 \ + $(top_srcdir)/m4/xstrndup.m4 $(top_srcdir)/m4/zzgnulib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/src/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +@METALINK_IS_ENABLED_TRUE@am__EXEEXT_1 = Test-metalink-http.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-quoted.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-baddigest.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-trust-name.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type-content.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type-trust-content.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-continue.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relpath.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-abspath.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homepath.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relpath-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-abspath-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homepath-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-prefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relprefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-absprefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homeprefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-prefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-absprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homeprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-emptyprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-size.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-nohash.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-nourls.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-urlbreak.py +TEST_SUITE_LOG = test-suite.log +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.py.log=.log) +PY_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +PY_LOG_COMPILE = $(PY_LOG_COMPILER) $(AM_PY_LOG_FLAGS) $(PY_LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/test-driver README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +ASM_SYMBOL_PREFIX = @ASM_SYMBOL_PREFIX@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +BYTESWAP_H = @BYTESWAP_H@ +CARES_CFLAGS = @CARES_CFLAGS@ +CARES_LIBS = @CARES_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +COMMENT_IF_NO_POD2MAN = @COMMENT_IF_NO_POD2MAN@ +CONFIG_INCLUDE = @CONFIG_INCLUDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +EXEEXT = @EXEEXT@ +FLOAT_H = @FLOAT_H@ +FNMATCH_H = @FNMATCH_H@ +FUZZ_LIBS = @FUZZ_LIBS@ +GETADDRINFO_LIB = @GETADDRINFO_LIB@ +GETOPT_CDEFS_H = @GETOPT_CDEFS_H@ +GETOPT_H = @GETOPT_H@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIB_ACCEPT = @GNULIB_ACCEPT@ +GNULIB_ACCEPT4 = @GNULIB_ACCEPT4@ +GNULIB_ACCESS = @GNULIB_ACCESS@ +GNULIB_ALIGNED_ALLOC = @GNULIB_ALIGNED_ALLOC@ +GNULIB_ALPHASORT = @GNULIB_ALPHASORT@ +GNULIB_ATOLL = @GNULIB_ATOLL@ +GNULIB_BIND = @GNULIB_BIND@ +GNULIB_BTOWC = @GNULIB_BTOWC@ +GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@ +GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@ +GNULIB_CHDIR = @GNULIB_CHDIR@ +GNULIB_CHOWN = @GNULIB_CHOWN@ +GNULIB_CLOSE = @GNULIB_CLOSE@ +GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@ +GNULIB_CONNECT = @GNULIB_CONNECT@ +GNULIB_COPY_FILE_RANGE = @GNULIB_COPY_FILE_RANGE@ +GNULIB_CREAT = @GNULIB_CREAT@ +GNULIB_CTIME = @GNULIB_CTIME@ +GNULIB_DIRFD = @GNULIB_DIRFD@ +GNULIB_DPRINTF = @GNULIB_DPRINTF@ +GNULIB_DUP = @GNULIB_DUP@ +GNULIB_DUP2 = @GNULIB_DUP2@ +GNULIB_DUP3 = @GNULIB_DUP3@ +GNULIB_DUPLOCALE = @GNULIB_DUPLOCALE@ +GNULIB_ENVIRON = @GNULIB_ENVIRON@ +GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@ +GNULIB_EXECL = @GNULIB_EXECL@ +GNULIB_EXECLE = @GNULIB_EXECLE@ +GNULIB_EXECLP = @GNULIB_EXECLP@ +GNULIB_EXECV = @GNULIB_EXECV@ +GNULIB_EXECVE = @GNULIB_EXECVE@ +GNULIB_EXECVP = @GNULIB_EXECVP@ +GNULIB_EXECVPE = @GNULIB_EXECVPE@ +GNULIB_EXPLICIT_BZERO = @GNULIB_EXPLICIT_BZERO@ +GNULIB_FACCESSAT = @GNULIB_FACCESSAT@ +GNULIB_FCHDIR = @GNULIB_FCHDIR@ +GNULIB_FCHMODAT = @GNULIB_FCHMODAT@ +GNULIB_FCHOWNAT = @GNULIB_FCHOWNAT@ +GNULIB_FCLOSE = @GNULIB_FCLOSE@ +GNULIB_FCNTL = @GNULIB_FCNTL@ +GNULIB_FDATASYNC = @GNULIB_FDATASYNC@ +GNULIB_FDOPEN = @GNULIB_FDOPEN@ +GNULIB_FDOPENDIR = @GNULIB_FDOPENDIR@ +GNULIB_FFLUSH = @GNULIB_FFLUSH@ +GNULIB_FFS = @GNULIB_FFS@ +GNULIB_FFSL = @GNULIB_FFSL@ +GNULIB_FFSLL = @GNULIB_FFSLL@ +GNULIB_FGETC = @GNULIB_FGETC@ +GNULIB_FGETS = @GNULIB_FGETS@ +GNULIB_FLOCK = @GNULIB_FLOCK@ +GNULIB_FNMATCH = @GNULIB_FNMATCH@ +GNULIB_FOPEN = @GNULIB_FOPEN@ +GNULIB_FPRINTF = @GNULIB_FPRINTF@ +GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@ +GNULIB_FPURGE = @GNULIB_FPURGE@ +GNULIB_FPUTC = @GNULIB_FPUTC@ +GNULIB_FPUTS = @GNULIB_FPUTS@ +GNULIB_FREAD = @GNULIB_FREAD@ +GNULIB_FREE_POSIX = @GNULIB_FREE_POSIX@ +GNULIB_FREOPEN = @GNULIB_FREOPEN@ +GNULIB_FSCANF = @GNULIB_FSCANF@ +GNULIB_FSEEK = @GNULIB_FSEEK@ +GNULIB_FSEEKO = @GNULIB_FSEEKO@ +GNULIB_FSTAT = @GNULIB_FSTAT@ +GNULIB_FSTATAT = @GNULIB_FSTATAT@ +GNULIB_FSYNC = @GNULIB_FSYNC@ +GNULIB_FTELL = @GNULIB_FTELL@ +GNULIB_FTELLO = @GNULIB_FTELLO@ +GNULIB_FTRUNCATE = @GNULIB_FTRUNCATE@ +GNULIB_FUTIMENS = @GNULIB_FUTIMENS@ +GNULIB_FWRITE = @GNULIB_FWRITE@ +GNULIB_GETADDRINFO = @GNULIB_GETADDRINFO@ +GNULIB_GETC = @GNULIB_GETC@ +GNULIB_GETCHAR = @GNULIB_GETCHAR@ +GNULIB_GETCWD = @GNULIB_GETCWD@ +GNULIB_GETDELIM = @GNULIB_GETDELIM@ +GNULIB_GETDOMAINNAME = @GNULIB_GETDOMAINNAME@ +GNULIB_GETDTABLESIZE = @GNULIB_GETDTABLESIZE@ +GNULIB_GETENTROPY = @GNULIB_GETENTROPY@ +GNULIB_GETGROUPS = @GNULIB_GETGROUPS@ +GNULIB_GETHOSTNAME = @GNULIB_GETHOSTNAME@ +GNULIB_GETLINE = @GNULIB_GETLINE@ +GNULIB_GETLOADAVG = @GNULIB_GETLOADAVG@ +GNULIB_GETLOGIN = @GNULIB_GETLOGIN@ +GNULIB_GETLOGIN_R = @GNULIB_GETLOGIN_R@ +GNULIB_GETOPT_POSIX = @GNULIB_GETOPT_POSIX@ +GNULIB_GETPAGESIZE = @GNULIB_GETPAGESIZE@ +GNULIB_GETPASS = @GNULIB_GETPASS@ +GNULIB_GETPEERNAME = @GNULIB_GETPEERNAME@ +GNULIB_GETRANDOM = @GNULIB_GETRANDOM@ +GNULIB_GETSOCKNAME = @GNULIB_GETSOCKNAME@ +GNULIB_GETSOCKOPT = @GNULIB_GETSOCKOPT@ +GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNULIB_GETUMASK = @GNULIB_GETUMASK@ +GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@ +GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@ +GNULIB_GRANTPT = @GNULIB_GRANTPT@ +GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@ +GNULIB_ICONV = @GNULIB_ICONV@ +GNULIB_IMAXABS = @GNULIB_IMAXABS@ +GNULIB_IMAXDIV = @GNULIB_IMAXDIV@ +GNULIB_INET_NTOP = @GNULIB_INET_NTOP@ +GNULIB_INET_PTON = @GNULIB_INET_PTON@ +GNULIB_IOCTL = @GNULIB_IOCTL@ +GNULIB_ISATTY = @GNULIB_ISATTY@ +GNULIB_ISBLANK = @GNULIB_ISBLANK@ +GNULIB_ISWBLANK = @GNULIB_ISWBLANK@ +GNULIB_ISWCTYPE = @GNULIB_ISWCTYPE@ +GNULIB_ISWDIGIT = @GNULIB_ISWDIGIT@ +GNULIB_ISWXDIGIT = @GNULIB_ISWXDIGIT@ +GNULIB_LCHMOD = @GNULIB_LCHMOD@ +GNULIB_LCHOWN = @GNULIB_LCHOWN@ +GNULIB_LINK = @GNULIB_LINK@ +GNULIB_LINKAT = @GNULIB_LINKAT@ +GNULIB_LISTEN = @GNULIB_LISTEN@ +GNULIB_LOCALECONV = @GNULIB_LOCALECONV@ +GNULIB_LOCALENAME = @GNULIB_LOCALENAME@ +GNULIB_LOCALTIME = @GNULIB_LOCALTIME@ +GNULIB_LSEEK = @GNULIB_LSEEK@ +GNULIB_LSTAT = @GNULIB_LSTAT@ +GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@ +GNULIB_MBRLEN = @GNULIB_MBRLEN@ +GNULIB_MBRTOWC = @GNULIB_MBRTOWC@ +GNULIB_MBSCASECMP = @GNULIB_MBSCASECMP@ +GNULIB_MBSCASESTR = @GNULIB_MBSCASESTR@ +GNULIB_MBSCHR = @GNULIB_MBSCHR@ +GNULIB_MBSCSPN = @GNULIB_MBSCSPN@ +GNULIB_MBSINIT = @GNULIB_MBSINIT@ +GNULIB_MBSLEN = @GNULIB_MBSLEN@ +GNULIB_MBSNCASECMP = @GNULIB_MBSNCASECMP@ +GNULIB_MBSNLEN = @GNULIB_MBSNLEN@ +GNULIB_MBSNRTOWCS = @GNULIB_MBSNRTOWCS@ +GNULIB_MBSPBRK = @GNULIB_MBSPBRK@ +GNULIB_MBSPCASECMP = @GNULIB_MBSPCASECMP@ +GNULIB_MBSRCHR = @GNULIB_MBSRCHR@ +GNULIB_MBSRTOWCS = @GNULIB_MBSRTOWCS@ +GNULIB_MBSSEP = @GNULIB_MBSSEP@ +GNULIB_MBSSPN = @GNULIB_MBSSPN@ +GNULIB_MBSSTR = @GNULIB_MBSSTR@ +GNULIB_MBSTOK_R = @GNULIB_MBSTOK_R@ +GNULIB_MBTOWC = @GNULIB_MBTOWC@ +GNULIB_MDA_ACCESS = @GNULIB_MDA_ACCESS@ +GNULIB_MDA_CHDIR = @GNULIB_MDA_CHDIR@ +GNULIB_MDA_CHMOD = @GNULIB_MDA_CHMOD@ +GNULIB_MDA_CLOSE = @GNULIB_MDA_CLOSE@ +GNULIB_MDA_CREAT = @GNULIB_MDA_CREAT@ +GNULIB_MDA_DUP = @GNULIB_MDA_DUP@ +GNULIB_MDA_DUP2 = @GNULIB_MDA_DUP2@ +GNULIB_MDA_ECVT = @GNULIB_MDA_ECVT@ +GNULIB_MDA_EXECL = @GNULIB_MDA_EXECL@ +GNULIB_MDA_EXECLE = @GNULIB_MDA_EXECLE@ +GNULIB_MDA_EXECLP = @GNULIB_MDA_EXECLP@ +GNULIB_MDA_EXECV = @GNULIB_MDA_EXECV@ +GNULIB_MDA_EXECVE = @GNULIB_MDA_EXECVE@ +GNULIB_MDA_EXECVP = @GNULIB_MDA_EXECVP@ +GNULIB_MDA_EXECVPE = @GNULIB_MDA_EXECVPE@ +GNULIB_MDA_FCLOSEALL = @GNULIB_MDA_FCLOSEALL@ +GNULIB_MDA_FCVT = @GNULIB_MDA_FCVT@ +GNULIB_MDA_FDOPEN = @GNULIB_MDA_FDOPEN@ +GNULIB_MDA_FILENO = @GNULIB_MDA_FILENO@ +GNULIB_MDA_GCVT = @GNULIB_MDA_GCVT@ +GNULIB_MDA_GETCWD = @GNULIB_MDA_GETCWD@ +GNULIB_MDA_GETPID = @GNULIB_MDA_GETPID@ +GNULIB_MDA_GETW = @GNULIB_MDA_GETW@ +GNULIB_MDA_ISATTY = @GNULIB_MDA_ISATTY@ +GNULIB_MDA_LSEEK = @GNULIB_MDA_LSEEK@ +GNULIB_MDA_MEMCCPY = @GNULIB_MDA_MEMCCPY@ +GNULIB_MDA_MKDIR = @GNULIB_MDA_MKDIR@ +GNULIB_MDA_MKTEMP = @GNULIB_MDA_MKTEMP@ +GNULIB_MDA_OPEN = @GNULIB_MDA_OPEN@ +GNULIB_MDA_PUTENV = @GNULIB_MDA_PUTENV@ +GNULIB_MDA_PUTW = @GNULIB_MDA_PUTW@ +GNULIB_MDA_READ = @GNULIB_MDA_READ@ +GNULIB_MDA_RMDIR = @GNULIB_MDA_RMDIR@ +GNULIB_MDA_STRDUP = @GNULIB_MDA_STRDUP@ +GNULIB_MDA_SWAB = @GNULIB_MDA_SWAB@ +GNULIB_MDA_TEMPNAM = @GNULIB_MDA_TEMPNAM@ +GNULIB_MDA_TZSET = @GNULIB_MDA_TZSET@ +GNULIB_MDA_UMASK = @GNULIB_MDA_UMASK@ +GNULIB_MDA_UNLINK = @GNULIB_MDA_UNLINK@ +GNULIB_MDA_UTIME = @GNULIB_MDA_UTIME@ +GNULIB_MDA_WCSDUP = @GNULIB_MDA_WCSDUP@ +GNULIB_MDA_WRITE = @GNULIB_MDA_WRITE@ +GNULIB_MEMCHR = @GNULIB_MEMCHR@ +GNULIB_MEMMEM = @GNULIB_MEMMEM@ +GNULIB_MEMPCPY = @GNULIB_MEMPCPY@ +GNULIB_MEMRCHR = @GNULIB_MEMRCHR@ +GNULIB_MKDIR = @GNULIB_MKDIR@ +GNULIB_MKDIRAT = @GNULIB_MKDIRAT@ +GNULIB_MKDTEMP = @GNULIB_MKDTEMP@ +GNULIB_MKFIFO = @GNULIB_MKFIFO@ +GNULIB_MKFIFOAT = @GNULIB_MKFIFOAT@ +GNULIB_MKNOD = @GNULIB_MKNOD@ +GNULIB_MKNODAT = @GNULIB_MKNODAT@ +GNULIB_MKOSTEMP = @GNULIB_MKOSTEMP@ +GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@ +GNULIB_MKSTEMP = @GNULIB_MKSTEMP@ +GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@ +GNULIB_MKTIME = @GNULIB_MKTIME@ +GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@ +GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@ +GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@ +GNULIB_OBSTACK_PRINTF = @GNULIB_OBSTACK_PRINTF@ +GNULIB_OBSTACK_PRINTF_POSIX = @GNULIB_OBSTACK_PRINTF_POSIX@ +GNULIB_OPEN = @GNULIB_OPEN@ +GNULIB_OPENAT = @GNULIB_OPENAT@ +GNULIB_OPENDIR = @GNULIB_OPENDIR@ +GNULIB_OVERRIDES_STRUCT_STAT = @GNULIB_OVERRIDES_STRUCT_STAT@ +GNULIB_OVERRIDES_WINT_T = @GNULIB_OVERRIDES_WINT_T@ +GNULIB_PCLOSE = @GNULIB_PCLOSE@ +GNULIB_PERROR = @GNULIB_PERROR@ +GNULIB_PIPE = @GNULIB_PIPE@ +GNULIB_PIPE2 = @GNULIB_PIPE2@ +GNULIB_POPEN = @GNULIB_POPEN@ +GNULIB_POSIX_MEMALIGN = @GNULIB_POSIX_MEMALIGN@ +GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@ +GNULIB_POSIX_SPAWN = @GNULIB_POSIX_SPAWN@ +GNULIB_POSIX_SPAWNATTR_DESTROY = @GNULIB_POSIX_SPAWNATTR_DESTROY@ +GNULIB_POSIX_SPAWNATTR_GETFLAGS = @GNULIB_POSIX_SPAWNATTR_GETFLAGS@ +GNULIB_POSIX_SPAWNATTR_GETPGROUP = @GNULIB_POSIX_SPAWNATTR_GETPGROUP@ +GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM = @GNULIB_POSIX_SPAWNATTR_GETSCHEDPARAM@ +GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY = @GNULIB_POSIX_SPAWNATTR_GETSCHEDPOLICY@ +GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT = @GNULIB_POSIX_SPAWNATTR_GETSIGDEFAULT@ +GNULIB_POSIX_SPAWNATTR_GETSIGMASK = @GNULIB_POSIX_SPAWNATTR_GETSIGMASK@ +GNULIB_POSIX_SPAWNATTR_INIT = @GNULIB_POSIX_SPAWNATTR_INIT@ +GNULIB_POSIX_SPAWNATTR_SETFLAGS = @GNULIB_POSIX_SPAWNATTR_SETFLAGS@ +GNULIB_POSIX_SPAWNATTR_SETPGROUP = @GNULIB_POSIX_SPAWNATTR_SETPGROUP@ +GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM = @GNULIB_POSIX_SPAWNATTR_SETSCHEDPARAM@ +GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY = @GNULIB_POSIX_SPAWNATTR_SETSCHEDPOLICY@ +GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT = @GNULIB_POSIX_SPAWNATTR_SETSIGDEFAULT@ +GNULIB_POSIX_SPAWNATTR_SETSIGMASK = @GNULIB_POSIX_SPAWNATTR_SETSIGMASK@ +GNULIB_POSIX_SPAWNP = @GNULIB_POSIX_SPAWNP@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDFCHDIR = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDFCHDIR@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY@ +GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT@ +GNULIB_PREAD = @GNULIB_PREAD@ +GNULIB_PRINTF = @GNULIB_PRINTF@ +GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@ +GNULIB_PSELECT = @GNULIB_PSELECT@ +GNULIB_PTHREAD_SIGMASK = @GNULIB_PTHREAD_SIGMASK@ +GNULIB_PTSNAME = @GNULIB_PTSNAME@ +GNULIB_PTSNAME_R = @GNULIB_PTSNAME_R@ +GNULIB_PUTC = @GNULIB_PUTC@ +GNULIB_PUTCHAR = @GNULIB_PUTCHAR@ +GNULIB_PUTENV = @GNULIB_PUTENV@ +GNULIB_PUTS = @GNULIB_PUTS@ +GNULIB_PWRITE = @GNULIB_PWRITE@ +GNULIB_QSORT_R = @GNULIB_QSORT_R@ +GNULIB_RAISE = @GNULIB_RAISE@ +GNULIB_RANDOM = @GNULIB_RANDOM@ +GNULIB_RANDOM_R = @GNULIB_RANDOM_R@ +GNULIB_RAWMEMCHR = @GNULIB_RAWMEMCHR@ +GNULIB_READ = @GNULIB_READ@ +GNULIB_READDIR = @GNULIB_READDIR@ +GNULIB_READLINK = @GNULIB_READLINK@ +GNULIB_READLINKAT = @GNULIB_READLINKAT@ +GNULIB_REALLOCARRAY = @GNULIB_REALLOCARRAY@ +GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@ +GNULIB_REALPATH = @GNULIB_REALPATH@ +GNULIB_RECV = @GNULIB_RECV@ +GNULIB_RECVFROM = @GNULIB_RECVFROM@ +GNULIB_REMOVE = @GNULIB_REMOVE@ +GNULIB_RENAME = @GNULIB_RENAME@ +GNULIB_RENAMEAT = @GNULIB_RENAMEAT@ +GNULIB_REWINDDIR = @GNULIB_REWINDDIR@ +GNULIB_RMDIR = @GNULIB_RMDIR@ +GNULIB_RPMATCH = @GNULIB_RPMATCH@ +GNULIB_SCANDIR = @GNULIB_SCANDIR@ +GNULIB_SCANF = @GNULIB_SCANF@ +GNULIB_SCHED_YIELD = @GNULIB_SCHED_YIELD@ +GNULIB_SECURE_GETENV = @GNULIB_SECURE_GETENV@ +GNULIB_SELECT = @GNULIB_SELECT@ +GNULIB_SEND = @GNULIB_SEND@ +GNULIB_SENDTO = @GNULIB_SENDTO@ +GNULIB_SETENV = @GNULIB_SETENV@ +GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@ +GNULIB_SETLOCALE = @GNULIB_SETLOCALE@ +GNULIB_SETLOCALE_NULL = @GNULIB_SETLOCALE_NULL@ +GNULIB_SETSOCKOPT = @GNULIB_SETSOCKOPT@ +GNULIB_SHUTDOWN = @GNULIB_SHUTDOWN@ +GNULIB_SIGABBREV_NP = @GNULIB_SIGABBREV_NP@ +GNULIB_SIGACTION = @GNULIB_SIGACTION@ +GNULIB_SIGDESCR_NP = @GNULIB_SIGDESCR_NP@ +GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@ +GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@ +GNULIB_SLEEP = @GNULIB_SLEEP@ +GNULIB_SNPRINTF = @GNULIB_SNPRINTF@ +GNULIB_SOCKET = @GNULIB_SOCKET@ +GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@ +GNULIB_STAT = @GNULIB_STAT@ +GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@ +GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@ +GNULIB_STPCPY = @GNULIB_STPCPY@ +GNULIB_STPNCPY = @GNULIB_STPNCPY@ +GNULIB_STRCASESTR = @GNULIB_STRCASESTR@ +GNULIB_STRCHRNUL = @GNULIB_STRCHRNUL@ +GNULIB_STRDUP = @GNULIB_STRDUP@ +GNULIB_STRERROR = @GNULIB_STRERROR@ +GNULIB_STRERRORNAME_NP = @GNULIB_STRERRORNAME_NP@ +GNULIB_STRERROR_R = @GNULIB_STRERROR_R@ +GNULIB_STRFTIME = @GNULIB_STRFTIME@ +GNULIB_STRNCAT = @GNULIB_STRNCAT@ +GNULIB_STRNDUP = @GNULIB_STRNDUP@ +GNULIB_STRNLEN = @GNULIB_STRNLEN@ +GNULIB_STRPBRK = @GNULIB_STRPBRK@ +GNULIB_STRPTIME = @GNULIB_STRPTIME@ +GNULIB_STRSEP = @GNULIB_STRSEP@ +GNULIB_STRSIGNAL = @GNULIB_STRSIGNAL@ +GNULIB_STRSTR = @GNULIB_STRSTR@ +GNULIB_STRTOD = @GNULIB_STRTOD@ +GNULIB_STRTOIMAX = @GNULIB_STRTOIMAX@ +GNULIB_STRTOK_R = @GNULIB_STRTOK_R@ +GNULIB_STRTOLD = @GNULIB_STRTOLD@ +GNULIB_STRTOLL = @GNULIB_STRTOLL@ +GNULIB_STRTOULL = @GNULIB_STRTOULL@ +GNULIB_STRTOUMAX = @GNULIB_STRTOUMAX@ +GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@ +GNULIB_SYMLINK = @GNULIB_SYMLINK@ +GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@ +GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@ +GNULIB_TIMEGM = @GNULIB_TIMEGM@ +GNULIB_TIME_R = @GNULIB_TIME_R@ +GNULIB_TIME_RZ = @GNULIB_TIME_RZ@ +GNULIB_TMPFILE = @GNULIB_TMPFILE@ +GNULIB_TOWCTRANS = @GNULIB_TOWCTRANS@ +GNULIB_TRUNCATE = @GNULIB_TRUNCATE@ +GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@ +GNULIB_TZSET = @GNULIB_TZSET@ +GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@ +GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@ +GNULIB_UNLINK = @GNULIB_UNLINK@ +GNULIB_UNLINKAT = @GNULIB_UNLINKAT@ +GNULIB_UNLOCKPT = @GNULIB_UNLOCKPT@ +GNULIB_UNSETENV = @GNULIB_UNSETENV@ +GNULIB_USLEEP = @GNULIB_USLEEP@ +GNULIB_UTIME = @GNULIB_UTIME@ +GNULIB_UTIMENSAT = @GNULIB_UTIMENSAT@ +GNULIB_VASPRINTF = @GNULIB_VASPRINTF@ +GNULIB_VDPRINTF = @GNULIB_VDPRINTF@ +GNULIB_VFPRINTF = @GNULIB_VFPRINTF@ +GNULIB_VFPRINTF_POSIX = @GNULIB_VFPRINTF_POSIX@ +GNULIB_VFSCANF = @GNULIB_VFSCANF@ +GNULIB_VPRINTF = @GNULIB_VPRINTF@ +GNULIB_VPRINTF_POSIX = @GNULIB_VPRINTF_POSIX@ +GNULIB_VSCANF = @GNULIB_VSCANF@ +GNULIB_VSNPRINTF = @GNULIB_VSNPRINTF@ +GNULIB_VSPRINTF_POSIX = @GNULIB_VSPRINTF_POSIX@ +GNULIB_WAITPID = @GNULIB_WAITPID@ +GNULIB_WARN_CFLAGS = @GNULIB_WARN_CFLAGS@ +GNULIB_WCPCPY = @GNULIB_WCPCPY@ +GNULIB_WCPNCPY = @GNULIB_WCPNCPY@ +GNULIB_WCRTOMB = @GNULIB_WCRTOMB@ +GNULIB_WCSCASECMP = @GNULIB_WCSCASECMP@ +GNULIB_WCSCAT = @GNULIB_WCSCAT@ +GNULIB_WCSCHR = @GNULIB_WCSCHR@ +GNULIB_WCSCMP = @GNULIB_WCSCMP@ +GNULIB_WCSCOLL = @GNULIB_WCSCOLL@ +GNULIB_WCSCPY = @GNULIB_WCSCPY@ +GNULIB_WCSCSPN = @GNULIB_WCSCSPN@ +GNULIB_WCSDUP = @GNULIB_WCSDUP@ +GNULIB_WCSFTIME = @GNULIB_WCSFTIME@ +GNULIB_WCSLEN = @GNULIB_WCSLEN@ +GNULIB_WCSNCASECMP = @GNULIB_WCSNCASECMP@ +GNULIB_WCSNCAT = @GNULIB_WCSNCAT@ +GNULIB_WCSNCMP = @GNULIB_WCSNCMP@ +GNULIB_WCSNCPY = @GNULIB_WCSNCPY@ +GNULIB_WCSNLEN = @GNULIB_WCSNLEN@ +GNULIB_WCSNRTOMBS = @GNULIB_WCSNRTOMBS@ +GNULIB_WCSPBRK = @GNULIB_WCSPBRK@ +GNULIB_WCSRCHR = @GNULIB_WCSRCHR@ +GNULIB_WCSRTOMBS = @GNULIB_WCSRTOMBS@ +GNULIB_WCSSPN = @GNULIB_WCSSPN@ +GNULIB_WCSSTR = @GNULIB_WCSSTR@ +GNULIB_WCSTOK = @GNULIB_WCSTOK@ +GNULIB_WCSWIDTH = @GNULIB_WCSWIDTH@ +GNULIB_WCSXFRM = @GNULIB_WCSXFRM@ +GNULIB_WCTOB = @GNULIB_WCTOB@ +GNULIB_WCTOMB = @GNULIB_WCTOMB@ +GNULIB_WCTRANS = @GNULIB_WCTRANS@ +GNULIB_WCTYPE = @GNULIB_WCTYPE@ +GNULIB_WCWIDTH = @GNULIB_WCWIDTH@ +GNULIB_WMEMCHR = @GNULIB_WMEMCHR@ +GNULIB_WMEMCMP = @GNULIB_WMEMCMP@ +GNULIB_WMEMCPY = @GNULIB_WMEMCPY@ +GNULIB_WMEMMOVE = @GNULIB_WMEMMOVE@ +GNULIB_WMEMPCPY = @GNULIB_WMEMPCPY@ +GNULIB_WMEMSET = @GNULIB_WMEMSET@ +GNULIB_WRITE = @GNULIB_WRITE@ +GNULIB__EXIT = @GNULIB__EXIT@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GPGME_CFLAGS = @GPGME_CFLAGS@ +GPGME_CONFIG = @GPGME_CONFIG@ +GPGME_LIBS = @GPGME_LIBS@ +GREP = @GREP@ +HAVE_ACCEPT4 = @HAVE_ACCEPT4@ +HAVE_ALIGNED_ALLOC = @HAVE_ALIGNED_ALLOC@ +HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ +HAVE_ALPHASORT = @HAVE_ALPHASORT@ +HAVE_ARPA_INET_H = @HAVE_ARPA_INET_H@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ +HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@ +HAVE_CRTDEFS_H = @HAVE_CRTDEFS_H@ +HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ +HAVE_DECL_ECVT = @HAVE_DECL_ECVT@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_EXECVPE = @HAVE_DECL_EXECVPE@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FCLOSEALL = @HAVE_DECL_FCLOSEALL@ +HAVE_DECL_FCVT = @HAVE_DECL_FCVT@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FREEADDRINFO = @HAVE_DECL_FREEADDRINFO@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GAI_STRERROR = @HAVE_DECL_GAI_STRERROR@ +HAVE_DECL_GCVT = @HAVE_DECL_GCVT@ +HAVE_DECL_GETADDRINFO = @HAVE_DECL_GETADDRINFO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN = @HAVE_DECL_GETLOGIN@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETNAMEINFO = @HAVE_DECL_GETNAMEINFO@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_INET_NTOP = @HAVE_DECL_INET_NTOP@ +HAVE_DECL_INET_PTON = @HAVE_DECL_INET_PTON@ +HAVE_DECL_INITSTATE = @HAVE_DECL_INITSTATE@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SETSTATE = @HAVE_DECL_SETSTATE@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DECL_TRUNCATE = @HAVE_DECL_TRUNCATE@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCSDUP = @HAVE_DECL_WCSDUP@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DIRENT_H = @HAVE_DIRENT_H@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_EXECVPE = @HAVE_EXECVPE@ +HAVE_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FDOPENDIR = @HAVE_FDOPENDIR@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFS = @HAVE_FFS@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FLOCK = @HAVE_FLOCK@ +HAVE_FNMATCH = @HAVE_FNMATCH@ +HAVE_FNMATCH_H = @HAVE_FNMATCH_H@ +HAVE_FREELOCALE = @HAVE_FREELOCALE@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETENTROPY = @HAVE_GETENTROPY@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETOPT_H = @HAVE_GETOPT_H@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETPASS = @HAVE_GETPASS@ +HAVE_GETRANDOM = @HAVE_GETRANDOM@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GETUMASK = @HAVE_GETUMASK@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_IMAXDIV_T = @HAVE_IMAXDIV_T@ +HAVE_INITSTATE = @HAVE_INITSTATE@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISBLANK = @HAVE_ISBLANK@ +HAVE_ISWBLANK = @HAVE_ISWBLANK@ +HAVE_ISWCNTRL = @HAVE_ISWCNTRL@ +HAVE_LANGINFO_ALTMON = @HAVE_LANGINFO_ALTMON@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LIBGNUTLS = @HAVE_LIBGNUTLS@ +HAVE_LIBSSL = @HAVE_LIBSSL@ +HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MBTOWC = @HAVE_MBTOWC@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NETDB_H = @HAVE_NETDB_H@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OPENDIR = @HAVE_OPENDIR@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_MEMALIGN = @HAVE_POSIX_MEMALIGN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_POSIX_SPAWN = @HAVE_POSIX_SPAWN@ +HAVE_POSIX_SPAWNATTR_T = @HAVE_POSIX_SPAWNATTR_T@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = @HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDFCHDIR = @HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDFCHDIR@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_T = @HAVE_POSIX_SPAWN_FILE_ACTIONS_T@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_QSORT_R = @HAVE_QSORT_R@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READDIR = @HAVE_READDIR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALLOCARRAY = @HAVE_REALLOCARRAY@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_REWINDDIR = @HAVE_REWINDDIR@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SA_FAMILY_T = @HAVE_SA_FAMILY_T@ +HAVE_SCANDIR = @HAVE_SCANDIR@ +HAVE_SCHED_H = @HAVE_SCHED_H@ +HAVE_SCHED_YIELD = @HAVE_SCHED_YIELD@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SETSTATE = @HAVE_SETSTATE@ +HAVE_SIGABBREV_NP = @HAVE_SIGABBREV_NP@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGDESCR_NP = @HAVE_SIGDESCR_NP@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_SPAWN_H = @HAVE_SPAWN_H@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRERRORNAME_NP = @HAVE_STRERRORNAME_NP@ +HAVE_STRINGS_H = @HAVE_STRINGS_H@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOLD = @HAVE_STRTOLD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_ADDRINFO = @HAVE_STRUCT_ADDRINFO@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SCHED_PARAM = @HAVE_STRUCT_SCHED_PARAM@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_SOCKADDR_STORAGE = @HAVE_STRUCT_SOCKADDR_STORAGE@ +HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = @HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@ +HAVE_SYS_FILE_H = @HAVE_SYS_FILE_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_IOCTL_H = @HAVE_SYS_IOCTL_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_RANDOM_H = @HAVE_SYS_RANDOM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_SYS_UIO_H = @HAVE_SYS_UIO_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIME = @HAVE_UTIME@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_UTIME_H = @HAVE_UTIME_H@ +HAVE_VALGRIND = @HAVE_VALGRIND@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSFTIME = @HAVE_WCSFTIME@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WCTRANS_T = @HAVE_WCTRANS_T@ +HAVE_WCTYPE_H = @HAVE_WCTYPE_H@ +HAVE_WCTYPE_T = @HAVE_WCTYPE_T@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMPCPY = @HAVE_WMEMPCPY@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +HOSTENT_LIB = @HOSTENT_LIB@ +ICONV_CONST = @ICONV_CONST@ +ICONV_H = @ICONV_H@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INET_NTOP_LIB = @INET_NTOP_LIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@ +INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBGNUTLS = @LIBGNUTLS@ +LIBGNUTLS_PREFIX = @LIBGNUTLS_PREFIX@ +LIBGNU_LIBDEPS = @LIBGNU_LIBDEPS@ +LIBGNU_LTLIBDEPS = @LIBGNU_LTLIBDEPS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPMULTITHREAD = @LIBPMULTITHREAD@ +LIBPSL_CFLAGS = @LIBPSL_CFLAGS@ +LIBPSL_LIBS = @LIBPSL_LIBS@ +LIBPTHREAD = @LIBPTHREAD@ +LIBS = @LIBS@ +LIBSOCKET = @LIBSOCKET@ +LIBSSL = @LIBSSL@ +LIBSSL_PREFIX = @LIBSSL_PREFIX@ +LIBSTDTHREAD = @LIBSTDTHREAD@ +LIBTHREAD = @LIBTHREAD@ +LIBUNISTRING = @LIBUNISTRING@ +LIBUNISTRING_PREFIX = @LIBUNISTRING_PREFIX@ +LIBUNISTRING_UNICASE_H = @LIBUNISTRING_UNICASE_H@ +LIBUNISTRING_UNICTYPE_H = @LIBUNISTRING_UNICTYPE_H@ +LIBUNISTRING_UNINORM_H = @LIBUNISTRING_UNINORM_H@ +LIBUNISTRING_UNISTR_H = @LIBUNISTRING_UNISTR_H@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@ +LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_CRYPTO = @LIB_CRYPTO@ +LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ +LIB_GETRANDOM = @LIB_GETRANDOM@ +LIB_HARD_LOCALE = @LIB_HARD_LOCALE@ +LIB_MBRTOWC = @LIB_MBRTOWC@ +LIB_NANOSLEEP = @LIB_NANOSLEEP@ +LIB_NL_LANGINFO = @LIB_NL_LANGINFO@ +LIB_POSIX_SPAWN = @LIB_POSIX_SPAWN@ +LIB_SCHED_YIELD = @LIB_SCHED_YIELD@ +LIB_SELECT = @LIB_SELECT@ +LIB_SETLOCALE_NULL = @LIB_SETLOCALE_NULL@ +LIMITS_H = @LIMITS_H@ +LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LTLIBGNUTLS = @LTLIBGNUTLS@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBSSL = @LTLIBSSL@ +LTLIBTHREAD = @LTLIBTHREAD@ +LTLIBUNISTRING = @LTLIBUNISTRING@ +MAKEINFO = @MAKEINFO@ +METALINK_CFLAGS = @METALINK_CFLAGS@ +METALINK_LIBS = @METALINK_LIBS@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NETINET_IN_H = @NETINET_IN_H@ +NETTLE_LIBS = @NETTLE_LIBS@ +NEXT_ARPA_INET_H = @NEXT_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H = @NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_CTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_CTYPE_H@ +NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_FNMATCH_H = @NEXT_AS_FIRST_DIRECTIVE_FNMATCH_H@ +NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ +NEXT_AS_FIRST_DIRECTIVE_ICONV_H = @NEXT_AS_FIRST_DIRECTIVE_ICONV_H@ +NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_NETDB_H = @NEXT_AS_FIRST_DIRECTIVE_NETDB_H@ +NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H = @NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H@ +NEXT_AS_FIRST_DIRECTIVE_SCHED_H = @NEXT_AS_FIRST_DIRECTIVE_SCHED_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_SPAWN_H = @NEXT_AS_FIRST_DIRECTIVE_SPAWN_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_FILE_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_FILE_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_RANDOM_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_RANDOM_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_WAIT_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_UTIME_H = @NEXT_AS_FIRST_DIRECTIVE_UTIME_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@ +NEXT_CTYPE_H = @NEXT_CTYPE_H@ +NEXT_DIRENT_H = @NEXT_DIRENT_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_FNMATCH_H = @NEXT_FNMATCH_H@ +NEXT_GETOPT_H = @NEXT_GETOPT_H@ +NEXT_ICONV_H = @NEXT_ICONV_H@ +NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LIMITS_H = @NEXT_LIMITS_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_NETDB_H = @NEXT_NETDB_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_SCHED_H = @NEXT_SCHED_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_SPAWN_H = @NEXT_SPAWN_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRINGS_H = @NEXT_STRINGS_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_FILE_H = @NEXT_SYS_FILE_H@ +NEXT_SYS_IOCTL_H = @NEXT_SYS_IOCTL_H@ +NEXT_SYS_RANDOM_H = @NEXT_SYS_RANDOM_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_SYS_UIO_H = @NEXT_SYS_UIO_H@ +NEXT_SYS_WAIT_H = @NEXT_SYS_WAIT_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_UTIME_H = @NEXT_UTIME_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NEXT_WCTYPE_H = @NEXT_WCTYPE_H@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCRE2_CFLAGS = @PCRE2_CFLAGS@ +PCRE2_LIBS = @PCRE2_LIBS@ +PCRE_CFLAGS = @PCRE_CFLAGS@ +PCRE_LIBS = @PCRE_LIBS@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POD2MAN = @POD2MAN@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +REPLACE_ACCESS = @REPLACE_ACCESS@ +REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ +REPLACE_CREAT = @REPLACE_CREAT@ +REPLACE_CTIME = @REPLACE_CTIME@ +REPLACE_DIRFD = @REPLACE_DIRFD@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_EXECL = @REPLACE_EXECL@ +REPLACE_EXECLE = @REPLACE_EXECLE@ +REPLACE_EXECLP = @REPLACE_EXECLP@ +REPLACE_EXECV = @REPLACE_EXECV@ +REPLACE_EXECVE = @REPLACE_EXECVE@ +REPLACE_EXECVP = @REPLACE_EXECVP@ +REPLACE_EXECVPE = @REPLACE_EXECVPE@ +REPLACE_FACCESSAT = @REPLACE_FACCESSAT@ +REPLACE_FCHMODAT = @REPLACE_FCHMODAT@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FNMATCH = @REPLACE_FNMATCH@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREE = @REPLACE_FREE@ +REPLACE_FREELOCALE = @REPLACE_FREELOCALE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GAI_STRERROR = @REPLACE_GAI_STRERROR@ +REPLACE_GETADDRINFO = @REPLACE_GETADDRINFO@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETPASS = @REPLACE_GETPASS@ +REPLACE_GETRANDOM = @REPLACE_GETRANDOM@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_ICONV = @REPLACE_ICONV@ +REPLACE_ICONV_OPEN = @REPLACE_ICONV_OPEN@ +REPLACE_ICONV_UTF = @REPLACE_ICONV_UTF@ +REPLACE_INET_NTOP = @REPLACE_INET_NTOP@ +REPLACE_INET_PTON = @REPLACE_INET_PTON@ +REPLACE_INITSTATE = @REPLACE_INITSTATE@ +REPLACE_IOCTL = @REPLACE_IOCTL@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ISWBLANK = @REPLACE_ISWBLANK@ +REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@ +REPLACE_ISWDIGIT = @REPLACE_ISWDIGIT@ +REPLACE_ISWXDIGIT = @REPLACE_ISWXDIGIT@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NEWLOCALE = @REPLACE_NEWLOCALE@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_OPENDIR = @REPLACE_OPENDIR@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_POSIX_MEMALIGN = @REPLACE_POSIX_MEMALIGN@ +REPLACE_POSIX_SPAWN = @REPLACE_POSIX_SPAWN@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDFCHDIR = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDFCHDIR@ +REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM = @REPLACE_RANDOM@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SCHED_YIELD = @REPLACE_SCHED_YIELD@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SETSTATE = @REPLACE_SETSTATE@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERRORNAME_NP = @REPLACE_STRERRORNAME_NP@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRFTIME = @REPLACE_STRFTIME@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOLD = @REPLACE_STRTOLD@ +REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TOWLOWER = @REPLACE_TOWLOWER@ +REPLACE_TRUNCATE = @REPLACE_TRUNCATE@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_TZSET = @REPLACE_TZSET@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIME = @REPLACE_UTIME@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSFTIME = @REPLACE_WCSFTIME@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSTOK = @REPLACE_WCSTOK@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SED = @SED@ +SERVENT_LIB = @SERVENT_LIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDALIGN_H = @STDALIGN_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_IOCTL_H_HAVE_WINSOCK2_H = @SYS_IOCTL_H_HAVE_WINSOCK2_H@ +SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ +UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_TESTS = @VALGRIND_TESTS@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@ +WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@METALINK_IS_ENABLED_FALSE@METALINK_TESTS = +@METALINK_IS_ENABLED_TRUE@METALINK_TESTS = Test-metalink-http.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-quoted.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-baddigest.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-trust-name.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type-content.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-http-xml-type-trust-content.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-continue.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relpath.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-abspath.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homepath.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relpath-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-abspath-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homepath-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-prefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relprefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-absprefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homeprefix.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-prefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-relprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-absprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-homeprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-emptyprefix-trust.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-size.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-nohash.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-nourls.py \ +@METALINK_IS_ENABLED_TRUE@ Test-metalink-xml-urlbreak.py + +AUTOMAKE_OPTIONS = parallel-tests +AM_TESTS_ENVIRONMENT = export WGETRC=/dev/null; MAKE_CHECK=True; \ + export MAKE_CHECK; export PYTHONPATH=$$PYTHONPATH:$(srcdir); \ + export VALGRIND_TESTS="@VALGRIND_TESTS@"; $(am__append_1) +EXTRA_DIST = certs conf exc misc server test README $(TESTS) +TEST_EXTENSIONS = .py +PY_LOG_COMPILER = python3 +AM_PY_LOG_FLAGS = -O +all: all-am + +.SUFFIXES: +.SUFFIXES: .log .py .py$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testenv/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu testenv/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.py.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.py$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(PY_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_PY_LOG_DRIVER_FLAGS) $(PY_LOG_DRIVER_FLAGS) -- $(PY_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: all all-am check check-TESTS check-am clean clean-generic \ + cscopelist-am ctags-am distclean distclean-generic distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am recheck tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/testenv/README b/testenv/README new file mode 100644 index 0000000..d4fabdd --- /dev/null +++ b/testenv/README @@ -0,0 +1,306 @@ +This document describes the working of the GNU Wget Test Suite. + +Install Instructions: +================================================================================ + +This Test Suite exploits the Parallel Test Harness available in GNU Autotools. +Since it uses features from a relatively recent version of Autotools, the minimum +required version as been bumped up to 1.11. +Run the './configure' command to generate the Makefile and then run 'make check' +to execute the Test Suite. Use the '-j n' option with 'make check' to execute +n tests simultaneously. + +Structure: +================================================================================ + + * server: This package contains custom programmatically configurable servers + (both HTTP and FTP) for testing Wget. The HTTP server runs an instance of + Python's http.server module. The FTP server is to be implemented. + + * test: This package contains the test case classes for HTTP and FTP. The + test case classes includes methods for initializing and cleaning up of the + test environment. + + * Test-Proto.py: This is a prototype Test Case file. The file defines all + the acceptable elements and their uses. Typically, one must copy this file + and edit it for writing Test Cases. + + * exc: This package contains custom exception classes used in this test + suite. + + * conf: This package contains the configuration classes for servers to be + configured with. + + * misc: This package contains several helper modules used in this test + suite. + - colour_terminal.py: A custom module for printing coloured output to + the terminal. Currently it only supports 4 colours in a *nix + environment. + - wget_file.py: Module which contains WgetFile, which is a file data + container object. + +Working: +================================================================================ + +The Test Files are valid Python scripts and the default mask for them is 755. +A singular Test must be invoked in the following manner, with the current +directory being the testenv directory: +$ ./python3 <Name of Test File> OR +$ ./<Name of Test File> +The script will then initialize the various elements and pass them to an object +of the respective Test Class. A directory with the name <Test name>-test will be +created and the PWD will be changed to this directory. The server is then +spawned with the required configuration elements. A blocking call to Wget is +made with the command line arguments specified in the Test Case along with the +list of URLs that it must download. The server is killed once Wget returns and +the following checks are used to determine the pass/fail status of the test: + * Return Code: The Exit code of Wget is matched against the expected Exit + Code as mentioned in the Test Case File. + * Downloaded Files: Check whether the expected downloaded files exist on + disk. + * File Content: Test whether the file contents were correctly downloaded by + Wget and not corrupted mid-way. + * Excess Files: Check to see whether any unexpected files were downloaded + by Wget. + +Exit Codes: +=============================================================================== + +Following is a list of Exit Status Codes for the tests: +* 0 Test Successful +* 66 Errors/Warnings Reported by Thread Sanitizer (If built with -fsanitize) +* 77 Test Skipped +* 99 Hard Error +* 100 Test Failed + +Tests are skipped when they are either not supported by the platform, or Wget +is not compiled with support for that feature. This feature has not yet been +implemented. + +Hard Errors occur when there are problems with the Environment code. Hard +Error reporting is currently not enabled and all errors are reported as +failures. + +All exceptions should ideally be handled gracefully. If you see any unhandled +exceptions, please file a bug report at <bug-wget@gnu.org> + +Environment Variables: +================================================================================ + +* SERVER_WAIT: Set this environment variable with a value for the number of + seconds the test should sleep between invoking the server and calling the Wget + executable. This is used when one would like to test a different version of + the executable or for running the test through external utilities like gdb and + valgrind. +* NO_CLEANUP: Do not remove the temporary files created by the test. + This will prevent the ${testname}-test directory from being deleted +* VALGRIND_TESTS: If this variable is set and contains the valgrind command line, + the test suite will execute all the tests via this command. + If it is set to "1", valgrind memcheck is enabled with hard coded options. + This variable is set by ./configure --enable-valgrind-tests. +* SSL_TESTS: This must be set to run any https tests. +* WGET_PATH: Set this environment variable to a path to wget binary on which you + want to run tests. This is useful for OS distributions, which want to reuse + upstream tests for testing wget build that they distribute. If the variable is + not set, the "../src/wget" binary is used by tests. + + +File Structure: +================================================================================ + +The test case files are Python scripts. It is believed that Python is a simple +yet elegant language and should be easy for everyone to comprehend. This test +suite is written with the objective of making it easy to write new tests. The +structure has been kept as intuitive as possible and should not require much +effort to get accustomed to. + +All Test Files MUST begin with the following Three Lines: +#!/usr/bin/python3 +from sys import exit +from WgetTest import {HTTPTest|FTPTest} +from misc.wget_file import WgetFile + +It is recommended that a small description of the Test Case is provided next. +This would be very helpful to future contributors. + +Each File in the Test must be represented as a WgetFile object. The WgetFile +Class has the following prototype: +WgetFile (str name, str contents, str timestamp, dict rules) +None except name is a mandatory parameter, one may pass only those parameters +that are required by the File object. + +The timestamp string should be in a format: "YYYY-MM-DD HH:MM:SS" in UTC zone. +The rules object is a dictionary element, with the key as the Rule Name and +value as the Rule Data. In most cases, the Rule Data is another dictionary. + +Various variables used consistently across all tests are: + * WGET_OPTIONS: The command line string passed to Wget upon invocation. This + string may contain URLs, like in the case where in-URL authentication is + used. Variable names passed like {{var_name}} will be replaced by the + contents of the variable self.var_name before being passed to Wget + * WGET_URLS: This is a list of filenames which will be appended as the URLs + to Wget during invocation. This is a list of lists, where WGET_URLS[0] + represents the list of Filenames called from Server[0], WGET_URLS[1] is a + list of files downloaded from Server[2], etc. They must be relative URLs, + i.e., not start with "/". + * Files: This variable defines the files that exist in the Server's + filesystem. The Files variable is a list of lists of WgetFile objects. + This means that File[0] is a list of WgetFile objects that lie on Server[0], + File[1] a list of files on Server[1] and so on. + * Existing_Files: This is a list of files that already exist in the + directory from which Wget is invoked. + * ExpectedReturnCode: The Exit Code expected to be returned by Wget after + the test. + * ExpectedDownloadedFiles: A list of files that are expected in the local + directory after Wget has finished executing. This does not include the files + already existing before Wget was launched and must be mentioned again. + * Request_List: An unordered list of Requests that each server must receive. + This too is a list of lists and follows the same convention as others above. + +Both, the HTTPTest and FTPTest modules have the same prototype: +{ + pre_hook, + test_options, + post_hook, + protocols +} +the three hooks should be Python dict objects and protocols should be a list of +protocols, like [HTTP, HTTPS]. + +Valid File Rules: +================================================================================ + +This section lists the currently supported File Rules and their structure. + + * Authentication: Used when a File must require Authorization for access. + The value for this key is the following dictionary: + |-->Type : Basic|Digest|Both|Both_inline + |-->User : <Username> + --->Pass : <Password> + + * ExpectHeader : The following Headers MUST exist in every Request for the + File. The value for this key is a dictionary object where each header is + represented as: + |-->Header Name : <Header Data> + + * RejectHeader : This list of Headers must NEVER occur in a request. It + uses the same value format as ExpectHeader. + + * SendHeader : This list of Headers will be sent in EVERY response to a + request for the respective file. It follows the same value format as + ExpectHeader. Additionally you can specify a list of strings as <Header Data> + if you want the header repeated with multiple values. + + * Response : The HTTP Response Code to send to a request for this File. + The value is an Integer that represents a valid HTTP Response Code. + +Pre Test Hooks: +================================================================================ + +The Pre-Test Hooks are executed just after starting the server and just before +spawning an instance of the server. These are usually used for setting up the +Test Environment and Server Rules. The currently supported Pre-Test Hooks are: + + * ServerFiles : A list of WgetFile objects that must exist on the Server + * LocalFiles : A list of WgetFile objects that exist locally on disk + before Wget is executed. + +Since pre_test is a dictionary, one may not assume that the hooks will be +executed in the same order as they are defined. + +Test Options: +================================================================================ + +The test_options dictionary defines the commands to be used when the Test is +executed. The currently supported options are: + + * Urls : A list of the filenames that Wget must attempt to + download. The complete URL will be created and passed to Wget + automatically. (alias URLs) + * WgetCommands : A string consisting of the various commandline switches + sent to Wget upon invocation. Any data placed between {{ }} in this string + will be replaced with the contents of self.<data> before being passed to + Wget. This is particularly useful for getting the hostname and port for a + file. While all Download URL's are passed to Urls, a notable exception is + when in-url authentication is used. In such a case, the URL is specified in + the WgetCommands string. + * EnvironmentVariables: A dictionary with key-value items, which will be + defined as environment variables during the execution of wget command in + test. + +Post-Test Hooks: +================================================================================ + +These hooks are executed as soon as the call to Wget returns. The post-test +hooks are usually used to run checks on the data, files downloaded, return code, +etc. The following hooks are currently supported: + + * ExpectedRetcode : This is an integer value of the ReturnCode with which + Wget is expected to exit. (alias ExpectedRetCode) + * ExpectedFiles : This is a list of WgetFile objects of the files that + must exist locally on disk in the Test directory. + * FilesCrawled : This requires a list of the Requests that the server is + expected to receive. The order is un-important since it will vary on the + parallel-wget branch. This hook is used in tests for Recursive mode to + ensure that the website is traversed correctly. + +Writing New Tests: +================================================================================ + +See Test-Proto.py for an example of how to write Test Case files. The +recommended method for writing new Test Case files is to copy Test-Proto.py and +modify it to ones needs. + +In case you require any functionality that is not currently defined in List of +Rules defined above, you should implement a new class in the conf package. The +file name doesn't matter (though it's better to give it an appropriate name). +The new rule or hook class should be like this: +============================================ +from conf import rule + + +@rule() +class MyNewRule: + def __init__(self, rule_arg): + self.rule_arg = rule_arg + # your rule initialization code goes here +============================================ +from conf import hook + + +@hook() +class MyNewHook: + def __init__(self, hook_arg): + self.hook_arg = hook_arg + # your hook initialization code goes here + + def __call__(self, test_obj): + # your hook code goes here +============================================ + +Once a new Test File is created, it must be added to the TESTS variable in +Makefile.am. This way the Test will be executed on running a 'make check'. +If a Test is expected to fail on the current master branch, then the Test should +also be added to the XFAIL_TESTS variable. This will allow expected failures to +pass through. If a test mentioned in the XFAIL_TESTS variable passes, it gets +red-flagged as a XPASS. Currently, tests expected to fail under valgrind are not +explicitly marked as XFAIL. Tests failing under valgrind must always be +considered a blocking error. + +Work Remaining: +================================================================================ + +Some amount of work still remains to be done. + * Errors in server-side checks need to be handled more explicitly + * Support parallel-wget branch + * Support to spawn multiple servers is already in place. Need to handle + multiple requests to a server simultaneously. Use THreading MixIn. + * SSL Tests. Use xyne's HTTPS server implementation + * Complete support for FTP Tests + * IRI Support. This shouldn't require much effort + +Requirements: +================================================================================ + +1. Python >= 3.0 +2. Automake >= 1.11 diff --git a/testenv/Test--convert-links--content-on-error.py b/testenv/Test--convert-links--content-on-error.py new file mode 100755 index 0000000..37fcc47 --- /dev/null +++ b/testenv/Test--convert-links--content-on-error.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget link conversion works also on HTTP error pages. +""" +############# File Definitions ############################################### +a_x_FileContent = """ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title></title> +</head> +<body> + <a href="/b/y.html"></a> +</body> +</html> +""" +a_x_LocalFileContent = """ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title></title> +</head> +<body> + <a href="../b/y.html"></a> +</body> +</html> +""" + +error_FileContent = '404 page content' +error_FileRules = { + 'Response': 404 , + 'SendHeader': { + 'Content-Length': len(error_FileContent), + 'Content-Type': 'text/plain', + } +} + +a_x_File = WgetFile ("a/x.html", a_x_FileContent) +robots_File = WgetFile ("robots.txt", '') +error_File = WgetFile ("b/y.html", error_FileContent, rules=error_FileRules) + +B_File = WgetFile ("a/x.html", a_x_LocalFileContent) + +WGET_OPTIONS = "--no-host-directories -r -l2 --convert-links --content-on-error" +WGET_URLS = [["a/x.html"]] + +Files = [[a_x_File, robots_File, error_File]] + +ExpectedReturnCode = 8 +ExpectedDownloadedFiles = [B_File, robots_File, error_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test--https-crl.py b/testenv/Test--https-crl.py new file mode 100755 index 0000000..6c7002e --- /dev/null +++ b/testenv/Test--https-crl.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +CRLFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'server-crl.pem')) +WGET_OPTIONS = "--crl-file " + CRLFILE + " --ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +Servers = [HTTPS] + +ExpectedReturnCode = 5 + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test--https.py b/testenv/Test--https.py new file mode 100755 index 0000000..d9431a3 --- /dev/null +++ b/testenv/Test--https.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) +C_File = WgetFile ("File3", File3) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +WGET_OPTIONS = "--ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +Servers = [HTTPS] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test--rejected-log.py b/testenv/Test--rejected-log.py new file mode 100755 index 0000000..fb4f9f4 --- /dev/null +++ b/testenv/Test--rejected-log.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test executed Wget in recursive mode with a rejected log outputted. +""" +############# File Definitions ############################################### +mainpage = """ +<html> +<head> + <title>Main Page</title> +</head> +<body> + <p> + Recurse to a <a href="http://localhost:{{port}}/secondpage.html">second page</a>. + </p> +</body> +</html> +""" + +secondpage = """ +<html> +<head> + <title>Second Page</title> +</head> +<body> + <p> + Recurse to a <a href="http://localhost:{{port}}/thirdpage.html">third page</a>. + Try the blacklisted <a href="http://localhost:{{port}}/index.html">main page</a>. + </p> +</body> +</html> +""" + +thirdpage = """ +<html> +<head> + <title>Third Page</title> +</head> +<body> + <p> + Try a hidden <a href="http://localhost:{{port}}/dummy.txt">dummy file</a>. + Try to leave to <a href="http://no.such.domain/">another domain</a>. + </p> +</body> +</html> +""" + +robots = """ +User-agent: * +Disallow: /dummy.txt +""" + +log = """\ +REASON\tU_URL\tU_SCHEME\tU_HOST\tU_PORT\tU_PATH\tU_PARAMS\tU_QUERY\tU_FRAGMENT\tP_URL\tP_SCHEME\tP_HOST\tP_PORT\tP_PATH\tP_PARAMS\tP_QUERY\tP_FRAGMENT +BLACKLIST\thttp%3A//localhost%3A{{port}}/index.html\tSCHEME_HTTP\tlocalhost\t{{port}}\tindex.html\t\t\t\thttp%3A//localhost%3A{{port}}/secondpage.html\tSCHEME_HTTP\tlocalhost\t{{port}}\tsecondpage.html\t\t\t +ROBOTS\thttp%3A//localhost%3A{{port}}/dummy.txt\tSCHEME_HTTP\tlocalhost\t{{port}}\tdummy.txt\t\t\t\thttp%3A//localhost%3A{{port}}/thirdpage.html\tSCHEME_HTTP\tlocalhost\t{{port}}\tthirdpage.html\t\t\t +SPANNEDHOST\thttp%3A//no.such.domain/\tSCHEME_HTTP\tno.such.domain\t80\t\t\t\t\thttp%3A//localhost%3A{{port}}/thirdpage.html\tSCHEME_HTTP\tlocalhost\t{{port}}\tthirdpage.html\t\t\t +""" + +dummyfile = "Don't care." + + +index_html = WgetFile ("index.html", mainpage) +secondpage_html = WgetFile ("secondpage.html", secondpage) +thirdpage_html = WgetFile ("thirdpage.html", thirdpage) +robots_txt = WgetFile ("robots.txt", robots) +dummy_txt = WgetFile ("dummy.txt", dummyfile) +log_csv = WgetFile ("log.csv", log) + +WGET_OPTIONS = "-nd -r --rejected-log log.csv" +WGET_URLS = [["index.html"]] + +Files = [[index_html, secondpage_html, thirdpage_html, robots_txt, dummy_txt]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [index_html, secondpage_html, thirdpage_html, robots_txt, log_csv] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test--spider-r.py b/testenv/Test--spider-r.py new file mode 100755 index 0000000..8d8c6f7 --- /dev/null +++ b/testenv/Test--spider-r.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test executed Wget in Spider mode with recursive retrieval. +""" +############# File Definitions ############################################### +mainpage = """ +<html> +<head> + <title>Main Page</title> +</head> +<body> + <p> + Some text and a link to a <a href="http://localhost:{{port}}/secondpage.html">second page</a>. + Also, a <a href="http://localhost:{{port}}/nonexistent">broken link</a>. + </p> +</body> +</html> +""" + + +secondpage = """ +<html> +<head> + <title>Second Page</title> +</head> +<body> + <p> + Some text and a link to a <a href="http://localhost:{{port}}/thirdpage.html">third page</a>. + Also, a <a href="http://localhost:{{port}}/nonexistent">broken link</a>. + </p> +</body> +</html> +""" + +thirdpage = """ +<html> +<head> + <title>Third Page</title> +</head> +<body> + <p> + Some text and a link to a <a href="http://localhost:{{port}}/dummy.txt">text file</a>. + Also, another <a href="http://localhost:{{port}}/againnonexistent">broken link</a>. + </p> +</body> +</html> +""" + +dummyfile = "Don't care." + + +index_html = WgetFile ("index.html", mainpage) +secondpage_html = WgetFile ("secondpage.html", secondpage) +thirdpage_html = WgetFile ("thirdpage.html", thirdpage) +dummy_txt = WgetFile ("dummy.txt", dummyfile) + +Request_List = [ + [ + "HEAD /", + "GET /", + "GET /robots.txt", + "HEAD /secondpage.html", + "GET /secondpage.html", + "HEAD /nonexistent", + "HEAD /thirdpage.html", + "GET /thirdpage.html", + "HEAD /dummy.txt", + "HEAD /againnonexistent" + ] +] + +WGET_OPTIONS = "--spider -r" +WGET_URLS = [[""]] + +Files = [[index_html, secondpage_html, thirdpage_html, dummy_txt]] + +ExpectedReturnCode = 8 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : Request_List +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-416.py b/testenv/Test-416.py new file mode 100755 index 0000000..76b9421 --- /dev/null +++ b/testenv/Test-416.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + Ensure that Wget behaves well when the server responds with a HTTP 416 + status code. This test checks both cases: + 1. Server sends no body + 2. Server sends a body +""" +############# File Definitions ############################################### +File1 = "abababababababababababababababababababababababababababababababababab" +File2 = "ababababababababababababababababababab" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File1", File1) + +C_File = WgetFile ("File2", File2) +D_File = WgetFile ("File2", File1) + +E_File = WgetFile ("File3", File1) + +WGET_OPTIONS = "-c" +WGET_URLS = [["File1", "File2", "File3"]] + +Files = [[A_File, C_File, E_File]] +Existing_Files = [B_File, D_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [B_File, D_File, E_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-504.py b/testenv/Test-504.py new file mode 100755 index 0000000..036f85d --- /dev/null +++ b/testenv/Test-504.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget handles a 504 Gateway Timeout response + correctly. + Since, we do not have a direct mechanism for conditionally sending responses + via the HTTP Server, I've used a workaround. + The server will always respond to a request for File1 with a 504 Gateway + Timeout. Using the --tries=2 option, we ensure that Wget attempts the file + only twice and then move on to the next file. Finally, check the exact + requests that the Server received and compare them, in order, to the + expected sequence of requests. + + In this case, we expect Wget to attempt File1 twice and File2 once. If Wget + considered 504 as a general Server Error, it would be a fatal failure and + Wget would request File1 only once. +""" +############# File Definitions ############################################### +File1 = """All happy families are alike; +Each unhappy family is unhappy in its own way""" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "Response" : 504 +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2) + +Request_List = [ + [ + "GET /File1", + "GET /File1", + "GET /File2", + ] +] + + +WGET_OPTIONS = "--tries=2" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 4 +ExpectedDownloadedFiles = [B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : Request_List +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Content-disposition-2.py b/testenv/Test-Content-disposition-2.py new file mode 100755 index 0000000..debd833 --- /dev/null +++ b/testenv/Test-Content-disposition-2.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget parses the Content-Disposition header + correctly and creates the appropriate file when the said filename exists. +""" +############# File Definitions ############################################### +File1 = "Teapot" +File2 = "The Teapot Protocol" + +# use upper case 'I' to provoke Wget failure with turkish locale +File2_rules = { + "SendHeader" : { + "Content-DIsposition" : "Attachment; FILENAME=HTTP.Teapot" + } +} +A_File = WgetFile ("HTTP.Teapot", File1) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "--content-disposition" +WGET_URLS = [["File2"]] + +Files = [[B_File]] +Existing_Files = [A_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("HTTP.Teapot.1", File2), A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Content-disposition.py b/testenv/Test-Content-disposition.py new file mode 100755 index 0000000..3ee7be8 --- /dev/null +++ b/testenv/Test-Content-disposition.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget parses the Content-Disposition header + correctly and creates a local file accordingly. +""" +############# File Definitions ############################################### +File1 = """All that is gold does not glitter, + Not all those who wander are lost; + The old that is strong does not wither, + Deep roots are not reached by the frost. + From the ashes a fire shall be woken, + A light from the shadows shall spring; + Renewed shall be blade that was broken, + The crownless again shall be king.""" + +File1_rules = { + "SendHeader" : { + "Content-Disposition" : "Attachment; filename=JRR.Tolkien" + } +} +A_File = WgetFile ("LOTR", File1, rules=File1_rules) + +WGET_OPTIONS = "--content-disposition" +WGET_URLS = [["LOTR"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("JRR.Tolkien", File1)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Head.py b/testenv/Test-Head.py new file mode 100755 index 0000000..b653b2d --- /dev/null +++ b/testenv/Test-Head.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget correctly handles responses to HEAD requests + and does not actually download any data +""" +############# File Definitions ############################################### +File1 = "You shall not pass!" + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "--method=HEAD" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-O.py b/testenv/Test-O.py new file mode 100755 index 0000000..f93e118 --- /dev/null +++ b/testenv/Test-O.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget correctly handles the -O command for output + filenames. +""" +############# File Definitions ############################################### +File1 = "Test Contents." + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "-O NewFile.txt" +WGET_URLS = [["File1"]] + +Files = [[A_File]] +ExistingFiles = [A_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("NewFile.txt", File1)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-Post.py b/testenv/Test-Post.py new file mode 100755 index 0000000..b2fa7d7 --- /dev/null +++ b/testenv/Test-Post.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + Simple test for HTTP POST Requests usiong the --method command +""" +############# File Definitions ############################################### +File1 = """A reader lives a thousand lives before he dies, said Jojen. +The man who never reads lives only one""" + +File1_response = """A reader lives a thousand lives before he dies, said Jojen. +The man who never reads lives only one +TestMessage""" + +A_File = WgetFile ("File1", File1) + +WGET_OPTIONS = "--method=post --body-data=TestMessage" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("File1", File1_response)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic-fail.py b/testenv/Test-auth-basic-fail.py new file mode 100755 index 0000000..7b4a223 --- /dev/null +++ b/testenv/Test-auth-basic-fail.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget returns the correct exit code when Basic + authentication fails due to a username/password error. +""" +############# File Definitions ############################################### +File1 = "I am an invisible man." + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Sauron", + "Pass" : "TheEye" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--user=Sauron --password=Eye" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 6 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic-netrc-pass-given.py b/testenv/Test-auth-basic-netrc-pass-given.py new file mode 100755 index 0000000..b8bff59 --- /dev/null +++ b/testenv/Test-auth-basic-netrc-pass-given.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget uses credentials from .netrc for Basic Authorization Negotiation. + In this case we test that .netrc credentials are used in case only + password is given on the command line. + Also, we ensure that Wget saves the host after a successful auth and + doesn't wait for a challenge the second time. +""" +############# File Definitions ############################################### +File1 = "I am an invisible man." +File2 = "I too am an invisible man." + +User = "Sauron" +Password = "TheEye" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : User, + "Pass" : Password + } +} +File2_rules = { + "ExpectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} + +Netrc = "machine localhost\n\tlogin {0}".format(User) + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +Netrc_File = WgetFile (".netrc", Netrc) + +WGET_OPTIONS = "--password={0}".format(Password) +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +LocalFiles = [Netrc_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, Netrc_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : LocalFiles +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic-netrc-user-given.py b/testenv/Test-auth-basic-netrc-user-given.py new file mode 100755 index 0000000..e5d1449 --- /dev/null +++ b/testenv/Test-auth-basic-netrc-user-given.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget uses credentials from .netrc for Basic Authorization Negotiation. + In this case we test that .netrc credentials are used in case only + user login is given on the command line. + Also, we ensure that Wget saves the host after a successful auth and + doesn't wait for a challenge the second time. +""" +############# File Definitions ############################################### +File1 = "I am an invisible man." +File2 = "I too am an invisible man." + +User = "Sauron" +Password = "TheEye" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : User, + "Pass" : Password + } +} +File2_rules = { + "ExpectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} + +Netrc = "machine localhost\n\tlogin {0}\n\tpassword {1}".format(User, Password) + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +Netrc_File = WgetFile (".netrc", Netrc) + +WGET_OPTIONS = "--user={0}".format(User) +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +LocalFiles = [Netrc_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, Netrc_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : LocalFiles +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic-netrc.py b/testenv/Test-auth-basic-netrc.py new file mode 100755 index 0000000..f670603 --- /dev/null +++ b/testenv/Test-auth-basic-netrc.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget uses credentials from .netrc for Basic Authorization Negotiation. + In this case we test that .netrc credentials are used in case no user + login and no password is given on the command line. + Also, we ensure that Wget saves the host after a successful auth and + doesn't wait for a challenge the second time. +""" +############# File Definitions ############################################### +File1 = "I am an invisible man." +File2 = "I too am an invisible man." + +User = "Sauron" +Password = "TheEye" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : User, + "Pass" : Password + } +} +File2_rules = { + "ExpectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} + +Netrc = "machine localhost\n\tlogin {0}\n\tpassword {1}".format(User, Password) + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +Netrc_File = WgetFile (".netrc", Netrc) + +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +LocalFiles = [Netrc_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, Netrc_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : LocalFiles +} +test_options = { + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic-no-netrc-fail.py b/testenv/Test-auth-basic-no-netrc-fail.py new file mode 100755 index 0000000..1c3a405 --- /dev/null +++ b/testenv/Test-auth-basic-no-netrc-fail.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget will not use credentials from .netrc + when --no-netrc option is specified and Basic authentication is required + and fails. +""" +############# File Definitions ############################################### +File1 = "I am an invisible man." + +User = "Sauron" +Password = "TheEye" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : User, + "Pass" : Password + } +} + +Netrc = "machine 127.0.0.1\n\tlogin {0}\n\tpassword {1}".format(User, Password) + +A_File = WgetFile ("File1", File1, rules=File1_rules) +Netrc_File = WgetFile (".netrc", Netrc) + +WGET_OPTIONS = "--no-netrc" +WGET_URLS = [["File1"]] + +Files = [[A_File]] +LocalFiles = [Netrc_File] + +ExpectedReturnCode = 6 +ExpectedDownloadedFiles = [Netrc_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : LocalFiles +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-basic.py b/testenv/Test-auth-basic.py new file mode 100755 index 0000000..4f60c30 --- /dev/null +++ b/testenv/Test-auth-basic.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation. + Also, we ensure that Wget saves the host after a successful auth and + doesn't wait for a challenge the second time. +""" +############# File Definitions ############################################### +File1 = "I am an invisible man." +File2 = "I too am an invisible man." + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Sauron", + "Pass" : "TheEye" + } +} +File2_rules = { + "ExpectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "--user=Sauron --password=TheEye" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-both.py b/testenv/Test-auth-both.py new file mode 100755 index 0000000..6e5d712 --- /dev/null +++ b/testenv/Test-auth-both.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation. + Also, we ensure that Wget saves the host after a successful auth and + doesn't wait for a challenge the second time. +""" +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +File1_rules = { + "Authentication" : { + "Type" : "Both", + "User" : "Sauron", + "Pass" : "TheEye", + "Parm" : { + "qop" : "auth" + } + }, + "RejectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} +File2_rules = { + "Authentication" : { + "Type" : "Both_inline", + "User" : "Sauron", + "Pass" : "TheEye", + "Parm" : { + "qop" : "auth" + } + }, + "RejectHeader" : { + "Authorization" : "Basic U2F1cm9uOlRoZUV5ZQ==" + } +} +File3_rules = { + "Authentication" : { + "Type" : "Digest", + "User" : "Sauron", + "Pass" : "TheEye", + "Parm" : { + "qop" : "auth" + } + + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +C_File = WgetFile ("File3", File3, rules=File3_rules) + +WGET_OPTIONS = "--user=Sauron --password=TheEye" +WGET_URLS = [["File1", "File2", "File3"]] + +Files = [[A_File, B_File, C_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-digest.py b/testenv/Test-auth-digest.py new file mode 100755 index 0000000..a5e624f --- /dev/null +++ b/testenv/Test-auth-digest.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Digest Authorization Negotiation. +""" +############# File Definitions ############################################### +File1 = "Need a cookie?" +File2 = "Want cookies with milk!" + +File1_rules = { + "Authentication" : { + "Type" : "Digest", + "User" : "Pacman", + "Pass" : "Omnomnom", + "Parm" : { + "qop" : "auth" + } + } +} + +File2_rules = { + "Authentication" : { + "Type" : "Digest", + "User" : "Pacman", + "Pass" : "Omnomnom", + "Parm" : { + "qop" : None + } + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "--user=Pacman --password=Omnomnom" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-no-challenge-url.py b/testenv/Test-auth-no-challenge-url.py new file mode 100755 index 0000000..6025232 --- /dev/null +++ b/testenv/Test-auth-no-challenge-url.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation, when credentials + are provided in-URL +""" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Pacman", + "Pass" : "Omnomnom" + }, + "ExpectHeader" : { + "Authorization" : "Basic UGFjbWFuOk9tbm9tbm9t" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--auth-no-challenge http://Pacman:Omnomnom@localhost:{{port}}/File1" +WGET_URLS = [[]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-no-challenge.py b/testenv/Test-auth-no-challenge.py new file mode 100755 index 0000000..2022ac8 --- /dev/null +++ b/testenv/Test-auth-no-challenge.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures Wget's Basic Authorization Negotiation, when the + --auth-no-challenge command is used. +""" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Pacman", + "Pass" : "Omnomnom" + }, + "ExpectHeader" : { + "Authorization" : "Basic UGFjbWFuOk9tbm9tbm9t" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--auth-no-challenge --user=Pacman --password=Omnomnom" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-retcode.py b/testenv/Test-auth-retcode.py new file mode 100755 index 0000000..6414b5b --- /dev/null +++ b/testenv/Test-auth-retcode.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget returns the correct return code when sent + a 403 Forbidden by the Server. +""" + + +############# File Definitions ############################################### +File1 = "Apples and Oranges? Really?" + +File1_rules = { + "Response" : 403 +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 8 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-auth-with-content-disposition.py b/testenv/Test-auth-with-content-disposition.py new file mode 100755 index 0000000..074b093 --- /dev/null +++ b/testenv/Test-auth-with-content-disposition.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget handles Content-Disposition correctly when + coupled with Authentication +""" +############# File Definitions ############################################### +File1 = "Need a cookie?" + +File1_rules = { + "Authentication" : { + "Type" : "Basic", + "User" : "Pacman", + "Pass" : "Omnomnom" + }, + "SendHeader" : { + "Content-Disposition" : "Attachment; filename=Arch" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) + +WGET_OPTIONS = "--user=Pacman --password=Omnomnom --content-disposition" +WGET_URLS = [["File1"]] + +Files = [[A_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [WgetFile ("Arch", File1)] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-c-full.py b/testenv/Test-c-full.py new file mode 100755 index 0000000..ada3c04 --- /dev/null +++ b/testenv/Test-c-full.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + Test Wget's response when the file requested already exists on disk with + a filesize greater than or equal to the requested file. +""" +############# File Definitions ############################################### +File1 = "abababababababababababababababababababababababababababababababababab" +File2 = "ababababababababababababababababababab" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File1", File1) + +C_File = WgetFile ("File2", File1) +D_File = WgetFile ("File2", File2) + +E_File = WgetFile ("File3", File1) + +WGET_OPTIONS = "-c" +WGET_URLS = [["File1", "File2", "File3"]] + +Files = [[A_File, C_File, E_File]] +Existing_Files = [B_File, D_File] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, C_File, E_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-condget.py b/testenv/Test-condget.py new file mode 100755 index 0000000..a192f92 --- /dev/null +++ b/testenv/Test-condget.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + Simple test for HTTP Conditional-GET Requests using the -N command +""" +############# File Definitions ############################################### +# Keep same length ! +Cont1 = """THIS IS 1 FILE""" +Cont2 = """THIS IS 2 FILE""" +Cont3 = """THIS IS 3 FILE""" +Cont4 = """THIS IS 4 FILE""" + +# Local Wget files + +# These have same timestamp as remote files +UpToDate_Local_File1 = WgetFile ("UpToDateFile1", Cont1, timestamp="1995-01-01 00:00:00") +UpToDate_Local_File2 = WgetFile ("UpToDateFile2", Cont1, timestamp="1995-01-01 00:00:00") +UpToDate_Local_File3 = WgetFile ("UpToDateFile3", Cont1, timestamp="1995-01-01 00:00:00") + +# This is newer than remote (expected same behaviour as for above files) +Newer_Local_File = WgetFile ("NewerFile", Cont1, timestamp="1995-02-02 02:02:02") + +# This is older than remote - should be clobbered +Outdated_Local_File = WgetFile ("UpdatedFile", Cont2, timestamp="1990-01-01 00:00:00") + +UpToDate_Rules1 = { + "SendHeader" : { + # RFC1123 format + "Last-Modified" : "Sun, 01 Jan 1995 00:00:00 GMT", + }, + "Response": 304, + "ExpectHeader" : { + "If-Modified-Since" : "Sun, 01 Jan 1995 00:00:00 GMT" + }, +} + +UpToDate_Rules2 = { + "SendHeader" : { + # RFC850 format + "Last-Modified" : "Sunday, 01-Jan-95 00:00:00 GMT", + }, + "Response": 304, + "ExpectHeader" : { + "If-Modified-Since" : "Sun, 01 Jan 1995 00:00:00 GMT" + }, +} + +UpToDate_Rules3 = { + "SendHeader" : { + # Asctime format + "Last-Modified" : "Sun Jan 01 00:00:00 1995", + }, + "Response": 304, + "ExpectHeader" : { + "If-Modified-Since" : "Sun, 01 Jan 1995 00:00:00 GMT" + }, +} + +Newer_Rules = { + "SendHeader" : { + # Asctime format + "Last-Modified" : "Sun Jan 01 00:00:00 1995", + }, + "Response": 304, + "ExpectHeader" : { + "If-Modified-Since" : "Thu, 02 Feb 1995 02:02:02 GMT" + }, +} + +Outdated_Rules = { + "SendHeader" : { + # RFC850 format + "Last-Modified" : "Thursday, 01-Jan-15 00:00:00 GMT", + }, + "ExpectHeader" : { + "If-Modified-Since" : "Mon, 01 Jan 1990 00:00:00 GMT", + }, +} + +UpToDate_Server_File1 = WgetFile ("UpToDateFile1", Cont3, rules=UpToDate_Rules1) +UpToDate_Server_File2 = WgetFile ("UpToDateFile2", Cont3, rules=UpToDate_Rules2) +UpToDate_Server_File3 = WgetFile ("UpToDateFile3", Cont3, rules=UpToDate_Rules3) +Newer_Server_File = WgetFile ("NewerFile", Cont3, rules=Newer_Rules) +Updated_Server_File = WgetFile ("UpdatedFile", Cont4, rules=Outdated_Rules) + +WGET_OPTIONS = "-N" +WGET_URLS = [["UpToDateFile1", "UpToDateFile2", "UpToDateFile3", "NewerFile", + "UpdatedFile", ]] + +Files = [[UpToDate_Server_File1, UpToDate_Server_File2, UpToDate_Server_File3, + Newer_Server_File, Updated_Server_File, ]] + +Existing_Files = [UpToDate_Local_File1, UpToDate_Local_File2, + UpToDate_Local_File3, Newer_Local_File, Outdated_Local_File] + +ExpectedReturnCode = 0 + +# The up-to-date file should not be downloaded +ExpectedDownloadedFiles = [UpToDate_Local_File1, UpToDate_Local_File2, + UpToDate_Local_File3, Newer_Local_File, + Updated_Server_File] + +# Kind of hack to ensure proper request types +Request_List = [ + [ + "GET /UpToDateFile1", + "GET /UpToDateFile2", + "GET /UpToDateFile3", + "GET /NewerFile", + "GET /UpdatedFile", + ] +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : Request_List, +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie-401.py b/testenv/Test-cookie-401.py new file mode 100755 index 0000000..b6ad5b8 --- /dev/null +++ b/testenv/Test-cookie-401.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget stores the cookie even in the event of a + 401 Unauthorized Response +""" +############# File Definitions ############################################### +File1 = """All happy families are alike; +Each unhappy family is unhappy in its own way""" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "SendHeader" : { + "Set-Cookie" : "sess-id=0213; path=/" + }, + "Response" : 401 +} +File2_rules = { + "ExpectHeader" : { + "Cookie" : "sess-id=0213" + }, +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 6 +ExpectedDownloadedFiles = [B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie-domain-mismatch.py b/testenv/Test-cookie-domain-mismatch.py new file mode 100755 index 0000000..06a9b69 --- /dev/null +++ b/testenv/Test-cookie-domain-mismatch.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget identifies bad servers trying to set cookies + for a different domain and rejects them. +""" +############# File Definitions ############################################### +File1 = "Would you care for a cup of coffee?" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "SendHeader" : { + # use upper case 'I' to provoke Wget failure with turkish locale + "Set-Cookie" : "sess-id=0213; path=/; DoMAIn=.example.com" + } +} +File2_rules = { + "RejectHeader" : { + "Cookie" : "sess-id=0213" + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie-expires.py b/testenv/Test-cookie-expires.py new file mode 100755 index 0000000..16fb980 --- /dev/null +++ b/testenv/Test-cookie-expires.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget handles Cookie expiry dates correctly. + Simultaneuously, we also check if multiple cookies to the same domain + are handled correctly +""" +############# File Definitions ############################################### +File1 = "Hello World!" +File2 = "'Ello! This is Amazing!" +File3 = "So what are we looking at?" +File4 = "This was downloaded" + +File1_rules = { + "SendHeader" : { + "Set-Cookie" : "sess-id=0213; path=/" + } +} +File2_rules = { + "ExpectHeader" : { + "Cookie" : "sess-id=0213" + }, + "SendHeader" : { + "Set-Cookie" : "new-sess=N" + } +} +File3_rules = { + "SendHeader" : { + # use upper case 'I' to provoke Wget failure with turkish locale + "Set-Cookie" : "sess-id=0213; path=/; ExPIRes=Sun, 06 Nov 2001 12:32:43 GMT" + }, + "ExpectHeader" : { + "Cookie" : "new-sess=N; sess-id=0213" + } +} +File4_rules = { + "RejectHeader" : { + "Cookie" : "sess-id=0213" + }, + "ExpectHeader" : { + "Cookie" : "new-sess=N" + } +} +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) +C_File = WgetFile ("File3", File3, rules=File3_rules) +D_File = WgetFile ("File4", File4, rules=File4_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2", "File3", "File4"]] + +Files = [[A_File, B_File, C_File, D_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File, D_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-cookie.py b/testenv/Test-cookie.py new file mode 100755 index 0000000..ba6c055 --- /dev/null +++ b/testenv/Test-cookie.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" + This test ensures that Wget's cookie jar support works correctly. +""" +############# File Definitions ############################################### +File1 = """All happy families are alike; +Each unhappy family is unhappy in its own way""" +File2 = "Anyone for chocochip cookies?" + +File1_rules = { + "SendHeader" : { + "Set-Cookie" : "sess-id=0213; path=/" + } +} +File2_rules = { + "ExpectHeader" : { + "Cookie" : "sess-id=0213" + } +} + +A_File = WgetFile ("File1", File1, rules=File1_rules) +B_File = WgetFile ("File2", File2, rules=File2_rules) + +WGET_OPTIONS = "" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-hsts.py b/testenv/Test-hsts.py new file mode 100755 index 0000000..19bd4c4 --- /dev/null +++ b/testenv/Test-hsts.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import time +import os + +""" +This test makes sure Wget can parse a given HSTS database and apply the indicated HSTS policy. +""" + +print (os.getenv('SSL_TESTS')) +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +def hsts_database_path(): + hsts_file = ".wget-hsts-testenv" + return os.path.abspath(hsts_file) + +def create_hsts_database(path, host, port): + # we want the current time as an integer, + # not as a floating point + curtime = int(time.time()) + max_age = "123456" + + f = open(path, "w") + + f.write("# dummy comment\n") + f.write(host + "\t" + str(port) + "\t0\t" + str(curtime) + "\t" + max_age + "\n") + f.close() + +File_Name = "hw" +File_Content = "Hello, world!" +File = WgetFile(File_Name, File_Content) + +Hsts_File_Path = hsts_database_path() + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) + +WGET_OPTIONS = "--hsts-file=" + Hsts_File_Path + " --ca-certificate=" + CAFILE +WGET_URLS = [[File_Name]] + +Files = [[File]] +Servers = [HTTPS] +Requests = ["http"] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [File] + +pre_test = { + "ServerFiles" : Files, + "Domains" : ["localhost"] +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetCode" : ExpectedReturnCode, +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} + +test = HTTPTest( + pre_hook = pre_test, + post_hook = post_test, + test_params = test_options, + protocols = Servers, + req_protocols = Requests +) + +# start the web server and create the temporary HSTS database +test.setup() +create_hsts_database(Hsts_File_Path, 'localhost', test.port) + +err = test.begin() + +# remove the temporary HSTS database +os.unlink(hsts_database_path()) +exit(err) diff --git a/testenv/Test-metalink-http-baddigest.py b/testenv/Test-metalink-http-baddigest.py new file mode 100755 index 0000000..2496da7 --- /dev/null +++ b/testenv/Test-metalink-http-baddigest.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with a malformed base64 Digest header. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" +bad_sha256 = b64encode (hashlib.sha256 (bad.encode ('UTF-8')).digest ()).decode ('ascii') + +LinkHeaders = ["<http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file>; rel=duplicate; pri=1"] +DigestHeader = "SHA-256=bad_base64,SHA-256={{BAD_HASH}}" + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) + +wrong_file = WgetFile ("wrong_file", bad) +wrong_file_down = WgetFile ("main.metalink", bad) + +WGET_OPTIONS = "--metalink-over-http" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /wrong_file" +]] + +Files = [[ + MetaHTTP, + wrong_file +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [wrong_file_down] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +DigestHeader = DigestHeader.replace('{{BAD_HASH}}', bad_sha256) + +# Helper function for hostname, port and digest substitution +def SubstituteServerInfo (text, host, port): + text = text.replace('{{SRV_HOST}}', host) + text = text.replace('{{SRV_PORT}}', str (port)) + return text + +MetaHTTPRules["SendHeader"] = { + 'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port) + for LinkHeader in LinkHeaders ], + 'Digest': DigestHeader +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-quoted.py b/testenv/Test-metalink-http-quoted.py new file mode 100755 index 0000000..af2c445 --- /dev/null +++ b/testenv/Test-metalink-http-quoted.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP quoted values support in Wget. +""" + +# Helper function for hostname, port and digest substitution +def SubstituteServerInfo (text, host, port, digest): + text = text.replace('{{FILE1_HASH}}', digest) + text = text.replace('{{SRV_HOST}}', host) + text = text.replace('{{SRV_PORT}}', str (port)) + return text + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File1_corrupted = "Would you like some Coffee?" +File1_lowPref = "Do not take this" +File1_sha256 = b64encode (hashlib.sha256 (File1.encode ('UTF-8')).digest ()).decode ('ascii') +Signature = '''-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +This is no valid signature. But it should be downloaded. +The attempt to verify should fail but should not prevent +a successful metalink resource retrieval (the sig failure +should not be fatal). +-----END PGP SIGNATURE----- +''' +File2 = "No meta data for this file." + +LinkHeaders = [ + # This file has low priority and should not be picked. + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref>; rel=\"duplicate\"; pri=\"9\"; geo=\"pl\"", + # This file should be picked second, after hash failure. + "<http://0.0.0.0/File1_try2_badconnection>; rel =\"duplicate\";pref; pri=\"7\"", + # This signature download will fail. + "<http://{{SRV_HOST}}:{{SRV_PORT}}/Sig2.asc>; rel=\"describedby\"; type=\"application/pgp-signature\"", + # Two good signatures + "<http://{{SRV_HOST}}:{{SRV_PORT}}/Sig.asc>; rel=\"describedby\"; type=\"application/pgp-signature\"", + "<http://{{SRV_HOST}}:{{SRV_PORT}}/Sig.asc>; rel=\"describedby\"; type=\"application/pgp-signature\"", + # Bad URL scheme + "<invalid_url>; rel=\"duplicate\"; pri=\"4\"", + # rel missing + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1>; pri=\"1\"; pref", + # invalid rel + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1>; rel=\"strange\"; pri=\"4\"", + # This file should be picked first, because it has the lowest pri among preferred. + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_try1_corrupted>; rel=\"duplicate\"; geo=\"su\"; pri=\"4\"; pref", + # This file should NOT be picked third due to preferred location set to 'uk' + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_badgeo>; rel =\"duplicate\";pri=\"5\"", + # This file should be picked as third try, and it should succeed + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_try3_ok>; rel=\'duplicate\'; pri=\"5\";geo=\"uk\"" + ] +DigestHeader = "SHA-256=\'{{FILE1_HASH}}\'" + +# This will be filled as soon as we know server hostname and port +MetaFileRules = {'SendHeader' : {}} + +FileOkServer = WgetFile ("File1_try3_ok", File1) +FileBadPref = WgetFile ("File1_lowPref", File1_lowPref) +FileBadHash = WgetFile ("File1_try1_corrupted", File1_corrupted) +MetaFile = WgetFile ("test.meta", rules=MetaFileRules) +# In case of Metalink over HTTP, the local file name is +# derived from the URL suffix. +FileOkLocal = WgetFile ("test.meta", File1) +SigFile = WgetFile ("Sig.asc", Signature) +FileNoMeta = WgetFile ("File2", File2) + +WGET_OPTIONS = "--metalink-over-http --preferred-location=uk" +WGET_URLS = [["test.meta", "File2"]] + +Files = [[FileOkServer, FileBadPref, FileBadHash, MetaFile, SigFile, FileNoMeta]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [FileNoMeta, FileOkLocal] + +RequestList = [ + [ + "HEAD /test.meta", + "GET /Sig2.asc", + "GET /Sig.asc", + "GET /File1_try1_corrupted", + "GET /File1_try3_ok", + "HEAD /File2", + "GET /File2", + ] +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList, +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, +) + +http_test.server_setup() +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaFileRules["SendHeader"] = { + 'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port, File1_sha256) + for LinkHeader in LinkHeaders ], + 'Digest': SubstituteServerInfo (DigestHeader, srv_host, srv_port, File1_sha256), +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml-trust-name.py b/testenv/Test-metalink-http-xml-trust-name.py new file mode 100755 index 0000000..7dae50e --- /dev/null +++ b/testenv/Test-metalink-http-xml-trust-name.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Metalink/XML Link headers. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" +bad_sha256 = hashlib.sha256 (bad.encode ('UTF-8')).hexdigest () + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml1 = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +MetaXml2 = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="bad"> + <verification> + <hash type="sha256">{{BAD_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/bad</url> + </resources> + </file> + </files> +</metalink> +""" + +LinkHeaders = [ + # This file has the lowest priority, and should go last + "<http://{{SRV_HOST}}:{{SRV_PORT}}/test1.metalink>; rel=describedby; pri=2; type=\"application/metalink4+xml\"; name=\"newname.metalink\"", + # This file has the highest priority, and should go first + "<http://{{SRV_HOST}}:{{SRV_PORT}}/test2.metalink>; rel=describedby; pri=1; type=\"application/metalink4+xml\"" +] + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("dir/File1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("dir/File2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("dir/File4", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("dir/File5", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +MetaFile1 = WgetFile ("test1.metalink", MetaXml1) +MetaFile1_down = WgetFile ("newname.metalink", MetaXml1) + +MetaFile2 = WgetFile ("test2.metalink", MetaXml2) + +WGET_OPTIONS = "--trust-server-names --metalink-over-http --metalink-index=2" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /test1.metalink", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + MetaFile1, MetaFile2, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaFile1_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml1 = MetaXml1.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml1 = MetaXml1.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml1 = MetaXml1.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml1 = MetaXml1.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml1 = MetaXml1.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml1 = MetaXml1.replace('{{SRV_HOST}}', srv_host) +MetaXml1 = MetaXml1.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile1.content = MetaXml1 +MetaFile1_down.content = MetaXml1 + +MetaXml2 = MetaXml2.replace('{{BAD_HASH}}', bad_sha256) +MetaXml2 = MetaXml2.replace('{{SRV_HOST}}', srv_host) +MetaXml2 = MetaXml2.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile2.content = MetaXml2 + +# Helper function for hostname, port and digest substitution +def SubstituteServerInfo (text, host, port): + text = text.replace('{{SRV_HOST}}', host) + text = text.replace('{{SRV_PORT}}', str (port)) + return text + +MetaHTTPRules["SendHeader"] = { + 'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port) + for LinkHeader in LinkHeaders ] +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml-trust.py b/testenv/Test-metalink-http-xml-trust.py new file mode 100755 index 0000000..1df6ce4 --- /dev/null +++ b/testenv/Test-metalink-http-xml-trust.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Metalink/XML Link headers. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" +bad_sha256 = hashlib.sha256 (bad.encode ('UTF-8')).hexdigest () + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml1 = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +MetaXml2 = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="bad"> + <verification> + <hash type="sha256">{{BAD_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/bad</url> + </resources> + </file> + </files> +</metalink> +""" + +LinkHeaders = [ + # This file has the lowest priority, and should go last + "<http://{{SRV_HOST}}:{{SRV_PORT}}/test1.metalink>; rel=describedby; pri=2; type=\"application/metalink4+xml\"", + # This file has the highest priority, and should go first + "<http://{{SRV_HOST}}:{{SRV_PORT}}/test2.metalink>; rel=describedby; pri=1; type=\"application/metalink4+xml\"" +] + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("dir/File1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("dir/File2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("dir/File4", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("dir/File5", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +MetaFile1 = WgetFile ("test1.metalink", MetaXml1) +MetaFile1_down = WgetFile ("test1.metalink", MetaXml1) + +MetaFile2 = WgetFile ("test2.metalink", MetaXml2) + +WGET_OPTIONS = "--trust-server-names --metalink-over-http --metalink-index=2" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /test1.metalink", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + MetaFile1, MetaFile2, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaFile1_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml1 = MetaXml1.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml1 = MetaXml1.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml1 = MetaXml1.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml1 = MetaXml1.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml1 = MetaXml1.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml1 = MetaXml1.replace('{{SRV_HOST}}', srv_host) +MetaXml1 = MetaXml1.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile1.content = MetaXml1 +MetaFile1_down.content = MetaXml1 + +MetaXml2 = MetaXml2.replace('{{BAD_HASH}}', bad_sha256) +MetaXml2 = MetaXml2.replace('{{SRV_HOST}}', srv_host) +MetaXml2 = MetaXml2.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile2.content = MetaXml2 + +# Helper function for hostname, port and digest substitution +def SubstituteServerInfo (text, host, port): + text = text.replace('{{SRV_HOST}}', host) + text = text.replace('{{SRV_PORT}}', str (port)) + return text + +MetaHTTPRules["SendHeader"] = { + 'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port) + for LinkHeader in LinkHeaders ] +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml-type-content.py b/testenv/Test-metalink-http-xml-type-content.py new file mode 100755 index 0000000..b1ace27 --- /dev/null +++ b/testenv/Test-metalink-http-xml-type-content.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Content-Type Metalink/XML. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) +MetaHTTP_down = WgetFile ("main.metalink.meta#1", MetaXml) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("main.metalink.meta#1.#1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("main.metalink.meta#1.#2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("main.metalink.meta#1.#3", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("main.metalink.meta#1.#4", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +WGET_OPTIONS = "--metalink-over-http --content-disposition --metalink-index=0" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaHTTP_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml = MetaXml.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml = MetaXml.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml = MetaXml.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml = MetaXml.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml = MetaXml.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml = MetaXml.replace('{{SRV_HOST}}', srv_host) +MetaXml = MetaXml.replace('{{SRV_PORT}}', str (srv_port)) +MetaHTTP_down.content = MetaXml + +MetaHTTP.content = MetaXml + +MetaHTTPRules["SendHeader"] = { + 'Content-Type': 'application/metalink4+xml', + 'Content-Disposition': 'filename="newname.metalink"' +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml-type-trust-content.py b/testenv/Test-metalink-http-xml-type-trust-content.py new file mode 100755 index 0000000..7ee4197 --- /dev/null +++ b/testenv/Test-metalink-http-xml-type-trust-content.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Content-Type Metalink/XML. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) +MetaHTTP_down = WgetFile ("newname.metalink", MetaXml) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("dir/File1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("dir/File2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("dir/File4", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("dir/File5", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +WGET_OPTIONS = "--trust-server-names --metalink-over-http --content-disposition --metalink-index=0" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaHTTP_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml = MetaXml.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml = MetaXml.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml = MetaXml.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml = MetaXml.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml = MetaXml.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml = MetaXml.replace('{{SRV_HOST}}', srv_host) +MetaXml = MetaXml.replace('{{SRV_PORT}}', str (srv_port)) +MetaHTTP_down.content = MetaXml + +MetaHTTP.content = MetaXml + +MetaHTTPRules["SendHeader"] = { + 'Content-Type': 'application/metalink4+xml', + 'Content-Disposition': 'filename="newname.metalink"' +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml-type-trust.py b/testenv/Test-metalink-http-xml-type-trust.py new file mode 100755 index 0000000..0cf2074 --- /dev/null +++ b/testenv/Test-metalink-http-xml-type-trust.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Content-Type Metalink/XML. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) +MetaHTTP_down = WgetFile ("main.metalink", MetaXml) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("dir/File1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("dir/File2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("dir/File4", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("dir/File5", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +WGET_OPTIONS = "--trust-server-names --metalink-over-http --metalink-index=0" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaHTTP_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml = MetaXml.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml = MetaXml.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml = MetaXml.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml = MetaXml.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml = MetaXml.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml = MetaXml.replace('{{SRV_HOST}}', srv_host) +MetaXml = MetaXml.replace('{{SRV_PORT}}', str (srv_port)) +MetaHTTP_down.content = MetaXml + +MetaHTTP.content = MetaXml + +MetaHTTPRules["SendHeader"] = { + 'Content-Type': 'application/metalink4+xml', + 'Content-Disposition': 'filename="newname.metalink"' +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml-type.py b/testenv/Test-metalink-http-xml-type.py new file mode 100755 index 0000000..19a65f1 --- /dev/null +++ b/testenv/Test-metalink-http-xml-type.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Content-Type Metalink/XML. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) +MetaHTTP_down = WgetFile ("main.metalink.meta#1", MetaXml) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("main.metalink.meta#1.#1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("main.metalink.meta#1.#2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("main.metalink.meta#1.#3", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("main.metalink.meta#1.#4", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +WGET_OPTIONS = "--metalink-over-http --metalink-index=0" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaHTTP_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml = MetaXml.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml = MetaXml.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml = MetaXml.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml = MetaXml.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml = MetaXml.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml = MetaXml.replace('{{SRV_HOST}}', srv_host) +MetaXml = MetaXml.replace('{{SRV_PORT}}', str (srv_port)) +MetaHTTP_down.content = MetaXml + +MetaHTTP.content = MetaXml + +MetaHTTPRules["SendHeader"] = { + 'Content-Type': 'application/metalink4+xml', + 'Content-Disposition': 'filename="newname.metalink"' +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http-xml.py b/testenv/Test-metalink-http-xml.py new file mode 100755 index 0000000..9cc49e9 --- /dev/null +++ b/testenv/Test-metalink-http-xml.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink/HTTP with Metalink/XML Link headers. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +bad = "Ouch!" +bad_sha256 = hashlib.sha256 (bad.encode ('UTF-8')).hexdigest () + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml1 = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="dir/File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File1</url> + </resources> + </file> + <file name="dir/File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File2</url> + </resources> + </file> + <file name="/dir/File3"> <!-- rejected by libmetalink --> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File3</url> + </resources> + </file> + <file name="dir/File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File4</url> + </resources> + </file> + <file name="dir/File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="25">http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/File5</url> + </resources> + </file> + </files> +</metalink> +""" + +MetaXml2 = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="bad"> + <verification> + <hash type="sha256">{{BAD_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35">http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file</url> + <url type="http" preference="40">http://{{SRV_HOST}}:{{SRV_PORT}}/404</url> + <url type="http" preference="30">http://{{SRV_HOST}}:{{SRV_PORT}}/bad</url> + </resources> + </file> + </files> +</metalink> +""" + +LinkHeaders = [ + # This file has the lowest priority, and should go last + "<http://{{SRV_HOST}}:{{SRV_PORT}}/test1.metalink>; rel=describedby; pri=2; type=\"application/metalink4+xml\"", + # This file has the highest priority, and should go first + "<http://{{SRV_HOST}}:{{SRV_PORT}}/test2.metalink>; rel=describedby; pri=1; type=\"application/metalink4+xml\"" +] + +# This will be filled as soon as we know server hostname and port +MetaHTTPRules = {'SendHeader' : {}} + +MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules) + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("main.metalink.meta#2.#1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("main.metalink.meta#2.#2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +# rejected by libmetalink +File3_orig = WgetFile ("File3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("main.metalink.meta#2.#3", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("main.metalink.meta#2.#4", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +MetaFile1 = WgetFile ("test1.metalink", MetaXml1) +MetaFile1_down = WgetFile ("main.metalink.meta#2", MetaXml1) + +MetaFile2 = WgetFile ("test2.metalink", MetaXml2) + +WGET_OPTIONS = "--metalink-over-http --metalink-index=2" +WGET_URLS = [["main.metalink"]] + +RequestList = [[ + "HEAD /main.metalink", + "GET /404", + "GET /wrong_file", + "GET /test1.metalink", + "GET /File1", + "GET /File2", + "GET /File4", + "GET /File5" +]] + +Files = [[ + MetaHTTP, + wrong_file, + MetaFile1, MetaFile2, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + MetaFile1_down, + File1_down, + File2_down, + File4_down, + File5_down +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml1 = MetaXml1.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml1 = MetaXml1.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml1 = MetaXml1.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml1 = MetaXml1.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml1 = MetaXml1.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml1 = MetaXml1.replace('{{SRV_HOST}}', srv_host) +MetaXml1 = MetaXml1.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile1.content = MetaXml1 +MetaFile1_down.content = MetaXml1 + +MetaXml2 = MetaXml2.replace('{{BAD_HASH}}', bad_sha256) +MetaXml2 = MetaXml2.replace('{{SRV_HOST}}', srv_host) +MetaXml2 = MetaXml2.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile2.content = MetaXml2 + +# Helper function for hostname, port and digest substitution +def SubstituteServerInfo (text, host, port): + text = text.replace('{{SRV_HOST}}', host) + text = text.replace('{{SRV_PORT}}', str (port)) + return text + +MetaHTTPRules["SendHeader"] = { + 'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port) + for LinkHeader in LinkHeaders ] +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-http.py b/testenv/Test-metalink-http.py new file mode 100755 index 0000000..b119da6 --- /dev/null +++ b/testenv/Test-metalink-http.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib +from base64 import b64encode + +""" + This is to test Metalink as HTTP file support in Wget. +""" + +# Helper function for hostname, port and digest substitution +def SubstituteServerInfo (text, host, port, digest): + text = text.replace('{{FILE1_HASH}}', digest) + text = text.replace('{{SRV_HOST}}', host) + text = text.replace('{{SRV_PORT}}', str (port)) + return text + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File1_corrupted = "Would you like some Coffee?" +File1_lowPref = "Do not take this" +File1_sha256 = b64encode (hashlib.sha256 (File1.encode ('UTF-8')).digest ()).decode ('ascii') +Signature = '''-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +This is no valid signature. But it should be downloaded. +The attempt to verify should fail but should not prevent +a successful metalink resource retrieval (the sig failure +should not be fatal). +-----END PGP SIGNATURE----- +''' +File2 = "No meta data for this file." + +LinkHeaders = [ + # This file has low priority and should not be picked. + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref>; rel=duplicate; pri=9; geo=pl", + # This file should be picked second, after hash failure. + "<http://this.is.no.good.example/File1_try2_badconnection>; rel =duplicate;pref; pri=7", + # This signature download will fail. + "<http://{{SRV_HOST}}:{{SRV_PORT}}/Sig2.asc>; rel=describedby; type=application/pgp-signature", + # Two good signatures + "<http://{{SRV_HOST}}:{{SRV_PORT}}/Sig.asc>; rel=describedby; type=application/pgp-signature", + "<http://{{SRV_HOST}}:{{SRV_PORT}}/Sig.asc>; rel=describedby; type=application/pgp-signature", + # Bad URL scheme + "<invalid_url>; rel=duplicate; pri=4", + # rel missing + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1>; pri=1; pref", + # invalid rel + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1>; rel=strange; pri=4", + # This file should be picked first, because it has the lowest pri among preferred. + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_try1_corrupted>; rel=duplicate; geo=su; pri=4; pref", + # This file should NOT be picked third due to preferred location set to 'uk' + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_badgeo>; rel =duplicate;pri=5", + # This file should be picked as third try, and it should succeed + "<http://{{SRV_HOST}}:{{SRV_PORT}}/File1_try3_ok>; rel=duplicate; pri=5;geo=uk" + ] +DigestHeader = "SHA-256={{FILE1_HASH}}" + +# This will be filled as soon as we know server hostname and port +MetaFileRules = {'SendHeader' : {}} + +FileOkServer = WgetFile ("File1_try3_ok", File1) +FileBadPref = WgetFile ("File1_lowPref", File1_lowPref) +FileBadHash = WgetFile ("File1_try1_corrupted", File1_corrupted) +MetaFile = WgetFile ("test.meta", rules=MetaFileRules) +# In case of Metalink over HTTP, the local file name is +# derived from the URL suffix. +FileOkLocal = WgetFile ("test.meta", File1) +SigFile = WgetFile ("Sig.asc", Signature) +FileNoMeta = WgetFile ("File2", File2) + +WGET_OPTIONS = "--metalink-over-http --preferred-location=uk" +WGET_URLS = [["test.meta", "File2"]] + +Files = [[FileOkServer, FileBadPref, FileBadHash, MetaFile, SigFile, FileNoMeta]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [FileNoMeta, FileOkLocal] + +RequestList = [ + [ + "HEAD /test.meta", + "GET /Sig2.asc", + "GET /Sig.asc", + "GET /File1_try1_corrupted", + "GET /File1_try3_ok", + "HEAD /File2", + "GET /File2", + ] +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList, +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, +) + +http_test.server_setup() +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaFileRules["SendHeader"] = { + 'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port, File1_sha256) + for LinkHeader in LinkHeaders ], + 'Digest': SubstituteServerInfo (DigestHeader, srv_host, srv_port, File1_sha256), +} + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-xml-abspath-trust.py b/testenv/Test-metalink-xml-abspath-trust.py new file mode 100755 index 0000000..5091cd0 --- /dev/null +++ b/testenv/Test-metalink-xml-abspath-trust.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML forbids absolute paths. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["/File1", None, File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", "File2", File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", "File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-abspath.py b/testenv/Test-metalink-xml-abspath.py new file mode 100755 index 0000000..e84fcf0 --- /dev/null +++ b/testenv/Test-metalink-xml-abspath.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML forbids absolute paths. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["/File1", None, File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", XmlName + ".#1", File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", XmlName + ".#2", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-absprefix-trust.py b/testenv/Test-metalink-xml-absprefix-trust.py new file mode 100755 index 0000000..4cf065d --- /dev/null +++ b/testenv/Test-metalink-xml-absprefix-trust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML absolute directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", "File1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", "File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--directory-prefix /dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-absprefix.py b/testenv/Test-metalink-xml-absprefix.py new file mode 100755 index 0000000..d19d178 --- /dev/null +++ b/testenv/Test-metalink-xml-absprefix.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML absolute directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", XmlName + ".#2", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--directory-prefix /dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-continue.py b/testenv/Test-metalink-xml-continue.py new file mode 100644 index 0000000..782dbd5 --- /dev/null +++ b/testenv/Test-metalink-xml-continue.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML --continue support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.add_LocalFiles ( + [XmlName + ".#1", File1[0:14]], # File1 to continue from partial file + [XmlName + ".#2", File2], # File2 to keep, different from server + [XmlName + ".#3", File3], # File3 to keep, already fully retrieved + [XmlName + ".#4", File4], # File4 to keep, different from server +) + +Meta.add_ExpectedFiles ( + [XmlName + ".#2", File2], # File2 to keep, different from server + [XmlName + ".#3", File3], # File3 to keep, already fully retrieved + [XmlName + ".#4", File4], # File4 to keep, different from server +) + +Meta.print_meta () + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["File1", XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", XmlName + ".#2", wrong_file, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["File3", XmlName + ".#3", File3, None, True, + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["File4", XmlName + ".#4", File4_lowPref, None, True, + ["wrong_file", wrong_file, "http", None, 35]], + ["File5", XmlName + ".#5", File5, None, True, + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--continue " + \ + "--input-metalink " + XmlName, 1 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-emptyprefix-trust.py b/testenv/Test-metalink-xml-emptyprefix-trust.py new file mode 100755 index 0000000..9b4272d --- /dev/null +++ b/testenv/Test-metalink-xml-emptyprefix-trust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML with an empty directory prefix. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", "subdir/File1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", "subdir/File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--directory-prefix '' " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-homepath-trust.py b/testenv/Test-metalink-xml-homepath-trust.py new file mode 100755 index 0000000..3831e80 --- /dev/null +++ b/testenv/Test-metalink-xml-homepath-trust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML forbids the home path and names + beginning with the ~ (tilde) character. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["~File1", None, File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["~/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["dir/~File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["dir/File4~", "dir/File4~", File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["dir/~/File5", "dir/~/File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-homepath.py b/testenv/Test-metalink-xml-homepath.py new file mode 100755 index 0000000..f38f2db --- /dev/null +++ b/testenv/Test-metalink-xml-homepath.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML forbids the home path and names + beginning with the ~ (tilde) character. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["~File1", None, File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["~/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["dir/~File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["dir/File4~", XmlName + ".#1", File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["dir/~/File5", XmlName + ".#2", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-homeprefix-trust.py b/testenv/Test-metalink-xml-homeprefix-trust.py new file mode 100755 index 0000000..23c7191 --- /dev/null +++ b/testenv/Test-metalink-xml-homeprefix-trust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML home directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", "File1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", "File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--directory-prefix ~/dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-homeprefix.py b/testenv/Test-metalink-xml-homeprefix.py new file mode 100755 index 0000000..03b17a8 --- /dev/null +++ b/testenv/Test-metalink-xml-homeprefix.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML home directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", XmlName + ".#2", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--directory-prefix ~/dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-nohash.py b/testenv/Test-metalink-xml-nohash.py new file mode 100755 index 0000000..4c82cb0 --- /dev/null +++ b/testenv/Test-metalink-xml-nohash.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML with no hashes generates a SIGSEGV. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["File1", None, File1, None, False, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", XmlName + ".#2", File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["File3", None, File3, None, None, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["File4", XmlName + ".#4", File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", None, File5, None, "", + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 1 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-nourls.py b/testenv/Test-metalink-xml-nourls.py new file mode 100755 index 0000000..9f3d93e --- /dev/null +++ b/testenv/Test-metalink-xml-nourls.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML with unknown url types. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["File1", XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", None, File2, None, True, + ["wrong_file", wrong_file, "unknown", None, 35], + ["404", None, "unknown", None, 40], + ["File2_lowPref", File2_lowPref, "unknown", None, 25], + ["File2", File2, "unknown", None, 30]], + ["File3", XmlName + ".#3", File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["File4", XmlName + ".#4", File4, None, True, + ["wrong_file", wrong_file, "unknown", None, 35], + ["404", None, "unknown", None, 40], + ["File4_lowPref", File4_lowPref, "unknown", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", XmlName + ".#5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 1 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-prefix-trust.py b/testenv/Test-metalink-xml-prefix-trust.py new file mode 100755 index 0000000..1fef7f9 --- /dev/null +++ b/testenv/Test-metalink-xml-prefix-trust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", "dir/" + "subdir/File1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", "dir/" + "subdir/File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--directory-prefix dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-prefix.py b/testenv/Test-metalink-xml-prefix.py new file mode 100755 index 0000000..4275a04 --- /dev/null +++ b/testenv/Test-metalink-xml-prefix.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", "dir/" + XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", "dir/" + XmlName + ".#2", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--directory-prefix dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-relpath-trust.py b/testenv/Test-metalink-xml-relpath-trust.py new file mode 100755 index 0000000..d2b4fc0 --- /dev/null +++ b/testenv/Test-metalink-xml-relpath-trust.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML forbids relative paths. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["./File1", None, File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["../File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["dir/./File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["dir/../File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", "File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-relpath.py b/testenv/Test-metalink-xml-relpath.py new file mode 100755 index 0000000..9405410 --- /dev/null +++ b/testenv/Test-metalink-xml-relpath.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test if Metalink/XML forbids relative paths. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["./File1", None, File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["../File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["dir/./File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["dir/../File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", XmlName + ".#1", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-relprefix-trust.py b/testenv/Test-metalink-xml-relprefix-trust.py new file mode 100755 index 0000000..e19a8dc --- /dev/null +++ b/testenv/Test-metalink-xml-relprefix-trust.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML relative directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", "File1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", "File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--directory-prefix ../dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-relprefix.py b/testenv/Test-metalink-xml-relprefix.py new file mode 100755 index 0000000..98718c7 --- /dev/null +++ b/testenv/Test-metalink-xml-relprefix.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML relative directory prefix support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["subdir/File1", XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["/subdir/File2", None, File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["~/subdir/File3", None, File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["../subdir/File4", None, File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["subdir/File5", XmlName + ".#2", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--directory-prefix ../dir " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-size.py b/testenv/Test-metalink-xml-size.py new file mode 100755 index 0000000..3250967 --- /dev/null +++ b/testenv/Test-metalink-xml-size.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML file size check in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["File1", XmlName + ".#1", File1, "", True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", None, File2, 2, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["File3", XmlName + ".#3", File3, 0, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["File4", XmlName + ".#4", File4, -5, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", XmlName + ".#5", File5, True, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 1 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-trust.py b/testenv/Test-metalink-xml-trust.py new file mode 100755 index 0000000..88049ca --- /dev/null +++ b/testenv/Test-metalink-xml-trust.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML file support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["File1", "File1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", "File2", File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["File3", "File3", File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["File4", "File4", File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", "File5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--trust-server-names " + \ + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-metalink-xml-urlbreak.py b/testenv/Test-metalink-xml-urlbreak.py new file mode 100755 index 0000000..e53ae11 --- /dev/null +++ b/testenv/Test-metalink-xml-urlbreak.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib + +""" + This is to test Metalink/XML white spaces in url resources. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" +############# File Definitions ############################################### +bad = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" +File1_sha256 = hashlib.sha256 (File1.encode ('UTF-8')).hexdigest () + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" +File2_sha256 = hashlib.sha256 (File2.encode ('UTF-8')).hexdigest () + +File3 = "A little more, please" +File3_lowPref = "That's just too much" +File3_sha256 = hashlib.sha256 (File3.encode ('UTF-8')).hexdigest () + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" +File4_sha256 = hashlib.sha256 (File4.encode ('UTF-8')).hexdigest () + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." +File5_sha256 = hashlib.sha256 (File5.encode ('UTF-8')).hexdigest () + +MetaXml = \ +"""<?xml version="1.0" encoding="utf-8"?> +<metalink version="3.0" xmlns="http://www.metalinker.org/"> + <publisher> + <name>GNU Wget</name> + </publisher> + <license> + <name>GNU GPL</name> + <url>http://www.gnu.org/licenses/gpl.html</url> + </license> + <identity>Wget Test Files</identity> + <version>1.2.3</version> + <description>Wget Test Files description</description> + <files> + <file name="File1"> + <verification> + <hash type="sha256">{{FILE1_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35"> + http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file + </url> + <url type="http" preference="40"> + http://{{SRV_HOST}}:{{SRV_PORT}}/404 + </url> + <url type="http" preference="25"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File1_lowPref + </url> + <url type="http" preference="30"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File1 + </url> + </resources> + </file> + <file name="File2"> + <verification> + <hash type="sha256">{{FILE2_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35"> + http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file + </url> + <url type="http" preference="40"> + http://{{SRV_HOST}}:{{SRV_PORT}}/404 + </url> + <url type="http" preference="25"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File2_lowPref + </url> + <url type="http" preference="30"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File2 + </url> + </resources> + </file> + <file name="File3"> + <verification> + <hash type="sha256">{{FILE3_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35"> + http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file + </url> + <url type="http" preference="40"> + http://{{SRV_HOST}}:{{SRV_PORT}}/404 + </url> + <url type="http" preference="25"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File3_lowPref + </url> + <url type="http" preference="30"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File3 + </url> + </resources> + </file> + <file name="File4"> + <verification> + <hash type="sha256">{{FILE4_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35"> + http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file + </url> + <url type="http" preference="40"> + http://{{SRV_HOST}}:{{SRV_PORT}}/404 + </url> + <url type="http" preference="25"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File4_lowPref + </url> + <url type="http" preference="30"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File4 + </url> + </resources> + </file> + <file name="File5"> + <verification> + <hash type="sha256">{{FILE5_HASH}}</hash> + </verification> + <resources> + <url type="http" preference="35"> + http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file + </url> + <url type="http" preference="40"> + http://{{SRV_HOST}}:{{SRV_PORT}}/404 + </url> + <url type="http" preference="25"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File5_lowPref + </url> + <url type="http" preference="30"> + http://{{SRV_HOST}}:{{SRV_PORT}}/File5 + </url> + </resources> + </file> + </files> +</metalink> +""" + +wrong_file = WgetFile ("wrong_file", bad) + +File1_orig = WgetFile ("File1", File1) +File1_down = WgetFile ("test.metalink.#1", File1) +File1_nono = WgetFile ("File1_lowPref", File1_lowPref) + +File2_orig = WgetFile ("File2", File2) +File2_down = WgetFile ("test.metalink.#2", File2) +File2_nono = WgetFile ("File2_lowPref", File2_lowPref) + +File3_orig = WgetFile ("File3", File3) +File3_down = WgetFile ("test.metalink.#3", File3) +File3_nono = WgetFile ("File3_lowPref", File3_lowPref) + +File4_orig = WgetFile ("File4", File4) +File4_down = WgetFile ("test.metalink.#4", File4) +File4_nono = WgetFile ("File4_lowPref", File4_lowPref) + +File5_orig = WgetFile ("File5", File5) +File5_down = WgetFile ("test.metalink.#5", File5) +File5_nono = WgetFile ("File5_lowPref", File5_lowPref) + +MetaFile = WgetFile ("test.metalink", MetaXml) + +WGET_OPTIONS = "--input-metalink test.metalink" +WGET_URLS = [[]] + +Files = [[ + wrong_file, + File1_orig, File1_nono, + File2_orig, File2_nono, + File3_orig, File3_nono, + File4_orig, File4_nono, + File5_orig, File5_nono +]] +Existing_Files = [MetaFile] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [ + File1_down, + File2_down, + File3_down, + File4_down, + File5_down, + MetaFile +] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, +) + +http_test.server_setup() +### Get and use dynamic server sockname +srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + +MetaXml = MetaXml.replace('{{FILE1_HASH}}', File1_sha256) +MetaXml = MetaXml.replace('{{FILE2_HASH}}', File2_sha256) +MetaXml = MetaXml.replace('{{FILE3_HASH}}', File3_sha256) +MetaXml = MetaXml.replace('{{FILE4_HASH}}', File4_sha256) +MetaXml = MetaXml.replace('{{FILE5_HASH}}', File5_sha256) +MetaXml = MetaXml.replace('{{SRV_HOST}}', srv_host) +MetaXml = MetaXml.replace('{{SRV_PORT}}', str (srv_port)) +MetaFile.content = MetaXml + +err = http_test.begin () + +exit (err) diff --git a/testenv/Test-metalink-xml.py b/testenv/Test-metalink-xml.py new file mode 100644 index 0000000..788d375 --- /dev/null +++ b/testenv/Test-metalink-xml.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +from sys import exit +from misc.metalinkv3_xml import Metalinkv3_XML + +""" + This is to test Metalink/XML file support in Wget. + + With --trust-server-names, trust the metalink:file names. + + Without --trust-server-names, don't trust the metalink:file names: + use the basename of --input-metalink, and add a sequential number + (e.g. .#1, .#2, etc.). + + Strip the directory from unsafe paths. +""" + +############# File Definitions ############################################### +wrong_file = "Ouch!" + +File1 = "Would you like some Tea?" +File1_lowPref = "Do not take this" + +File2 = "This is gonna be good" +File2_lowPref = "Not this one too" + +File3 = "A little more, please" +File3_lowPref = "That's just too much" + +File4 = "Maybe a biscuit?" +File4_lowPref = "No, thanks" + +File5 = "More Tea...?" +File5_lowPref = "I have to go..." + +############# Metalink/XML ################################################### +Meta = Metalinkv3_XML() + +# file_name: metalink:file "name" field +# save_name: metalink:file save name, if None the file is rejected +# content : metalink:file content +# +# size: +# True auto-compute size +# None no <size></size> +# any use this size +# +# hash_sha256: +# False no <verification></verification> +# True auto-compute sha256 +# None no <hash></hash> +# any use this hash +# +# srv_file : metalink:url server file +# srv_content: metalink:url server file content, if None the file doesn't exist +# utype : metalink:url type (http, ftp, etc.) +# location : metalink:url location (default 'no location field') +# preference : metalink:url preference (default 999999) + +XmlName = "test.metalink" + +Meta.xml ( + # Metalink/XML file name + XmlName, + # file_name, save_name, content, size, hash_sha256 + ["File1", XmlName + ".#1", File1, None, True, + # srv_file, srv_content, utype, location, preference + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File1_lowPref", File1_lowPref, "http", None, 25], + ["File1", File1, "http", None, 30]], + ["File2", XmlName + ".#2", File2, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File2_lowPref", File2_lowPref, "http", None, 25], + ["File2", File2, "http", None, 30]], + ["File3", XmlName + ".#3", File3, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File3_lowPref", File3_lowPref, "http", None, 25], + ["File3", File3, "http", None, 30]], + ["File4", XmlName + ".#4", File4, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File4_lowPref", File4_lowPref, "http", None, 25], + ["File4", File4, "http", None, 30]], + ["File5", XmlName + ".#5", File5, None, True, + ["wrong_file", wrong_file, "http", None, 35], + ["404", None, "http", None, 40], + ["File5_lowPref", File5_lowPref, "http", None, 25], + ["File5", File5, "http", None, 30]], +) + +Meta.print_meta () + +err = Meta.http_test ( + "--input-metalink " + XmlName, 0 +) + +exit (err) diff --git a/testenv/Test-missing-scheme-retval.py b/testenv/Test-missing-scheme-retval.py new file mode 100755 index 0000000..dca3a72 --- /dev/null +++ b/testenv/Test-missing-scheme-retval.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget complains about missing scheme +""" +############# File Definitions ############################################### +A_File = WgetFile ("bar", 'Content') + +# put the URL into 'options' to avoid prepending scheme/localhost/port +WGET_OPTIONS = "/foo/bar" +WGET_URLS = [[]] + +Files = [[A_File]] + +ExpectedReturnCode = 1 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, +).begin () + +exit (err) diff --git a/testenv/Test-no_proxy-env.py b/testenv/Test-no_proxy-env.py new file mode 100755 index 0000000..beec72e --- /dev/null +++ b/testenv/Test-no_proxy-env.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +import socket +from sys import exit +from test.http_test import HTTPTest +from test.base_test import SKIP_TEST +from test.base_test import HTTP +from misc.wget_file import WgetFile + +""" + This test ensures, that domains with and without leftmost dot defined in + no_proxy environment variable are accepted by wget. The idea is to use + non-existing proxy server address and detect whether files are downloaded + when proxy settings are omitted based on no_proxy environment variable + value. + + current wget's behavior: + - "no_proxy=.mit.edu" + - will match the domain and subdomains e.g. "www.mit.edu" or "www.subdomain.mit.edu" (Case #4) + - will NOT match the host "mit.edu" (Case #3) + - "no_proxy=mit.edu" + - will match the domain and subdomains e.g. "www.mit.edu" or "www.subdomain.mit.edu" (Case #2) + - will match the host "mit.edu" (Case #1) + - downside: can not match only the host +""" + +# Check whether the system supports translating localhost subdomains +# to localhost address and if not, skip it. +hostnames_to_check = [ + "working1.localhost", + "working2.localhost", + "www.working1.localhost", + "www.working2.localhost", +] +for hostname in hostnames_to_check: + try: + ip = socket.gethostbyname(hostname) + except socket.gaierror as _: + # resolution of the name fails + # return value 77 -> SKIP + exit(SKIP_TEST) + +# File Definitions +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) + +WGET_URLS = [["File1", "File2"]] +WGET_ENVS = { + "http_proxy": "nonexisting.localhost:8080", + "no_proxy": "working1.localhost,.working2.localhost" +} + +Servers = [HTTP] +Files = [[A_File, B_File]] + +ExpectedReturnCodeWorking = 0 +ExpectedReturnCodeNotWorking = 4 # network error (non-existing proxy address) + +ExpectedDownloadedFilesWorking = [A_File, B_File] + +# Pre and Post Test Hooks +test_options = { + "Urls" : WGET_URLS, + "EnvironmentVariables": WGET_ENVS +} +post_test_working = { + "ExpectedFiles" : ExpectedDownloadedFilesWorking, + "ExpectedRetcode" : ExpectedReturnCodeWorking +} +post_test_not_working = { + "ExpectedRetcode" : ExpectedReturnCodeNotWorking +} + +# Case #1: +# - Requested domain matches exactly the domain definition in no_proxy. +# - Domain definition in no_proxy is NOT dot-prefixed +# Expected result: proxy settings don't apply and files are downloaded. +pre_case_1 = { + "ServerFiles" : Files, + "Domains" : ["working1.localhost"] +} + +err_case_1 = HTTPTest ( + pre_hook=pre_case_1, + test_params=test_options, + post_hook=post_test_working, + protocols=Servers +).begin () + +# Case #2: +# - Requested domain is sub-domain of a domain definition in no_proxy. +# - Domain definition in no_proxy is NOT dot-prefixed +# Expected result: proxy settings don't apply and files are downloaded. +pre_case_2 = { + "ServerFiles" : Files, + "Domains" : ["www.working1.localhost"] +} + +err_case_2 = HTTPTest ( + pre_hook=pre_case_2, + test_params=test_options, + post_hook=post_test_working, + protocols=Servers +).begin () + +# Case #3: +# - Requested domain matches exactly the domain definition in no_proxy, +# except for the leftmost dot (".") in no_proxy domain definition. +# - Domain definition in no_proxy IS dot-prefixed +# Expected result: proxy settings apply and files are downloaded. This is +# due to the mismatch in leftmost dot. +# NOTE: This is inconsistent with curl's behavior, but has less drawbacks. +pre_case_3 = { + "ServerFiles" : Files, + "Domains" : ["working2.localhost"] +} + +err_case_3 = HTTPTest ( + pre_hook=pre_case_3, + test_params=test_options, + post_hook=post_test_not_working, + protocols=Servers +).begin () + +# Case #4: +# - Requested domain is sub-domain of a domain definition in no_proxy. +# - Domain definition in no_proxy IS dot-prefixed +# Expected result: proxy settings don't apply and files are downloaded. +pre_case_4 = { + "ServerFiles" : Files, + "Domains" : ["www.working2.localhost"] +} + +err_case_4 = HTTPTest ( + pre_hook=pre_case_4, + test_params=test_options, + post_hook=post_test_working, + protocols=Servers +).begin () + +# Case #5 +# - Requested domain does not match a domain definition in no_proxy. +# - Requested domain is NOT sub-domain of a domain definition in no_proxy. +# Expected result: proxy settings apply and files are NOT downloaded due to +# network error when using proxy with non-existing URL. +pre_case_5 = { + "ServerFiles" : Files, + "Domains" : ["www.example.localhost"] +} + +err_case_5 = HTTPTest ( + pre_hook=pre_case_5, + test_params=test_options, + post_hook=post_test_not_working, + protocols=Servers +).begin () + +# Combine error codes from all test cases +exit (max(err_case_1, err_case_2, err_case_3, err_case_4, err_case_5)) diff --git a/testenv/Test-pinnedpubkey-der-https.py b/testenv/Test-pinnedpubkey-der-https.py new file mode 100755 index 0000000..1e55d68 --- /dev/null +++ b/testenv/Test-pinnedpubkey-der-https.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) +C_File = WgetFile ("File3", File3) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +PINNEDPUBKEY = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'server-pubkey.der')) +WGET_OPTIONS = "--pinnedpubkey=" + PINNEDPUBKEY + " --ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +Servers = [HTTPS] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-pinnedpubkey-der-no-check-https.py b/testenv/Test-pinnedpubkey-der-no-check-https.py new file mode 100755 index 0000000..44a7098 --- /dev/null +++ b/testenv/Test-pinnedpubkey-der-no-check-https.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) +C_File = WgetFile ("File3", File3) + +PINNEDPUBKEY = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'server-pubkey.der')) +WGET_OPTIONS = "--no-check-certificate --pinnedpubkey=" + PINNEDPUBKEY +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +Servers = [HTTPS] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-pinnedpubkey-hash-https.py b/testenv/Test-pinnedpubkey-hash-https.py new file mode 100755 index 0000000..5cdc987 --- /dev/null +++ b/testenv/Test-pinnedpubkey-hash-https.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) +C_File = WgetFile ("File3", File3) + +CERTDIR = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs')) +CAFILE = CERTDIR + '/ca-cert.pem' +KEYFILE = CERTDIR + '/server-pubkey-sha256.base64' +with open(KEYFILE, 'r') as f: + KEY = f.read().replace('\n', '') +WGET_OPTIONS = "--pinnedpubkey=sha256//" + KEY + " --ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +Servers = [HTTPS] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-pinnedpubkey-hash-no-check-fail-https.py b/testenv/Test-pinnedpubkey-hash-no-check-fail-https.py new file mode 100755 index 0000000..5203039 --- /dev/null +++ b/testenv/Test-pinnedpubkey-hash-no-check-fail-https.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) + +WGET_OPTIONS = "--no-check-certificate --pinnedpubkey=sha256//invalid" +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +Servers = [HTTPS] + +ExpectedReturnCode = 5 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-pinnedpubkey-pem-fail-https.py b/testenv/Test-pinnedpubkey-pem-fail-https.py new file mode 100755 index 0000000..c6f7f1e --- /dev/null +++ b/testenv/Test-pinnedpubkey-pem-fail-https.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +PINNEDPUBKEY = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-key.pem')) +WGET_OPTIONS = "--pinnedpubkey=" + PINNEDPUBKEY + " --ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] + +Servers = [HTTPS] + +ExpectedReturnCode = 5 +ExpectedDownloadedFiles = [] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-pinnedpubkey-pem-https.py b/testenv/Test-pinnedpubkey-pem-https.py new file mode 100755 index 0000000..dcc0c55 --- /dev/null +++ b/testenv/Test-pinnedpubkey-pem-https.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTPS, SKIP_TEST +from misc.wget_file import WgetFile +import os + +""" + This test ensures that Wget can download files from HTTPS Servers +""" +if os.getenv('SSL_TESTS') is None: + exit (SKIP_TEST) + +############# File Definitions ############################################### +File1 = "Would you like some Tea?" +File2 = "With lemon or cream?" +File3 = "Sure you're joking Mr. Feynman" + +A_File = WgetFile ("File1", File1) +B_File = WgetFile ("File2", File2) +C_File = WgetFile ("File3", File3) + +CAFILE = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'ca-cert.pem')) +PINNEDPUBKEY = os.path.abspath(os.path.join(os.getenv('srcdir', '.'), 'certs', 'server-pubkey.pem')) +WGET_OPTIONS = "--pinnedpubkey=" + PINNEDPUBKEY + " --ca-certificate=" + CAFILE +WGET_URLS = [["File1", "File2"]] + +Files = [[A_File, B_File]] +Existing_Files = [C_File] + +Servers = [HTTPS] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [A_File, B_File, C_File] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-recursive-basic.py b/testenv/Test-recursive-basic.py new file mode 100755 index 0000000..6fb2f5e --- /dev/null +++ b/testenv/Test-recursive-basic.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP, HTTPS +from misc.wget_file import WgetFile + +""" + Basic test of --recursive. +""" +############# File Definitions ############################################### +File1 = """<html><body> +<a href=\"/a/File2.html\">text</a> +<a href=\"/b/File3.html\">text</a> +</body></html>""" +File2 = "With lemon or cream?" +File3 = "Surely you're joking Mr. Feynman" + +File1_File = WgetFile ("a/File1.html", File1) +File2_File = WgetFile ("a/File2.html", File2) +File3_File = WgetFile ("b/File3.html", File3) + +WGET_OPTIONS = "--recursive --no-host-directories" +WGET_URLS = [["a/File1.html"]] + +Servers = [HTTP] + +Files = [[File1_File, File2_File, File3_File]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [File1_File, File2_File, File3_File] +Request_List = [["GET /a/File1.html", + "GET /robots.txt", + "GET /a/File2.html", + "GET /b/File3.html"]] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : Request_List +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-recursive-include.py b/testenv/Test-recursive-include.py new file mode 100755 index 0000000..1fe33cd --- /dev/null +++ b/testenv/Test-recursive-include.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP, HTTPS +from misc.wget_file import WgetFile + +""" + Basic test of --recursive. +""" +############# File Definitions ############################################### +File1 = """<html><body> +<a href=\"/a/File2.html\">text</a> +<a href=\"/b/File3.html\">text</a> +</body></html>""" +File2 = "With lemon or cream?" +File3 = "Surely you're joking Mr. Feynman" + +File1_File = WgetFile ("a/File1.html", File1) +File2_File = WgetFile ("a/File2.html", File2) +File3_File = WgetFile ("b/File3.html", File3) + +WGET_OPTIONS = "--recursive --no-host-directories --include-directories=a" +WGET_URLS = [["a/File1.html"]] + +Servers = [HTTP] + +Files = [[File1_File, File2_File, File3_File]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [File1_File, File2_File] +Request_List = [["GET /a/File1.html", + "GET /a/File2.html"]] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-recursive-redirect.py b/testenv/Test-recursive-redirect.py new file mode 100644 index 0000000..8a114a5 --- /dev/null +++ b/testenv/Test-recursive-redirect.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP, HTTPS +from misc.wget_file import WgetFile + +""" + Basic test of --recursive. +""" +############# File Definitions ############################################### +File1 = """<html><body> +<a href=\"/a/File2.html\">text</a> +<a href=\"/b/File3.html\">text</a> +</body></html>""" +File2 = "With lemon or cream?" +File3 = "Surely you're joking Mr. Feynman" + +File1_rules = { + "Response" : 301, + "SendHeader" : {"Location" : "/b/File1.html"} +} + +File1_File = WgetFile ("a/File1.html", "", rules=File1_rules) +File1_Redirected = WgetFile ("b/File1.html", File1) +File1_Retrieved = WgetFile ("a/File1.html", File1) +File2_File = WgetFile ("a/File2.html", File2) +File3_File = WgetFile ("b/File3.html", File3) + +WGET_OPTIONS = "--recursive --no-host-directories --include-directories=a" +WGET_URLS = [["a/File1.html"]] + +Servers = [HTTP] + +Files = [[File1_Redirected, File1_File, File2_File, File3_File]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [File1_Retrieved, File2_File] +Request_List = [["GET /a/File1.html", + "GET /a/File2.html", + "GET /b/File3.html"]] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-redirect-crash.py b/testenv/Test-redirect-crash.py new file mode 100755 index 0000000..1f5bb0d --- /dev/null +++ b/testenv/Test-redirect-crash.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import os + +# This test caused wget up to 1.16 to crash +#os.environ["LC_ALL"] = "en_US.UTF-8" + +urls = [ + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory", + "File formats/Images/SVG, Scalable Vector Graphics/html, W3C v1.2 rec (tiny)/directory/", + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/somefile.rng", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2c%20W3C%20v1.2%20rec%20%28tiny%29/directory/somefile.rng", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2c%20W3C%20v1.2%20rec%20%28tiny%29/directory/", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2C%20W3C%20v1.2%20rec%20%28tiny%29/directory"] + + +redirected = [ + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/" +] + +############# File Definitions ############################################### +Index = "" +for i in urls: + Index = Index + "<a href='/%s'></a>" % i + +File1 = "" + +def get_redirect(url): + data = { + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory" : + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/", + "File%20formats/Images/SVG%2C%20Scalable%20Vector%20Graphics/html%2C%20W3C%20v1.2%20rec%20%28tiny%29/directory" : + "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/directory/" + } + dest = data.get(url) + if dest: + return {"Response" : 301, + "SendHeader" : {"Location" : "/%s" % dest}} + return None + + +index_url = "File%20formats/Images/SVG,%20Scalable%20Vector%20Graphics/html,%20W3C%20v1.2%20rec%20(tiny)/index.html" +Index_File = WgetFile (index_url, Index) +Files = ([Index_File] + [WgetFile(i, File1, rules=get_redirect(i)) for i in (redirected + urls)]) + +WGET_OPTIONS = "--recursive -e robots=off" + +WGET_URLS = [[index_url]] + +ExpectedReturnCode = 0 + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : [Files] +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedRetcode" : ExpectedReturnCode, +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/Test-redirect.py b/testenv/Test-redirect.py new file mode 100755 index 0000000..02adf52 --- /dev/null +++ b/testenv/Test-redirect.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from test.http_test import HTTPTest +from test.base_test import HTTP, HTTPS +from misc.wget_file import WgetFile + +""" + This is a Prototype Test File. + Ideally this File should be copied and edited to write new tests. +""" +############# File Definitions ############################################### +File2 = "Would you like some Tea?" + +File1_rules = { + "Response" : 301, + "SendHeader" : {"Location" : "/File2.txt"} +} + +# /File1.txt is only a redirect, and so has no file content. +File1_File = WgetFile ("File1.txt", "", rules=File1_rules) +# File1_Retrieved is what will be retrieved for URL /File1.txt. +File1_Retrieved = WgetFile ("File1.txt", File2) +File2_File = WgetFile ("File2.txt", File2) + +WGET_OPTIONS = "" +WGET_URLS = [["File1.txt"]] + +Servers = [HTTP] + +Files = [[File1_File, File2_File]] +Existing_Files = [] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [File1_Retrieved] + +################ Pre and Post Test Hooks ##################################### +pre_test = { + "ServerFiles" : Files, + "LocalFiles" : Existing_Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + protocols=Servers +).begin () + +exit (err) diff --git a/testenv/Test-reserved-chars.py b/testenv/Test-reserved-chars.py new file mode 100755 index 0000000..fb617f5 --- /dev/null +++ b/testenv/Test-reserved-chars.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +from sys import exit +from os import environ # to set LC_ALL +from test.http_test import HTTPTest +from misc.wget_file import WgetFile + +""" +This test ensures that Wget keeps reserved characters in URLs in non-UTF-8 charsets. +""" +# This bug only happened with ASCII charset, +# so we need to set LC_ALL="C" in order to reproduce it. +environ["LC_ALL"] = "C" + +######### File Definitions ######### +RequestList = [ + [ + "HEAD /base.html", + "GET /base.html", + "GET /robots.txt", + "HEAD /a%2Bb.html", + "GET /a%2Bb.html" + ] +] +A_File_Name = "base.html" +B_File_Name = "a%2Bb.html" +A_File = WgetFile (A_File_Name, "<a href=\"a%2Bb.html\">") +B_File = WgetFile (B_File_Name, "this is file B") + +WGET_OPTIONS = " --spider -r" +WGET_URLS = [[A_File_Name]] + +Files = [[A_File, B_File]] + +ExpectedReturnCode = 0 +ExpectedDownloadedFiles = [] + +######### Pre and Post Test Hooks ######### +pre_test = { + "ServerFiles" : Files +} +test_options = { + "WgetCommands" : WGET_OPTIONS, + "Urls" : WGET_URLS +} +post_test = { + "ExpectedFiles" : ExpectedDownloadedFiles, + "ExpectedRetcode" : ExpectedReturnCode, + "FilesCrawled" : RequestList +} + +err = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test +).begin () + +exit (err) diff --git a/testenv/certs/README b/testenv/certs/README new file mode 100644 index 0000000..2aabd3f --- /dev/null +++ b/testenv/certs/README @@ -0,0 +1,87 @@ +To create the server RSA private key: +$ certtool --generate-privkey --outfile server-key.pem --rsa + + +To create a self signed CA certificate: +$ certtool --generate-privkey --outfile ca-key.pem +$ certtool --generate-self-signed --load-privkey ca-key.pem --outfile ca-cert.pem +Common name: GNU Wget +UID: +Organizational unit name: Wget +Organization name: GNU +Locality name: +State or province name: +Country name (2 chars): +Enter the subject's domain component (DC): +This field should not be used in new certificates. +E-mail: +Enter the certificate's serial number in decimal (default: 6080487640893163573): + +Activation/Expiration time. +The certificate will expire in (days): -1 + +Extensions. +Does the certificate belong to an authority? (y/N): y +Path length constraint (decimal, -1 for no constraint): +Is this a TLS web client certificate? (y/N): +Will the certificate be used for IPsec IKE operations? (y/N): +Is this a TLS web server certificate? (y/N): +Enter a dnsName of the subject of the certificate: +Enter a URI of the subject of the certificate: +Enter the IP address of the subject of the certificate: +Enter the e-mail of the subject of the certificate: +Will the certificate be used to sign OCSP requests? (y/N): +Will the certificate be used to sign code? (y/N): +Will the certificate be used for time stamping? (y/N): +Will the certificate be used to sign other certificates? (y/N): y +Will the certificate be used to sign CRLs? (y/N): y +Enter the URI of the CRL distribution point: + + +To generate a server certificate using the private key only: +$ certtool --generate-certificate --load-privkey server-key.pem --outfile server-cert.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem +Common name: 127.0.0.1 +UID: +Organizational unit name: Wget +Organization name: GNU +Locality name: +State or province name: +Country name (2 chars): +Enter the subject's domain component (DC): +This field should not be used in new certificates. +E-mail: +Enter the certificate's serial number in decimal (default: 6080488276853553635): + +Activation/Expiration time. +The certificate will expire in (days): -1 + +Extensions. +Does the certificate belong to an authority? (y/N): +Is this a TLS web client certificate? (y/N): +Will the certificate be used for IPsec IKE operations? (y/N): +Is this a TLS web server certificate? (y/N): y +Enter a dnsName of the subject of the certificate: 127.0.0.1 +Enter a dnsName of the subject of the certificate: localhost +Enter a dnsName of the subject of the certificate: +Enter a URI of the subject of the certificate: +Enter the IP address of the subject of the certificate: +Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): +Will the certificate be used for encryption (RSA ciphersuites)? (Y/n): + + +To create a CRL for the server certificate: +$ certtool --generate-crl --load-ca-privkey ca-key.pem --load-ca-certificate ca-cert.pem --load-certificate server-cert.pem --outfile server-crl.pem +Generating a signed CRL... +Update times. +The certificate will expire in (days): -1 +CRL Number (default: 6080006793650397145): + +To generate a public key in PEM format: +$ openssl x509 -noout -pubkey < server-cert.pem > server-pubkey.pem + +To generate a public key in DER format: +$ openssl x509 -noout -pubkey < server-cert.pem | openssl asn1parse -noout -inform pem -out server-pubkey.der + +To generate a sha256 hash of the public key: +$ openssl x509 -noout -pubkey < server-cert.pem | openssl asn1parse -noout -inform pem -out /dev/stdout | openssl dgst -sha256 -binary | openssl base64 +mHiEhWHvusnzP7COZk+SzSJ+Gl7nZT+ADx0PUnDD7mM= diff --git a/testenv/certs/ca-cert.pem b/testenv/certs/ca-cert.pem new file mode 100644 index 0000000..2c06476 --- /dev/null +++ b/testenv/certs/ca-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDJzCCAg+gAwIBAgIIWRQ9uws3g5owDQYJKoZIhvcNAQELBQAwMDERMA8GA1UE +AxMIR05VIFdnZXQxDTALBgNVBAsTBFdnZXQxDDAKBgNVBAoTA0dOVTAgFw0xNzA1 +MTExMDMyMzdaGA85OTk5MTIzMTIzNTk1OVowMDERMA8GA1UEAxMIR05VIFdnZXQx +DTALBgNVBAsTBFdnZXQxDDAKBgNVBAoTA0dOVTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAL9iEdf4LGibJ/noLVRWzDDG4ryvnlcz2PMBF29n5aXvWipM +M/NuJ0kq1n0YoEJn/zg5DZStsfdZKaXz5lpApVEREAdyOHf7BxZ86gpBSpjcLVU+ +A7C+O1bpoGRemY0qk2EA9zAx91YRY9Yiq0TDP2gmV8J7Q/uu7CsOlD13xW31DkXn +KW+3wmT2RVRWErcYHBe3Mh/gwAy1+UAhI4i2B9XrOhV63cPsqYMAZfh7i5EP+IBN +CS0CuTwCkmHi8tCRAVD6L5DF0/q/Wj5EARf/Vg+rlD4mtBER2zCE9DMvOIQaxvXe +buYFz5x9WcSiK/IiTmAsnVY2J3Z9tc7NiBMcC+sCAwEAAaNDMEEwDwYDVR0TAQH/ +BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBTzPk44hEqpvsFvx2Gj +UNpuKYvrVDANBgkqhkiG9w0BAQsFAAOCAQEAAsAugT64gwFMMtwDJo5r3/f9sMPA +lWi1N7Nz8LjBa6Vqrk/3No3Fxxidb3IMO5RGecgZdGV/CL5lG7yjzgVB2ADx+68K +TmcNEO4CDja5vDyRpG7NPGmhtc48iiOsnEhhWCw084S2rUKf7hAX3+yKg63Uwuik +C0xHT6HwbrWcmWFQAQOqucPWEwzGRMjqn++3cHAG8XlNSL8tWIr7NmTKr7yufLPC +HcDAVgJsBHTOWgs/Casq4EovO83hgustD6rAWJOf89DP6bB2yOPEHKVq6cBsuGDM +F+V2Cr2ytyGPHrOCfH3IzCpQ45cxZX4TaJ7tgV9x7WlMLoNaZgo1ijsKOw== +-----END CERTIFICATE----- diff --git a/testenv/certs/ca-key.pem b/testenv/certs/ca-key.pem new file mode 100644 index 0000000..ac51f60 --- /dev/null +++ b/testenv/certs/ca-key.pem @@ -0,0 +1,144 @@ +Public Key Info: + Public Key Algorithm: RSA + Key Security Level: Medium (2048 bits) + +modulus: + 00:bf:62:11:d7:f8:2c:68:9b:27:f9:e8:2d:54:56: + cc:30:c6:e2:bc:af:9e:57:33:d8:f3:01:17:6f:67: + e5:a5:ef:5a:2a:4c:33:f3:6e:27:49:2a:d6:7d:18: + a0:42:67:ff:38:39:0d:94:ad:b1:f7:59:29:a5:f3: + e6:5a:40:a5:51:11:10:07:72:38:77:fb:07:16:7c: + ea:0a:41:4a:98:dc:2d:55:3e:03:b0:be:3b:56:e9: + a0:64:5e:99:8d:2a:93:61:00:f7:30:31:f7:56:11: + 63:d6:22:ab:44:c3:3f:68:26:57:c2:7b:43:fb:ae: + ec:2b:0e:94:3d:77:c5:6d:f5:0e:45:e7:29:6f:b7: + c2:64:f6:45:54:56:12:b7:18:1c:17:b7:32:1f:e0: + c0:0c:b5:f9:40:21:23:88:b6:07:d5:eb:3a:15:7a: + dd:c3:ec:a9:83:00:65:f8:7b:8b:91:0f:f8:80:4d: + 09:2d:02:b9:3c:02:92:61:e2:f2:d0:91:01:50:fa: + 2f:90:c5:d3:fa:bf:5a:3e:44:01:17:ff:56:0f:ab: + 94:3e:26:b4:11:11:db:30:84:f4:33:2f:38:84:1a: + c6:f5:de:6e:e6:05:cf:9c:7d:59:c4:a2:2b:f2:22: + 4e:60:2c:9d:56:36:27:76:7d:b5:ce:cd:88:13:1c: + 0b:eb: + +public exponent: + 01:00:01: + +private exponent: + 45:0c:7f:fd:98:a7:85:12:3d:a9:17:90:8b:36:49: + b3:6b:7e:50:af:58:04:84:4b:48:d9:62:f8:29:d7: + 1c:38:30:22:c4:9d:95:bd:6f:65:21:94:83:4b:c8: + 3e:4d:41:32:aa:ba:f0:a2:7e:6c:0c:7a:4f:4a:a1: + 18:7c:ec:68:44:2c:b1:53:0f:76:92:56:2b:51:e4: + 2a:d1:05:b6:02:f2:44:27:fc:b2:de:df:8f:ea:f8: + 98:5d:dd:2e:a6:66:c7:ff:ce:2f:50:47:b9:80:ca: + b1:6e:8e:b6:5f:6f:58:07:45:70:80:82:b5:a2:95: + c8:af:18:e2:d8:7c:9d:bf:c5:a9:da:4f:af:08:37: + 92:27:94:12:c0:94:70:90:ff:e4:05:8b:ed:18:a9: + 19:3c:47:3a:7c:fe:4f:9c:15:ab:f6:7e:48:2a:58: + d7:14:67:96:bd:e6:fa:9f:3a:51:0c:63:49:14:d5: + 9d:e9:a8:24:19:2a:83:e4:fe:e2:ec:db:f9:13:33: + a6:d3:62:d2:6b:7e:a9:5b:93:73:f5:c9:d0:ad:58: + 11:cb:77:d3:13:3c:bf:37:f9:64:95:c7:4c:69:f2: + 6e:b8:36:69:57:93:4a:03:06:58:8a:51:3d:d6:97: + 61:2f:7c:76:33:14:88:51:45:68:4e:29:fe:12:43: + 69: + +prime1: + 00:e0:e6:81:38:18:3e:c8:98:51:71:2d:5f:22:8c: + 93:95:37:17:47:00:4f:6a:87:98:73:8d:f3:c3:02: + f7:e1:9d:a0:5c:a5:10:a6:0d:88:5d:e0:72:10:93: + 24:af:6e:a4:0e:55:5c:03:37:5f:1d:90:41:c2:d6: + e3:a6:ba:20:08:0b:01:31:eb:fc:7e:97:66:3c:fe: + b5:ab:4c:0b:2f:18:16:f3:28:47:70:41:dc:cf:04: + 9c:7e:28:78:3b:3f:31:cf:b1:77:2c:6d:c9:bf:ad: + 19:ff:03:1f:c6:98:9a:60:47:a5:1d:c4:52:c5:9e: + 77:5a:cc:a4:e3:96:81:d4:4d: + +prime2: + 00:d9:d9:0c:6e:81:bb:0e:5d:c6:92:cc:48:70:b8: + da:60:e8:56:e7:2a:20:da:29:0f:c9:f0:9f:b8:9f: + df:d9:a1:68:7e:ce:3e:7c:f2:00:66:68:79:c4:01: + fa:b9:71:3e:73:06:3f:85:5c:83:33:ee:58:77:50: + 89:aa:90:33:d0:6c:aa:6f:34:b2:30:8b:e9:a9:82: + df:e2:7f:04:09:9f:14:9a:db:c7:cb:e5:85:46:b2: + 42:d0:a7:fe:7a:e3:ff:1e:84:9c:36:50:e3:de:fb: + 11:1c:34:09:fe:46:db:45:c3:50:19:f1:25:c0:e3: + 5c:d5:0d:88:13:e1:9a:5d:17: + +coefficient: + 00:ca:79:cb:79:87:91:9f:9a:99:0b:5d:c5:78:21: + a7:60:c6:8a:2d:a5:b5:87:a2:d6:df:b0:17:5f:bf: + e1:ce:f0:ca:89:18:0e:e0:4a:7f:00:e5:41:2d:04: + 5b:05:51:e5:08:89:dd:80:82:c7:94:94:1c:f4:0f: + 1b:9a:d0:72:83:bb:e9:ca:d5:09:0d:4b:c0:b7:6a: + a7:b4:c3:df:4e:f1:7f:0f:57:ad:25:ff:e4:d3:ef: + 05:95:31:ca:00:54:97:4b:2d:56:aa:1a:89:d8:a0: + d6:dc:64:88:88:36:26:92:39:57:8b:da:18:23:77: + c3:e3:39:0e:95:f7:3c:77:fe: + +exp1: + 00:99:f2:8f:4f:93:a1:1e:74:cd:82:f8:78:df:d0: + 74:91:b6:a5:53:6f:cd:ec:f1:26:95:2a:fd:4a:67: + 34:c1:16:c2:17:c8:d1:ed:a8:e3:c8:c7:03:ad:7e: + db:a4:ce:ca:b4:19:10:24:0f:7a:27:65:80:ee:5b: + 64:77:d3:7e:6b:a3:04:cd:64:69:71:4a:37:ac:d6: + fa:0a:68:c2:5b:19:55:54:5b:25:13:9d:b2:05:6f: + 75:a4:12:15:c3:10:8e:0b:4a:c2:76:02:2d:10:ec: + f0:17:94:ce:e2:85:c1:5e:d8:8c:19:25:33:37:9d: + 32:bc:4f:cb:2b:12:f2:8a:1d: + +exp2: + 3e:53:68:c9:1c:f8:a5:6d:92:e8:60:e5:c0:ca:42: + 40:43:78:c9:7e:36:13:f4:77:7d:f1:07:e1:4c:6c: + 40:d9:7b:09:fc:7b:c8:47:7c:71:d0:26:36:3b:d2: + bd:c7:76:74:76:2f:2a:3a:83:97:11:f3:e1:7e:fb: + 43:ff:29:b3:d1:c3:19:39:dc:59:23:4e:60:9e:fe: + ea:d0:28:19:90:97:d6:8e:56:a5:31:2f:66:40:8d: + f9:20:77:20:35:a6:c1:d6:72:d2:df:65:b2:5f:e6: + 4f:49:5c:2a:91:9f:1e:60:78:c4:53:47:d7:dd:b4: + ab:87:c9:8c:d6:98:d1:55: + + +Public Key ID: F3:3E:4E:38:84:4A:A9:BE:C1:6F:C7:61:A3:50:DA:6E:29:8B:EB:54 +Public key's random art: ++--[ RSA 2048]----+ +| | +| | +| | +| .. . | +| Eo . S | +| .+o..+. + | +| .+o.= oo o | +|.o.o* o +. | +|+o+*.. .o. | ++-----------------+ + +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAv2IR1/gsaJsn+egtVFbMMMbivK+eVzPY8wEXb2flpe9aKkwz +824nSSrWfRigQmf/ODkNlK2x91kppfPmWkClUREQB3I4d/sHFnzqCkFKmNwtVT4D +sL47VumgZF6ZjSqTYQD3MDH3VhFj1iKrRMM/aCZXwntD+67sKw6UPXfFbfUORecp +b7fCZPZFVFYStxgcF7cyH+DADLX5QCEjiLYH1es6FXrdw+ypgwBl+HuLkQ/4gE0J +LQK5PAKSYeLy0JEBUPovkMXT+r9aPkQBF/9WD6uUPia0ERHbMIT0My84hBrG9d5u +5gXPnH1ZxKIr8iJOYCydVjYndn21zs2IExwL6wIDAQABAoIBAEUMf/2Yp4USPakX +kIs2SbNrflCvWASES0jZYvgp1xw4MCLEnZW9b2UhlINLyD5NQTKquvCifmwMek9K +oRh87GhELLFTD3aSVitR5CrRBbYC8kQn/LLe34/q+Jhd3S6mZsf/zi9QR7mAyrFu +jrZfb1gHRXCAgrWilcivGOLYfJ2/xanaT68IN5InlBLAlHCQ/+QFi+0YqRk8Rzp8 +/k+cFav2fkgqWNcUZ5a95vqfOlEMY0kU1Z3pqCQZKoPk/uLs2/kTM6bTYtJrfqlb +k3P1ydCtWBHLd9MTPL83+WSVx0xp8m64NmlXk0oDBliKUT3Wl2EvfHYzFIhRRWhO +Kf4SQ2kCgYEA4OaBOBg+yJhRcS1fIoyTlTcXRwBPaoeYc43zwwL34Z2gXKUQpg2I +XeByEJMkr26kDlVcAzdfHZBBwtbjprogCAsBMev8fpdmPP61q0wLLxgW8yhHcEHc +zwScfih4Oz8xz7F3LG3Jv60Z/wMfxpiaYEelHcRSxZ53Wsyk45aB1E0CgYEA2dkM +boG7Dl3GksxIcLjaYOhW5yog2ikPyfCfuJ/f2aFofs4+fPIAZmh5xAH6uXE+cwY/ +hVyDM+5Yd1CJqpAz0GyqbzSyMIvpqYLf4n8ECZ8UmtvHy+WFRrJC0Kf+euP/HoSc +NlDj3vsRHDQJ/kbbRcNQGfElwONc1Q2IE+GaXRcCgYEAmfKPT5OhHnTNgvh439B0 +kbalU2/N7PEmlSr9Smc0wRbCF8jR7ajjyMcDrX7bpM7KtBkQJA96J2WA7ltkd9N+ +a6MEzWRpcUo3rNb6CmjCWxlVVFslE52yBW91pBIVwxCOC0rCdgItEOzwF5TO4oXB +XtiMGSUzN50yvE/LKxLyih0CgYA+U2jJHPilbZLoYOXAykJAQ3jJfjYT9Hd98Qfh +TGxA2XsJ/HvIR3xx0CY2O9K9x3Z0di8qOoOXEfPhfvtD/ymz0cMZOdxZI05gnv7q +0CgZkJfWjlalMS9mQI35IHcgNabB1nLS32WyX+ZPSVwqkZ8eYHjEU0fX3bSrh8mM +1pjRVQKBgQDKect5h5GfmpkLXcV4IadgxootpbWHotbfsBdfv+HO8MqJGA7gSn8A +5UEtBFsFUeUIid2AgseUlBz0Dxua0HKDu+nK1QkNS8C3aqe0w99O8X8PV60l/+TT +7wWVMcoAVJdLLVaqGonYoNbcZIiINiaSOVeL2hgjd8PjOQ6V9zx3/g== +-----END RSA PRIVATE KEY----- diff --git a/testenv/certs/ca-template.cfg b/testenv/certs/ca-template.cfg new file mode 100644 index 0000000..087cd70 --- /dev/null +++ b/testenv/certs/ca-template.cfg @@ -0,0 +1,246 @@ +# X.509 Certificate options +# +# DN options + +# The organization of the subject. +organization = "GNU" + +# The organizational unit of the subject. +unit = "Wget" + +# The locality of the subject. +# locality = + +# The state of the certificate owner. +# state = "" + +# The country of the subject. Two letter code. +# country = GR + +# The common name of the certificate owner. +cn = "GNU Wget" + +# A user id of the certificate owner. +#uid = "" + +# Set domain components +#dc = "name" +#dc = "domain" + +# If the supported DN OIDs are not adequate you can set +# any OID here. +# For example set the X.520 Title and the X.520 Pseudonym +# by using OID and string pairs. +#dn_oid = 2.5.4.12 Dr. +#dn_oid = 2.5.4.65 jackal + +# This is deprecated and should not be used in new +# certificates. +# pkcs9_email = "bug-wget@gnu.org" + +# An alternative way to set the certificate's distinguished name directly +# is with the "dn" option. The attribute names allowed are: +# C (country), street, O (organization), OU (unit), title, CN (common name), +# L (locality), ST (state), placeOfBirth, gender, countryOfCitizenship, +# countryOfResidence, serialNumber, telephoneNumber, surName, initials, +# generationQualifier, givenName, pseudonym, dnQualifier, postalCode, name, +# businessCategory, DC, UID, jurisdictionOfIncorporationLocalityName, +# jurisdictionOfIncorporationStateOrProvinceName, +# jurisdictionOfIncorporationCountryName, XmppAddr, and numeric OIDs. + +#dn = "cn = Nikos,st = New Something,C=GR,surName=Mavrogiannopoulos,2.5.4.9=Arkadias" + +# The serial number of the certificate +# Comment the field for a time-based serial number. +# serial = 007 + +# In how many days, counting from today, this certificate will expire. +# Use -1 if there is no expiration date. +expiration_days = -1 + +# Alternatively you may set concrete dates and time. The GNU date string +# formats are accepted. See: +# http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html + +#activation_date = "2004-02-29 16:21:42" +#expiration_date = "2025-02-29 16:24:41" + +# X.509 v3 extensions + +# A dnsname in case of a WWW server. +#dns_name = "www.none.org" +#dns_name = "www.morethanone.org" + +# A subject alternative name URI +#uri = "http://www.example.com" + +# An IP address in case of a server. +#ip_address = "192.168.1.1" + +# An email in case of a person +# email = "none@none.org" + +# Challenge password used in certificate requests +challenge_password = 123456 + +# Password when encrypting a private key +#password = secret + +# An URL that has CRLs (certificate revocation lists) +# available. Needed in CA certificates. +#crl_dist_points = "http://www.getcrl.crl/getcrl/" + +# Whether this is a CA certificate or not +ca + +# Subject Unique ID (in hex) +#subject_unique_id = 00153224 + +# Issuer Unique ID (in hex) +#issuer_unique_id = 00153225 + +#### Key usage + +# The following key usage flags are used by CAs and end certificates + +# Whether this certificate will be used to sign data (needed +# in TLS DHE ciphersuites). This is the digitalSignature flag +# in RFC5280 terminology. +# signing_key + +# Whether this certificate will be used to encrypt data (needed +# in TLS RSA ciphersuites). Note that it is preferred to use different +# keys for encryption and signing. This is the keyEncipherment flag +# in RFC5280 terminology. +# encryption_key + +# Whether this key will be used to sign other certificates. The +# keyCertSign flag in RFC5280 terminology. +cert_signing_key + +# Whether this key will be used to sign CRLs. The +# cRLSign flag in RFC5280 terminology. +crl_signing_key + +# The keyAgreement flag of RFC5280. It's purpose is loosely +# defined. Not use it unless required by a protocol. +#key_agreement + +# The dataEncipherment flag of RFC5280. It's purpose is loosely +# defined. Not use it unless required by a protocol. +#data_encipherment + +# The nonRepudiation flag of RFC5280. It's purpose is loosely +# defined. Not use it unless required by a protocol. +#non_repudiation + +#### Extended key usage (key purposes) + +# The following extensions are used in an end certificate +# to clarify its purpose. Some CAs also use it to indicate +# the types of certificates they are purposed to sign. + +# Whether this certificate will be used for a TLS client; +# this sets the id-kp-serverAuth (1.3.6.1.5.5.7.3.1) of +# extended key usage. +#tls_www_client + +# Whether this certificate will be used for a TLS server; +# This sets the id-kp-clientAuth (1.3.6.1.5.5.7.3.2) of +# extended key usage. +#tls_www_server + +# Whether this key will be used to sign code. This sets the +# id-kp-codeSigning (1.3.6.1.5.5.7.3.3) of extended key usage +# extension. +#code_signing_key + +# Whether this key will be used to sign OCSP data. This sets the +# id-kp-OCSPSigning (1.3.6.1.5.5.7.3.9) of extended key usage extension. +#ocsp_signing_key + +# Whether this key will be used for time stamping. This sets the +# id-kp-timeStamping (1.3.6.1.5.5.7.3.8) of extended key usage extension. +#time_stamping_key + +# Whether this key will be used for email protection. This sets the +# id-kp-emailProtection (1.3.6.1.5.5.7.3.4) of extended key usage extension. +#email_protection_key + +# Whether this key will be used for IPsec IKE operations (1.3.6.1.5.5.7.3.17). +#ipsec_ike_key + +## adding custom key purpose OIDs + +# for microsoft smart card logon +# key_purpose_oid = 1.3.6.1.4.1.311.20.2.2 + +# for email protection +# key_purpose_oid = 1.3.6.1.5.5.7.3.4 + +# for any purpose (must not be used in intermediate CA certificates) +# key_purpose_oid = 2.5.29.37.0 + +### end of key purpose OIDs + +# When generating a certificate from a certificate +# request, then honor the extensions stored in the request +# and store them in the real certificate. +honor_crq_extensions + +# Path length constraint. Sets the maximum number of +# certificates that can be used to certify this certificate. +# (i.e. the certificate chain length) +#path_len = -1 +#path_len = 2 + +# OCSP URI +# ocsp_uri = http://my.ocsp.server/ocsp + +# CA issuers URI +# ca_issuers_uri = http://my.ca.issuer + +# Certificate policies +#policy1 = 1.3.6.1.4.1.5484.1.10.99.1.0 +#policy1_txt = "This is a long policy to summarize" +#policy1_url = http://www.example.com/a-policy-to-read + +#policy2 = 1.3.6.1.4.1.5484.1.10.99.1.1 +#policy2_txt = "This is a short policy" +#policy2_url = http://www.example.com/another-policy-to-read + +# Name constraints + +# DNS +#nc_permit_dns = example.com +#nc_exclude_dns = test.example.com + +# EMAIL +#nc_permit_email = "nmav@ex.net" + +# Exclude subdomains of example.com +#nc_exclude_email = .example.com + +# Exclude all e-mail addresses of example.com +#nc_exclude_email = example.com + +# Options for proxy certificates +#proxy_policy_language = 1.3.6.1.5.5.7.21.1 + +# Options for generating a CRL + +# The number of days the next CRL update will be due. +# next CRL update will be in 43 days +#crl_next_update = 43 + +# this is the 5th CRL by this CA +# Comment the field for a time-based number. +#crl_number = 5 + +# Specify the update dates more precisely. +#crl_this_update_date = "2004-02-29 16:21:42" +#crl_next_update_date = "2025-02-29 16:24:41" + +# The date that the certificates will be made seen as +# being revoked. +#crl_revocation_date = "2025-02-29 16:24:41" diff --git a/testenv/certs/make_ca.sh b/testenv/certs/make_ca.sh new file mode 100755 index 0000000..f9b5676 --- /dev/null +++ b/testenv/certs/make_ca.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +# create a self signed CA certificate +certtool --generate-privkey --outfile ca-key.pem +certtool --generate-self-signed --load-privkey ca-key.pem --template=ca-template.cfg --outfile ca-cert.pem + +# create the server RSA private key +certtool --generate-privkey --outfile server-key.pem --rsa + +# generate a server certificate using the private key only +certtool --generate-certificate --load-privkey server-key.pem --template=server-template.cfg --outfile server-cert.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem + +# create a CRL for the server certificate +certtool --generate-crl --load-ca-privkey ca-key.pem --load-ca-certificate ca-cert.pem --load-certificate server-cert.pem --outfile server-crl.pem --template=server-template.cfg + +# generate a public key in PEM format +openssl x509 -noout -pubkey < server-cert.pem > server-pubkey.pem + +# generate a public key in DER format +openssl x509 -noout -pubkey < server-cert.pem | openssl asn1parse -noout -inform pem -out server-pubkey.der + +# generate a sha256 hash of the public key +openssl x509 -noout -pubkey < server-cert.pem | openssl asn1parse -noout -inform pem -out /dev/stdout | openssl dgst -sha256 -binary | openssl base64 > server-pubkey-sha256.base64 diff --git a/testenv/certs/server-cert.pem b/testenv/certs/server-cert.pem new file mode 100644 index 0000000..c9f474a --- /dev/null +++ b/testenv/certs/server-cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIMWWD1GB1UFkEICdQvMA0GCSqGSIb3DQEBCwUAMDAxETAP +BgNVBAMTCEdOVSBXZ2V0MQ0wCwYDVQQLEwRXZ2V0MQwwCgYDVQQKEwNHTlUwIBcN +MTcwNzA4MTUwNzA0WhgPOTk5OTEyMzEyMzU5NTlaMDExEjAQBgNVBAMTCTEyNy4w +LjAuMTENMAsGA1UECxMEV2dldDEMMAoGA1UEChMDR05VMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAyMLca3nkR9K2XqYTfvX6kPf9ylHkwvGR1sGyzkyU +g/ZMOGI84i0teaXyjGzgGNSbfB+fcZX2IkuZvNshYv7SRtGRDYsI8pR/4KWffPZk +T6tfB1aVPyBV+/nU6l+SnaUsNVSot80pEZCCK+NIKYupjYup4HRJpU2+5oPcSmpn +IgfQTlJmCOoEeBFG28aRzLSs6anlIjY0BIu6BSKhdr04taOlgPCh2x3cRGUvQMnV +olbxMLxOqLHiLSixbNqv4tcEiKfRC9qv3+5Ec3SnWSrenReA0cqpamJNPnj5ZjHs +96a/ipFfPXWzCInNQv4/DUO6tD2yZvMOACzPtXYUmdR4JwIDAQABo4GNMIGKMAwG +A1UdEwEB/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsG +AQUFBwMBMA8GA1UdDwEB/wQFAwMHoAAwHQYDVR0OBBYEFJfm323LJbKTM/tMKSt0 +qlUqewbnMB8GA1UdIwQYMBaAFPM+TjiESqm+wW/HYaNQ2m4pi+tUMA0GCSqGSIb3 +DQEBCwUAA4IBAQC1a0NQfmqT8Ky/BFo5H+G+GoQTlqi3J83ujAMdLUD57zYCEyDL +XzAhMPfrOSLPDcQb0ooD1Ie+Rz8Xs1h00cD2OGKwH479+nisF5ksqJVJ4fn/aNFE +6W2Xb3MCB+4FRdmy0UeDDA6N2OpVskCM30s9tmovlBLVK46HogdLvy/O1o7z/gbx +vV8luevxobnevZ3NdWLyVE3BJZiThBHmZUvL1XNy4KAR4wDAkbCwoTN/JkehTu0i +WR6DaG7N7M6psc7rctfzRqimlAkxnoAUwc8LwNLTB3v613xXX8iSUsLKsh6pQfZR +e5wnYQIS4MzowvDx8WevTPMRKlN72d8HHuv9 +-----END CERTIFICATE----- diff --git a/testenv/certs/server-crl.pem b/testenv/certs/server-crl.pem new file mode 100644 index 0000000..ca70479 --- /dev/null +++ b/testenv/certs/server-crl.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIB1jCBvwIBATANBgkqhkiG9w0BAQsFADAwMREwDwYDVQQDEwhHTlUgV2dldDEN +MAsGA1UECxMEV2dldDEMMAoGA1UEChMDR05VFw0xNzA3MDgxNTA3MDRaFw0xODA3 +MDgxNTA3MDRaMB8wHQIMWWD1GB1UFkEICdQvFw0xNzA3MDgxNTA3MDRaoDowODAf +BgNVHSMEGDAWgBTzPk44hEqpvsFvx2GjUNpuKYvrVDAVBgNVHRQEDgIMWWD1GB4C +YfERSnyEMA0GCSqGSIb3DQEBCwUAA4IBAQAAKu+Lum1l/XtcCJ43WveouPK97iOE +bjUZWaGYx8Ys/iBdhTa1GXG+E+JuyqgyHTW0HrWJi1D+GiYmsjPJXoEgVgtxXEQ7 +8b3NyIQ8OCsSTTlVCmLECN9R0xlsitzH+HXOaIEs5sbmIxCnxu+brqno9gQocmCv +LHYvoSxsSsOCkkmodbYtKssl2dBonvQPSijN/z3NhZ259e2U3Yv4V7/MrEoTvOxg +M0GC0u0Nx86EWbq0sWeiUu270Qk9En5YGNtRhkeq0bXerJswmMAmvrtuKdyfouny +4WMvtn30xsO3WwWSV2oyrDSN/IQdDbcmul/bg8ewqlnN77cVf2m70c/W +-----END X509 CRL----- diff --git a/testenv/certs/server-key.pem b/testenv/certs/server-key.pem new file mode 100644 index 0000000..80d61cc --- /dev/null +++ b/testenv/certs/server-key.pem @@ -0,0 +1,144 @@ +Public Key Info: + Public Key Algorithm: RSA + Key Security Level: Medium (2048 bits) + +modulus: + 00:c8:c2:dc:6b:79:e4:47:d2:b6:5e:a6:13:7e:f5: + fa:90:f7:fd:ca:51:e4:c2:f1:91:d6:c1:b2:ce:4c: + 94:83:f6:4c:38:62:3c:e2:2d:2d:79:a5:f2:8c:6c: + e0:18:d4:9b:7c:1f:9f:71:95:f6:22:4b:99:bc:db: + 21:62:fe:d2:46:d1:91:0d:8b:08:f2:94:7f:e0:a5: + 9f:7c:f6:64:4f:ab:5f:07:56:95:3f:20:55:fb:f9: + d4:ea:5f:92:9d:a5:2c:35:54:a8:b7:cd:29:11:90: + 82:2b:e3:48:29:8b:a9:8d:8b:a9:e0:74:49:a5:4d: + be:e6:83:dc:4a:6a:67:22:07:d0:4e:52:66:08:ea: + 04:78:11:46:db:c6:91:cc:b4:ac:e9:a9:e5:22:36: + 34:04:8b:ba:05:22:a1:76:bd:38:b5:a3:a5:80:f0: + a1:db:1d:dc:44:65:2f:40:c9:d5:a2:56:f1:30:bc: + 4e:a8:b1:e2:2d:28:b1:6c:da:af:e2:d7:04:88:a7: + d1:0b:da:af:df:ee:44:73:74:a7:59:2a:de:9d:17: + 80:d1:ca:a9:6a:62:4d:3e:78:f9:66:31:ec:f7:a6: + bf:8a:91:5f:3d:75:b3:08:89:cd:42:fe:3f:0d:43: + ba:b4:3d:b2:66:f3:0e:00:2c:cf:b5:76:14:99:d4: + 78:27: + +public exponent: + 01:00:01: + +private exponent: + 00:92:80:1f:f9:0d:e9:d7:bf:9b:f5:55:9b:c4:7a: + 1b:6e:ce:89:14:aa:ce:14:b3:d3:88:b3:b0:97:7a: + aa:a5:e1:85:9d:5f:92:ae:39:e9:85:6b:e3:a3:35: + 90:12:8e:93:27:f0:ab:99:67:a5:45:41:85:de:9a: + c9:b2:43:e1:8e:6c:3f:3d:72:c8:04:bc:f8:d4:26: + 08:4c:58:40:bb:22:83:26:07:b8:c1:68:07:56:e8: + e8:c6:5f:17:ce:92:49:c0:61:16:fd:89:68:fe:b8: + 45:45:61:85:b7:4b:83:5f:17:1b:cf:ff:0b:fe:e4: + cc:f9:ca:1f:66:ee:5e:74:25:94:7a:27:0e:0f:43: + 50:14:48:ad:c6:8a:e1:ac:ff:8e:10:ed:e6:92:48: + c8:94:c1:3a:2c:db:86:71:66:8e:19:93:13:ed:f9: + 47:06:5e:8b:e2:2e:cb:3a:c2:b3:5e:8d:31:e4:c5: + a7:cd:3f:09:70:e4:02:5d:34:2a:4d:b7:f5:06:e2: + f5:3b:8f:b6:ad:4a:22:b8:fe:43:a7:4d:67:ef:c3: + e1:ed:83:e2:d5:f2:d0:37:0f:56:ab:5b:47:69:0a: + 14:03:2c:43:a3:73:e9:05:72:5e:df:68:9c:67:4b: + 08:64:2d:c2:67:23:aa:e5:35:88:56:99:95:17:60: + 20:01: + +prime1: + 00:ea:ca:12:86:c0:25:b8:ab:fd:44:2c:1a:3f:1b: + 19:68:d4:26:6e:9c:ad:6d:35:12:29:9f:40:c2:4c: + 96:ef:8b:08:61:39:08:b7:8a:1f:81:97:71:ff:af: + 5a:5b:db:9a:2f:2f:29:ab:92:bb:c5:51:a2:84:c5: + f4:88:79:ac:a2:b8:17:1e:4a:66:62:be:e5:ab:fd: + 01:42:6b:16:f9:73:7b:cd:3e:f7:5c:5c:95:dd:79: + 73:c4:60:a8:cf:95:80:ba:7d:02:14:9c:7e:58:4f: + 8c:08:2c:b8:46:31:23:b2:1a:c3:38:78:5c:ea:50: + 9d:42:23:31:30:9a:0f:3f:27: + +prime2: + 00:da:e5:d3:66:0f:34:53:8c:e8:bf:5f:1e:46:93: + 47:df:30:57:be:1f:30:6a:7e:e9:f0:6b:3f:61:89: + 51:e2:0b:da:51:09:65:f6:23:3a:61:86:02:46:0a: + cf:11:73:7c:2d:65:bd:64:b8:0e:24:d2:b7:51:8f: + 39:b4:a2:1b:e4:9a:bc:66:31:e2:00:eb:3e:20:06: + 97:0a:a0:bb:82:da:bf:d5:e9:20:77:a7:55:86:69: + ce:eb:38:d3:f4:ad:82:9e:ce:02:05:c5:11:aa:c0: + b9:66:6f:e7:f4:26:57:72:fa:50:0b:ad:76:44:86: + e0:3e:f7:c0:3e:f3:94:9f:01: + +coefficient: + 00:94:f2:42:a9:1a:62:1c:7a:bf:34:1b:a7:87:ae: + bd:3a:d9:f1:8c:4e:f6:f5:27:5a:ae:f1:1e:15:06: + a6:d0:e4:e0:ec:3a:40:02:13:b9:31:9a:cd:3a:c6: + 34:7d:c6:9d:9e:60:5b:ca:03:88:87:56:f0:e1:ea: + 37:96:2b:53:40:b2:78:4e:80:e2:e0:24:8c:83:0e: + f8:77:a4:64:d5:cc:09:6c:d6:52:49:f9:55:61:16: + 72:b5:d2:ea:e1:61:fb:31:24:f0:30:8c:fe:5c:29: + 71:06:09:11:4d:ef:51:a6:33:62:54:d2:c7:de:ba: + 78:17:b1:27:50:f4:ef:c4:3a: + +exp1: + 1f:36:0d:90:6c:2a:97:8a:05:78:f2:83:ea:af:a7: + 89:0f:ea:ab:f9:97:f4:54:81:bd:96:b5:fd:1e:41: + 52:46:a1:2e:8b:6e:65:37:af:48:82:e1:5c:a3:ea: + d7:1b:32:3b:e3:81:1e:95:ba:f0:58:11:ca:a4:a6: + 05:1e:67:9c:99:ec:38:d2:9b:19:b5:56:c2:ae:37: + 64:a4:e7:c0:f1:61:1b:bf:ab:12:54:1c:77:fc:95: + 2f:1d:ca:53:0e:04:b6:c5:b7:69:16:04:95:a8:bd: + 6c:b8:c5:26:4f:91:f7:33:27:90:72:2f:a7:d6:5f: + 91:53:2c:4e:d1:ac:05:31: + +exp2: + 00:83:a4:55:a6:fa:1b:d8:e7:54:0d:ca:f1:55:36: + 3b:b1:f0:cb:c3:cd:d3:fb:27:ca:1e:c9:10:bb:e2: + ae:78:c7:f2:0a:6c:21:82:8e:1b:0d:0d:5f:8e:a9: + ef:6f:aa:49:12:b0:2d:df:45:85:54:05:d9:33:56: + 74:38:ba:89:15:c9:2c:e6:34:b7:9b:1f:de:23:ba: + 72:d9:74:62:70:46:87:b9:e8:52:9b:42:e9:ff:44: + e0:a8:bb:6b:54:a9:88:75:62:a4:fa:bd:52:6b:a3: + 2d:9c:7a:4e:3f:99:53:5c:15:47:50:4e:88:62:9b: + ce:7e:6f:d6:90:c5:42:2b:01: + + +Public Key ID: 97:E6:DF:6D:CB:25:B2:93:33:FB:4C:29:2B:74:AA:55:2A:7B:06:E7 +Public key's random art: ++--[ RSA 2048]----+ +| | +| | +| | +| . | +| S + . | +| .+oo. . | +| .=+oo.+ .| +| +E.=O.oo| +| o+ .=*++o| ++-----------------+ + +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAyMLca3nkR9K2XqYTfvX6kPf9ylHkwvGR1sGyzkyUg/ZMOGI8 +4i0teaXyjGzgGNSbfB+fcZX2IkuZvNshYv7SRtGRDYsI8pR/4KWffPZkT6tfB1aV +PyBV+/nU6l+SnaUsNVSot80pEZCCK+NIKYupjYup4HRJpU2+5oPcSmpnIgfQTlJm +COoEeBFG28aRzLSs6anlIjY0BIu6BSKhdr04taOlgPCh2x3cRGUvQMnVolbxMLxO +qLHiLSixbNqv4tcEiKfRC9qv3+5Ec3SnWSrenReA0cqpamJNPnj5ZjHs96a/ipFf +PXWzCInNQv4/DUO6tD2yZvMOACzPtXYUmdR4JwIDAQABAoIBAQCSgB/5DenXv5v1 +VZvEehtuzokUqs4Us9OIs7CXeqql4YWdX5KuOemFa+OjNZASjpMn8KuZZ6VFQYXe +msmyQ+GObD89csgEvPjUJghMWEC7IoMmB7jBaAdW6OjGXxfOkknAYRb9iWj+uEVF +YYW3S4NfFxvP/wv+5Mz5yh9m7l50JZR6Jw4PQ1AUSK3GiuGs/44Q7eaSSMiUwTos +24ZxZo4ZkxPt+UcGXoviLss6wrNejTHkxafNPwlw5AJdNCpNt/UG4vU7j7atSiK4 +/kOnTWfvw+Htg+LV8tA3D1arW0dpChQDLEOjc+kFcl7faJxnSwhkLcJnI6rlNYhW +mZUXYCABAoGBAOrKEobAJbir/UQsGj8bGWjUJm6crW01EimfQMJMlu+LCGE5CLeK +H4GXcf+vWlvbmi8vKauSu8VRooTF9Ih5rKK4Fx5KZmK+5av9AUJrFvlze80+91xc +ld15c8RgqM+VgLp9AhScflhPjAgsuEYxI7Iawzh4XOpQnUIjMTCaDz8nAoGBANrl +02YPNFOM6L9fHkaTR98wV74fMGp+6fBrP2GJUeIL2lEJZfYjOmGGAkYKzxFzfC1l +vWS4DiTSt1GPObSiG+SavGYx4gDrPiAGlwqgu4Lav9XpIHenVYZpzus40/Stgp7O +AgXFEarAuWZv5/QmV3L6UAutdkSG4D73wD7zlJ8BAoGAHzYNkGwql4oFePKD6q+n +iQ/qq/mX9FSBvZa1/R5BUkahLotuZTevSILhXKPq1xsyO+OBHpW68FgRyqSmBR5n +nJnsONKbGbVWwq43ZKTnwPFhG7+rElQcd/yVLx3KUw4EtsW3aRYElai9bLjFJk+R +9zMnkHIvp9ZfkVMsTtGsBTECgYEAg6RVpvob2OdUDcrxVTY7sfDLw83T+yfKHskQ +u+KueMfyCmwhgo4bDQ1fjqnvb6pJErAt30WFVAXZM1Z0OLqJFcks5jS3mx/eI7py +2XRicEaHuehSm0Lp/0TgqLtrVKmIdWKk+r1Sa6MtnHpOP5lTXBVHUE6IYpvOfm/W +kMVCKwECgYEAlPJCqRpiHHq/NBunh669OtnxjE729SdarvEeFQam0OTg7DpAAhO5 +MZrNOsY0fcadnmBbygOIh1bw4eo3litTQLJ4ToDi4CSMgw74d6Rk1cwJbNZSSflV +YRZytdLq4WH7MSTwMIz+XClxBgkRTe9RpjNiVNLH3rp4F7EnUPTvxDo= +-----END RSA PRIVATE KEY----- diff --git a/testenv/certs/server-pubkey-sha256.base64 b/testenv/certs/server-pubkey-sha256.base64 new file mode 100644 index 0000000..6c24e4f --- /dev/null +++ b/testenv/certs/server-pubkey-sha256.base64 @@ -0,0 +1 @@ +mHiEhWHvusnzP7COZk+SzSJ+Gl7nZT+ADx0PUnDD7mM= diff --git a/testenv/certs/server-pubkey.der b/testenv/certs/server-pubkey.der Binary files differnew file mode 100644 index 0000000..6db082a --- /dev/null +++ b/testenv/certs/server-pubkey.der diff --git a/testenv/certs/server-pubkey.pem b/testenv/certs/server-pubkey.pem new file mode 100644 index 0000000..44a3628 --- /dev/null +++ b/testenv/certs/server-pubkey.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMLca3nkR9K2XqYTfvX6 +kPf9ylHkwvGR1sGyzkyUg/ZMOGI84i0teaXyjGzgGNSbfB+fcZX2IkuZvNshYv7S +RtGRDYsI8pR/4KWffPZkT6tfB1aVPyBV+/nU6l+SnaUsNVSot80pEZCCK+NIKYup +jYup4HRJpU2+5oPcSmpnIgfQTlJmCOoEeBFG28aRzLSs6anlIjY0BIu6BSKhdr04 +taOlgPCh2x3cRGUvQMnVolbxMLxOqLHiLSixbNqv4tcEiKfRC9qv3+5Ec3SnWSre +nReA0cqpamJNPnj5ZjHs96a/ipFfPXWzCInNQv4/DUO6tD2yZvMOACzPtXYUmdR4 +JwIDAQAB +-----END PUBLIC KEY----- diff --git a/testenv/certs/server-template.cfg b/testenv/certs/server-template.cfg new file mode 100644 index 0000000..00389aa --- /dev/null +++ b/testenv/certs/server-template.cfg @@ -0,0 +1,245 @@ +# X.509 Certificate options +# +# DN options + +# The organization of the subject. +organization = "GNU" + +# The organizational unit of the subject. +unit = "Wget" + +# The locality of the subject. +# locality = + +# The state of the certificate owner. +# state = "" + +# The country of the subject. Two letter code. +# country = GR + +# The common name of the certificate owner. +cn = "127.0.0.1" + +# A user id of the certificate owner. +#uid = "" + +# Set domain components +#dc = "name" +#dc = "domain" + +# If the supported DN OIDs are not adequate you can set +# any OID here. +# For example set the X.520 Title and the X.520 Pseudonym +# by using OID and string pairs. +#dn_oid = 2.5.4.12 Dr. +#dn_oid = 2.5.4.65 jackal + +# This is deprecated and should not be used in new +# certificates. +# pkcs9_email = "bug-wget@gnu.org" + +# An alternative way to set the certificate's distinguished name directly +# is with the "dn" option. The attribute names allowed are: +# C (country), street, O (organization), OU (unit), title, CN (common name), +# L (locality), ST (state), placeOfBirth, gender, countryOfCitizenship, +# countryOfResidence, serialNumber, telephoneNumber, surName, initials, +# generationQualifier, givenName, pseudonym, dnQualifier, postalCode, name, +# businessCategory, DC, UID, jurisdictionOfIncorporationLocalityName, +# jurisdictionOfIncorporationStateOrProvinceName, +# jurisdictionOfIncorporationCountryName, XmppAddr, and numeric OIDs. + +#dn = "cn = Nikos,st = New Something,C=GR,surName=Mavrogiannopoulos,2.5.4.9=Arkadias" + +# The serial number of the certificate +# Comment the field for a time-based serial number. +# serial = 007 + +# In how many days, counting from today, this certificate will expire. +# Use -1 if there is no expiration date. +expiration_days = -1 + +# Alternatively you may set concrete dates and time. The GNU date string +# formats are accepted. See: +# http://www.gnu.org/software/tar/manual/html_node/Date-input-formats.html + +#activation_date = "2004-02-29 16:21:42" +#expiration_date = "2025-02-29 16:24:41" + +# X.509 v3 extensions + +# A dnsname in case of a WWW server. +dns_name = "localhost" + +# A subject alternative name URI +#uri = "http://www.example.com" + +# An IP address in case of a server. +# ip_address = "127.0.0.1" + +# An email in case of a person +# email = "none@none.org" + +# Challenge password used in certificate requests +challenge_password = 123456 + +# Password when encrypting a private key +#password = secret + +# An URL that has CRLs (certificate revocation lists) +# available. Needed in CA certificates. +#crl_dist_points = "http://www.getcrl.crl/getcrl/" + +# Whether this is a CA certificate or not +# ca + +# Subject Unique ID (in hex) +#subject_unique_id = 00153224 + +# Issuer Unique ID (in hex) +#issuer_unique_id = 00153225 + +#### Key usage + +# The following key usage flags are used by CAs and end certificates + +# Whether this certificate will be used to sign data (needed +# in TLS DHE ciphersuites). This is the digitalSignature flag +# in RFC5280 terminology. +signing_key + +# Whether this certificate will be used to encrypt data (needed +# in TLS RSA ciphersuites). Note that it is preferred to use different +# keys for encryption and signing. This is the keyEncipherment flag +# in RFC5280 terminology. +encryption_key + +# Whether this key will be used to sign other certificates. The +# keyCertSign flag in RFC5280 terminology. +# cert_signing_key + +# Whether this key will be used to sign CRLs. The +# cRLSign flag in RFC5280 terminology. +# crl_signing_key + +# The keyAgreement flag of RFC5280. It's purpose is loosely +# defined. Not use it unless required by a protocol. +#key_agreement + +# The dataEncipherment flag of RFC5280. It's purpose is loosely +# defined. Not use it unless required by a protocol. +#data_encipherment + +# The nonRepudiation flag of RFC5280. It's purpose is loosely +# defined. Not use it unless required by a protocol. +#non_repudiation + +#### Extended key usage (key purposes) + +# The following extensions are used in an end certificate +# to clarify its purpose. Some CAs also use it to indicate +# the types of certificates they are purposed to sign. + +# Whether this certificate will be used for a TLS client; +# this sets the id-kp-serverAuth (1.3.6.1.5.5.7.3.1) of +# extended key usage. +#tls_www_client + +# Whether this certificate will be used for a TLS server; +# This sets the id-kp-clientAuth (1.3.6.1.5.5.7.3.2) of +# extended key usage. +tls_www_server + +# Whether this key will be used to sign code. This sets the +# id-kp-codeSigning (1.3.6.1.5.5.7.3.3) of extended key usage +# extension. +#code_signing_key + +# Whether this key will be used to sign OCSP data. This sets the +# id-kp-OCSPSigning (1.3.6.1.5.5.7.3.9) of extended key usage extension. +#ocsp_signing_key + +# Whether this key will be used for time stamping. This sets the +# id-kp-timeStamping (1.3.6.1.5.5.7.3.8) of extended key usage extension. +#time_stamping_key + +# Whether this key will be used for email protection. This sets the +# id-kp-emailProtection (1.3.6.1.5.5.7.3.4) of extended key usage extension. +#email_protection_key + +# Whether this key will be used for IPsec IKE operations (1.3.6.1.5.5.7.3.17). +#ipsec_ike_key + +## adding custom key purpose OIDs + +# for microsoft smart card logon +# key_purpose_oid = 1.3.6.1.4.1.311.20.2.2 + +# for email protection +# key_purpose_oid = 1.3.6.1.5.5.7.3.4 + +# for any purpose (must not be used in intermediate CA certificates) +# key_purpose_oid = 2.5.29.37.0 + +### end of key purpose OIDs + +# When generating a certificate from a certificate +# request, then honor the extensions stored in the request +# and store them in the real certificate. +honor_crq_extensions + +# Path length constraint. Sets the maximum number of +# certificates that can be used to certify this certificate. +# (i.e. the certificate chain length) +#path_len = -1 +#path_len = 2 + +# OCSP URI +# ocsp_uri = http://my.ocsp.server/ocsp + +# CA issuers URI +# ca_issuers_uri = http://my.ca.issuer + +# Certificate policies +#policy1 = 1.3.6.1.4.1.5484.1.10.99.1.0 +#policy1_txt = "This is a long policy to summarize" +#policy1_url = http://www.example.com/a-policy-to-read + +#policy2 = 1.3.6.1.4.1.5484.1.10.99.1.1 +#policy2_txt = "This is a short policy" +#policy2_url = http://www.example.com/another-policy-to-read + +# Name constraints + +# DNS +#nc_permit_dns = example.com +#nc_exclude_dns = test.example.com + +# EMAIL +#nc_permit_email = "nmav@ex.net" + +# Exclude subdomains of example.com +#nc_exclude_email = .example.com + +# Exclude all e-mail addresses of example.com +#nc_exclude_email = example.com + +# Options for proxy certificates +#proxy_policy_language = 1.3.6.1.5.5.7.21.1 + +# Options for generating a CRL + +# The number of days the next CRL update will be due. +# next CRL update will be in 43 days +#crl_next_update = 43 + +# this is the 5th CRL by this CA +# Comment the field for a time-based number. +#crl_number = 5 + +# Specify the update dates more precisely. +#crl_this_update_date = "2004-02-29 16:21:42" +#crl_next_update_date = "2025-02-29 16:24:41" + +# The date that the certificates will be made seen as +# being revoked. +#crl_revocation_date = "2025-02-29 16:24:41" diff --git a/testenv/conf/__init__.py b/testenv/conf/__init__.py new file mode 100644 index 0000000..55433c9 --- /dev/null +++ b/testenv/conf/__init__.py @@ -0,0 +1,48 @@ +import os + +# this file implements the mechanism of conf class auto-registration, +# don't modify this file if you have no idea what you're doing + + +def gen_hook(): + hook_table = {} + + class Wrapper: + """ + Decorator class which implements the conf class registration. + """ + def __init__(self, alias=None): + self.alias = alias + + def __call__(self, cls): + # register the class object with the name of the class + hook_table[cls.__name__] = cls + if self.alias: + # also register the alias of the class + hook_table[self.alias] = cls + + return cls + + def find_hook(name): + try: + return hook_table[name] + except: + raise AttributeError + + return Wrapper, find_hook + +_register, find_conf = gen_hook() +hook = rule = _register + +__all__ = ['hook', 'rule'] + +for module in os.listdir(os.path.dirname(__file__)): + # import every module under this package except __init__.py, + # so that the decorator `register` applies + # (nothing happens if the script is not loaded) + if module != '__init__.py' and module.endswith('.py'): + module_name = module[:-3] + mod = __import__('%s.%s' % (__name__, module_name), + globals(), + locals()) + __all__.append(module_name) diff --git a/testenv/conf/authentication.py b/testenv/conf/authentication.py new file mode 100644 index 0000000..ca5149c --- /dev/null +++ b/testenv/conf/authentication.py @@ -0,0 +1,23 @@ +from conf import rule + +""" Rule: Authentication +This file defines an authentication rule which when applied to any file will +cause the server to prompt the client for the required authentication details +before serving it. +auth_type must be either of: Basic, Digest, Both or Both-inline +When auth_type is Basic or Digest, the server asks for the respective +authentication in its response. When auth_type is Both, the server sends two +Authenticate headers, one requesting Basic and the other requesting Digest +authentication. If auth_type is Both-inline, the server sends only one +Authenticate header, but lists both Basic and Digest as supported mechanisms in +that. +""" + + +@rule() +class Authentication: + def __init__(self, auth_obj): + self.auth_type = auth_obj['Type'] + self.auth_user = auth_obj['User'] + self.auth_pass = auth_obj['Pass'] + self.auth_parm = auth_obj.get('Parm', None) diff --git a/testenv/conf/domains.py b/testenv/conf/domains.py new file mode 100644 index 0000000..ac03fe1 --- /dev/null +++ b/testenv/conf/domains.py @@ -0,0 +1,9 @@ +from conf import hook + +@hook(alias='Domains') +class Domains: + def __init__(self, domains): + self.domains = domains + + def __call__(self, test_obj): + test_obj.domains = self.domains diff --git a/testenv/conf/environment_variables.py b/testenv/conf/environment_variables.py new file mode 100644 index 0000000..323c051 --- /dev/null +++ b/testenv/conf/environment_variables.py @@ -0,0 +1,14 @@ +from conf import hook + +""" Test Option: EnvironmentVariables +This hook is used to define environment variables used for execution of wget +command in test.""" + + +@hook(alias='EnvironmentVariables') +class URLs: + def __init__(self, envs): + self.envs = envs + + def __call__(self, test_obj): + test_obj.envs.update(**self.envs) diff --git a/testenv/conf/expect_header.py b/testenv/conf/expect_header.py new file mode 100644 index 0000000..055099f --- /dev/null +++ b/testenv/conf/expect_header.py @@ -0,0 +1,12 @@ +from conf import rule + +""" Rule: ExpectHeader +This rule defines a dictionary of headers and their value which the server +should expect in each request for the file to which the rule was applied. +""" + + +@rule() +class ExpectHeader: + def __init__(self, header_obj): + self.headers = header_obj diff --git a/testenv/conf/expected_files.py b/testenv/conf/expected_files.py new file mode 100644 index 0000000..65adb70 --- /dev/null +++ b/testenv/conf/expected_files.py @@ -0,0 +1,58 @@ +from difflib import unified_diff +import os +import sys +from conf import hook +from exc.test_failed import TestFailed + +""" Post-Test Hook: ExpectedFiles +This is a Post-Test hook that checks the test directory for the files it +contains. A dictionary object is passed to it, which contains a mapping of +filenames and contents of all the files that the directory is expected to +contain. +Raises a TestFailed exception if the expected files are not found or if extra +files are found, else returns gracefully. +""" + + +@hook() +class ExpectedFiles: + def __init__(self, expected_fs): + self.expected_fs = expected_fs + + @staticmethod + def gen_local_fs_snapshot(): + snapshot = {} + for parent, dirs, files in os.walk('.'): + for name in files: + # pubring.gpg, pubring.kbx, dirmngr.conf, gpg.conf will be created by libgpgme + # if $HOME doesn't contain the .gnupg directory. + # setting $HOME to CWD (in base_test.py) breaks two Metalink tests, so we skip this file here. + if name in [ 'pubring.gpg', 'pubring.kbx', 'dirmngr.conf', 'gpg.conf' ]: + continue + + f = {'content': ''} + file_path = os.path.join(parent, name) + with open(file_path) as fp: + f['content'] = fp.read() + snapshot[file_path[2:]] = f + + return snapshot + + def __call__(self, test_obj): + local_fs = self.gen_local_fs_snapshot() + for file in self.expected_fs: + if file.name in local_fs: + local_file = local_fs.pop(file.name) + formatted_content = test_obj._replace_substring(file.content) + if formatted_content != local_file['content']: + for line in unified_diff(local_file['content'], + formatted_content, + fromfile='Actual', + tofile='Expected'): + print(line, file=sys.stderr) + raise TestFailed('Contents of %s do not match' % file.name) + else: + raise TestFailed('Expected file %s not found.' % file.name) + if local_fs: + print(local_fs) + raise TestFailed('Extra files downloaded.') diff --git a/testenv/conf/expected_ret_code.py b/testenv/conf/expected_ret_code.py new file mode 100644 index 0000000..87cba13 --- /dev/null +++ b/testenv/conf/expected_ret_code.py @@ -0,0 +1,27 @@ +from exc.test_failed import TestFailed +from conf import hook + +""" Post-Test Hook: ExpectedRetCode +This is a post-test hook which checks if the exit code of the Wget instance +under test is the same as that expected. As a result, this is a very important +post test hook which is checked in all the tests. +Returns a TestFailed exception if the return code does not match the expected +value. Else returns gracefully. +""" + + +@hook(alias='ExpectedRetcode') +class ExpectedRetCode: + def __init__(self, expected_ret_code): + self.expected_ret_code = expected_ret_code + + def __call__(self, test_obj): + if test_obj.ret_code != self.expected_ret_code: + if test_obj.ret_code == 45: + failure = "Memory Leak Found by Valgrind" + else: + failure = "Return codes do not match.\n" \ + "Expected: %s\n" \ + "Actual: %s" % (self.expected_ret_code, + test_obj.ret_code) + raise TestFailed(failure) diff --git a/testenv/conf/files_crawled.py b/testenv/conf/files_crawled.py new file mode 100644 index 0000000..7db8392 --- /dev/null +++ b/testenv/conf/files_crawled.py @@ -0,0 +1,27 @@ +from misc.colour_terminal import print_red +from conf import hook +from exc.test_failed import TestFailed + +""" Post-Test Hook: FilesCrawled +This is a post test hook that is invoked in tests that check wget's behaviour +in recursive mode. It expects an ordered list of the request lines that Wget +must send to the server. If the requests received by the server do not match +the provided list, IN THE GIVEN ORDER, then it raises a TestFailed exception. +Such a test can be used to check the implementation of the recursion algorithm +in Wget too. +""" + + +@hook() +class FilesCrawled: + def __init__(self, request_headers): + self.request_headers = request_headers + + def __call__(self, test_obj): + for headers, remaining in zip(map(set, self.request_headers), + test_obj.request_remaining()): + diff = headers.symmetric_difference(remaining) + + if diff: + print_red(str(diff)) + raise TestFailed('Not all files were crawled correctly.') diff --git a/testenv/conf/hook_sample.py b/testenv/conf/hook_sample.py new file mode 100644 index 0000000..591ec3b --- /dev/null +++ b/testenv/conf/hook_sample.py @@ -0,0 +1,22 @@ +from exc.test_failed import TestFailed +from conf import hook + +""" Hook: SampleHook +This a sample file for how a new hook should be defined. +Any errors should always be reported by raising a TestFailed exception instead +of returning a true or false value. +""" + + +@hook(alias='SampleHookAlias') +class SampleHook: + def __init__(self, sample_hook_arg): + # do conf initialization here + self.arg = sample_hook_arg + + def __call__(self, test_obj): + # implement hook here + # if you need the test case instance, refer to test_obj + if False: + raise TestFailed("Reason") + pass diff --git a/testenv/conf/local_files.py b/testenv/conf/local_files.py new file mode 100644 index 0000000..908ced1 --- /dev/null +++ b/testenv/conf/local_files.py @@ -0,0 +1,26 @@ +from os import utime +from time import strptime +from calendar import timegm +from conf import hook + +""" Pre-Test Hook: LocalFiles +This is a pre-test hook used to generate the specific environment before a test +is run. The LocalFiles hook creates the files which should exist on disk before +invoking Wget. +""" + + +@hook() +class LocalFiles: + def __init__(self, local_files): + self.local_files = local_files + + def __call__(self, _): + for f in self.local_files: + with open(f.name, 'w') as fp: + fp.write(f.content) + if f.timestamp is not None: + tstamp = timegm(strptime(f.timestamp, '%Y-%m-%d %H:%M:%S')) + atime = tstamp + mtime = tstamp + utime(f.name, (atime, mtime)) diff --git a/testenv/conf/reject_header.py b/testenv/conf/reject_header.py new file mode 100644 index 0000000..0dcf463 --- /dev/null +++ b/testenv/conf/reject_header.py @@ -0,0 +1,13 @@ +from conf import rule + +""" Rule: RejectHeader +This is a server side rule which expects a dictionary object of Headers and +their values which should be blacklisted by the server for a particular file's +requests. +""" + + +@rule() +class RejectHeader: + def __init__(self, header_obj): + self.headers = header_obj diff --git a/testenv/conf/response.py b/testenv/conf/response.py new file mode 100644 index 0000000..976a9ce --- /dev/null +++ b/testenv/conf/response.py @@ -0,0 +1,11 @@ +from conf import rule + +""" Rule: Response +When this rule is set against a certain file, the server will unconditionally +respond to any request for the said file with the provided response code. """ + + +@rule() +class Response: + def __init__(self, ret_code): + self.response_code = ret_code diff --git a/testenv/conf/rule_sample.py b/testenv/conf/rule_sample.py new file mode 100644 index 0000000..6345a3c --- /dev/null +++ b/testenv/conf/rule_sample.py @@ -0,0 +1,10 @@ +from conf import rule + + +@rule(alias='SampleRuleAlias') +class SampleRule: + def __init__(self, rule): + # do rule initialization here + # you may also need to implement a method the same name of this + # class in server/protocol/protocol_server.py to apply this rule. + self.rule = rule diff --git a/testenv/conf/send_header.py b/testenv/conf/send_header.py new file mode 100644 index 0000000..1ac54cc --- /dev/null +++ b/testenv/conf/send_header.py @@ -0,0 +1,12 @@ +from conf import rule + +""" Rule: SendHeader +Have the server send custom headers when responding to a request for the file +this rule is applied to. The header_obj object is expected to be dictionary +mapping headers to their contents. """ + + +@rule() +class SendHeader: + def __init__(self, header_obj): + self.headers = header_obj diff --git a/testenv/conf/server_files.py b/testenv/conf/server_files.py new file mode 100644 index 0000000..eaa9cd0 --- /dev/null +++ b/testenv/conf/server_files.py @@ -0,0 +1,26 @@ +from conf import hook + +""" Pre-Test Hook: ServerFiles +This hook is used to define a set of files on the server's virtual filesystem. +server_files is expected to be dictionary that maps filenames to their +contents. In the future, this can be used to add additional metadata to the +files using the WgetFile class too. + +This hook also does some additional processing on the contents of the file. Any +text between {{and}} is replaced by the contents of a class variable of the +same name. This is useful in creating files that contain an absolute link to +another file on the same server. """ + + +@hook() +class ServerFiles: + def __init__(self, server_files): + self.server_files = server_files + + def __call__(self, test_obj): + for server, files in zip(test_obj.servers, self.server_files): + files_content = {f.name: test_obj._replace_substring(f.content) + for f in files} + files_rules = {f.name: test_obj.get_server_rules(f) + for f in files} + server.server_conf(files_content, files_rules) diff --git a/testenv/conf/urls.py b/testenv/conf/urls.py new file mode 100644 index 0000000..f34c13e --- /dev/null +++ b/testenv/conf/urls.py @@ -0,0 +1,14 @@ +from conf import hook + +""" Pre-Test Hook: URLS +This hook is used to define the paths of the files on the test server that wget +will send a request for. """ + + +@hook(alias='Urls') +class URLs: + def __init__(self, urls): + self.urls = urls + + def __call__(self, test_obj): + test_obj.urls = self.urls diff --git a/testenv/conf/wget_commands.py b/testenv/conf/wget_commands.py new file mode 100644 index 0000000..fb379be --- /dev/null +++ b/testenv/conf/wget_commands.py @@ -0,0 +1,15 @@ +from conf import hook + +""" Pre-Test Hook: WgetCommands +This hook is used to specify the test specific switches that must be passed to +wget on invocation. Default switches are hard coded in the test suite itself. +""" + + +@hook() +class WgetCommands: + def __init__(self, commands): + self.commands = commands + + def __call__(self, test_obj): + test_obj.wget_options = test_obj._replace_substring(self.commands) diff --git a/testenv/exc/__init__.py b/testenv/exc/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/exc/__init__.py diff --git a/testenv/exc/server_error.py b/testenv/exc/server_error.py new file mode 100644 index 0000000..fe359f5 --- /dev/null +++ b/testenv/exc/server_error.py @@ -0,0 +1,19 @@ + +class ServerError (Exception): + """ A custom exception which is raised by the test servers. Often used to + handle control flow. """ + + def __init__(self, err_message): + self.err_message = err_message + +class NoBodyServerError (Exception): + """ A custom exception which is raised by the test servers. + Used if no body should be sent in response. """ + + def __init__(self, err_message): + self.err_message = err_message + +class AuthError (ServerError): + """ A custom exception raised byt he servers when authentication of the + request fails. """ + pass diff --git a/testenv/exc/test_failed.py b/testenv/exc/test_failed.py new file mode 100644 index 0000000..89f7960 --- /dev/null +++ b/testenv/exc/test_failed.py @@ -0,0 +1,7 @@ + +class TestFailed(Exception): + + """ A Custom Exception raised by the Test Environment. """ + + def __init__(self, error): + self.error = error diff --git a/testenv/misc/__init__.py b/testenv/misc/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/misc/__init__.py diff --git a/testenv/misc/colour_terminal.py b/testenv/misc/colour_terminal.py new file mode 100644 index 0000000..bc549a2 --- /dev/null +++ b/testenv/misc/colour_terminal.py @@ -0,0 +1,46 @@ +from functools import partial +import platform +from os import getenv +import sys + +""" This module allows printing coloured output to the terminal when running a +Wget Test under certain conditions. +The output is coloured only on Linux systems. This is because coloured output +in the terminal on Windows requires too much effort for what is simply a +convenience. This might work on OSX terminals, but without a confirmation, it +remains unsupported. + +Another important aspect is that the coloured output is printed only if the +environment variable MAKE_CHECK is not set. This variable is set when running +the test suite through, `make check`. In that case, the output is not only +printed to the terminal but also copied to a log file where the ANSI escape +codes on;y add clutter. """ + + +T_COLORS = { + 'PURPLE': '\033[95m', + 'BLUE': '\033[94m', + 'GREEN': '\033[92m', + 'YELLOW': '\033[93m', + 'RED': '\033[91m', + 'ENDC': '\033[0m' +} + +system = True if platform.system() in ('Linux', 'Darwin') else False +check = False if getenv("MAKE_CHECK") == 'True' else True + + +def printer(color, string): + if sys.stdout.isatty() and system and check: + print(T_COLORS.get(color) + string + T_COLORS.get('ENDC')) + else: + print(string) + + +print_blue = partial(printer, 'BLUE') +print_red = partial(printer, 'RED') +print_green = partial(printer, 'GREEN') +print_purple = partial(printer, 'PURPLE') +print_yellow = partial(printer, 'YELLOW') + +# vim: set ts=8 sw=3 tw=80 et : diff --git a/testenv/misc/metalinkv3_xml.py b/testenv/misc/metalinkv3_xml.py new file mode 100644 index 0000000..794bf87 --- /dev/null +++ b/testenv/misc/metalinkv3_xml.py @@ -0,0 +1,305 @@ +from test.http_test import HTTPTest +from misc.wget_file import WgetFile +import hashlib + +class Metalinkv3_XML: + + """ Metalink/XML v3 object """ + + # Initialize the Metalink object + def __init__ (self): + self.reset () + + # Reset the Metalink object + def reset (self): + self.LocalFiles = [] # list of WgetFile objects + self.ServerFiles = [[]] # list of WgetFile objects + self.ExpectedFiles = [] # list of WgetFile objects + self.LocalFiles_Set = [] # used as `list (set (var))` + self.ServerFiles_Set = [[]] # used as `list (set (var))` + self.ExpectedFiles_Set = [] # used as `list (set (var))` + self.Xml = '' # Metalink/XML content + self.XmlName = '' # Metalink/XML file name + self.XmlFile = None # Metalink/XML WgetFile object + self.Xml_Header = '<?xml version="1.0" encoding="utf-8"?>\n' + \ + '<metalink version="3.0" xmlns="http://www.metalinker.org/">\n' + \ + ' <publisher>\n' + \ + ' <name>GNU Wget</name>\n' + \ + ' </publisher>\n' + \ + ' <license>\n' + \ + ' <name>GNU GPL</name>\n' + \ + ' <url>http://www.gnu.org/licenses/gpl.html</url>\n' + \ + ' </license>\n' + \ + ' <identity>Wget Test Files</identity>\n' + \ + ' <version>1.2.3</version>\n' + \ + ' <description>Wget Test Files description</description>\n' + \ + ' <files>\n' + self.Xml_Footer = ' </files>\n' + \ + '</metalink>\n' + + # Print the Metalink object. + def print_meta (self): + + print (self.Xml) + print ("LocalFiles = " + str (self.LocalFiles_Set)) + print ("ServerFiles = " + str (self.ServerFiles_Set)) + print ("ExpectedFiles = " + str (self.ExpectedFiles_Set)) + + # Add LocalFiles as WgetFile objects + # + # ["file_name", "content"], + # ["file_name", "content"] + def add_LocalFiles (self, *local_files): + + for (file_name, content) in local_files: + if not file_name in self.LocalFiles_Set: + self.LocalFiles_Set.append (file_name) + self.LocalFiles.append (WgetFile (file_name, content)) + + # Add ServerFiles as WgetFile objects + # + # ["file_name", "content"], + # ["file_name", "content"] + def add_ServerFiles (self, *server_files): + + for (file_name, content) in server_files: + if not file_name in self.ServerFiles_Set[0]: + self.ServerFiles_Set[0].append (file_name) + self.ServerFiles[0].append (WgetFile (file_name, content)) + + # Add ExpectedFiles as WgetFile objects + # + # ["file_name", "content"], + # ["file_name", "content"] + def add_ExpectedFiles (self, *expected_files): + + for (file_name, content) in expected_files: + if not file_name in self.ExpectedFiles_Set: + self.ExpectedFiles_Set.append (file_name) + self.ExpectedFiles.append (WgetFile (file_name, content)) + + # Run a Wget HTTP test for the Metalink object. + def http_test (self, command_line, expected_retcode): + + pre_test = { + "ServerFiles" : self.ServerFiles, # list of WgetFile objects as [[]] + "LocalFiles" : self.LocalFiles, # list of WgetFile objects as [] + } + + test_options = { + "WgetCommands" : command_line, # Wget cli + "Urls" : [[]], # Wget urls + } + + post_test = { + "ExpectedFiles" : self.ExpectedFiles, # list of WgetFile objects as [] + "ExpectedRetcode" : expected_retcode, # Wget return status code + } + + http_test = HTTPTest ( + pre_hook=pre_test, + test_params=test_options, + post_hook=post_test, + ) + + http_test.server_setup() + # Get and use dynamic server sockname + srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname () + + self.set_srv (srv_host, srv_port) + + err = http_test.begin () + + return err + + # Set the Wget server host and port in the Metalink/XML content. + def set_srv (self, srv_host, srv_port): + + self.Xml = self.Xml.replace('{{SRV_HOST}}', srv_host) + self.Xml = self.Xml.replace('{{SRV_PORT}}', str (srv_port)) + + if self.XmlFile is not None: + self.XmlFile.content = self.Xml + + # Create the Metalink/XML file. + # + # Add the Metalink/XML file to the list of ExpectedFiles. + # + # size: + # True auto-compute size + # None no <size></size> + # any use this size + # + # hash_sha256: + # False no <verification></verification> + # True auto-compute sha256 + # None no <hash></hash> + # any use this hash + # + # ARGUMENTS: + # + # "xml_name", # Metalink/XML file name + # ["file_name", "save_name", "content", size, hash_sha256, # metalink:file + # ["srv_file", "srv_content", utype, location, preference], # resource + # ["srv_file", "srv_content", utype, location, preference]], # resource + # ["file_name", "save_name", "content", size, hash_sha256, + # ["srv_file", "srv_content", utype, location, preference], + # ["srv_file", "srv_content", utype, location, preference]] + def xml (self, xml_name, *xml_data): + + self.Xml = self.Xml_Header + + for (file_name, save_name, content, size, hash_sha256, *resources) in xml_data: + self.Xml += self.file_tag (file_name, save_name, content, size, hash_sha256, resources) + '\n' + + self.Xml += self.Xml_Footer + + self.XmlName = xml_name + self.XmlFile = WgetFile (xml_name, self.Xml) + + if not xml_name in self.LocalFiles_Set: + self.LocalFiles_Set.append (xml_name) + self.LocalFiles.append (self.XmlFile) + + if not xml_name in self.ExpectedFiles_Set: + self.ExpectedFiles_Set.append (xml_name) + self.ExpectedFiles.append (self.XmlFile) + + # Create the file tag. + # + # Add the file to be saved to the list of ExpectedFiles. + # + # size: + # True auto-compute size + # None no <size></size> + # any use this size + # + # hash_sha256: + # False no <verification></verification> + # True auto-compute sha256 + # None no <hash></hash> + # any use this hash + # + # ARGUMENTS: + # + # ["file_name", "save_name", "content", size, hash_sha256, # metalink:file + # ["srv_file", "srv_content", utype, location, preference], # resource + # ["srv_file", "srv_content", utype, location, preference]] # resource + def file_tag (self, file_name, save_name, content, size, hash_sha256, resources): + + Tag = ' <file name="' + file_name + '">\n' + + if save_name is not None: + self.add_ExpectedFiles ([save_name, content]) + + size_Tag = self.size_tag (content, size) + + if size_Tag is not None: + Tag += size_Tag + '\n' + + verification_Tag = self.verification_tag (content, hash_sha256) + + if verification_Tag is not None: + Tag += verification_Tag + '\n' + + Tag += self.resources_tag (resources) + '\n' + + Tag += ' </file>' + + return Tag + + # Create the size tag. + # + # size: + # True auto-compute size + # None no <size></size> + # any use this size + # + # ARGUMENTS: + # + # "content", size + def size_tag (self, content = None, size = None): + + Tag = None + + if content is not None and size is True: + size = len (content) + + if size is not None: + Tag = ' <size>' + str (size) + '</size>' + + return Tag + + # Create the verification tag. + # + # hash_sha256: + # False no <verification></verification> + # True auto-compute sha256 + # None no <hash></hash> + # any use this hash + # + # ARGUMENTS: + # + # "content", hash_sha256 + def verification_tag (self, content = None, hash_sha256 = None): + + Tag = None + + if hash_sha256 is not False: + + if content is not None and hash_sha256 is True: + hash_sha256 = hashlib.sha256 (content.encode ('UTF-8')).hexdigest () + + if hash_sha256 is None: + Tag = ' <verification>\n' + \ + ' </verification>' + else: + Tag = ' <verification>\n' + \ + ' <hash type="sha256">' + str (hash_sha256) + '</hash>\n' + \ + ' </verification>' + + return Tag + + # Create the resources tag. + # + # ARGUMENTS: + # + # ["srv_file", "srv_content", utype, location, preference], # resource + # ["srv_file", "srv_content", utype, location, preference] # resource + def resources_tag (self, resources): + + Tag = ' <resources>\n' + + for (srv_file, srv_content, utype, location, preference) in resources: + Tag += self.url_tag (srv_file, srv_content, utype, location, preference) + '\n' + + Tag += ' </resources>' + + return Tag + + # Create the url tag. + # + # Add the file to the list of Files when there is a content. + # + # ARGUMENTS: + # + # "srv_file", "srv_content", utype, location, preference # resource + def url_tag (self, srv_file, srv_content = None, utype = "http", location = None, preference = 999999): + + Loc = '' + + if location is not None: + Loc = 'location="' + location + '" ' + + Tag = ' ' + \ + '<url ' + \ + 'type="' + utype + '" ' + \ + Loc + \ + 'preference="' + str (preference) + '">' + \ + 'http://{{SRV_HOST}}:{{SRV_PORT}}/' + srv_file + \ + '</url>' + + if srv_content is not None: + self.add_ServerFiles ([srv_file, srv_content]) + + return Tag diff --git a/testenv/misc/wget_file.py b/testenv/misc/wget_file.py new file mode 100644 index 0000000..c2a7239 --- /dev/null +++ b/testenv/misc/wget_file.py @@ -0,0 +1,16 @@ + +class WgetFile: + + """ WgetFile is a File Data Container object """ + + def __init__( + self, + name, + content="Test Contents", + timestamp=None, + rules=None + ): + self.name = name + self.content = content + self.timestamp = timestamp + self.rules = rules or {} diff --git a/testenv/server/__init__.py b/testenv/server/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/server/__init__.py diff --git a/testenv/server/ftp/__init__.py b/testenv/server/ftp/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/server/ftp/__init__.py diff --git a/testenv/server/ftp/ftp_server.py b/testenv/server/ftp/ftp_server.py new file mode 100644 index 0000000..f7d7771 --- /dev/null +++ b/testenv/server/ftp/ftp_server.py @@ -0,0 +1,162 @@ +import os +import re +import threading +import socket +import pyftpdlib.__main__ +from pyftpdlib.ioloop import IOLoop +import pyftpdlib.handlers as Handle +from pyftpdlib.servers import FTPServer +from pyftpdlib.authorizers import DummyAuthorizer +from pyftpdlib._compat import PY3, u, b, getcwdu, callable + +class FTPDHandler (Handle.FTPHandler): + + def ftp_LIST (self, path): + try: + iterator = self.run_as_current_user(self.fs.get_list_dir, path) + except (OSError, FilesystemError): + err = sys.exc_info()[1] + why = _strerror (err) + self.respond ('550 %s. ' % why) + else: + if self.isRule ("Bad List") is True: + iter_list = list () + for flist in iterator: + line = re.compile (r'(\s+)').split (flist.decode ('utf-8')) + line[8] = '0' + iter_l = ''.join (line).encode ('utf-8') + iter_list.append (iter_l) + iterator = (n for n in iter_list) + producer = Handle.BufferedIteratorProducer (iterator) + self.push_dtp_data (producer, isproducer=True, cmd="LIST") + return path + + def ftp_PASV (self, line): + if self._epsvall: + self.respond ("501 PASV not allowed after EPSV ALL.") + return + self._make_epasv(extmode=False) + if self.isRule ("FailPASV") is True: + del self.server.global_rules["FailPASV"] + self.socket.close () + + def isRule (self, rule): + rule_obj = self.server.global_rules[rule] + return False if not rule_obj else rule_obj[0] + +class FTPDServer (FTPServer): + + def set_global_rules (self, rules): + self.global_rules = rules + +class FTPd(threading.Thread): + """A threaded FTP server used for running tests. + + This is basically a modified version of the FTPServer class which + wraps the polling loop into a thread. + + The instance returned can be used to start(), stop() and + eventually re-start() the server. + """ + handler = FTPDHandler + server_class = FTPDServer + + def __init__(self, addr=None): + os.mkdir ('server') + os.chdir ('server') + try: + HOST = socket.gethostbyname ('localhost') + except socket.error: + HOST = 'localhost' + USER = 'user' + PASSWD = '12345' + HOME = getcwdu () + + threading.Thread.__init__(self) + self.__serving = False + self.__stopped = False + self.__lock = threading.Lock() + self.__flag = threading.Event() + if addr is None: + addr = (HOST, 0) + + authorizer = DummyAuthorizer() + authorizer.add_user(USER, PASSWD, HOME, perm='elradfmwM') # full perms + authorizer.add_anonymous(HOME) + self.handler.authorizer = authorizer + # lowering buffer sizes = more cycles to transfer data + # = less false positive test failures + self.handler.dtp_handler.ac_in_buffer_size = 32768 + self.handler.dtp_handler.ac_out_buffer_size = 32768 + self.server = self.server_class(addr, self.handler) + self.host, self.port = self.server.socket.getsockname()[:2] + os.chdir ('..') + + def set_global_rules (self, rules): + self.server.set_global_rules (rules) + + def __repr__(self): + status = [self.__class__.__module__ + "." + self.__class__.__name__] + if self.__serving: + status.append('active') + else: + status.append('inactive') + status.append('%s:%s' % self.server.socket.getsockname()[:2]) + return '<%s at %#x>' % (' '.join(status), id(self)) + + @property + def running(self): + return self.__serving + + def start(self, timeout=0.001): + """Start serving until an explicit stop() request. + Polls for shutdown every 'timeout' seconds. + """ + if self.__serving: + raise RuntimeError("Server already started") + if self.__stopped: + # ensure the server can be started again + FTPd.__init__(self, self.server.socket.getsockname(), self.handler) + self.__timeout = timeout + threading.Thread.start(self) + self.__flag.wait() + + def run(self): + self.__serving = True + self.__flag.set() + while self.__serving: + self.__lock.acquire() + self.server.serve_forever(timeout=self.__timeout, blocking=False) + self.__lock.release() + self.server.close_all() + + def stop(self): + """Stop serving (also disconnecting all currently connected + clients) by telling the serve_forever() loop to stop and + waits until it does. + """ + if not self.__serving: + raise RuntimeError("Server not started yet") + self.__serving = False + self.__stopped = True + self.join() + + +def mk_file_sys (file_list): + os.chdir ('server') + for name, content in file_list.items (): + file_h = open (name, 'w') + file_h.write (content) + file_h.close () + os.chdir ('..') + +def filesys (): + fileSys = dict () + os.chdir ('server') + for parent, dirs, files in os.walk ('.'): + for filename in files: + file_handle = open (filename, 'r') + file_content = file_handle.read () + fileSys[filename] = file_content + os.chdir ('..') + return fileSys diff --git a/testenv/server/http/__init__.py b/testenv/server/http/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/server/http/__init__.py diff --git a/testenv/server/http/http_server.py b/testenv/server/http/http_server.py new file mode 100644 index 0000000..2cc82fb --- /dev/null +++ b/testenv/server/http/http_server.py @@ -0,0 +1,492 @@ +from http.server import HTTPServer, BaseHTTPRequestHandler +from exc.server_error import ServerError, AuthError, NoBodyServerError +from socketserver import BaseServer +from posixpath import basename, splitext +from base64 import b64encode +from random import random +from hashlib import md5 +import threading +import socket +import os + + +class StoppableHTTPServer(HTTPServer): + """ This class extends the HTTPServer class from default http.server library + in Python 3. The StoppableHTTPServer class is capable of starting an HTTP + server that serves a virtual set of files made by the WgetFile class and + has most of its properties configurable through the server_conf() + method. """ + + request_headers = list() + + """ Define methods for configuring the Server. """ + + def server_conf(self, filelist, conf_dict): + """ Set Server Rules and File System for this instance. """ + self.server_configs = conf_dict + self.fileSys = filelist + + def get_req_headers(self): + return self.request_headers + + +class HTTPSServer(StoppableHTTPServer): + """ The HTTPSServer class extends the StoppableHTTPServer class with + additional support for secure connections through SSL. """ + + def __init__(self, address, handler): + import ssl + BaseServer.__init__(self, address, handler) + # step one up because test suite change directory away from $srcdir + # (don't do that !!!) + CERTFILE = os.path.abspath(os.path.join('..', + os.getenv('srcdir', '.'), + 'certs', + 'server-cert.pem')) + KEYFILE = os.path.abspath(os.path.join('..', + os.getenv('srcdir', '.'), + 'certs', + 'server-key.pem')) + self.socket = ssl.wrap_socket( + sock=socket.socket(self.address_family, self.socket_type), + certfile=CERTFILE, + keyfile=KEYFILE, + server_side=True + ) + self.server_bind() + self.server_activate() + + +class _Handler(BaseHTTPRequestHandler): + """ This is a private class which tells the server *HOW* to handle each + request. For each HTTP Request Command that the server should be capable of + responding to, there must exist a do_REQUESTNAME() method which details the + steps in which such requests should be processed. The rest of the methods + in this class are auxiliary methods created to help in processing certain + requests. """ + + def get_rule_list(self, name): + return self.rules.get(name) + + # The default protocol version of the server we run is HTTP/1.1 not + # HTTP/1.0 which is the default with the http.server module. + protocol_version = 'HTTP/1.1' + + """ Define functions for various HTTP Requests. """ + + def do_HEAD(self): + self.send_head("HEAD") + + def do_GET(self): + """ Process HTTP GET requests. This is the same as processing HEAD + requests and then actually transmitting the data to the client. If + send_head() does not specify any "start" offset, we send the complete + data, else transmit only partial data. """ + + content, start = self.send_head("GET") + if content: + if start is None: + self.wfile.write(content.encode('utf-8')) + else: + self.wfile.write(content.encode('utf-8')[start:]) + + def do_POST(self): + """ According to RFC 7231 sec 4.3.3, if the resource requested in a POST + request does not exist on the server, the first POST request should + create that resource. PUT requests are otherwise used to create a + resource. Hence, we call the handle for processing PUT requests if the + resource requested does not already exist. + + Currently, when the server receives a POST request for a resource, we + simply append the body data to the existing file and return the new + file to the client. If the file does not exist, a new file is created + using the contents of the request body. """ + + path = self.path[1:] + if path in self.server.fileSys: + self.rules = self.server.server_configs.get(path) + if not self.rules: + self.rules = dict() + + if not self.custom_response(): + return(None, None) + + body_data = self.get_body_data() + self.send_response(200) + self.add_header("Content-type", "text/plain") + content = self.server.fileSys.pop(path) + "\n" + body_data + total_length = len(content) + self.server.fileSys[path] = content + self.add_header("Content-Length", total_length) + self.add_header("Location", self.path) + self.finish_headers() + try: + self.wfile.write(content.encode('utf-8')) + except Exception: + pass + else: + self.send_put(path) + + def do_PUT(self): + path = self.path[1:] + self.rules = self.server.server_configs.get(path) + if not self.custom_response(): + return(None, None) + self.send_put(path) + + """ End of HTTP Request Method Handlers. """ + + """ Helper functions for the Handlers. """ + + def parse_range_header(self, header_line, length): + import re + if header_line is None: + return None + if not header_line.startswith("bytes="): + raise ServerError("Cannot parse header Range: %s" % + (header_line)) + regex = re.match(r"^bytes=(\d*)\-$", header_line) + range_start = int(regex.group(1)) + if range_start >= length: + raise ServerError("Range Overflow") + return range_start + + def get_body_data(self): + cLength_header = self.headers.get("Content-Length") + cLength = int(cLength_header) if cLength_header is not None else 0 + body_data = self.rfile.read(cLength).decode('utf-8') + return body_data + + def send_put(self, path): + if path in self.server.fileSys: + self.server.fileSys.pop(path, None) + self.send_response(204) + else: + self.rules = dict() + self.send_response(201) + body_data = self.get_body_data() + self.server.fileSys[path] = body_data + self.add_header("Location", self.path) + self.finish_headers() + + """ This empty method is called automatically when all the rules are + processed for a given request. However, send_header() should only be called + AFTER a response has been sent. But, at the moment of processing the rules, + the appropriate response has not yet been identified. As a result, we defer + the processing of this rule till later. Each do_* request handler MUST call + finish_headers() instead of end_headers(). The finish_headers() method + takes care of sending the appropriate headers before completing the + response. """ + def SendHeader(self, header_obj): + pass + + def send_cust_headers(self): + header_obj = self.get_rule_list('SendHeader') + if header_obj: + for header in header_obj.headers: + self.add_header(header, header_obj.headers[header]) + + def finish_headers(self): + self.send_cust_headers() + try: + for keyword, value in self._headers_dict.items(): + if isinstance(value, list): + for value_el in value: + self.send_header(keyword, value_el) + else: + self.send_header(keyword, value) + # Clear the dictionary of existing headers for the next request + self._headers_dict.clear() + except AttributeError: + pass + self.end_headers() + + def Response(self, resp_obj): + self.send_response(resp_obj.response_code) + if resp_obj.response_code == 304: + raise NoBodyServerError("Conditional get falling to head") + raise ServerError("Custom Response code sent.") + + def custom_response(self): + codes = self.get_rule_list('Response') + if codes: + self.send_response(codes.response_code) + self.finish_headers() + return False + else: + return True + + def add_header(self, keyword, value): + if not hasattr(self, "_headers_dict"): + self._headers_dict = dict() + self._headers_dict[keyword.lower()] = value + + def base64(self, data): + string = b64encode(data.encode('utf-8')) + return string.decode('utf-8') + + """ Send an authentication challenge. + This method calls self.send_header() directly instead of using the + add_header() method because sending multiple WWW-Authenticate headers + actually makes sense and we do use that feature in some tests. """ + def send_challenge(self, auth_type, auth_parm): + auth_type = auth_type.lower() + if auth_type == "both": + self.send_challenge("basic", auth_parm) + self.send_challenge("digest", auth_parm) + return + if auth_type == "basic": + challenge_str = 'BasIc realm="Wget-Test"' + elif auth_type == "digest" or auth_type == "both_inline": + self.nonce = md5(str(random()).encode('utf-8')).hexdigest() + self.opaque = md5(str(random()).encode('utf-8')).hexdigest() + # 'DIgest' to provoke a Wget failure with turkish locales + challenge_str = 'DIgest realm="Test", nonce="%s", opaque="%s"' % ( + self.nonce, + self.opaque) + try: + if auth_parm['qop']: + challenge_str += ', qop="%s"' % auth_parm['qop'] + except KeyError: + pass + if auth_type == "both_inline": + # 'BasIc' to provoke a Wget failure with turkish locales + challenge_str = 'BasIc realm="Wget-Test", ' + challenge_str + self.send_header("WWW-Authenticate", challenge_str) + + def authorize_basic(self, auth_header, auth_rule): + if auth_header is None or auth_header.split(' ')[0].lower() != 'basic': + return False + else: + self.user = auth_rule.auth_user + self.passw = auth_rule.auth_pass + auth_str = "basic " + self.base64(self.user + ":" + self.passw) + return True if auth_str.lower() == auth_header.lower() else False + + def parse_auth_header(self, auth_header): + n = len("digest ") + auth_header = auth_header[n:].strip() + items = auth_header.split(", ") + keyvals = [i.split("=", 1) for i in items] + keyvals = [(k.strip(), v.strip().replace('"', '')) for k, v in keyvals] + return dict(keyvals) + + def KD(self, secret, data): + return self.H(secret + ":" + data) + + def H(self, data): + return md5(data.encode('utf-8')).hexdigest() + + def A1(self): + return "%s:%s:%s" % (self.user, "Test", self.passw) + + def A2(self, params): + return "%s:%s" % (self.command, params["uri"]) + + def check_response(self, params): + if "qop" in params: + data_str = params['nonce'] \ + + ":" + params['nc'] \ + + ":" + params['cnonce'] \ + + ":" + params['qop'] \ + + ":" + self.H(self.A2(params)) + else: + data_str = params['nonce'] + ":" + self.H(self.A2(params)) + resp = self.KD(self.H(self.A1()), data_str) + + return True if resp == params['response'] else False + + def authorize_digest(self, auth_header, auth_rule): + if auth_header is None or \ + auth_header.split(' ')[0].lower() != 'digest': + return False + else: + self.user = auth_rule.auth_user + self.passw = auth_rule.auth_pass + params = self.parse_auth_header(auth_header) + if self.user != params['username'] or \ + self.nonce != params['nonce'] or \ + self.opaque != params['opaque']: + return False + req_attribs = ['username', 'realm', 'nonce', 'uri', 'response'] + for attrib in req_attribs: + if attrib not in params: + return False + if not self.check_response(params): + return False + + def authorize_both(self, auth_header, auth_rule): + return False + + def authorize_both_inline(self, auth_header, auth_rule): + return False + + def Authentication(self, auth_rule): + try: + self.handle_auth(auth_rule) + except AuthError as se: + self.send_response(401, "Authorization Required") + self.send_challenge(auth_rule.auth_type, auth_rule.auth_parm) + raise se + + def handle_auth(self, auth_rule): + is_auth = True + auth_header = self.headers.get("Authorization") + required_auth = auth_rule.auth_type.lower() + if required_auth == "both" or required_auth == "both_inline": + if auth_header: + auth_type = auth_header.split(' ')[0].lower() + else: + auth_type = required_auth + else: + auth_type = required_auth + try: + assert hasattr(self, "authorize_" + auth_type) + is_auth = getattr(self, "authorize_" + auth_type)(auth_header, + auth_rule) + except AssertionError: + raise AuthError("Authentication Mechanism %s not supported" % + auth_type) + except AttributeError as ae: + raise AuthError(ae.__str__()) + if is_auth is False: + raise AuthError("Unable to Authenticate") + + def ExpectHeader(self, header_obj): + exp_headers = header_obj.headers + for header_line in exp_headers: + header_recd = self.headers.get(header_line) + if header_recd is None or header_recd != exp_headers[header_line]: + self.send_error(400, "Expected Header %s not found" % + header_line) + raise ServerError("Header " + header_line + " not found") + + def RejectHeader(self, header_obj): + rej_headers = header_obj.headers + for header_line in rej_headers: + header_recd = self.headers.get(header_line) + if header_recd and header_recd == rej_headers[header_line]: + self.send_error(400, 'Blacklisted Header %s received' % + header_line) + raise ServerError("Header " + header_line + ' received') + + def __log_request(self, method): + req = method + " " + self.path + self.server.request_headers.append(req) + + def send_head(self, method): + """ Common code for GET and HEAD Commands. + This method is overridden to use the fileSys dict. + + The method variable contains whether this was a HEAD or a GET Request. + According to RFC 2616, the server should not differentiate between + the two requests, however, we use it here for a specific test. + """ + + if self.path == "/": + path = "index.html" + else: + path = self.path[1:] + + self.__log_request(method) + + if path in self.server.fileSys: + self.rules = self.server.server_configs.get(path) + + content = self.server.fileSys.get(path) + content_length = len(content) + + for rule_name in self.rules: + try: + assert hasattr(self, rule_name) + getattr(self, rule_name)(self.rules[rule_name]) + except AssertionError as ae: + msg = "Rule " + rule_name + " not defined" + self.send_error(500, msg) + return(None, None) + except AuthError as ae: + print(ae.__str__()) + self.finish_headers() + return(None, None) + except NoBodyServerError as nbse: + print(nbse.__str__()) + self.finish_headers() + return(None, None) + except ServerError as se: + print(se.__str__()) + self.add_header("Content-Length", content_length) + self.finish_headers() + return(content, None) + + try: + self.range_begin = self.parse_range_header( + self.headers.get("Range"), content_length) + except ServerError as ae: + # self.log_error("%s", ae.err_message) + if ae.err_message == "Range Overflow": + try: + self.overflows += 1 + except AttributeError as s: + self.overflows = 0 + self.send_response(416) + if self.overflows > 0: + self.add_header("Content-Length", 17) + self.finish_headers() + if self.overflows > 0: + return("Range Unsatisfied", 0) + return(None, None) + else: + self.range_begin = None + if self.range_begin is None: + self.send_response(200) + else: + self.send_response(206) + self.add_header("Accept-Ranges", "bytes") + self.add_header("Content-Range", + "bytes %d-%d/%d" % (self.range_begin, + content_length - 1, + content_length)) + content_length -= self.range_begin + cont_type = self.guess_type(path) + self.add_header("Content-Type", cont_type) + self.add_header("Content-Length", content_length) + self.finish_headers() + return(content, self.range_begin) + else: + self.send_error(404, "Not Found") + return(None, None) + + def guess_type(self, path): + base_name = basename("/" + path) + name, ext = splitext(base_name) + extension_map = { + ".txt": "text/plain", + ".css": "text/css", + ".html": "text/html" + } + return extension_map.get(ext, "text/plain") + + +class HTTPd(threading.Thread): + server_class = StoppableHTTPServer + handler = _Handler + + def __init__(self, addr=None): + threading.Thread.__init__(self) + if addr is None: + addr = ('localhost', 0) + self.server_inst = self.server_class(addr, self.handler) + self.server_address = self.server_inst.socket.getsockname()[:2] + + def run(self): + self.server_inst.serve_forever() + + def server_conf(self, file_list, server_rules): + self.server_inst.server_conf(file_list, server_rules) + + +class HTTPSd(HTTPd): + + server_class = HTTPSServer + +# vim: set ts=4 sts=4 sw=4 tw=79 et : diff --git a/testenv/test/__init__.py b/testenv/test/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/testenv/test/__init__.py diff --git a/testenv/test/base_test.py b/testenv/test/base_test.py new file mode 100644 index 0000000..1cdfba1 --- /dev/null +++ b/testenv/test/base_test.py @@ -0,0 +1,278 @@ +import os +import shutil +import shlex +import traceback +import re +import time +import sys +from subprocess import call +from misc.colour_terminal import print_red, print_blue +from exc.test_failed import TestFailed +import conf + +HTTP = "HTTP" +HTTPS = "HTTPS" + +SKIP_TEST = 77 + +class BaseTest: + + """ + Class that defines methods common to both HTTP and FTP Tests. + Note that this is an abstract class, subclasses must implement + * stop_server() + * instantiate_server_by(protocol) + """ + + def __init__(self, pre_hook, test_params, post_hook, protocols, req_protocols): + """ + Define the class-wide variables (or attributes). + Attributes should not be defined outside __init__. + """ + self.name = os.path.basename(os.path.realpath(sys.argv[0])) + # if pre_hook == None, then {} (an empty dict object) is passed to + # self.pre_configs + self.pre_configs = pre_hook or {} + + self.test_params = test_params or {} + self.post_configs = post_hook or {} + self.protocols = protocols + + if req_protocols is None: + self.req_protocols = map(lambda p: p.lower(), self.protocols) + else: + self.req_protocols = req_protocols + + self.servers = [] + self.domains = [] + self.ports = [] + + self.addr = None + self.port = -1 + + self.wget_options = '' + self.urls = [] + self.envs = dict() + + self.tests_passed = True + self.ready = False + self.init_test_env() + + self.ret_code = 0 + + def get_test_dir(self): + return self.name + '-test' + + def init_test_env(self): + test_dir = self.get_test_dir() + try: + os.mkdir(test_dir) + except FileExistsError: + shutil.rmtree(test_dir) + os.mkdir(test_dir) + os.chdir(test_dir) + + def get_domain_addr(self, addr): + # TODO if there's a multiple number of ports, wouldn't it be + # overridden to the port of the last invocation? + # Set the instance variables 'addr' and 'port' so that + # they can be queried by test cases. + self.addr = str(addr[0]) + self.port = str(addr[1]) + + return [self.addr, self.port] + + def server_setup(self): + print_blue("Running Test %s" % self.name) + for protocol in self.protocols: + instance = self.instantiate_server_by(protocol) + self.servers.append(instance) + + # servers instantiated by different protocols may differ in + # ports and etc. + # so we should record different domains respect to servers. + domain = self.get_domain_addr(instance.server_address) + self.domains.append('localhost') + self.ports.append(domain[1]) + + def exec_wget(self): + cmd_line = self.gen_cmd_line() + params = shlex.split(cmd_line) + print(params) + envs = {"HOME": os.getcwd()} + envs.update(**self.envs) + print(envs) + + if os.getenv("SERVER_WAIT"): + time.sleep(float(os.getenv("SERVER_WAIT"))) + + try: + ret_code = call(params, env=envs) + except FileNotFoundError: + raise TestFailed("The Wget Executable does not exist at the " + "expected path.") + + return ret_code + + def gen_cmd_line(self): + test_path = os.path.abspath(".") + if os.getenv("WGET_PATH"): + wget_path = os.path.abspath(os.getenv("WGET_PATH")) + else: + wget_path = os.path.abspath(os.path.join(test_path, + "..", '..', 'src', + "wget")) + wget_options = '--debug --no-config %s' % self.wget_options + + valgrind = os.getenv("VALGRIND_TESTS", "") + gdb = os.getenv("GDB_TESTS", "") + + # GDB has precedence over Valgrind + # If both VALGRIND_TESTS and GDB_TESTS are defined, + # GDB will be executed. + if gdb == "1": + cmd_line = 'gdb --args %s %s ' % (wget_path, wget_options) + elif valgrind == "1": + cmd_line = 'valgrind --error-exitcode=301 ' \ + '--leak-check=yes ' \ + '--track-origins=yes ' \ + '--gen-suppressions=all ' \ + '--suppressions=../valgrind-suppression-ssl ' \ + '%s %s ' % (wget_path, wget_options) + elif valgrind not in ("", "0"): + cmd_line = '%s %s %s ' % (os.getenv("VALGRIND_TESTS", ""), + wget_path, + wget_options) + else: + cmd_line = '%s %s ' % (wget_path, wget_options) + + for req_protocol, urls, domain, port in zip(self.req_protocols, + self.urls, + self.domains, + self.ports): + # zip is function for iterating multiple lists at the same time. + # e.g. for item1, item2 in zip([1, 5, 3], + # ['a', 'e', 'c']): + # print(item1, item2) + # generates the following output: + # 1 a + # 5 e + # 3 c + for url in urls: + cmd_line += '%s://%s:%s/%s ' % (req_protocol, domain, port, url) + + + print(cmd_line) + + return cmd_line + + def __test_cleanup(self): + os.chdir('..') + try: + if not os.getenv("NO_CLEANUP"): + shutil.rmtree(self.get_test_dir()) + except: + print("Unknown Exception while trying to remove Test Environment.") + self.tests_passed = False + + def _exit_test(self): + self.__test_cleanup() + + def begin(self): + return 0 if self.tests_passed else 100 + + def call_test(self): + self.hook_call(self.test_params, 'Test Option') + + try: + self.ret_code = self.exec_wget() + except TestFailed as e: + raise e + finally: + self.stop_server() + + def do_test(self): + self.pre_hook_call() + self.call_test() + self.post_hook_call() + + def hook_call(self, configs, name): + for conf_name, conf_arg in configs.items(): + try: + # conf.find_conf(conf_name) returns the required conf class, + # then the class is instantiated with conf_arg, then the + # conf instance is called with this test instance itself to + # invoke the desired hook + conf.find_conf(conf_name)(conf_arg)(self) + except AttributeError: + self.stop_server() + raise TestFailed("%s %s not defined." % + (name, conf_name)) + + def pre_hook_call(self): + self.hook_call(self.pre_configs, 'Pre Test Function') + + def post_hook_call(self): + self.hook_call(self.post_configs, 'Post Test Function') + + def _replace_substring(self, string): + """ + Replace first occurrence of "{{name}}" in @string with + "getattr(self, name)". + """ + pattern = re.compile(r'\{\{\w+\}\}') + match_obj = pattern.search(string) + if match_obj is not None: + rep = match_obj.group() + temp = getattr(self, rep.strip('{}')) + string = string.replace(rep, temp) + return string + + def instantiate_server_by(self, protocol): + """ + Subclasses must override this method to actually instantiate servers + for test cases. + """ + raise NotImplementedError + + def stop_server(self): + """ + Subclasses must implement this method in order to stop certain + servers of different types. + """ + raise NotImplementedError + + @staticmethod + def get_server_rules(file_obj): + """ + The handling of expect header could be made much better when the + options are parsed in a true and better fashion. For an example, + see the commented portion in Test-basic-auth.py. + """ + server_rules = {} + for rule_name, rule in file_obj.rules.items(): + server_rules[rule_name] = conf.find_conf(rule_name)(rule) + return server_rules + + def __enter__(self): + """ + Initialization for with statement. + """ + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """ + If the with statement got executed with no exception raised, then + exc_type, exc_val, exc_tb are all None. + """ + if exc_val: + self.tests_passed = False + if exc_type is TestFailed: + print_red('Error: %s.' % exc_val.error) + else: + print_red('Unhandled exception caught.') + print(exc_val) + traceback.print_tb(exc_tb) + self.__test_cleanup() + + return self.tests_passed diff --git a/testenv/test/http_test.py b/testenv/test/http_test.py new file mode 100644 index 0000000..462ac6e --- /dev/null +++ b/testenv/test/http_test.py @@ -0,0 +1,61 @@ +from misc.colour_terminal import print_green +from server.http.http_server import HTTPd, HTTPSd +from test.base_test import BaseTest, HTTP, HTTPS + + +class HTTPTest(BaseTest): + + """ Class for HTTP Tests. """ + + # Temp Notes: It is expected that when pre-hook functions are executed, + # only an empty test-dir exists. pre-hook functions are executed just prior + # to the call to Wget is made. post-hook functions will be executed + # immediately after the call to Wget returns. + + def __init__(self, + pre_hook=None, + test_params=None, + post_hook=None, + protocols=(HTTP,), + req_protocols=None): + super(HTTPTest, self).__init__(pre_hook, + test_params, + post_hook, + protocols, + req_protocols) + + def setup(self): + self.server_setup() + self.ready = True + + def begin(self): + if not self.ready: + # this is to maintain compatibility with scripts that + # don't call setup() + self.setup() + with self: + # If any exception occurs, self.__exit__ will be immediately called. + # We must call the parent method in the end in order to verify + # whether the tests succeeded or not. + if self.ready: + self.do_test() + print_green("Test Passed.") + else: + self.tests_passed = False + return super(HTTPTest, self).begin() + + def instantiate_server_by(self, protocol): + server = {HTTP: HTTPd, + HTTPS: HTTPSd}[protocol]() + server.start() + + return server + + def request_remaining(self): + return [s.server_inst.get_req_headers() + for s in self.servers] + + def stop_server(self): + for server in self.servers: + server.server_inst.shutdown() +# vim: set ts=4 sts=4 sw=4 tw=80 et : |