diff options
Diffstat (limited to 'test')
23 files changed, 629 insertions, 194 deletions
diff --git a/test/integration/Packages-pdiff-usage b/test/integration/Packages-pdiff-usage index d1530a95c..ac962f29a 100644 --- a/test/integration/Packages-pdiff-usage +++ b/test/integration/Packages-pdiff-usage @@ -19,6 +19,7 @@ Description: Advanced front-end for dpkg . APT features complete installation ordering, multiple source capability and several other unique features, see the Users Guide in apt-doc. +Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c Package: oldstuff Version: 1.0 @@ -32,3 +33,4 @@ SHA1: 3c695e028f74d5c544deeddaaa1242desa81088c SHA256: b46fd1546151c545fe4bfa56a5cc0e7deaef23e2da3e4f129727fd660f28f050 Description: some cool but old stuff This package will disappear in the next mirror update +Description-md5: 1948af60eda0a41dfa9fe83f60eb8389 diff --git a/test/integration/Packages-pdiff-usage-new b/test/integration/Packages-pdiff-usage-new index 4f374b37f..f8d7b1958 100644 --- a/test/integration/Packages-pdiff-usage-new +++ b/test/integration/Packages-pdiff-usage-new @@ -22,6 +22,7 @@ Description: Advanced front-end for dpkg . APT features complete installation ordering, multiple source capability and several other unique features, see the Users Guide in apt-doc. +Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c Package: newstuff Version: 1.0 @@ -35,3 +36,4 @@ SHA1: 3c695e028f7a1ae324deeddaaa1242desa81088c SHA256: b46fd154615edefab321cc56a5cc0e7deaef23e2da3e4f129727fd660f28f050 Description: some cool and shiny new stuff This package will appear in the next mirror update +Description-md5: d5f89fbbc2ac69c43d7e4c9b67d82b6b diff --git a/test/integration/Packages-releasefile-verification b/test/integration/Packages-releasefile-verification index 29a385f4f..eb7327279 100644 --- a/test/integration/Packages-releasefile-verification +++ b/test/integration/Packages-releasefile-verification @@ -16,3 +16,4 @@ Description: Advanced front-end for dpkg . APT features complete installation ordering, multiple source capability and several other unique features, see the Users Guide in apt-doc. +Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c diff --git a/test/integration/Packages-releasefile-verification-new b/test/integration/Packages-releasefile-verification-new index e3b2edf1f..61509d157 100644 --- a/test/integration/Packages-releasefile-verification-new +++ b/test/integration/Packages-releasefile-verification-new @@ -19,3 +19,4 @@ Description: Advanced front-end for dpkg . APT features complete installation ordering, multiple source capability and several other unique features, see the Users Guide in apt-doc. +Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c diff --git a/test/integration/framework b/test/integration/framework index 9b01c3161..7dd7c20a7 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -38,7 +38,11 @@ msgtest() { } msgpass() { echo "${CPASS}PASS${CNORMAL}" >&2; } msgskip() { echo "${CWARNING}SKIP${CNORMAL}" >&2; } -msgfail() { echo "${CFAIL}FAIL${CNORMAL}" >&2; EXIT_CODE=$((EXIT_CODE+1)); } +msgfail() { + if [ $# -gt 0 ]; then echo "${CFAIL}FAIL: $*${CNORMAL}" >&2; + else echo "${CFAIL}FAIL${CNORMAL}" >&2; fi + EXIT_CODE=$((EXIT_CODE+1)); +} # enable / disable Debugging MSGLEVEL=${MSGLEVEL:-3} @@ -56,9 +60,9 @@ if [ $MSGLEVEL -le 2 ]; then msgpass() { echo -n " ${CPASS}P${CNORMAL}" >&2; } msgskip() { echo -n " ${CWARNING}S${CNORMAL}" >&2; } if [ -n "$CFAIL" ]; then - msgfail() { echo -n " ${CFAIL}FAIL${CNORMAL}" >&2; } + msgfail() { echo -n " ${CFAIL}FAIL${CNORMAL}" >&2; EXIT_CODE=$((EXIT_CODE+1)); } else - msgfail() { echo -n " ###FAILED###" >&2; } + msgfail() { echo -n " ###FAILED###" >&2; EXIT_CODE=$((EXIT_CODE+1)); } fi fi if [ $MSGLEVEL -le 3 ]; then @@ -114,6 +118,9 @@ gdb() { echo "gdb: run »$*«" APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} $(which gdb) ${BUILDDIRECTORY}/$1 } +http() { + LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/methods/http +} exitwithstatus() { # error if we about to overflow, but ... @@ -125,7 +132,11 @@ exitwithstatus() { } addtrap() { - CURRENTTRAP="$CURRENTTRAP $1" + if [ "$1" = 'prefix' ]; then + CURRENTTRAP="$2 $CURRENTTRAP" + else + CURRENTTRAP="$CURRENTTRAP $1" + fi trap "$CURRENTTRAP exitwithstatus;" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM } @@ -135,8 +146,7 @@ setupenvironment() { msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… " BUILDDIRECTORY="${TESTDIRECTORY}/../../build/bin" test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first" - local OLDWORKINGDIRECTORY=$(pwd) - addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;" + addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY;" cd $TMPWORKINGDIRECTORY mkdir rootdir aptarchive keys cd rootdir @@ -483,6 +493,7 @@ insertpackage() { local VERSION="$4" local DEPENDENCIES="$5" local PRIORITY="${6:-optional}" + local DESCRIPTION="${7}" local ARCHS="" for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do if [ "$arch" = 'all' -o "$arch" = 'none' ]; then @@ -504,11 +515,16 @@ Maintainer: Joe Sixpack <joe@example.org>" >> $FILE echo "Version: $VERSION Filename: pool/main/${NAME}/${NAME}_${VERSION}_${arch}.deb" >> $FILE test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE - echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} + echo -n 'Description: ' >> $FILE + if [ -z "$DESCRIPTION" ]; then + echo "an autogenerated dummy ${NAME}=${VERSION}/${RELEASE} If you find such a package installed on your system, YOU did something horribly wrong! They are autogenerated - und used only by testcases for APT and surf no other propose… -" >> $FILE + und used only by testcases for APT and surf no other propose…" >> $FILE + else + echo "$DESCRIPTION" >> $FILE + fi + echo >> $FILE done done } @@ -589,9 +605,12 @@ buildaptarchivefromfiles() { cat ${line} | bzip2 > ${line}.bz2 cat ${line} | xz --format=lzma > ${line}.lzma cat ${line} | xz > ${line}.xz + if [ -n "$1" ]; then + touch -d "$1" ${line}.gz ${line}.bz2 ${line}.lzma ${line}.xz + fi msgdone "info" done - generatereleasefiles + generatereleasefiles "$@" } # can be overridden by testcases for their pleasure @@ -683,9 +702,11 @@ setupaptarchive() { setupflataptarchive fi signreleasefiles - msgninfo "\tSync APT's cache with the archive… " - aptget update -qq - msgdone "info" + if [ "$1" != '--no-update' ]; then + msgninfo "\tSync APT's cache with the archive… " + aptget update -qq + msgdone "info" + fi } signreleasefiles() { @@ -701,40 +722,44 @@ signreleasefiles() { done for RELEASE in $(find aptarchive/ -name Release); do gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE} - gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o "$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" $RELEASE + local INRELEASE="$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" + gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o $INRELEASE $RELEASE + # we might have set a specific date for the Release file, so copy it + touch -d "$(stat --format "%y" ${RELEASE})" ${RELEASE}.gpg ${INRELEASE} done msgdone "info" } changetowebserver() { - if [ -n "$1" ] && ! test -x ${BUILDDIRECTORY}/aptwebserver; then - msgdie 'Need the aptwebserver when passing arguments' - fi - local LOG='/dev/null' if test -x ${BUILDDIRECTORY}/aptwebserver; then cd aptarchive - LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/aptwebserver $@ 2> $LOG > $LOG & - addtrap "kill $!;" + LD_LIBRARY_PATH=${BUILDDIRECTORY} ${BUILDDIRECTORY}/aptwebserver -o aptwebserver::fork=1 "$@" >$LOG 2>&1 + local PID="$(cat aptwebserver.pid)" + if [ -z "$PID" ]; then + msgdie 'Could not fork aptwebserver successfully' + fi + addtrap "kill $PID;" cd - > /dev/null + elif [ $# -gt 0 ]; then + msgdie 'Need the aptwebserver when passing arguments for the webserver' elif which weborf > /dev/null; then - weborf -xb aptarchive/ 2> $LOG > $LOG & + weborf -xb aptarchive/ >$LOG 2>&1 & addtrap "kill $!;" elif which gatling > /dev/null; then cd aptarchive - gatling -p 8080 -F -S 2> $LOG > $LOG & + gatling -p 8080 -F -S >$LOG 2>&1 & addtrap "kill $!;" cd - > /dev/null elif which lighttpd > /dev/null; then echo "server.document-root = \"$(readlink -f ./aptarchive)\" server.port = 8080 server.stat-cache-engine = \"disable\"" > lighttpd.conf - lighttpd -t -f lighttpd.conf 2> $LOG > $LOG || msgdie 'Can not change to webserver: our lighttpd config is invalid' - lighttpd -D -f lighttpd.conf 2> $LOG > $LOG & + lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid' + lighttpd -D -f lighttpd.conf >$LOG 2>&1 & addtrap "kill $!;" else - msgdie 'You have to install weborf or lighttpd first' - return 1 + msgdie 'You have to build aptwerbserver or install a webserver' fi local APTARCHIVE="file://$(readlink -f ./aptarchive)" for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do diff --git a/test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch b/test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch new file mode 100755 index 000000000..9e683b5b9 --- /dev/null +++ b/test/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch @@ -0,0 +1,47 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' 'i386' + +buildsimplenativepackage 'testing' 'amd64,i386' '0.8.15' 'stable' 'Depends: libtest' +buildsimplenativepackage 'libtest' 'amd64,i386' '0.8.15' 'stable' 'Multi-Arch: same' +buildsimplenativepackage 'libtest' 'amd64,i386' '1' 'unstable' 'Multi-Arch: same' + +# needed by the ftparchive.conf +cd aptarchive +ln -s ../incoming pool +createaptftparchiveconfig +cd - >/dev/null +# create an amd64 cdrom +sed -i 's#Architectures .*$#Architectures "amd64 source";#' aptarchive/ftparchive.conf +setupaptarchive --no-update +changetocdrom 'Debian APT Testdisk amd64 0.8.15' +mv rootdir/media/cdrom rootdir/media/cdrom-amd64 +addtrap 'prefix' "chmod -R +w $PWD/rootdir/media/cdrom-amd64/dists/;" +chmod -R -w rootdir/media/cdrom-amd64/dists +ln -s $PWD/rootdir/media/cdrom-amd64 $PWD/rootdir/media/cdrom +aptcdrom add -m -o quiet=1 +rm $PWD/rootdir/media/cdrom +# do it again to create a i386 cdrom +sed -i 's#Architectures .*$#Architectures "i386 source";#' aptarchive/ftparchive.conf +setupaptarchive --no-update +changetocdrom 'Debian APT Testdisk i386 0.8.15' +mv rootdir/media/cdrom rootdir/media/cdrom-i386 +addtrap 'prefix' "chmod -R +w $PWD/rootdir/media/cdrom-i386/dists/;" +chmod -R -w rootdir/media/cdrom-i386/dists +ln -s $PWD/rootdir/media/cdrom-i386 $PWD/rootdir/media/cdrom +aptcdrom add -m -o quiet=1 + +# play with the cdroms +testdpkgnotinstalled testing +aptget install testing -t stable -y #> /dev/null 2>&1 +testdpkginstalled testing + +testdpkgnotinstalled testing:i386 +aptget install testing:i386 -t stable -y #> /dev/null 2>&1 +testdpkginstalled testing:i386 + +aptget dist-upgrade -y diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom index f1c4fd9d3..6e3533152 100755 --- a/test/integration/test-apt-cdrom +++ b/test/integration/test-apt-cdrom @@ -7,7 +7,7 @@ setupenvironment configarchitecture 'amd64' 'i386' buildsimplenativepackage 'testing' 'amd64,i386' '0.8.15' 'stable' -setupaptarchive +setupaptarchive --no-update changetocdrom 'Debian APT Testdisk 0.8.15' @@ -24,7 +24,7 @@ cat Translation-de | xz --format=lzma > Translation-de.lzma cat Translation-de | xz > Translation-de.xz rm Translation-en Translation-de cd - > /dev/null -addtrap "chmod -R +w $PWD/rootdir/media/cdrom/dists/;" +addtrap 'prefix' "chmod -R +w $PWD/rootdir/media/cdrom/dists/;" chmod -R -w rootdir/media/cdrom/dists aptcdrom add -m -o quiet=1 > apt-cdrom.log 2>&1 diff --git a/test/integration/test-bug-590041-prefer-non-virtual-packages b/test/integration/test-bug-590041-prefer-non-virtual-packages index e0dd7737f..0ce4c1413 100755 --- a/test/integration/test-bug-590041-prefer-non-virtual-packages +++ b/test/integration/test-bug-590041-prefer-non-virtual-packages @@ -9,6 +9,7 @@ pkglibc6="Package: libc6 Architecture: armel Version: 2.11.2-2~0.3 Description: Embedded GNU C Library: Shared libraries +Description-md5: b8c1e0561b75e2dc6b6482a99079c3e4 Filename: pool/main/e/eglibc/libc6_2.11.2-2_armel.deb Installed-Size: 9740 MD5sum: f5b878ce5fb8aa01a7927fa1460df537 @@ -25,6 +26,7 @@ Architecture: i386 Version: 2.1.3-13~0.3 Replaces: libc6 (<< 2.2.5-13~0.3) Description: The Berkeley database routines [glibc 2.0/2.1 compatibility] +Description-md5: de1876f7fe7f7709a110875e145e38a8 Filename: pool/main/d/db1-compat/libdb1-compat_2.1.3-13_armel.deb Installed-Size: 136 MD5sum: 4043f176ab2b40b0c01bc1211b8c103c diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files index 4611b8b8e..a05ed5fa6 100755 --- a/test/integration/test-bug-595691-empty-and-broken-archive-files +++ b/test/integration/test-bug-595691-empty-and-broken-archive-files @@ -103,23 +103,23 @@ testoverhttp() { setupcompressor "$1" createemptyfile 'en' - testaptgetupdate "Get: http://localhost Packages [] -Get: http://localhost Translation-en + testaptgetupdate "Get: http://localhost:8080 Packages [] +Get: http://localhost:8080 Translation-en Reading package lists..." "empty file en.$COMPRESS over http" createemptyarchive 'en' - testaptgetupdate "Get: http://localhost Packages [] -Get: http://localhost Translation-en [] + testaptgetupdate "Get: http://localhost:8080 Packages [] +Get: http://localhost:8080 Translation-en [] Reading package lists..." "empty archive en.$COMPRESS over http" createemptyarchive 'Packages' - testaptgetupdate "Get: http://localhost Packages [] + testaptgetupdate "Get: http://localhost:8080 Packages [] Reading package lists..." "empty archive Packages.$COMPRESS over http" createemptyfile 'Packages' #FIXME: we should response with a good error message instead - testaptgetupdate "Get: http://localhost Packages -Err http://localhost Packages + testaptgetupdate "Get: http://localhost:8080 Packages +Err http://localhost:8080 Packages Empty files can't be valid archives W: Failed to fetch ${COMPRESSOR}:$(readlink -f rootdir/var/lib/apt/lists/partial/localhost:8080_Packages) Empty files can't be valid archives diff --git a/test/integration/test-bug-601016-description-translation b/test/integration/test-bug-601016-description-translation index 03fddbfda..33c209e9d 100755 --- a/test/integration/test-bug-601016-description-translation +++ b/test/integration/test-bug-601016-description-translation @@ -9,8 +9,9 @@ configarchitecture 'i386' 'amd64' # we need a valid locale here, otherwise the language configuration # will be overridden by LC_ALL=C LOCALE="$(echo "$LANG" | cut -d'_' -f 1)" +MD5Sum='Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c' -PACKAGESTANZA="Package: apt +PACKAGESTANZA='Package: apt Priority: important Section: admin Installed-Size: 5984 @@ -19,8 +20,7 @@ Architecture: i386 Version: 0.8.7 Filename: pool/main/a/apt/apt_0.8.7_i386.deb Size: 2140230 -MD5sum: 74769bfbcef9ebc4fa74f7a5271b9c08 -Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c" +MD5sum: 74769bfbcef9ebc4fa74f7a5271b9c08' PACKAGESTANZA2='Package: apt Priority: important @@ -31,22 +31,23 @@ Architecture: amd64 Version: 0.8.7 Filename: pool/main/a/apt/apt_0.8.7_amd64.deb Size: 2210342 -MD5sum: 4a869bfbdef9ebc9fa74f7a5271e8d1a -Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c' +MD5sum: 4a869bfbdef9ebc9fa74f7a5271e8d1a' echo "$PACKAGESTANZA Description: Advanced front-end for dpkg +$MD5Sum $PACKAGESTANZA2 -Description: Advanced front-end for dpkg" > aptarchive/Packages +Description: Advanced front-end for dpkg +$MD5Sum" > aptarchive/Packages echo "Package: apt -Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c Description-${LOCALE}: Mächtige Oberfläche für dpkg Das Paket bietet dem Nutzer technisch führende Methoden für den Zugriff auf den dpkg-Paketmanager. Es beinhaltet das apt-get-Werkzeug und die APT-Dselect-Methode. Beides sind einfache und sicherere Wege, - um Pakete zu installieren und Upgrades durchzuführen." | bzip2 > aptarchive/${LOCALE}.bz2 + um Pakete zu installieren und Upgrades durchzuführen. +$MD5Sum" | bzip2 > aptarchive/${LOCALE}.bz2 # the $LOCALE translation file will not be included as it is a flat archive it came from and therefore # its name can not be guessed correctly… (in non-flat archives the files are called Translation-*) @@ -54,10 +55,12 @@ echo 'APT::Cache::Generate "false";' > rootdir/etc/apt/apt.conf.d/00nogenerate NOLONGSTANZA="$PACKAGESTANZA Description: Advanced front-end for dpkg +$MD5Sum " ENGLISHSTANZA="$PACKAGESTANZA Description: Advanced front-end for dpkg +$MD5Sum " LOCALESTANZA="$PACKAGESTANZA @@ -66,6 +69,7 @@ Description-${LOCALE}: Mächtige Oberfläche für dpkg auf den dpkg-Paketmanager. Es beinhaltet das apt-get-Werkzeug und die APT-Dselect-Methode. Beides sind einfache und sicherere Wege, um Pakete zu installieren und Upgrades durchzuführen. +$MD5Sum " LOCALESTANZA2="$PACKAGESTANZA2 Description-${LOCALE}: Mächtige Oberfläche für dpkg @@ -73,6 +77,7 @@ Description-${LOCALE}: Mächtige Oberfläche für dpkg auf den dpkg-Paketmanager. Es beinhaltet das apt-get-Werkzeug und die APT-Dselect-Methode. Beides sind einfache und sicherere Wege, um Pakete zu installieren und Upgrades durchzuführen. +$MD5Sum " testrun() { @@ -97,28 +102,32 @@ testrun echo "$PACKAGESTANZA Description: Advanced front-end for dpkg +$MD5Sum $PACKAGESTANZA2 -Description: Advanced front-end for dpkg" > aptarchive/Packages +Description: Advanced front-end for dpkg +$MD5Sum" > aptarchive/Packages echo "Package: apt -Description-md5: d41ee493aa9fcc6cbc9ce4eb7069959c Description-en: Advanced front-end for dpkg This is Debian's next generation front-end for the dpkg package manager. It provides the apt-get utility and APT dselect method that provides a - simpler, safer way to install and upgrade packages." | bzip2 > aptarchive/en.bz2 + simpler, safer way to install and upgrade packages. +$MD5Sum" | bzip2 > aptarchive/en.bz2 ENGLISHSTANZA="$PACKAGESTANZA Description-en: Advanced front-end for dpkg This is Debian's next generation front-end for the dpkg package manager. It provides the apt-get utility and APT dselect method that provides a simpler, safer way to install and upgrade packages. +$MD5Sum " ENGLISHSTANZA2="$PACKAGESTANZA2 Description-en: Advanced front-end for dpkg This is Debian's next generation front-end for the dpkg package manager. It provides the apt-get utility and APT dselect method that provides a simpler, safer way to install and upgrade packages. +$MD5Sum " testrun diff --git a/test/integration/test-bug-602412-dequote-redirect b/test/integration/test-bug-602412-dequote-redirect index 43ecda867..c20443559 100755 --- a/test/integration/test-bug-602412-dequote-redirect +++ b/test/integration/test-bug-602412-dequote-redirect @@ -19,12 +19,11 @@ msgtest 'Test redirection works in' 'apt-get update' aptget update -qq && msgpass || msgfail # check that I-M-S header is kept in redirections -testequal 'Hit http://localhost unstable Release.gpg -Hit http://localhost unstable Release -Hit http://localhost unstable/main Sources -Hit http://localhost unstable/main amd64 Packages -Hit http://localhost unstable/main Translation-en -Reading package lists...' aptget update +testequal 'Hit http://localhost:8080 unstable InRelease +Hit http://localhost:8080 unstable/main Sources +Hit http://localhost:8080 unstable/main amd64 Packages +Hit http://localhost:8080 unstable/main Translation-en +Reading package lists...' aptget update #-o debug::pkgacquire=1 -o debug::pkgacquire::worker=1 msgtest 'Test redirection works in' 'package download' aptget install unrelated --download-only -qq && msgpass || msgfail diff --git a/test/integration/test-bug-691453-apt-cache-search-multi-pattern b/test/integration/test-bug-691453-apt-cache-search-multi-pattern new file mode 100755 index 000000000..0367892fc --- /dev/null +++ b/test/integration/test-bug-691453-apt-cache-search-multi-pattern @@ -0,0 +1,33 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'native' + +insertpackage 'unstable' 'foobar' 'native' '1' '' '' 'funky tool' +insertpackage 'unstable' 'coolstuff' 'native' '1' '' '' 'funky tool just like foo and bar' +insertpackage 'unstable' 'foo' 'native' '1' '' '' 'tool best used with bar' +insertpackage 'unstable' 'bar' 'native' '1' '' '' 'tool best used with foo' +insertpackage 'unstable' 'baz' 'native' '1' 'Provides: bar' '' 'alternative tool best used with foo' + +setupaptarchive + +# in this special case the following queries should be equal +FOOBAR='foobar - funky tool +coolstuff - funky tool just like foo and bar +foo - tool best used with bar +bar - tool best used with foo +baz - alternative tool best used with foo' + +testequal "$FOOBAR" aptcache search foo +testequal "$FOOBAR" aptcache search bar +testequal "$FOOBAR" aptcache search foo bar + +testequal 'foobar - funky tool +foo - tool best used with bar' aptcache search -n foo +testequal 'foobar - funky tool +bar - tool best used with foo +baz - alternative tool best used with foo' aptcache search -n bar +testequal 'foobar - funky tool' aptcache search -n foo bar diff --git a/test/integration/test-bug-712435-missing-descriptions b/test/integration/test-bug-712435-missing-descriptions new file mode 100755 index 000000000..9b3c2ee50 --- /dev/null +++ b/test/integration/test-bug-712435-missing-descriptions @@ -0,0 +1,89 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +PACKAGESTANZA='Version: 0.9.7.8 +Installed-Size: 3270 +Maintainer: APT Development Team <deity@lists.debian.org> +Architecture: amd64 +Filename: pool/main/a/apt/apt_0.9.7.8_amd64.deb +MD5sum: 3a622acda41620df50aa22a9fac6f32e' + +DESCRIPTION='Description: commandline package manager + This APT has Super Cow Powers.' + +TRANSDESCRIPTION='Description-en: commandline package manager + This APT has translated Super Cow Powers.' + +echo "Package: apt-normal +$PACKAGESTANZA +$DESCRIPTION +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +Package: apt-both-below +$PACKAGESTANZA +$DESCRIPTION +$TRANSDESCRIPTION +Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + +Package: apt-both-middle +$PACKAGESTANZA +$DESCRIPTION +Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +$TRANSDESCRIPTION + +Package: apt-both-top +$PACKAGESTANZA +Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +$DESCRIPTION +$TRANSDESCRIPTION + +Package: apt-trans +$PACKAGESTANZA +$TRANSDESCRIPTION +Description-md5: cccccccccccccccccccccccccccccccc + +Package: apt-md5 +$PACKAGESTANZA +Description-md5: dddddddddddddddddddddddddddddddd + +Package: apt-none +$PACKAGESTANZA" > aptarchive/Packages + +setupaptarchive + +testequal "Package: apt-normal +$PACKAGESTANZA +$DESCRIPTION +Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +" aptcache show apt-normal + +# displaying the translated Description would be equally valid, +# but we assume only one description is in a Packages file and +# so we prefer "Description" over "Description-*" currently. +for variant in 'below' 'middle' 'top'; do + testequal "Package: apt-both-$variant +$PACKAGESTANZA +$DESCRIPTION +Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +" aptcache show apt-both-$variant +done + +testequal "Package: apt-trans +$PACKAGESTANZA +$TRANSDESCRIPTION +Description-md5: cccccccccccccccccccccccccccccccc +" aptcache show apt-trans + +testequal "Package: apt-md5 +$PACKAGESTANZA +Description-md5: dddddddddddddddddddddddddddddddd +" aptcache show apt-md5 + +testequal "Package: apt-none +$PACKAGESTANZA +" aptcache show apt-none diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing index bd68fccf6..6764fefff 100755 --- a/test/integration/test-cve-2013-1051-InRelease-parsing +++ b/test/integration/test-cve-2013-1051-InRelease-parsing @@ -12,7 +12,7 @@ insertpackage 'stable' 'good-pkg' 'all' '1.0' setupaptarchive changetowebserver -ARCHIVE='http://localhost/' +ARCHIVE='http://localhost:8080/' msgtest 'Initial apt-get update should work with' 'InRelease' aptget update -qq && msgpass || msgfail @@ -37,7 +37,7 @@ sed -i '/^-----BEGIN PGP SIGNATURE-----/,/^-----END PGP SIGNATURE-----/ s/^$/ / # we append the (evil unsigned) Release file to the (good signed) InRelease cat aptarchive/dists/stable/Release >> aptarchive/dists/stable/InRelease - +touch -d '+1hour' aptarchive/dists/stable/InRelease # ensure the update fails # useful for debugging to add "-o Debug::pkgAcquire::auth=true" diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage index 29301d07d..e45326970 100755 --- a/test/integration/test-pdiff-usage +++ b/test/integration/test-pdiff-usage @@ -35,7 +35,7 @@ SHA1-History: SHA1-Patches: 7651fc0ac57cd83d41c63195a9342e2db5650257 19722 2010-08-18-0814.28 $(sha1sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE)" > $PATCHINDEX -generatereleasefiles +generatereleasefiles '+1hour' signreleasefiles find aptarchive -name 'Packages*' -type f -delete aptget update -qq diff --git a/test/integration/test-prefer-higher-priority-providers b/test/integration/test-prefer-higher-priority-providers new file mode 100755 index 000000000..64b901dd0 --- /dev/null +++ b/test/integration/test-prefer-higher-priority-providers @@ -0,0 +1,106 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'native' + +insertpackage 'unstable' 'foo' 'all' '1' 'Provides: stuff' 'important' +insertpackage 'unstable' 'bar' 'all' '1' 'Provides: stuff' 'optional' +insertpackage 'unstable' 'baz' 'all' '1' 'Provides: stuff' 'extra' +insertpackage 'unstable' 'awesome' 'all' '1' 'Depends: stuff' + +setupaptarchive + +testequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +The following NEW packages will be installed: + awesome foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1 unstable [all]) +Inst awesome (1 unstable [all]) +Conf foo (1 unstable [all]) +Conf awesome (1 unstable [all])' aptget install awesome -s + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + awesome foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1 unstable [all]) +Inst awesome (1 unstable [all]) +Conf foo (1 unstable [all]) +Conf awesome (1 unstable [all])' aptget install awesome foo -s + +testequal "Reading package lists... +Building dependency tree... +Package 'bar' is not installed, so not removed +Package 'baz' is not installed, so not removed +The following extra packages will be installed: + foo +The following NEW packages will be installed: + awesome foo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1 unstable [all]) +Inst awesome (1 unstable [all]) +Conf foo (1 unstable [all]) +Conf awesome (1 unstable [all])" aptget install awesome bar- baz- -s + +testequal "Reading package lists... +Building dependency tree... +Package 'foo' is not installed, so not removed +The following extra packages will be installed: + bar +The following NEW packages will be installed: + awesome bar +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1 unstable [all]) +Inst awesome (1 unstable [all]) +Conf bar (1 unstable [all]) +Conf awesome (1 unstable [all])" aptget install awesome foo- -s + +testequal "Reading package lists... +Building dependency tree... +Package 'foo' is not installed, so not removed +Package 'baz' is not installed, so not removed +The following extra packages will be installed: + bar +The following NEW packages will be installed: + awesome bar +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1 unstable [all]) +Inst awesome (1 unstable [all]) +Conf bar (1 unstable [all]) +Conf awesome (1 unstable [all])" aptget install awesome foo- baz- -s + +testequal "Reading package lists... +Building dependency tree... +Package 'foo' is not installed, so not removed +Package 'bar' is not installed, so not removed +The following extra packages will be installed: + baz +The following NEW packages will be installed: + awesome baz +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst baz (1 unstable [all]) +Inst awesome (1 unstable [all]) +Conf baz (1 unstable [all]) +Conf awesome (1 unstable [all])" aptget install awesome foo- bar- -s + +testequal "Reading package lists... +Building dependency tree... +Package 'foo' is not installed, so not removed +Package 'bar' is not installed, so not removed +Package 'baz' is not installed, so not removed +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + awesome : Depends: stuff +E: Unable to correct problems, you have held broken packages." aptget install awesome foo- bar- baz- -s diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 01fb2e529..e56f458d3 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -37,7 +37,7 @@ The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. After this operation, 5370 kB of additional disk space will be used. -Get:1 http://localhost/ apt 0.7.25.3 +Get:1 http://localhost:8080/ apt 0.7.25.3 Download complete and in download only mode' aptget install apt -dy } @@ -50,7 +50,7 @@ The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. After this operation, 5808 kB of additional disk space will be used. -Get:1 http://localhost/ apt 0.8.0~pre1 +Get:1 http://localhost:8080/ apt 0.8.0~pre1 Download complete and in download only mode' aptget install apt -dy } @@ -184,5 +184,5 @@ runtest2 DELETEFILE="InRelease" runtest -#DELETEFILE="Release.gpg" -#runtest +DELETEFILE="Release.gpg" +runtest diff --git a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall index 25cccf067..1576c396c 100755 --- a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall +++ b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall @@ -1,23 +1,6 @@ #!/bin/sh set -e -ensure_n_canary_strings_in_dir() { - DIR=$1 - CANARY_STRING=$2 - EXPECTED_N=$3 - - msgtest "Testing for $EXPECTED_N canary strings '$CANARY_STRING' in in" "$DIR" - - N=$(grep "$CANARY_STRING" $DIR/* 2>/dev/null |wc -l ) - if [ "$N" = "$EXPECTED_N" ]; then - msgpass - return 0 - else - msgfail "Expected $EXPECTED_N canaries, got $N" - return 1 - fi -} - TESTDIR=$(readlink -f $(dirname $0)) . $TESTDIR/framework @@ -25,23 +8,57 @@ setupenvironment configarchitecture 'native' insertpackage 'unstable' 'unrelated' 'all' '1.0' 'stable' +insertsource 'unstable' 'unrelated' 'all' '1.0' 'stable' + +echo 'ni ni ni' > aptarchive/knights setupaptarchive -changetowebserver --simulate-paywall +changetowebserver -o 'aptwebserver::overwrite::.*::filename=/knights' + +msgtest 'Acquire test file from the webserver to check' 'overwrite' +echo '601 Configuration +Config-Item: Acquire::http::DependOnSTDIN=0 + +600 Acquire URI +URI: http://localhost:8080/holygrail +Filename: knights-talking +' | http >/dev/null 2>&1 && msgpass || msgfail +testfileequal knights-talking 'ni ni ni' + +ensure_n_canary_strings_in_dir() { + local DIR="$1" + local CANARY_STRING="$2" + local EXPECTED_N="$3" + + msgtest "Testing in $DIR for $EXPECTED_N canary" "$CANARY_STRING" + local N=$(grep "$CANARY_STRING" $DIR/* 2>/dev/null |wc -l ) + test "$N" = "$EXPECTED_N" && msgpass || msgfail "Expected $EXPECTED_N canaries, got $N" +} +LISTS='rootdir/var/lib/apt/lists' rm -rf rootdir/var/lib/apt/lists -msgtest 'excpected failure of' 'apt-get update' -aptget update -qq 2>/dev/null && msgfail || msgpass +msgtest 'Got expected NODATA failure in' 'apt-get update' +aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail -ensure_n_canary_strings_in_dir rootdir/var/lib/apt/lists/ 'ni ni ni' 0 -testequal 'partial' ls rootdir/var/lib/apt/lists/ +ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 +testequal 'partial' ls $LISTS -# again, this time with pre-existing files valid data -for f in Release Release.gpg main_binary-amd64_Packages stable_main_source_Sources; do - echo "canary" > rootdir/var/lib/apt/lists/localhost:8080_dists_stable_${f} +# and again with pre-existing files with "valid data" which should remain +for f in Release Release.gpg main_binary-amd64_Packages main_source_Sources; do + echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_${f} done -# this will fail, the important part is that the canaries remain +msgtest 'Got expected NODATA failure in' 'apt-get update' +aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail + +ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 4 +ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 + +# and now with a pre-existing InRelease file +echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_InRelease +rm -f $LISTS/localhost:8080_dists_stable_Release $LISTS/localhost:8080_dists_stable_Release.gpg msgtest 'excpected failure of' 'apt-get update' -aptget update -qq 2>/dev/null && msgfail || msgpass -ensure_n_canary_strings_in_dir rootdir/var/lib/apt/lists/ 'canary' 4 +aptget update -qq 2>&1 | grep -q 'E: GPG error.*NODATA' && msgpass || msgfail + +ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 3 +ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 diff --git a/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages b/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages new file mode 100755 index 000000000..7f3b05e59 --- /dev/null +++ b/test/integration/test-very-tight-loop-configure-with-unpacking-new-packages @@ -0,0 +1,46 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +# the difference between version 3 and 4 is the new package 'ure' which +# we have to unpack before we start configuring parts of the loop +insertinstalledpackage 'libreoffice' 'amd64' '3' 'Depends: libreoffice-core (= 3)' +insertinstalledpackage 'libreoffice-core' 'amd64' '3' 'Depends: libreoffice-common (>= 3)' +insertinstalledpackage 'libreoffice-common' 'all' '3' 'Depends: libreoffice-style +Breaks: libreoffice-core (>= 3+), libreoffice-core (<= 3~), libreoffice-style-galaxy (>= 3+), libreoffice-style-galaxy (<= 3~)' +insertinstalledpackage 'libreoffice-style-galaxy' 'amd64' '3' 'Depends: libreoffice-core +Provides: libreoffice-style' + +buildsimplenativepackage 'libreoffice' 'amd64' '4' 'sid' 'Depends: libreoffice-core (= 4)' +buildsimplenativepackage 'libreoffice-core' 'amd64' '4' 'sid' 'Depends: libreoffice-common (>= 4) +Breaks: libreoffice-common (<< 4), libreoffice-style-galaxy (<< 4)' +buildsimplenativepackage 'libreoffice-common' 'all' '4' 'sid' 'Depends: libreoffice-style, ure +Breaks: libreoffice-core (>= 4+), libreoffice-core (<= 4~), libreoffice-style-galaxy (>= 4+), libreoffice-style-galaxy (<= 4~)' +buildsimplenativepackage 'libreoffice-style-galaxy' 'amd64' '4' 'sid' 'Depends: libreoffice-core +Provides: libreoffice-style' + +buildsimplenativepackage 'ure' 'amd64' '4' 'sid' + +setupaptarchive + +testequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + ure +The following packages will be upgraded: + libreoffice libreoffice-common libreoffice-core libreoffice-style-galaxy +4 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst libreoffice [3] (4 sid [amd64]) [] +Inst libreoffice-style-galaxy [3] (4 sid [amd64]) [libreoffice-common:amd64 on libreoffice-style-galaxy:amd64] [libreoffice-common:amd64 ] +Inst libreoffice-core [3] (4 sid [amd64]) [libreoffice-core:amd64 on libreoffice-common:amd64] [libreoffice-common:amd64 on libreoffice-core:amd64] [libreoffice-common:amd64 on libreoffice-style-galaxy:amd64] [libreoffice-common:amd64 ] +Inst libreoffice-common [3] (4 sid [all]) [] +Inst ure (4 sid [amd64]) +Conf ure (4 sid [amd64]) +Conf libreoffice-style-galaxy (4 sid [amd64]) +Conf libreoffice-common (4 sid [all]) +Conf libreoffice-core (4 sid [amd64]) +Conf libreoffice (4 sid [amd64])' aptget dist-upgrade -s diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc index ff60d64a3..dc17d4991 100644 --- a/test/interactive-helper/aptwebserver.cc +++ b/test/interactive-helper/aptwebserver.cc @@ -23,8 +23,10 @@ #include <dirent.h> #include <signal.h> -char const * const httpcodeToStr(int const httpcode) { /*{{{*/ - switch (httpcode) { +char const * const httpcodeToStr(int const httpcode) /*{{{*/ +{ + switch (httpcode) + { // Informational 1xx case 100: return "100 Continue"; case 101: return "101 Switching Protocols"; @@ -63,6 +65,7 @@ char const * const httpcodeToStr(int const httpcode) { /*{{{*/ case 415: return "415 Unsupported Media Type"; case 416: return "416 Requested range not satisfiable"; case 417: return "417 Expectation Failed"; + case 418: return "418 I'm a teapot"; // Server error 5xx case 500: return "500 Internal Server Error"; case 501: return "501 Not Implemented"; @@ -74,7 +77,8 @@ char const * const httpcodeToStr(int const httpcode) { /*{{{*/ return NULL; } /*}}}*/ -void addFileHeaders(std::list<std::string> &headers, FileFd &data) { /*{{{*/ +void addFileHeaders(std::list<std::string> &headers, FileFd &data) /*{{{*/ +{ std::ostringstream contentlength; contentlength << "Content-Length: " << data.FileSize(); headers.push_back(contentlength.str()); @@ -82,27 +86,17 @@ void addFileHeaders(std::list<std::string> &headers, FileFd &data) { /*{{{*/ std::string lastmodified("Last-Modified: "); lastmodified.append(TimeRFC1123(data.ModificationTime())); headers.push_back(lastmodified); - - std::string const fileext = flExtension(data.Name()); - if (fileext.empty() == false && fileext != data.Name()) { - std::string confcontenttype("aptwebserver::ContentType::"); - confcontenttype.append(fileext); - std::string const contenttype = _config->Find(confcontenttype); - if (contenttype.empty() == false) { - std::string header("Content-Type: "); - header.append(contenttype); - headers.push_back(header); - } - } } /*}}}*/ -void addDataHeaders(std::list<std::string> &headers, std::string &data) {/*{{{*/ +void addDataHeaders(std::list<std::string> &headers, std::string &data) /*{{{*/ +{ std::ostringstream contentlength; contentlength << "Content-Length: " << data.size(); headers.push_back(contentlength.str()); } /*}}}*/ -bool sendHead(int const client, int const httpcode, std::list<std::string> &headers) { /*{{{*/ +bool sendHead(int const client, int const httpcode, std::list<std::string> &headers)/*{{{*/ +{ std::string response("HTTP/1.1 "); response.append(httpcodeToStr(httpcode)); headers.push_front(response); @@ -113,12 +107,11 @@ bool sendHead(int const client, int const httpcode, std::list<std::string> &head date.append(TimeRFC1123(time(NULL))); headers.push_back(date); - headers.push_back("Accept-Ranges: bytes"); - std::clog << ">>> RESPONSE >>>" << std::endl; bool Success = true; for (std::list<std::string>::const_iterator h = headers.begin(); - Success == true && h != headers.end(); ++h) { + Success == true && h != headers.end(); ++h) + { Success &= FileFd::Write(client, h->c_str(), h->size()); if (Success == true) Success &= FileFd::Write(client, "\r\n", 2); @@ -130,11 +123,13 @@ bool sendHead(int const client, int const httpcode, std::list<std::string> &head return Success; } /*}}}*/ -bool sendFile(int const client, FileFd &data) { /*{{{*/ +bool sendFile(int const client, FileFd &data) /*{{{*/ +{ bool Success = true; char buffer[500]; unsigned long long actual = 0; - while ((Success &= data.Read(buffer, sizeof(buffer), &actual)) == true) { + while ((Success &= data.Read(buffer, sizeof(buffer), &actual)) == true) + { if (actual == 0) break; if (Success == true) @@ -145,7 +140,8 @@ bool sendFile(int const client, FileFd &data) { /*{{{*/ return Success; } /*}}}*/ -bool sendData(int const client, std::string const &data) { /*{{{*/ +bool sendData(int const client, std::string const &data) /*{{{*/ +{ bool Success = true; Success &= FileFd::Write(client, data.c_str(), data.size()); if (Success == true) @@ -153,7 +149,9 @@ bool sendData(int const client, std::string const &data) { /*{{{*/ return Success; } /*}}}*/ -void sendError(int const client, int const httpcode, std::string const &request, bool content, std::string const &error = "") { /*{{{*/ +void sendError(int const client, int const httpcode, std::string const &request,/*{{{*/ + bool content, std::string const &error = "") +{ std::list<std::string> headers; std::string response("<html><head><title>"); response.append(httpcodeToStr(httpcode)).append("</title></head>"); @@ -168,7 +166,9 @@ void sendError(int const client, int const httpcode, std::string const &request, sendData(client, response); } /*}}}*/ -void sendRedirect(int const client, int const httpcode, std::string const &uri, std::string const &request, bool content) { /*{{{*/ +void sendRedirect(int const client, int const httpcode, std::string const &uri,/*{{{*/ + std::string const &request, bool content) +{ std::list<std::string> headers; std::string response("<html><head><title>"); response.append(httpcodeToStr(httpcode)).append("</title></head>"); @@ -188,8 +188,8 @@ void sendRedirect(int const client, int const httpcode, std::string const &uri, sendData(client, response); } /*}}}*/ -// sendDirectoryLisiting /*{{{*/ -int filter_hidden_files(const struct dirent *a) { +int filter_hidden_files(const struct dirent *a) /*{{{*/ +{ if (a->d_name[0] == '.') return 0; #ifdef _DIRENT_HAVE_D_TYPE @@ -225,13 +225,17 @@ int grouped_alpha_case_sort(const struct dirent **a, const struct dirent **b) { } return strcasecmp((*a)->d_name, (*b)->d_name); } -void sendDirectoryListing(int const client, std::string const &dir, std::string const &request, bool content) { + /*}}}*/ +void sendDirectoryListing(int const client, std::string const &dir, /*{{{*/ + std::string const &request, bool content) +{ std::list<std::string> headers; std::ostringstream listing; struct dirent **namelist; int const counter = scandir(dir.c_str(), &namelist, filter_hidden_files, grouped_alpha_case_sort); - if (counter == -1) { + if (counter == -1) + { sendError(client, 500, request, content); return; } @@ -251,11 +255,14 @@ void sendDirectoryListing(int const client, std::string const &dir, std::string std::string filename(dir); filename.append("/").append(namelist[i]->d_name); stat(filename.c_str(), &fs); - if (S_ISDIR(fs.st_mode)) { + if (S_ISDIR(fs.st_mode)) + { listing << "<tr><td>d</td>" << "<td><a href=\"" << namelist[i]->d_name << "/\">" << namelist[i]->d_name << "</a></td>" << "<td>-</td>"; - } else { + } + else + { listing << "<tr><td>f</td>" << "<td><a href=\"" << namelist[i]->d_name << "\">" << namelist[i]->d_name << "</a></td>" << "<td>" << SizeToStr(fs.st_size) << "B</td>"; @@ -271,7 +278,10 @@ void sendDirectoryListing(int const client, std::string const &dir, std::string sendData(client, response); } /*}}}*/ -bool parseFirstLine(int const client, std::string const &request, std::string &filename, bool &sendContent, bool &closeConnection) { /*{{{*/ +bool parseFirstLine(int const client, std::string const &request, /*{{{*/ + std::string &filename, bool &sendContent, + bool &closeConnection) +{ if (strncmp(request.c_str(), "HEAD ", 5) == 0) sendContent = false; if (strncmp(request.c_str(), "GET ", 4) != 0) @@ -285,7 +295,8 @@ bool parseFirstLine(int const client, std::string const &request, std::string &f for (; request[filestart] == ' '; ++filestart); size_t fileend = request.rfind(' ', lineend); if (lineend == std::string::npos || filestart == std::string::npos || - fileend == std::string::npos || filestart == fileend) { + fileend == std::string::npos || filestart == fileend) + { sendError(client, 500, request, sendContent, "Filename can't be extracted"); return false; } @@ -296,13 +307,15 @@ bool parseFirstLine(int const client, std::string const &request, std::string &f closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "Keep-Alive") != 0; else if (strncmp(request.c_str() + httpstart, "HTTP/1.0\r", 9) == 0) closeConnection = strcasecmp(LookupTag(request, "Connection", "Keep-Alive").c_str(), "close") == 0; - else { - sendError(client, 500, request, sendContent, "Not an HTTP/1.{0,1} request"); + else + { + sendError(client, 500, request, sendContent, "Not a HTTP/1.{0,1} request"); return false; } filename = request.substr(filestart, fileend - filestart); - if (filename.find(' ') != std::string::npos) { + if (filename.find(' ') != std::string::npos) + { sendError(client, 500, request, sendContent, "Filename contains an unencoded space"); return false; } @@ -312,7 +325,8 @@ bool parseFirstLine(int const client, std::string const &request, std::string &f if (filename.empty() == true || filename[0] != '/' || strncmp(filename.c_str(), "//", 2) == 0 || filename.find_first_of("\r\n\t\f\v") != std::string::npos || - filename.find("/../") != std::string::npos) { + filename.find("/../") != std::string::npos) + { sendError(client, 400, request, sendContent, "Filename contains illegal character (sequence)"); return false; } @@ -336,7 +350,8 @@ int main(int const argc, const char * argv[]) }; CommandLine CmdL(Args, _config); - if(CmdL.Parse(argc,argv) == false) { + if(CmdL.Parse(argc,argv) == false) + { _error->DumpErrors(); exit(1); } @@ -345,7 +360,8 @@ int main(int const argc, const char * argv[]) // ignore SIGPIPE, this can happen on write() if the socket closes connection signal(SIGPIPE, SIG_IGN); int sock = socket(AF_INET6, SOCK_STREAM, 0); - if(sock < 0 ) { + if(sock < 0) + { _error->Errno("aptwerbserver", "Couldn't create socket"); _error->DumpErrors(std::cerr); return 1; @@ -358,7 +374,7 @@ int main(int const argc, const char * argv[]) // ensure that we accept all connections: v4 or v6 int const iponly = 0; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &iponly, sizeof(iponly)); - // to not linger to an address + // to not linger on an address int const enable = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); @@ -368,29 +384,66 @@ int main(int const argc, const char * argv[]) locAddr.sin6_port = htons(port); locAddr.sin6_addr = in6addr_any; - if (bind(sock, (struct sockaddr*) &locAddr, sizeof(locAddr)) < 0) { + if (bind(sock, (struct sockaddr*) &locAddr, sizeof(locAddr)) < 0) + { _error->Errno("aptwerbserver", "Couldn't bind"); _error->DumpErrors(std::cerr); return 2; } + FileFd pidfile; + if (_config->FindB("aptwebserver::fork", false) == true) + { + std::string const pidfilename = _config->Find("aptwebserver::pidfile", "aptwebserver.pid"); + int const pidfilefd = GetLock(pidfilename); + if (pidfilefd < 0 || pidfile.OpenDescriptor(pidfilefd, FileFd::WriteOnly) == false) + { + _error->Errno("aptwebserver", "Couldn't acquire lock on pidfile '%s'", pidfilename.c_str()); + _error->DumpErrors(std::cerr); + return 3; + } + + pid_t child = fork(); + if (child < 0) + { + _error->Errno("aptwebserver", "Forking failed"); + _error->DumpErrors(std::cerr); + return 4; + } + else if (child != 0) + { + // successfully forked: ready to serve! + std::string pidcontent; + strprintf(pidcontent, "%d", child); + pidfile.Write(pidcontent.c_str(), pidcontent.size()); + if (_error->PendingError() == true) + { + _error->DumpErrors(std::cerr); + return 5; + } + std::cout << "Successfully forked as " << child << std::endl; + return 0; + } + } + if (simulate_broken_server) { std::clog << "Simulating a broken web server that return nonsense " "for all querries" << std::endl; } else { std::clog << "Serving ANY file on port: " << port << std::endl; } - listen(sock, 1); /*}}}*/ std::vector<std::string> messages; int client; - while ((client = accept(sock, NULL, NULL)) != -1) { + while ((client = accept(sock, NULL, NULL)) != -1) + { std::clog << "ACCEPT client " << client << " on socket " << sock << std::endl; - while (ReadMessages(client, messages)) { + while (ReadMessages(client, messages)) + { bool closeConnection = false; for (std::vector<std::string>::const_iterator m = messages.begin(); m != messages.end() && closeConnection == false; ++m) { @@ -403,7 +456,8 @@ int main(int const argc, const char * argv[]) continue; std::string host = LookupTag(*m, "Host", ""); - if (host.empty() == true) { + if (host.empty() == true) + { // RFC 2616 §14.23 requires Host sendError(client, 400, *m, sendContent, "Host header is required"); continue; @@ -414,90 +468,80 @@ int main(int const argc, const char * argv[]) addDataHeaders(headers, data); sendHead(client, 200, headers); sendData(client, data); + continue; } - else if (RealFileExists(filename) == true) { + + // string replacements in the requested filename + ::Configuration::Item const *Replaces = _config->Tree("aptwebserver::redirect::replace"); + if (Replaces != NULL) + { + std::string redirect = "/" + filename; + for (::Configuration::Item *I = Replaces->Child; I != NULL; I = I->Next) + redirect = SubstVar(redirect, I->Tag, I->Value); + redirect.erase(0,1); + if (redirect != filename) + { + sendRedirect(client, 301, redirect, *m, sendContent); + continue; + } + } + + ::Configuration::Item const *Overwrite = _config->Tree("aptwebserver::overwrite"); + if (Overwrite != NULL) + { + for (::Configuration::Item *I = Overwrite->Child; I != NULL; I = I->Next) + { + regex_t *pattern = new regex_t; + int const res = regcomp(pattern, I->Tag.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB); + if (res != 0) + { + char error[300]; + regerror(res, pattern, error, sizeof(error)); + sendError(client, 500, *m, sendContent, error); + continue; + } + if (regexec(pattern, filename.c_str(), 0, 0, 0) == 0) + { + filename = _config->Find("aptwebserver::overwrite::" + I->Tag + "::filename", filename); + if (filename[0] == '/') + filename.erase(0,1); + regfree(pattern); + break; + } + regfree(pattern); + } + } + + // deal with the request + if (RealFileExists(filename) == true) + { FileFd data(filename, FileFd::ReadOnly); std::string condition = LookupTag(*m, "If-Modified-Since", ""); - if (condition.empty() == false) { + if (condition.empty() == false) + { time_t cache; if (RFC1123StrToTime(condition.c_str(), cache) == true && - cache >= data.ModificationTime()) { + cache >= data.ModificationTime()) + { sendHead(client, 304, headers); continue; } } - condition = LookupTag(*m, "If-Range", ""); - bool ignoreRange = false; - if (condition.empty() == false) { - time_t cache; - if (RFC1123StrToTime(condition.c_str(), cache) == false || - cache < data.ModificationTime()) - ignoreRange = true; - } - condition = LookupTag(*m, "Range", ""); - if (ignoreRange == false && condition.empty() == false && - strncmp(condition.c_str(), "bytes=", 6) == 0) { - size_t end = condition.find(','); - // FIXME: support multiple byte-ranges - if (end == std::string::npos) { - size_t start = 6; - unsigned long long filestart = strtoull(condition.c_str() + start, NULL, 10); - // FIXME: no fileend support - size_t dash = condition.find('-') + 1; - unsigned long long fileend = strtoull(condition.c_str() + dash, NULL, 10); - unsigned long long filesize = data.FileSize(); - if (fileend == 0 || fileend == filesize) { - if (filesize > filestart) { - data.Skip(filestart); - std::ostringstream contentlength; - contentlength << "Content-Length: " << (filesize - filestart); - headers.push_back(contentlength.str()); - std::ostringstream contentrange; - contentrange << "Content-Range: bytes " << filestart << "-" - << filesize - 1 << "/" << filesize; - headers.push_back(contentrange.str()); - sendHead(client, 206, headers); - if (sendContent == true) - sendFile(client, data); - continue; - } else { - headers.push_back("Content-Length: 0"); - std::ostringstream contentrange; - contentrange << "Content-Range: bytes 0-0/" << filesize; - headers.push_back(contentrange.str()); - sendHead(client, 416, headers); - continue; - } - } - } - } addFileHeaders(headers, data); sendHead(client, 200, headers); if (sendContent == true) sendFile(client, data); } - else if (DirectoryExists(filename) == true) { + else if (DirectoryExists(filename) == true) + { if (filename == "." || filename[filename.length()-1] == '/') sendDirectoryListing(client, filename, *m, sendContent); else sendRedirect(client, 301, filename.append("/"), *m, sendContent); } else - { - ::Configuration::Item const *Replaces = _config->Tree("aptwebserver::redirect::replace"); - if (Replaces != NULL) { - std::string redirect = "/" + filename; - for (::Configuration::Item *I = Replaces->Child; I != NULL; I = I->Next) - redirect = SubstVar(redirect, I->Tag, I->Value); - redirect.erase(0,1); - if (redirect != filename) { - sendRedirect(client, 301, redirect, *m, sendContent); - continue; - } - } sendError(client, 404, *m, sendContent); - } } _error->DumpErrors(std::cerr); messages.clear(); @@ -509,5 +553,7 @@ int main(int const argc, const char * argv[]) << " on socket " << sock << std::endl; close(client); } + pidfile.Close(); + return 0; } diff --git a/test/interactive-helper/makefile b/test/interactive-helper/makefile index fee94cd77..74659cf12 100644 --- a/test/interactive-helper/makefile +++ b/test/interactive-helper/makefile @@ -1,6 +1,7 @@ # -*- make -*- BASE=../.. SUBDIR=test/interactive-helper +APT_DOMAIN=none # Bring in the default rules include ../../buildlib/defaults.mak diff --git a/test/libapt/makefile b/test/libapt/makefile index 953e455e0..1b67cba9d 100644 --- a/test/libapt/makefile +++ b/test/libapt/makefile @@ -2,6 +2,7 @@ BASE=../.. SUBDIR=test/libapt BASENAME=_libapt_test +APT_DOMAIN=none # Bring in the default rules include ../../buildlib/defaults.mak diff --git a/test/libapt/uri_test.cc b/test/libapt/uri_test.cc index 99bb3067e..8216ade71 100644 --- a/test/libapt/uri_test.cc +++ b/test/libapt/uri_test.cc @@ -108,5 +108,13 @@ int main() { equals("/debian/", U.Path); } + // Percent-encoding. + { + URI U("ftp://foo:b%40r@example.org"); + equals("foo", U.User); + equals("b@r", U.Password); + equals("ftp://foo:b%40r@example.org/", (std::string) U); + } + return 0; } |