summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMichael Vogt <mvo@debian.org>2013-07-02 08:32:34 +0200
committerMichael Vogt <mvo@debian.org>2013-07-02 08:32:34 +0200
commit8e4c3f0a42664b8c37cc2e0de285849fbf118e11 (patch)
tree059b76fef1c1636a7e1ad16e5a4ce06304271718 /test
parent25a4d2049fb79bc2c86cd45e977b4a071e5300ac (diff)
parente3c62328abbd548bb0da42fdbad954b3ce4f7102 (diff)
Merge remote-tracking branch 'donkult/debian/sid' into debian/sid
Conflicts: debian/changelog
Diffstat (limited to 'test')
-rw-r--r--test/integration/Packages-pdiff-usage2
-rw-r--r--test/integration/Packages-pdiff-usage-new2
-rw-r--r--test/integration/Packages-releasefile-verification1
-rw-r--r--test/integration/Packages-releasefile-verification-new1
-rw-r--r--test/integration/framework75
-rwxr-xr-xtest/integration/skip-bug-602412-dequote-redirect38
-rwxr-xr-xtest/integration/skip-bug-711456-apt-cdrom-multiple-cds-multiarch47
-rwxr-xr-xtest/integration/test-apt-cdrom4
-rwxr-xr-xtest/integration/test-bug-590041-prefer-non-virtual-packages2
-rwxr-xr-xtest/integration/test-bug-601016-description-translation31
-rwxr-xr-xtest/integration/test-bug-602412-dequote-redirect29
-rwxr-xr-xtest/integration/test-bug-691453-apt-cache-search-multi-pattern33
-rwxr-xr-xtest/integration/test-bug-712435-missing-descriptions89
-rwxr-xr-xtest/integration/test-cve-2013-1051-InRelease-parsing4
-rwxr-xr-xtest/integration/test-pdiff-usage2
-rwxr-xr-xtest/integration/test-prefer-higher-priority-providers106
-rwxr-xr-xtest/integration/test-releasefile-verification4
-rwxr-xr-xtest/integration/test-ubuntu-bug-346386-apt-get-update-paywall64
-rwxr-xr-xtest/integration/test-very-tight-loop-configure-with-unpacking-new-packages46
-rw-r--r--test/interactive-helper/aptwebserver.cc543
-rw-r--r--test/interactive-helper/makefile8
-rw-r--r--test/libapt/makefile1
22 files changed, 1056 insertions, 76 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 31b12e8bf..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,18 +722,33 @@ 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 which weborf > /dev/null; then
- weborf -xb aptarchive/ 2>&1 > /dev/null &
+ local LOG='/dev/null'
+ if test -x ${BUILDDIRECTORY}/aptwebserver; then
+ cd aptarchive
+ 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/ >$LOG 2>&1 &
addtrap "kill $!;"
elif which gatling > /dev/null; then
cd aptarchive
- gatling -p 8080 -F -S 2>&1 > /dev/null &
+ gatling -p 8080 -F -S >$LOG 2>&1 &
addtrap "kill $!;"
cd - > /dev/null
elif which lighttpd > /dev/null; then
@@ -720,11 +756,10 @@ changetowebserver() {
server.port = 8080
server.stat-cache-engine = \"disable\"" > lighttpd.conf
lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid'
- lighttpd -D -f lighttpd.conf 2>/dev/null >/dev/null &
+ 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-602412-dequote-redirect b/test/integration/skip-bug-602412-dequote-redirect
deleted file mode 100755
index 689b671ce..000000000
--- a/test/integration/skip-bug-602412-dequote-redirect
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-set -e
-
-TESTDIR=$(readlink -f $(dirname $0))
-. $TESTDIR/framework
-setupenvironment
-configarchitecture 'i386'
-
-if ! which lighttpd > /dev/null; then
- msgdie 'You need lighttpd for this testcase, sorry…'
- exit 1
-fi
-
-buildsimplenativepackage 'unrelated' 'all' '0.5~squeeze1' 'unstable'
-
-setupaptarchive
-
-echo "server.modules = ( \"mod_redirect\" )
-server.document-root = \"$(readlink -f ./aptarchive)\"
-server.port = 8080
-server.stat-cache-engine = \"disable\"
-url.redirect = ( \"^/pool/(.*)$\" => \"/newpool/\$1\",
- \"^/dists/(.*)$\" => \"/newdists/\$1\" )" > lighttpd.conf
-
-mv aptarchive/pool aptarchive/newpool
-mv aptarchive/dists aptarchive/newdists
-
-lighttpd -t -f lighttpd.conf >/dev/null || msgdie 'Can not change to webserver: our lighttpd config is invalid'
-lighttpd -D -f lighttpd.conf 2>/dev/null >/dev/null &
-addtrap "kill $!;"
-
-APTARCHIVE="file://$(readlink -f ./aptarchive)"
-for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do
- sed -i $LIST -e "s#$APTARCHIVE#http://localhost:8080/#"
-done
-
-aptget update || msgdie 'apt-get update failed'
-aptget install unrelated --download-only || msgdie 'downloading package failed'
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-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
new file mode 100755
index 000000000..c20443559
--- /dev/null
+++ b/test/integration/test-bug-602412-dequote-redirect
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+buildsimplenativepackage 'unrelated' 'all' '0.5~squeeze1' 'unstable'
+
+setupaptarchive
+changetowebserver -o aptwebserver::redirect::replace::/pool/=/newpool/ \
+ -o aptwebserver::redirect::replace::/dists/=/newdists/
+
+mv aptarchive/pool aptarchive/newpool
+mv aptarchive/dists aptarchive/newdists
+
+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: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 fba7ab290..e56f458d3 100755
--- a/test/integration/test-releasefile-verification
+++ b/test/integration/test-releasefile-verification
@@ -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
new file mode 100755
index 000000000..1576c396c
--- /dev/null
+++ b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
@@ -0,0 +1,64 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+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 -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 '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 'ni ni ni' 0
+testequal 'partial' ls $LISTS
+
+# 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
+
+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>&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
new file mode 100644
index 000000000..a8d191d0e
--- /dev/null
+++ b/test/interactive-helper/aptwebserver.cc
@@ -0,0 +1,543 @@
+#include <config.h>
+
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/cmndline.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/init.h>
+
+#include <vector>
+#include <string>
+#include <list>
+#include <sstream>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <signal.h>
+
+char const * const httpcodeToStr(int const httpcode) /*{{{*/
+{
+ switch (httpcode)
+ {
+ // Informational 1xx
+ case 100: return "100 Continue";
+ case 101: return "101 Switching Protocols";
+ // Successful 2xx
+ case 200: return "200 OK";
+ case 201: return "201 Created";
+ case 202: return "202 Accepted";
+ case 203: return "203 Non-Authoritative Information";
+ case 204: return "204 No Content";
+ case 205: return "205 Reset Content";
+ case 206: return "206 Partial Content";
+ // Redirections 3xx
+ case 300: return "300 Multiple Choices";
+ case 301: return "301 Moved Permanently";
+ case 302: return "302 Found";
+ case 303: return "303 See Other";
+ case 304: return "304 Not Modified";
+ case 305: return "304 Use Proxy";
+ case 307: return "307 Temporary Redirect";
+ // Client errors 4xx
+ case 400: return "400 Bad Request";
+ case 401: return "401 Unauthorized";
+ case 402: return "402 Payment Required";
+ case 403: return "403 Forbidden";
+ case 404: return "404 Not Found";
+ case 405: return "405 Method Not Allowed";
+ case 406: return "406 Not Acceptable";
+ case 407: return "407 Proxy Authentication Required";
+ case 408: return "408 Request Time-out";
+ case 409: return "409 Conflict";
+ case 410: return "410 Gone";
+ case 411: return "411 Length Required";
+ case 412: return "412 Precondition Failed";
+ case 413: return "413 Request Entity Too Large";
+ case 414: return "414 Request-URI Too Large";
+ 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";
+ case 502: return "502 Bad Gateway";
+ case 503: return "503 Service Unavailable";
+ case 504: return "504 Gateway Time-out";
+ case 505: return "505 HTTP Version not supported";
+ }
+ return NULL;
+}
+ /*}}}*/
+void addFileHeaders(std::list<std::string> &headers, FileFd &data) /*{{{*/
+{
+ std::ostringstream contentlength;
+ contentlength << "Content-Length: " << data.FileSize();
+ headers.push_back(contentlength.str());
+
+ std::string lastmodified("Last-Modified: ");
+ lastmodified.append(TimeRFC1123(data.ModificationTime()));
+ headers.push_back(lastmodified);
+}
+ /*}}}*/
+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)/*{{{*/
+{
+ std::string response("HTTP/1.1 ");
+ response.append(httpcodeToStr(httpcode));
+ headers.push_front(response);
+
+ headers.push_back("Server: APT webserver");
+
+ std::string date("Date: ");
+ date.append(TimeRFC1123(time(NULL)));
+ headers.push_back(date);
+
+ 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 &= FileFd::Write(client, h->c_str(), h->size());
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ std::clog << *h << std::endl;
+ }
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ std::clog << "<<<<<<<<<<<<<<<<" << std::endl;
+ return Success;
+}
+ /*}}}*/
+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)
+ {
+ if (actual == 0)
+ break;
+ if (Success == true)
+ Success &= FileFd::Write(client, buffer, actual);
+ }
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ return Success;
+}
+ /*}}}*/
+bool sendData(int const client, std::string const &data) /*{{{*/
+{
+ bool Success = true;
+ Success &= FileFd::Write(client, data.c_str(), data.size());
+ if (Success == true)
+ Success &= FileFd::Write(client, "\r\n", 2);
+ return Success;
+}
+ /*}}}*/
+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>");
+ response.append("<body><h1>").append(httpcodeToStr(httpcode)).append("</h1>");
+ if (error.empty() == false)
+ response.append("<p><em>Error</em>: ").append(error).append("</p>");
+ response.append("This error is a result of the request: <pre>");
+ response.append(request).append("</pre></body></html>");
+ addDataHeaders(headers, response);
+ sendHead(client, httpcode, headers);
+ if (content == true)
+ sendData(client, response);
+}
+ /*}}}*/
+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>");
+ response.append("<body><h1>").append(httpcodeToStr(httpcode)).append("</h1");
+ response.append("<p>You should be redirected to <em>").append(uri).append("</em></p>");
+ response.append("This page is a result of the request: <pre>");
+ response.append(request).append("</pre></body></html>");
+ addDataHeaders(headers, response);
+ std::string location("Location: ");
+ if (strncmp(uri.c_str(), "http://", 7) != 0)
+ location.append("http://").append(LookupTag(request, "Host")).append("/").append(uri);
+ else
+ location.append(uri);
+ headers.push_back(location);
+ sendHead(client, httpcode, headers);
+ if (content == true)
+ sendData(client, response);
+}
+ /*}}}*/
+int filter_hidden_files(const struct dirent *a) /*{{{*/
+{
+ if (a->d_name[0] == '.')
+ return 0;
+#ifdef _DIRENT_HAVE_D_TYPE
+ // if we have the d_type check that only files and dirs will be included
+ if (a->d_type != DT_UNKNOWN &&
+ a->d_type != DT_REG &&
+ a->d_type != DT_LNK && // this includes links to regular files
+ a->d_type != DT_DIR)
+ return 0;
+#endif
+ return 1;
+}
+int grouped_alpha_case_sort(const struct dirent **a, const struct dirent **b) {
+#ifdef _DIRENT_HAVE_D_TYPE
+ if ((*a)->d_type == DT_DIR && (*b)->d_type == DT_DIR);
+ else if ((*a)->d_type == DT_DIR && (*b)->d_type == DT_REG)
+ return -1;
+ else if ((*b)->d_type == DT_DIR && (*a)->d_type == DT_REG)
+ return 1;
+ else
+#endif
+ {
+ struct stat f_prop; //File's property
+ stat((*a)->d_name, &f_prop);
+ int const amode = f_prop.st_mode;
+ stat((*b)->d_name, &f_prop);
+ int const bmode = f_prop.st_mode;
+ if (S_ISDIR(amode) && S_ISDIR(bmode));
+ else if (S_ISDIR(amode))
+ return -1;
+ else if (S_ISDIR(bmode))
+ return 1;
+ }
+ return strcasecmp((*a)->d_name, (*b)->d_name);
+}
+ /*}}}*/
+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)
+ {
+ sendError(client, 500, request, content);
+ return;
+ }
+
+ listing << "<html><head><title>Index of " << dir << "</title>"
+ << "<style type=\"text/css\"><!-- td {padding: 0.02em 0.5em 0.02em 0.5em;}"
+ << "tr:nth-child(even){background-color:#dfdfdf;}"
+ << "h1, td:nth-child(3){text-align:center;}"
+ << "table {margin-left:auto;margin-right:auto;} --></style>"
+ << "</head>" << std::endl
+ << "<body><h1>Index of " << dir << "</h1>" << std::endl
+ << "<table><tr><th>#</th><th>Name</th><th>Size</th><th>Last-Modified</th></tr>" << std::endl;
+ if (dir != ".")
+ listing << "<tr><td>d</td><td><a href=\"..\">Parent Directory</a></td><td>-</td><td>-</td></tr>";
+ for (int i = 0; i < counter; ++i) {
+ struct stat fs;
+ std::string filename(dir);
+ filename.append("/").append(namelist[i]->d_name);
+ stat(filename.c_str(), &fs);
+ 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
+ {
+ 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>";
+ }
+ listing << "<td>" << TimeRFC1123(fs.st_mtime) << "</td></tr>" << std::endl;
+ }
+ listing << "</table></body></html>" << std::endl;
+
+ std::string response(listing.str());
+ addDataHeaders(headers, response);
+ sendHead(client, 200, headers);
+ if (content == true)
+ sendData(client, response);
+}
+ /*}}}*/
+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)
+ {
+ sendError(client, 501, request, true);
+ return false;
+ }
+
+ size_t const lineend = request.find('\n');
+ size_t filestart = request.find(' ');
+ 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)
+ {
+ sendError(client, 500, request, sendContent, "Filename can't be extracted");
+ return false;
+ }
+
+ size_t httpstart = fileend;
+ for (; request[httpstart] == ' '; ++httpstart);
+ if (strncmp(request.c_str() + httpstart, "HTTP/1.1\r", 9) == 0)
+ 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 a HTTP/1.{0,1} request");
+ return false;
+ }
+
+ filename = request.substr(filestart, fileend - filestart);
+ if (filename.find(' ') != std::string::npos)
+ {
+ sendError(client, 500, request, sendContent, "Filename contains an unencoded space");
+ return false;
+ }
+ filename = DeQuoteString(filename);
+
+ // this is not a secure server, but at least prevent the obvious …
+ 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)
+ {
+ sendError(client, 400, request, sendContent, "Filename contains illegal character (sequence)");
+ return false;
+ }
+
+ // nuke the first character which is a / as we assured above
+ filename.erase(0, 1);
+ if (filename.empty() == true)
+ filename = ".";
+ return true;
+}
+ /*}}}*/
+int main(int const argc, const char * argv[])
+{
+ CommandLine::Args Args[] = {
+ {0, "port", "aptwebserver::port", CommandLine::HasArg},
+ {'c',"config-file",0,CommandLine::ConfigFile},
+ {'o',"option",0,CommandLine::ArbItem},
+ {0,0,0,0}
+ };
+
+ CommandLine CmdL(Args, _config);
+ if(CmdL.Parse(argc,argv) == false)
+ {
+ _error->DumpErrors();
+ exit(1);
+ }
+
+ // create socket, bind and listen to it {{{
+ // 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)
+ {
+ _error->Errno("aptwerbserver", "Couldn't create socket");
+ _error->DumpErrors(std::cerr);
+ return 1;
+ }
+
+ int const port = _config->FindI("aptwebserver::port", 8080);
+
+ // 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 on an address
+ int const enable = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
+
+ struct sockaddr_in6 locAddr;
+ memset(&locAddr, 0, sizeof(locAddr));
+ locAddr.sin6_family = AF_INET6;
+ locAddr.sin6_port = htons(port);
+ locAddr.sin6_addr = in6addr_any;
+
+ 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;
+ }
+ }
+
+ 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)
+ {
+ std::clog << "ACCEPT client " << client
+ << " on socket " << sock << std::endl;
+
+ while (ReadMessages(client, messages))
+ {
+ bool closeConnection = false;
+ for (std::vector<std::string>::const_iterator m = messages.begin();
+ m != messages.end() && closeConnection == false; ++m) {
+ std::clog << ">>> REQUEST >>>>" << std::endl << *m
+ << std::endl << "<<<<<<<<<<<<<<<<" << std::endl;
+ std::list<std::string> headers;
+ std::string filename;
+ bool sendContent = true;
+ if (parseFirstLine(client, *m, filename, sendContent, closeConnection) == false)
+ continue;
+
+ std::string host = LookupTag(*m, "Host", "");
+ if (host.empty() == true)
+ {
+ // RFC 2616 §14.23 requires Host
+ sendError(client, 400, *m, sendContent, "Host header is required");
+ continue;
+ }
+
+ // 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)
+ {
+ time_t cache;
+ if (RFC1123StrToTime(condition.c_str(), cache) == true &&
+ cache >= data.ModificationTime())
+ {
+ sendHead(client, 304, headers);
+ continue;
+ }
+ }
+
+ addFileHeaders(headers, data);
+ sendHead(client, 200, headers);
+ if (sendContent == true)
+ sendFile(client, data);
+ }
+ 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
+ sendError(client, 404, *m, sendContent);
+ }
+ _error->DumpErrors(std::cerr);
+ messages.clear();
+ if (closeConnection == true)
+ break;
+ }
+
+ std::clog << "CLOSE client " << client
+ << " on socket " << sock << std::endl;
+ close(client);
+ }
+ pidfile.Close();
+
+ return 0;
+}
diff --git a/test/interactive-helper/makefile b/test/interactive-helper/makefile
index 10d1e44ec..f43df97e3 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
@@ -37,3 +38,10 @@ include $(PROGRAM_H)
#SLIBS = -lapt-pkg -lrpm
#SOURCE = rpmver.cc
#include $(PROGRAM_H)
+
+# Program for testing udevcdrom
+PROGRAM=aptwebserver
+SLIBS = -lapt-pkg
+LIB_MAKES = apt-pkg/makefile
+SOURCE = aptwebserver.cc
+include $(PROGRAM_H)
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