diff --git a/.gitignore b/.gitignore
index 77f1b42..0606f02 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,6 @@
*.eggs
*.egg-info
dist
-build
eggs
parts
bin
diff --git a/build-deb b/build-deb
new file mode 100755
index 0000000..dec2ce7
--- /dev/null
+++ b/build-deb
@@ -0,0 +1,128 @@
+#!/usr/bin/env bash
+#
+# Debian/Ubuntu Packaging Scripts
+# Copyright (C) 2002-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+
+# ====== Obtain package and version information =============================
+OVERRIDE_PACKAGE_DISTRIBUTION="$1"
+
+CHANGELOG_HEADER="`head -n1 debian/changelog`"
+
+# The package name, e.g. MyApplication
+PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"`
+# The package distribution, e.g. precise, raring, ...
+PACKAGE_DISTRIBUTION=`echo ${CHANGELOG_HEADER} | sed -e "s/[^)]*)//" -e "s/;.*//g" -e "s/ //g"`
+# The package's version, e.g. 1.2.3-1ubuntu1
+PACKAGE_VERSION=`echo ${CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"`
+# The package's output version, e.g. 1.2.3-1ubuntu
+OUTPUT_VERSION=`echo ${PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"`
+# The package's Debian version, e.g. 1.2.3-1
+DEBIAN_VERSION=`echo ${OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"`
+# The package's upstream version, e.g. 1.2.3
+UPSTREAM_VERSION=`echo ${DEBIAN_VERSION} | sed -e "s/-[0-9]*$//"`
+# The package's plain upstream version, e.g. 1.2.3 (without e.g. ~svn)
+PLAIN_VERSION=`echo ${UPSTREAM_VERSION} | sed -e "s/\([0-9\.]*\)[-+~].*$/\1/"`
+
+
+echo -e "\x1b[34m######################################################################\x1b[0m"
+echo -e "\x1b[34mCHANGELOG_HEADER: ${CHANGELOG_HEADER}\x1b[0m"
+echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_DISTRIBUTION: ${PACKAGE_DISTRIBUTION}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_VERSION ${PACKAGE_VERSION}\x1b[0m"
+echo -e "\x1b[34mOUTPUT_VERSION: ${OUTPUT_VERSION}\x1b[0m"
+echo -e "\x1b[34mDEBIAN_VERSION: ${DEBIAN_VERSION}\x1b[0m"
+echo -e "\x1b[34mUPSTREAM_VERSION: ${UPSTREAM_VERSION}\x1b[0m"
+echo -e "\x1b[34mPLAIN_VERSION: ${PLAIN_VERSION}\x1b[0m"
+echo -e "\x1b[34m######################################################################\x1b[0m"
+
+if [ ! -e ./packaging.conf ] ; then
+ echo >&2 "ERROR: packaging.conf does not exist -> no configuration for the new package!"
+ exit 1
+fi
+. ./packaging.conf
+
+if [ "${OVERRIDE_PACKAGE_DISTRIBUTION}" != "" ] ; then
+ PACKAGE_DISTRIBUTION="${OVERRIDE_PACKAGE_DISTRIBUTION}"
+ echo ""
+ echo -e "\x1b[34m**** Overriding PACKAGE_DISTRIBUTION: PACKAGE_DISTRIBUTION=${PACKAGE_DISTRIBUTION}! ****\x1b[0m"
+ echo ""
+fi
+
+
+# ====== Create source package ==============================================
+sudo echo ""
+./clean-deb
+./make-deb ${PACKAGE_DISTRIBUTION}
+
+if [ "${ARCH}" == "" ] ; then
+ ARCH=`dpkg --print-architecture`
+fi
+if [ "${PACKAGE_DISTRIBUTION}" == "unstable" -o \
+ "${PACKAGE_DISTRIBUTION}" == "testing" -o \
+ "${PACKAGE_DISTRIBUTION}" == "stable" -o \
+ "${PACKAGE_DISTRIBUTION}" == "oldstable" -o \
+ "${PACKAGE_DISTRIBUTION}" == "default" ] ; then
+ if [ "${PACKAGE_DISTRIBUTION}" == "default" ] ; then
+ version=${PACKAGE_VERSION}
+ else
+ version=${DEBIAN_VERSION}
+ fi
+ changesFilesPattern="${PACKAGE}_${version}_${ARCH}*.changes"
+ dscFile=`ls ${PACKAGE}_${version}.dsc | tail -n1`
+else
+ changesFilesPattern="${PACKAGE}_${OUTPUT_VERSION}~${PACKAGE_DISTRIBUTION}[0-9]_${ARCH}*.changes"
+ dscFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${PACKAGE_DISTRIBUTION}[0-9].dsc | tail -n1`
+fi
+
+
+# ====== Build binary package ===============================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Building binary package ========================================\x1b[0m"
+echo -e ""
+
+if [ ! -e "${dscFile}" ] ; then
+ echo >&2 "ERROR: Unable to find description file ${dscFile}!"
+ exit 1
+fi
+sudo OS=${OS} DIST=${DIST} ARCH=${ARCH} pbuilder build ${dscFile}
+
+
+# ====== Run lintian ========================================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Running lintian ================================================\x1b[0m"
+echo -e ""
+
+changesFile=`find /var/cache/pbuilder/result/ -name "${changesFilesPattern}"`
+if [ ! -e "${changesFile}" ] ; then
+ echo >&2 "ERROR: Unable to find changes file ${changesFile}!"
+ exit 1
+fi
+
+profile="ubuntu"
+if [ "${PACKAGE_DISTRIBUTION}" == "unstable" -o \
+ "${PACKAGE_DISTRIBUTION}" == "testing" -o \
+ "${PACKAGE_DISTRIBUTION}" == "stable" -o \
+ "${PACKAGE_DISTRIBUTION}" == "oldstable" ] ; then
+ profile="debian"
+fi
+echo "Calling: lintian -iIEv --pedantic --suppress-tags file-references-package-build-path --profile ${profile} ${changesFile}"
+lintian -iIEv --pedantic --suppress-tags file-references-package-build-path --profile ${profile} ${changesFile} || true
diff --git a/build-rpm b/build-rpm
new file mode 100755
index 0000000..19ac7dc
--- /dev/null
+++ b/build-rpm
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+#
+# Packaging Scripts
+# Copyright (C) 2017-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+
+# ---------------------------------------------------------------------------
+# USAGE:
+# ./make-rpm => Use current distribution and architecture
+# ./make-rpm fedora-30-x86_64 => F30, amd64
+# ./make-rpm fedora-rawhide-i386 => F30, i386
+# ...
+# ---------------------------------------------------------------------------
+
+
+DISTRIBUTIONS=`\
+( \
+while [ x$1 != "x" ] ; do \
+ echo $1
+ shift
+done \
+) | sort -u`
+if [ "${DISTRIBUTIONS}" == "" ] ; then
+ release=`cat /etc/fedora-release | sed -e "s/^\(.*\) release \([0-9]*\) (\(.*\))$/\2/g"`
+ arch=`uname -m`
+
+ DISTRIBUTIONS="fedora-${release}-${arch}"
+fi
+
+PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"`
+PACKAGE_VERSION=`grep "^Version:" rpm/*.spec | head -n1 | sed -e "s/Version://g" -e "s/[ \t]*//g"`
+
+echo -e "\x1b[34m###########################################\x1b[0m"
+echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_VERSION: ${PACKAGE_VERSION}\x1b[0m"
+echo -e "\x1b[34m###########################################\x1b[0m"
+
+
+# ====== Create source RPM ==================================================
+./make-srpm
+
+PACKAGE_SRPM=`find $HOME/rpmbuild/SRPMS/ -name "${PACKAGE}-*-*.src.rpm"`
+if [ ! -e "${PACKAGE_SRPM}" ] ; then
+ echo >&2 "ERROR: Cannot find SRPM ${PACKAGE}-*-*.src.rpm in $HOME/rpmbuild/SRPMS!"
+ exit 1
+fi
+
+
+# ====== Build binary RPMs ==================================================
+# Create binary RPMs
+for DISTRIBUTION in ${DISTRIBUTIONS} ; do
+ echo -e ""
+ echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating binary RPM for ${DISTRIBUTION} ==========\x1b[0m"
+ echo -e ""
+
+ # NOTE: DISTRIBUTION may point to another directory (e.g. "rawhide" instead of "30")!
+ if [ ! -e "/etc/mock/${DISTRIBUTION}.cfg" ] ; then
+ echo >&2 "ERROR: Cannot find /etc/mock/${DISTRIBUTION}.cfg!"
+ exit 1
+ fi
+
+ # Remove old files
+ find /var/lib/mock/${DISTRIBUTION}/result -name "${PACKAGE}-*.rpm" | xargs --no-run-if-empty rm -f
+
+ # Build the binary RPM
+ # NOTE: using old chroot instead of container, to allow running it inside a container!
+ mock -r ${DISTRIBUTION} --isolation=simple --init
+ mock -r ${DISTRIBUTION} --isolation=simple --installdeps ${PACKAGE_SRPM}
+ mock -r ${DISTRIBUTION} --isolation=simple --install openssl pesign
+ mock -r ${DISTRIBUTION} --isolation=simple --no-clean --rebuild ${PACKAGE_SRPM}
+
+ # Check whether files are at the right location
+ PACKAGE_RPMS=`find /var/lib/mock/${DISTRIBUTION}/result -name "${PACKAGE}-*-*.rpm" | grep -v "${PACKAGE}-*-*.src.rpm" || true`
+ if [ "${PACKAGE_RPMS}" == "" ] ; then
+ echo >&2 "ERROR: Cannot find RPMs!"
+ exit 1
+ fi
+done
diff --git a/ci/ci-build b/ci/ci-build
new file mode 100755
index 0000000..0e18d61
--- /dev/null
+++ b/ci/ci-build
@@ -0,0 +1,138 @@
+#!/usr/bin/env bash
+#
+# GitHub Actions Scripts
+# Copyright (C) 2021-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+DIRNAME=`dirname $0`
+UNAME=`uname`
+if [ "${UNAME}" == "Linux" ] ; then
+ DISTRIBUTION=`lsb_release -is`
+else
+ DISTRIBUTION="Unknown"
+fi
+
+if [ $# -lt 1 ] ; then
+ echo >&2 "Usage: $0 compile|package|... ..."
+ exit 1
+fi
+
+
+# ###### Configure ##########################################################
+
+# ====== Configure with CMake ===============================================
+if [ -e CMakeLists.txt ] ; then
+ cmake .
+
+# ====== Configure with autoconf/automake (via bootstrap script) ============
+elif [ -e configure.ac -o -e configure.in ] ; then
+ if [ -e autogen.sh ] ; then
+ ./autogen.sh
+ elif [ -e bootstrap ] ; then
+ ./bootstrap
+ ./configure
+ else
+ ./configure
+ fi
+else
+ echo >&2 "WARNING: No build system detected. Trying to just call \"make\" ..."
+fi
+
+if [ ${UNAME} == "Linux" ] ; then
+ cores=`getconf _NPROCESSORS_ONLN 2>/dev/null || true`
+ MAKEFLAGS="-j${cores}"
+elif [ ${UNAME} == "FreeBSD" ] ; then
+ cores=`sysctl -a | grep 'hw.ncpu' | cut -d ':' -f2 | tr -d ' '`
+ MAKEFLAGS="-j${cores}"
+else
+ MAKEFLAGS=""
+fi
+
+
+# ###### Perform builds #####################################################
+while [ $# -gt 0 ] ; do
+ TOOL="$1"
+ shift
+
+
+ # ====== Compile =========================================================
+ if [ "${TOOL}" == "compile" ] ; then
+ MAKEFLAGS=${MAKEFLAGS} make # VERBOSE=1
+
+
+# # ====== Coverity Scan ===================================================
+# elif [ "${TOOL}" == "coverity" ] ; then
+# # ------ Build --------------------------------------------------------
+# cd coverity
+# export PATH="coverity/$(ls -d cov*)/bin:$PATH"
+# cd ..
+#
+# MAKEFLAGS=${MAKEFLAGS} cov-build --dir cov-int make
+# tar czf coverity-results.tar.gz cov-int
+# ls -l coverity-results.tar.gz
+#
+# # ------ Upload results -----------------------------------------------
+# if [ "${TRAVIS_BRANCH}" == "${COVERITY_SCAN_BRANCH}" ] ; then
+# curl --form token=${COVERITY_SCAN_TOKEN} \
+# --form email=${COVERITY_SCAN_NOTIFICATION_EMAIL} \
+# --form file=@coverity-results.tar.gz \
+# --form version="master branch head" \
+# --form description="$(git log -1|head -1)" \
+# https://scan.coverity.com/builds?project=${COVERITY_PROJECT}
+# CURL_RESULT=$?
+# echo "curl returned ${CURL_RESULT}"
+# if [ $CURL_RESULT -ne 0 ]; then
+# echo >&2 "ERROR: Upload to Coverity Scan failed; curl returned ${CURL_RESULT}!"
+# exit 1
+# fi
+# else
+# echo >&2 "###### NOTE: This branch \"${TRAVIS_BRANCH}\" is not the scan branch \"${COVERITY_SCAN_BRANCH}\"! Skipping upload! ######"
+# fi
+
+
+ # ====== Package =======================================================
+ elif [ "${TOOL}" == "package" ] ; then
+ if [ "${DISTRIBUTION}" == "Ubuntu" -o "${DISTRIBUTION}" == "Debian" ] ; then
+ OVERRIDE_SKIP_PACKAGE_SIGNING=1 ./build-deb ${DIST}
+
+ # ====== Fedora ==========================================================
+ elif [ "${DISTRIBUTION}" == "Fedora" ] ; then
+ release=`cat /etc/fedora-release | sed -e "s/^\(.*\) release \([0-9]*\) (\(.*\))$/\2/g" | sed -e "s/[^0-9]//g"`
+ if [ "${ARCH}" == "" ] ; then
+ arch=`uname -m | sed -e "s/[^0-9a-zA-Z_+-]//g"`
+ else
+ arch="${ARCH}"
+ fi
+ LD_PRELOAD=/usr/lib64/nosync/nosync.so OVERRIDE_SKIP_PACKAGE_SIGNING=1 ./build-rpm fedora-${release}-${arch}
+
+ # ====== Unknown =========================================================
+ else
+ echo >&2 "ERROR: Unknown Linux distribution ${DISTRIBUTION}!"
+ exit 1
+ fi
+
+
+ # ====== Invalid setting =================================================
+ else
+ echo >&2 "ERROR: Invalid setting of TOOL=${TOOL}!"
+ exit 1
+ fi
+
+done
diff --git a/ci/ci-install b/ci/ci-install
new file mode 100755
index 0000000..8e92f65
--- /dev/null
+++ b/ci/ci-install
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+#
+# GitHub Actions Scripts
+# Copyright (C) 2021-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+DIRNAME=`dirname $0`
+UNAME=`uname`
+if [ "${UNAME}" == "Linux" ] ; then
+ DISTRIBUTION=`lsb_release -is`
+else
+ DISTRIBUTION="Unknown"
+fi
+
+
+# ###### Linux ##############################################################
+if [ "${UNAME}" == "Linux" ] ; then
+
+ # ====== Ubuntu ==========================================================
+ if [ "${DISTRIBUTION}" == "Ubuntu" ] ; then
+ DEBIAN_FRONTEND=noninteractive ${DIRNAME}/get-dependencies ubuntu --install
+
+ # ====== Debian ==========================================================
+ elif [ "${DISTRIBUTION}" == "Debian" ] ; then
+ DEBIAN_FRONTEND=noninteractive ${DIRNAME}/get-dependencies debian --install
+
+ # ====== Fedora ==========================================================
+ elif [ "${DISTRIBUTION}" == "Fedora" ] ; then
+ ${DIRNAME}/get-dependencies fedora --install
+
+ # ====== Unknown =========================================================
+ else
+ echo >&2 "ERROR: Unknown Linux distribution ${DISTRIBUTION}!"
+ exit 1
+ fi
+
+# ###### FreeBSD ############################################################
+elif [ "${UNAME}" == "FreeBSD" ] ; then
+
+ ${DIRNAME}/get-dependencies freebsd --install
+
+# ###### Unknown ############################################################
+else
+
+ echo >&2 "ERROR: Unexpected system ${UNAME}!"
+ exit 1
+
+fi
diff --git a/ci/ci-setup b/ci/ci-setup
new file mode 100755
index 0000000..4e0a963
--- /dev/null
+++ b/ci/ci-setup
@@ -0,0 +1,219 @@
+#!/usr/bin/env bash
+#
+# GitHub Actions Scripts
+# Copyright (C) 2021-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+UNAME=`uname`
+USE_PACKAGING=0
+
+while [ $# -gt 0 ] ; do
+ if [ "$1" == "package" ] ; then
+ USE_PACKAGING=1
+ fi
+ shift
+done
+
+
+# ###### Linux ##############################################################
+if [ "${UNAME}" == "Linux" ] ; then
+
+ # NOTE: lsb_release may not be installed, yet!
+ # => Guess distribution by checking for the packaging tool.
+
+ # ====== Ubuntu/Deban ====================================================
+ if [ -e /usr/bin/apt-get ] ; then
+ PACKAGES="lsb-release python3"
+ if [[ "${CC}" =~ .*gcc.* ]] ; then
+ PACKAGES="${PACKAGES} gcc"
+ elif [[ "${CC}" =~ .*clang.* ]] ; then
+ PACKAGES="${PACKAGES} clang"
+ fi
+ if [ ${USE_PACKAGING} -eq 1 ] ; then
+ # Need to install pbuilder as well:
+ PACKAGES="${PACKAGES} build-essential debian-archive-keyring debian-ports-archive-keyring devscripts eatmydata fakeroot lintian pbuilder python3-debian qemu-user-static"
+ fi
+
+ apt-get update -qq
+ # DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -qy
+ DEBIAN_FRONTEND=noninteractive apt-get install -qqy -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --no-install-recommends \
+ ${PACKAGES}
+
+ if [ "`lsb_release -is`" == "Ubuntu" ] ; then
+ # Add PPA dreibh/ppa for Ubuntu:
+ DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --no-install-recommends \
+ software-properties-common
+ apt-add-repository -y ppa:dreibh/ppa || true
+ apt-get update -q
+ fi
+
+ if [ ${USE_PACKAGING} -eq 1 ] ; then
+ # ====== pbuilder environment ======================================
+ # Example for GitHub Actions:
+ # https://github.com/jrl-umi3218/github-actions/tree/master/setup-pbuilder
+
+ if [ "${OS}" == "" ] ; then
+ OS=`lsb_release -is`
+ OS=${OS,,}
+ fi
+ if [ "${DIST}" == "" ] ; then
+ DIST=`lsb_release -cs`
+ fi
+ if [ "${ARCH}" == "" ] ; then
+ ARCH=`dpkg --print-architecture`
+ fi
+
+ if [ "${OS}" == "ubuntu" ] ; then
+ COMPONENTS="main universe"
+ MIRRORSITE=http://no.archive.ubuntu.com/ubuntu/
+ KEYRING="/usr/share/keyrings/ubuntu-archive-keyring.gpg"
+ elif [ "${OS}" == "debian" ] ; then
+ COMPONENTS="main"
+ if [ "${ARCH}" == "m68k" -o "${ARCH}" == "riscv64" ] ; then
+ # Debian Ports (special architectures)
+ MIRRORSITE="http://ftp.ports.debian.org/debian-ports/"
+ KEYRING="/usr/share/keyrings/debian-ports-archive-keyring.gpg"
+ else
+ # Debian (supported architectures)
+ MIRRORSITE="http://ftp.no.debian.org/debian/"
+ KEYRING="/usr/share/keyrings/debian-archive-keyring.gpg"
+ fi
+ else
+ echo >&2 "ERROR: Unknown Linux distribution ${OS}!"
+ exit 1
+ fi
+
+ cores=`getconf _NPROCESSORS_ONLN 2>/dev/null || true`
+ cat >/etc/pbuilderrc < /etc/dpkg/dpkg.cfg.d/02apt-speedup" | \
+ pbuilder login --save-after-exec
+
+ # ====== Add ppa:dreibh/ppa, updates and backports =================
+ if [ "${OS}" == "ubuntu" ] ; then
+ # Add PPA dreibh/ppa for Ubuntu:
+ pbuilder login --save-after-login <&2 "ERROR: Unable to inject PPA configuration into Mock configuration file /etc/mock/fedora-${release}-${arch}.cfg!"
+ exit 1
+ fi
+ fi
+ fi
+
+
+ # ====== Unknown =========================================================
+ else
+ echo >&2 "ERROR: Unknown Linux distribution!"
+ exit 1
+ fi
+
+# ###### FreeBSD ############################################################
+elif [ "${UNAME}" == "FreeBSD" ] ; then
+
+ ASSUME_ALWAYS_YES=yes pkg install -y bash gcc libtool git python3
+
+ # Ports collection:
+ # This is the slow method via portsnap:
+ # portsnap --interactive fetch extract | grep -v ^/usr/ports
+ # Using Git is much faster:
+ rm -rf /usr/ports
+ git clone --depth=1 https://github.com/freebsd/freebsd-ports /usr/ports
+
+# ###### Unknown ############################################################
+else
+
+ echo >&2 "ERROR: Unexpected system ${UNAME}!"
+ exit 1
+
+fi
diff --git a/ci/ci-test b/ci/ci-test
new file mode 100755
index 0000000..914f7a3
--- /dev/null
+++ b/ci/ci-test
@@ -0,0 +1,135 @@
+#!/usr/bin/env bash
+#
+# GitHub Actions Scripts
+# Copyright (C) 2021-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+
+UNAME=`uname`
+if [ "${UNAME}" == "Linux" ] ; then
+ DISTRIBUTION=`lsb_release -is`
+else
+ DISTRIBUTION="Unknown"
+fi
+
+
+# ###### Linux ##############################################################
+if [ "${UNAME}" == "Linux" ] ; then
+
+ # ====== Ubuntu ==========================================================
+ if [ "${DISTRIBUTION}" == "Ubuntu" -o "${DISTRIBUTION}" == "Debian" ] ; then
+
+ # ====== pbuilder environment =========================================
+ CHANGELOG_HEADER="`head -n1 debian/changelog`"
+ PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"`
+ PACKAGE_VERSION=`echo ${CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"`
+ OUTPUT_VERSION=`echo ${PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"`
+ DEBIAN_VERSION=`echo ${OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"`
+
+ packages=""
+ if [ $# -eq 0 ] ; then
+ echo "Looking for *${DEBIAN_VERSION}*.deb in /var/cache/pbuilder/result ..."
+ packages="`find /var/cache/pbuilder/result -name "*${DEBIAN_VERSION}*.deb"`"
+ fi
+ while [ $# -gt 0 ] ; do
+ echo "Looking for $1*${DEBIAN_VERSION}*.deb in /var/cache/pbuilder/result ..."
+ packages="${packages} `find /var/cache/pbuilder/result -name "$1*${DEBIAN_VERSION}*.deb"`"
+ shift
+ done
+ packages=`echo "${packages}" | xargs -n1 | sort -u | xargs`
+ if [ "${packages}" == "" ] ; then
+ echo >&2 "ERROR: No packages have been found!"
+ exit 1
+ fi
+
+ echo "Installing ${packages} ..."
+ DEBIAN_FRONTEND=noninteractive eatmydata apt-get install -fy ${packages} || {
+ echo "NOTE: apt-get failed -> trying dpkg instead of apt-get for local file!"
+ # NOTE: Older "apt-get" versions do not handle local files!
+ if ! DEBIAN_FRONTEND=noninteractive eatmydata dpkg -i ${packages} ; then
+ echo "There may be some dependencies missing. Trying to install them ..."
+ DEBIAN_FRONTEND=noninteractive eatmydata apt-get install -fy -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-confdef" --no-install-recommends
+ echo "Retrying to install ${packages} ..."
+ DEBIAN_FRONTEND=noninteractive eatmydata dpkg -i ${packages}
+ fi
+ }
+ echo "Done!"
+
+
+ # ====== Fedora ==========================================================
+ elif [ "${DISTRIBUTION}" == "Fedora" ] ; then
+
+ # ====== mock environment =============================================
+ PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"`
+ PACKAGE_VERSION=`grep "^Version:" rpm/*.spec | head -n1 | sed -e "s/Version://g" -e "s/[ \t]*//g"`
+
+ release=`bash -c "LANG=C.UTF-8 ; cat /etc/fedora-release | sed -e \"s/^\(.*\) release \([0-9]*\) (\(.*\))$/\2/g\"" | sed -e "s/[^0-9]//g"`
+ arch=`uname -m | sed -e "s/[^0-9a-zA-Z_+-]//g"`
+ if ! cd /var/lib/mock/fedora-${release}-${arch}/result ; then
+ if cd /var/lib/mock/fedora-rawhide-${arch}/result ; then
+ release="rawhide"
+ else
+ echo >&2 "ERROR: No results have been found!"
+ exit 1
+ fi
+ fi
+
+ packages=""
+ if [ $# -eq 0 ] ; then
+ echo "Looking for *${PACKAGE_VERSION}*.rpm in /var/lib/mock/fedora-${release}-${arch}/result ..."
+ packages="`find /var/lib/mock/fedora-${release}-${arch}/result -name "*${PACKAGE_VERSION}*.rpm" | grep -v "\.src\.rpm$"`"
+ fi
+ while [ $# -gt 0 ] ; do
+ echo "Looking for $1*${PACKAGE_VERSION}*.rpm in /var/lib/mock/fedora-${release}-${arch}/result ..."
+ packages="${packages} `find /var/lib/mock/fedora-${release}-${arch}/result -name "$1*${PACKAGE_VERSION}*.rpm" | grep -v "\.src\.rpm$"`"
+ shift
+ done
+ packages=`echo "${packages}" | xargs -n1 | sort -u | xargs`
+ if [ "${packages}" == "" ] ; then
+ echo >&2 "ERROR: No packages have been found!"
+ exit 1
+ fi
+
+ echo "Installing ${packages} ..."
+ LD_PRELOAD=/usr/lib64/nosync/nosync.so dnf install -y --allowerasing ${packages}
+ echo "Done!"
+
+
+ # ====== Unknown =========================================================
+ else
+ echo >&2 "ERROR: Unknown Linux distribution ${DISTRIBUTION}!"
+ exit 1
+ fi
+
+
+# ###### FreeBSD ############################################################
+elif [ "${UNAME}" == "FreeBSD" ] ; then
+
+ # TDB
+ true
+
+
+# ###### Unknown ############################################################
+else
+
+ echo >&2 "ERROR: Unexpected system ${UNAME}!"
+ exit 1
+
+fi
diff --git a/ci/get-dependencies b/ci/get-dependencies
new file mode 100755
index 0000000..3edde45
--- /dev/null
+++ b/ci/get-dependencies
@@ -0,0 +1,185 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Travis CI Scripts
+# Copyright (C) 2018-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+
+import glob
+import os
+import re
+import subprocess
+import sys
+
+
+# ###### Extract dependencies ###############################################
+depLine = re.compile(r'^(.*:[ \t]*)(.*)$')
+depItem = re.compile(r'^([a-zA-Z0-9-+\.]+)[\s]*(|\|.*|\(.*)[\s]*$')
+
+def extractDependencies(line, system):
+ dependencies = []
+
+ # Remove "build-depends:", etc.:
+ m = depLine.match(line)
+ if m != None:
+ line = m.group(2)
+ line = line.strip()
+
+ # Split into segments
+ for l in line.split(','):
+ l = l.strip()
+ m = depItem.match(l)
+ if m != None:
+ dependency = m.group(1)
+
+ # ------ Ugly work-around for cmake --------------------------------
+ # We need cmake >= 3.0!
+ if ((dependency == 'cmake') or (dependency == 'cmake3')):
+ if ((system == 'debian') or (system == 'ubuntu')):
+ try:
+ distribution = subprocess.check_output( ["lsb_release", "-cs"] ).decode('utf-8').strip()
+ # print("distribution=", distribution, ".")
+ if distribution in [ 'trusty' ]:
+ dependency = 'cmake3'
+ except:
+ pass
+
+ dependencies.append(dependency)
+
+ return dependencies
+
+
+# ###### Main program #######################################################
+
+# ====== Check arguments ====================================================
+if len(sys.argv) < 2:
+ sys.stderr.write('Usage: ' + sys.argv[0] + ' debian|ubuntu|fedora|freebsd [-i|--install]\n')
+ sys.exit(1)
+system = sys.argv[1]
+runInstall = False
+for i in range(2, len(sys.argv)):
+ if sys.argv[i] == '-i' or sys.argv[i] == '--install':
+ runInstall = True
+ else:
+ sys.stderr.write('ERROR: Bad parameter ' + sys.argv[i] + '!')
+ sys.exit(1)
+
+# ====== Debian/Ubuntu ======================================================
+dependencies = [ ]
+if ((system == 'debian') or (system == 'ubuntu')):
+ if os.path.exists('debian/control'):
+ with open('debian/control', 'r', encoding='utf-8') as fp:
+ inside = False
+ for line in fp:
+ if not line:
+ break
+ line_lower = line.lower()
+ if inside:
+ if line.startswith((' ', "\t")):
+ dependencies = dependencies + extractDependencies(line, system)
+ continue
+ elif line.startswith('#'):
+ continue
+ inside = False
+ if line_lower.startswith(('build-depends:', 'build-depends-indep:')):
+ dependencies = dependencies + extractDependencies(line, system)
+ inside = True
+
+ for dependency in sorted(set(dependencies)):
+ sys.stdout.write(dependency + ' ')
+ sys.stdout.write('\n')
+
+ if runInstall == True:
+ subprocess.call([ 'apt-get', 'install', '-qy' ] + dependencies)
+
+ else:
+ sys.stderr.write('ERROR: Unable to locate Debian control file!\n')
+ sys.exit(1)
+
+
+# ====== Fedora =============================================================
+elif system == 'fedora':
+ specFiles = glob.glob('rpm/*.spec')
+ if len(specFiles) == 1:
+ with open(specFiles[0], 'r', encoding='utf-8') as fp:
+ inside = False
+ for line in fp:
+ if not line:
+ break
+ line_lower = line.lower()
+ if inside:
+ if line.startswith((' ', "\t")):
+ dependencies = dependencies + extractDependencies(line, system)
+ continue
+ elif line.startswith('#'):
+ continue
+ inside = False
+ if line_lower.startswith('buildrequires:'):
+ dependencies = dependencies + extractDependencies(line, system)
+ inside = True
+
+ for dependency in sorted(set(dependencies)):
+ sys.stdout.write(dependency + ' ')
+ sys.stdout.write('\n')
+
+ if runInstall == True:
+ subprocess.call([ 'dnf', 'install', '-y' ] + dependencies)
+
+ else:
+ sys.stderr.write('ERROR: Unable to locate RPM spec file!\n')
+ sys.exit(1)
+
+
+# ====== FreeBSD ============================================================
+elif system == 'freebsd':
+ freeBSDMakefile = glob.glob('freebsd/*/Makefile')
+ if len(freeBSDMakefile) == 1:
+ freeBSDDirectory = os.path.dirname(freeBSDMakefile[0])
+
+ cmd = 'make build-depends-list && make run-depends-list'
+ try:
+ os.chdir(freeBSDDirectory)
+ output = subprocess.check_output(cmd, shell=True)
+ except Exception as e:
+ sys.stderr.write('ERROR: Getting FreeBSD dependencies failed: ' + str(e) + '\n')
+ sys.exit(1)
+
+ if output != None:
+ ports = output.decode('utf-8').splitlines()
+ for port in ports:
+ basename = os.path.basename(port)
+ if basename == 'glib20':
+ basename = 'glib' # May be there is a better solution here?
+ dependencies.append(basename)
+
+ for dependency in sorted(set(dependencies)):
+ sys.stdout.write(dependency + ' ')
+ sys.stdout.write('\n')
+
+ if runInstall == True:
+ subprocess.call([ 'pkg', 'install', '-y' ] + dependencies)
+
+ else:
+ sys.stderr.write('ERROR: Unable to locate FreeBSD port makefile!\n')
+ sys.exit(1)
+
+
+# ====== Error ==============================================================
+else:
+ sys.stderr.write('ERROR: Invalid system name "' + system + '"!\n')
+ sys.exit(1)
diff --git a/clean-deb b/clean-deb
new file mode 100755
index 0000000..defcd75
--- /dev/null
+++ b/clean-deb
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+#
+# Debian/Ubuntu Packaging Scripts
+# Copyright (C) 2002-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+
+# ====== Obtain package information =========================================
+CHANGELOG_HEADER="`head -n1 debian/changelog`"
+PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"`
+
+
+# ====== Clean up ===========================================================
+rm -f *.deb *.dsc *.asc *.changes *.build *.upload *.tar.gz stamp-h* svn-commit* *~
+
+for type in gz bz2 xz ; do
+ find . -maxdepth 1 -name "${PACKAGE}-*.${type}" | xargs -r rm
+ find . -maxdepth 1 -name "${PACKAGE}_*.${type}" | xargs -r rm
+done
+find . -maxdepth 1 -name "*.buildinfo" | xargs -r rm
+
+shopt -s extglob
+rm -rf ${PACKAGE}-+([0-9]).+([0-9]).+([0-9])*
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..c1b0861
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+ripe.atlas.cousteau (1.5.0a2.td1-1ubuntu1) jammy; urgency=medium
+
+ * New upstream version.
+
+ -- Thomas Dreibholz Wed, 16 Feb 2022 08:08:08 +0800
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+12
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..093a9bf
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,42 @@
+Source: ripe.atlas.cousteau
+Section: python
+Priority: optional
+Maintainer: Thomas Dreibholz
+Homepage: https://github.com/dreibh/ripe-atlas-cousteau
+Build-Depends: debhelper (>= 12),
+ dh-python,
+ python3-all,
+ python3-coverage,
+ python3-dateutil,
+ python3-funcsigs,
+ python3-jsonschema,
+ python3-mock,
+ python3-nose,
+ python3-pytest,
+ python3-requests,
+ python3-setuptools,
+ python3-socketio,
+ python3-socketio-client,
+ python3-websocket
+Standards-Version: 4.6.0.1
+Rules-Requires-Root: no
+
+Package: ripe.atlas.cousteau
+Architecture: all
+Depends: python3-coverage,
+ python3-dateutil,
+ python3-funcsigs,
+ python3-jsonschema,
+ python3-mock,
+ python3-nose,
+ python3-requests,
+ python3-socketio,
+ python3-socketio-client,
+ python3-websocket,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends}
+Description: RIPE Atlas Cousteau
+ A Python wrapper around the
+ RIPE ATLAS API.
+ See https://ripe-atlas-cousteau.readthedocs.io/en/latest/ for details!
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..35cda26
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,24 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: RIPE Atlas Cousteau
+Source: https://github.com/dreibh/ripe-atlas-cousteau
+
+Files: *
+Copyright: 2014-2018 The RIPE Atlas Team
+License: GPL-3+
+
+License: GPL-3+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License can be found in `/usr/share/common-licenses/GPL-3'.
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..0d409c8
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,6 @@
+#!/usr/bin/make -f
+#export DH_VERBOSE=1
+export PYBUILD_NAME=ripe-atlas-cousteau
+
+%:
+ dh $@ --with python3 --buildsystem=pybuild
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..5647142
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1 @@
+Tests:
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
new file mode 100644
index 0000000..adebe51
--- /dev/null
+++ b/debian/upstream/metadata
@@ -0,0 +1,7 @@
+Name: TSCTP
+Homepage: https://github.com/RIPE-NCC/ripe-atlas-cousteau
+Repository: https://github.com/RIPE-NCC/ripe-atlas-cousteau.git
+Repository-Browse: https://github.com/RIPE-NCC/ripe-atlas-cousteau
+Bug-Submit: https://github.com/RIPE-NCC/ripe-atlas-cousteau/issues
+Contact: The RIPE Atlas Team
+Security-Contact: The RIPE Atlas Team
diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc
new file mode 100644
index 0000000..4b16925
--- /dev/null
+++ b/debian/upstream/signing-key.asc
@@ -0,0 +1,405 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+mQGiBDr2cOgRBAC71Xhy1yzNTBxnousyxwtZ+zxRQJIfkDUQ8Yry5/rdoRkUldnE
+VQUNX9owxKKwA40DsKMX5lfPIgfPpefqnSOx1/XOtjpffkF8+FY8ncU/LKvHPPw3
+oNXzFAr8F6NqpJAIbp8eW6DlfraXiJFZk0D6sZyIk9XDqTY01+Dn5WmAewCg4Szj
+r52geHYk+6n83yfVqw8+c3MD/A9d4ylhJikTHzbL83HTO7WozqlGtZq0rwGY+JIq
+wPAaRAdBnu0brQz7xtfTZrvxA6v3sYb73bpuosaQNtg1K5Z0l0fbJQxls7wCdSC4
+GmkXyl64c1bPiGMHu7WVE85mwdm4KyD7qELnnNKZoagFgK1HNYFJtuUDYQ3ihBQq
+k0VnBACaqJ4k/VJYPQvuWy0fppX+Ultyqz2rrHqqVvaSotjc8muxwM0OL42ZCjL1
+scuFb1TonojymUFa1nqe6uYU5Owjh2CRfs5+TnMUO7S7vXQRQgWPffIE7kJqL46G
+S79MmHXVWwmO1WMpJooTlsCUv+J+pAWpYu5nJY4X/s+1DXSA9LQoVGhvbWFzIERy
+ZWliaG9seiA8ZHJlaWJoQGllbS51bmktZHVlLmRlPoheBBMRAgAeBQJCWjEIAhsD
+BgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEN9gW7B2Dy1lSRAAnj/KX959nDkAh9Af
+RYaLHkz7+60/AKDWAxDnQxnNnB32zjxJvtLKxK0uY7QvVGhvbWFzIERyZWliaG9s
+eiA8ZHJlaWJoQGV4cC1tYXRoLnVuaS1lc3Nlbi5kZT6IVwQTEQIAFwUCOvZw6AUL
+BwoDBAMVAwIDFgIBAheAAAoJEN9gW7B2Dy1l6BcAnRhM7hgy3qOLDKpsqIY88XZa
+MjMqAKDHqpiM/8CFpti9TKeIP/mRbva/3tH/AABE5v8AAEThARAAAQEAAAAAAAAA
+AAAAAAD/2P/gABBKRklGAAEBAgAcABwAAP/bAEMABgQFBgUEBgYFBgcHBggKEAoK
+CQkKFA4PDBAXFBgYFxQWFhodJR8aGyMcFhYgLCAjJicpKikZHy0wLSgwJSgpKP/b
+AEMBBwcHCggKEwoKEygaFhooKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo
+KCgoKCgoKCgoKCgoKCgoKCgoKP/CABEIARgA2wMBIgACEQEDEQH/xAAbAAACAwEB
+AQAAAAAAAAAAAAAEBQIDBgEAB//EABoBAAMBAQEBAAAAAAAAAAAAAAECAwQABQb/
+2gAMAwEAAhADEAAAAeqiTpUM5HnoZIrCQOQqjleLSxqphChihquBJvrqop1cI8bp
+VktOiYomZ2XR/OzCiB1Rys5c3dsKr2ZlchjvO1W0RrovRbKXS6JKccyCktbmfEM5
+Uexz3iNbSjuQv7kTPMSxC5dwnbw6c8r8HdZCVijmlBF2yCokCvz9TPgUOJUJEuoq
++KmiyrheRKdtgYCNthFc7Lwe9stViGOZJiNAH6sBjKkzQqUZ0p7rtQDKdMddO6sy
+JzpVvDXqe5cWaKWLHlwGVJnSodRxHEhXrJS0ZmTRC0zVvCGnTr8+eBeaNaZ1yqmH
+sIGIvNPHwBDA1A6Vl4/EU6EbBHvo6cIB9csV8Bd9AS92H0d+mIVmW8RwQmg6thU2
+8zl8qpovFrHVcQszNxyUkpfCcfQwiUsj6J86cSAx6lqlwulba6fO6DJuZXB3o99w
+1jzLH5F05VdUlaBSxJuvy2rz9JJ05NWrH7VZbSvN5QIEhag+VUlqOOVezOCMbCVc
+8r1eRzaNs+z2hxegxvGLWk5TlSUJekVrqvpDDik0SsGkeqmT5/yv23z2eky21Qhg
+nhKCVrIQjQs8u+3ZVw2p+cqdB8/12Sjba6jE6HJ6GityfVprp5ZuGZxoo4GwRrSN
+SPlyTzpNwcLg+E16sTzRrbJN2qkasnScniM6ryp1UYL2qvgcrialFLdXdPSQtaT5
+lj67qvrFD0CVMAHtLqTwbPRjMoFtpqHKha18xytbRQ2atY0BMmBy2ziDd0cHltdJ
+BDBa1R9CZ6c9vplS40BsFvE0W+kUuJCO6dHToFRVrFYGrf5zRPPICQsObgdwiiBI
+nnWwG8dxCwWDKyJBgjfS54/TT2u5iTWlYVgwLOo0MkYsK1eayoi8+Jjk/Gu1NYc0
+ej3dLwXInqKyPMg3j1xIBdlTqZ6M1f2qxmvSrogOctNWJ265xEFEayQ2wpq0OEr6
+hHBZLSqiVwT5OTWuSo/CvKFxEeuF1Fwrm4OJJWMrKONj9GxSmwVHnR05hqMje23l
+gOd20Cz7HuveXSnIVKehINTb/ADOQaruupVyuA5qBerPQpukyD2XVAxjZfwO3N+T
+8m4jvFaz0X9ZNYNWlnkpOW1gTRBYMQpGcaQ+uys1+TfVvkXZiCrKd6xIiT3cpM6C
+nHg15AqeMe6nYqdd517Pje2xOiVjSobW26PweoSzzy6sM1GqUFblIxUGYbdez8zl
+Hy36F8+9PL9BzGnKzWwcjat8hLipMV1VUBGGsWp0fQ/QM97zq4EXsfbzP2cDc+vB
+WazGUVlcqlxPrD6vG7iDTJRv3sfJTHYrY473YbTQ5PXedfLrHWS3K6HSNLxXcrpd
+bGXPpGV78D9E+PZHoqtq9rPr2uG2Ofc0VMj5t89r+hwZcJrGd68qffPPpOFZ893z
++weS0+X+gz6jaYzY+ddFgt/gdq0wup9DL0n3kb62T73y21H8z97280Kve9CXifen
+ve7L3kobz3pogzPvVZT9f97BkM573k1+b573vos+r1fveXpz+I97fKrvvb83/8QA
+KxAAAgICAQQBAwQDAQEAAAAAAQIAAwQREgUTISIQIzEyFCQzQQYVIDRC/9oACAEB
+AAEFAnsYTHpazIC7D642EqrOZaCqr7DMsXntXN/oaxysPtDYFpRNhAEZXNzMrEud
+RW8/dt7iEFSUMGmgR9quiANc2JqeJ5Lb3ZaGQ2rDe3GlmpNI0NjuPp1Q7PrXKxys
+UfWNnKY2wbNbI0VPKVtyln2p+nV6CWNxqFoCj8VYcaeKIFYhDsXZYqZJbtolddSh
+ud19ljHluLbwneFcDCuDI9hkrysf3X2nHyxKiiv2dCpRxZO1NrMrKUQaKUd9pa9y
+Wb3G9m58X8PZtuA3yehDAW/U81Q2X+dz+ixnKIeU34GSVmPYHQE81V1juAeOpa/J
+L0IoHmks0xMrcJLlbNCyxDA3ms+tjGKWUtzC2vxNlhJEGoUh+EPnZBHtPao15JIW
+5WUlTPBe5S1rhu2w4zuM1uLX71oAlfkbg+6HT+vIK8tt1GYsQNlE8irz+M+5ZYE2
+BoytNM3mFZRk8IchdY6aTbcKxxNwVU7JlCQ9xjX6z304UqtYWcu2+Rb9I7YiiChd
+BeM2bBxZ4BxCAsK6/ptX5X1gYbZRLU9gOMqQfpTpZy9chDaVXgvPSjhp0EtVRUvk
+WKxb+7tu1SipBtofQVXAQFC3HjFXlK6pRTsHG5S3H8W1Mk5MsQh1f2rxW4qj6Vpk
+FoT61bQhoiFqyC1OO21XVikamVxUITbZTj8RlYdlbLRYxxOnOZkVcWHlqcUhKUGi
+kNYluOrjJoNRatgtVuxQ4SyxgVVyw48n4NZOzuc9S4OkTfdRwi79chyK7GnR6tvS
+vEAeAiz+uzzyzhfvhWAoXUMaNM1d18u3bmU8Ilsqs3NMlmuTeed79uC5NNoPbQna
+uTViPrGzDuGdMULjpFPyvwZuGGPLfIyvV1f6ZHmpvbvcpR4rR9i64OGdeWPSrS9A
+1NNZto7jizIXdrD3wv4a4pg+B86+DHjjzmfbepvcpH1ql2brgleGSy2Rt8uy1ENy
+3pVuuY6rc2R/JYffB/jqiwf8ahG5qGNDMwejH2WY43kL+OZWETD3t6ios4l0RXbL
+xGV/1Fdz4FR7WYPpWkF+nfhVFiwf8GGGNDMobR/zWYwLXD1OcxlD7i2HYUtEyRyr
+Vxb1ip6x023eNmfVq/rpZ3TV4ggac5ym5ynKcozRnEf7ZB9W+4nSl+vzPLqgZq8I
++to4rzEvVsacudbujY9VttLHM41uNHpNgFXc3Gy+B/2A1VnBotu5y8NZqX5grB6j
+P1nIrYSGuYAtyW5fqqvmrSIT7WsNVWEWNazP5EW6s23ZTuEtCHIXjZkZJsryqU7O
+N4UMTGqYxmVIlgmFf9RQSuYCqu+4W8JkgGvJrhsDCvzMyvT10sXYCu1vEyWPaDBH
+x9WQp57PGVOUXHyiWvf29TdwN1WKh1yZJTiXXlukNzPRnFaYJplP4ZIDR+nV2Sjp
+9FcfpNW7unI0XpZWdjthsRsiwYvZot4/q7axq8AKygjG1Wu1i1QVah5JddB6zFJr
+ybaVQ1qs4kQc4Elsx/tadun3ZA07c4/F8xG01jbXLc9wywARgNq3FVx3dWXk7e50
+XNu5SfCsC2WZX8ASw6B8yrxH/IRDNQiPLvtg/wA95Fdb+7AeB7S0+CNv3bViE7b8
+yeK3NttgCl5kMHxqfMHxd9hEEs+KzAfh/tafGJatduZld+FgJ44tvTEAM26+4YbQ
+ITzca5VjcC/GLlHsY7eOXgNLmlbgtUBLT55CUmc/BeWNLDG8sPxs/MN6Uvu3jPGh
+F5rbafNQ9qwvNazplNbV+poaK0BmZ/B+qsW2rqSlcnP3Ey7N4G+wTG3GMs+x2bF1
+xttVHXc1XzbU1yq9Z45H2ITS8A7cGrDvubmL7KPA5xm8XVLcl2LZS2HhNdK6krVW
+0OU3NS/xKl3Mg8Ux95LFdB6lhVYv0ozezeJYfGw1REX8bdbNnp0y3aD2ljWIa81e
+QyaTKrqXFl1SQ5NMtyEAqueyVA9vcy31EVlmSQ06f6g6C+IutFRx15bXPzBvky7K
+LyYD24gjAR5jv5J9sypLC2C6j3QDuWQYNrTFwEDkABmHDl5uPcsz6NYf6ZrWU+x5
+cSHMbcrZlj8udi+9S+2zy+7Dw6CYmI2RbdTXT0/Ft5ANLpW0UVNNKkt9mq+Lm0rn
+VfTKe5k2AFatl1rMap2FidywUrO2eTLZyI0FB2yqrHXJV4yuv2wMYY1HXszzhvxF
+bclZOQdXWd24QPkNK0sMrTwxlzbje7dNq4pe3Gqt+FtyGu6xh2g/1nI5JrnvUbjq
+uv3Ue7V8raq++/TMKuo5doox7WNllanhiZHFqXBgCmAADxDG0svs1OW5h1coo4r1
+I8cI/fEQZHSszGNapUeTVvtarud2+5WRyPhKrOdqDuta64a4VPZx+v5Hkzp4PPJq
+NNmLlcZVeGXvDilnlrZfkCFy5x17z4lWhOuvrEnQm5YWTUHBr7dpaJvbFiQgBvsY
+ysB3J/19HRqjdlswrryLTdd/84C/traRfVYrVuljLFyn2cqyfqHMLyrlc+JSEghn
+Xz6f3/j7eMj8+oINt5hbU+8a72R1Io44Vbu91nQkAxOvXdvFMb8enr+wSZ+L3k+x
+BnKbiK1j4WKKKsIcmhn+Qn2nQD+4yft1UbxzkvrkQ3fBltbhqO3QGLWvhYxyb8ep
+aa+uW882NOkPyr1plmZgJdP9fds4N0Tp1xOFhJjjqF3Zx6E7dPx/kH886D/6b5me
+2J/Z3NS20vPucPEsynxcZMat2CLc/Oz4xbWqenJS+JAIVnGKPjPv72cPnrx/dzoP
+/ou++R/B8b+McI11CJXXOs29vDPwYn2UzFz2SY9yXLqHQGR1GquZGddbFmM/do+O
+tnefP8f/AJ7T5z34YcM0J//EACURAAICAgMAAQQDAQAAAAAAAAABAhEQIQMSMUET
+ICIyBEJRcf/aAAgBAwEBPwFkodmRTRB37j0YrP7bE8PRY25M6konRes+pa0JsvKG
+r8KolG8QjKUmXh159tFFtCbbO/5UeFqK2KR2wojVFCjZ9MlBrHhQ42zlmR3sZ4cM
+dWOESkxVHPJChi1o5H1jZcpHanRfZ0Mh+pRJCjRHHItDHGzm2qIxo90x62RlaIeD
+LxHE1rCWyVSKK+SCtUyOjjl+J2RSZ1LSOxKRR4Uki9DhESOOHwRVaHfwiN4ab8Iq
+Y4kONWcn7NFFFHhx+lbwitkl8osoj6S27+yy9kZWUITtjKH4PkrWLLwscTLJb8O8
+ha9LGSNs6srHuON7PT6TSspf4OD/AMzMRY/sX4qyMjj5a0xzj/pPltVjxWcnxmij
+3wSSOV/BH9SMsNkUcj+DlFFSR1KFs/T/AKLURuyC0OPXHYTrHL6cXiOVpSO9jaT0
+Qhe2cr1iK/FPHVHWi7xyenF4j+R8Yj7jl9xx+LM/xWjjxP04fD+R7j//xAApEQAC
+AgEEAQQBBAMAAAAAAAAAAQIREAMSITEEEyIzQQUgI0JhMlGB/9oACAECAQE/AYLk
+jOlZOUX9mrGP8SldnCfAiW1dDfsqB6PJto0/dwUvsioxVnqENRvo9Vv2xFoOMvcy
+UY9ChRRKNk4yiiOq4M327Zp6ldYepCEF9jjyUJNKxX+i8S0IvlC00haXG5C9xTm+
+BwNjQixPDZvFLFWR1FFtMU6TRowJe3gXPeNR/QtRm52O2MshKz+zUt8mmt86Hsjw
+ONo/w/6In3iLHIeNNiFLaaD2ys1NSx8dHfA40T7xQkNYjiToVxaG0+ROyb2u0Sdk
+48m3FiKEsPljk2xq2LUZJkp3ySF/ZKsJodFm8Q5CZeGx4Z9CZWd30d4RRQ1muMXh
+8YqsJ2XieI8G1EucI7GqyjrEmqOjhlHAzo8fVWorGUIssbJTl5OqoR6GqxaG8eRq
+VE8C6kJ7uVluhvbyzydWTjf0eBpbY739j7occUTl/o1pbnR+PjUGxar0tVr6N18i
+kJfZt9Z1/E1/3tfYiK2qkPsTsocbNee2NrHhfEjylWszxk5w4HBxFBtcnleVHRW2
+PZ+Pju1HN4nHm8bmNtnncbVjxPiR5nzM8Hp4l0Ps/HJeneZRXeFFI/JLhPHjfFE8
+r5meCvZj/8QANhAAAQMCBQIFAwIGAQUAAAAAAQACESExAxASQVEiYSAycYGhE0KR
+MFIEI2JyscEUQ4Ki0eH/2gAIAQEABj8Ct0wvqOtwuM6Gey6RRDQKOpVEAzHSoM6j
+ug0iwTq0C7C5Rpew7qjqm6l08I7AWaunZATULsqLrVu6Bd/ldImQmtoT62VQTVUH
+wnNBlcFR/wCQQiqhEhpHKLen8rqnsiSAVSguv6mc8Kg86A2UuoG/asRwlo4R7KDc
+87I6a/7Um67jYImYR1T/ANqbO7k2OOEC3YAFd8v/AKtTnS5ya9tHDZT+Qi1rZkUW
+rFivwqGg7KWVPN11xRNiKCIR0mya+kqGCXmx/agXOJxFwhQ15Wr2UBXRgW90ZZpf
+33UtUbkx6JuuIAQ78J7eHUAW2pFrulFoavt9lSWyLqI2qvqABrTROGkl2yoPmigU
+JqCEGO2EI64RGHabq6oq5VnKi1cbID3Uk0RqjFJKw2D8qAbHZazdGYButOI/4utT
+RIKhw9gmhtK7o0F+dk8I6apwhF3lNlLxU+AVzhboUWrCkDdNNJ3ViVQVCImiGjyx
+RGBqjbleVx3AlAPG8L6h9kAqwNqK8+qkUKdNAREFABso+WSLKhUnI7rqWp2/hpPo
+pbvcKi0mrVQiFjOOyA/6e0KgNryuqddwVP3IzRS0iPVDaVodsZTdcyBdTT0Riqjd
+RuVUqAalBxsjqhrUBvCqFOymmXB5y/ygeV2K6R5lMQrdKiOkQSUOFA3KqfhXqpYO
+mbTZNHmm0Lq8vKJa6gU/atT4JKmq1ON0ddRk1111WC5C3ytXnKqgwEAawg2TOy6/
+RRNCo2UVJWqlbSt/wnarIsjuUOycwiJ53WjzcIQaoMFytOHflTBVGlVHujh73Wmy
+kIUjOyiKLWyyhy1GrUawu6E/ajpIqYae3KpQCyiy8ukFASRKe2d1ui4+Y5OxD7Z+
+UZatk6LX8U8J7btcm4rLFXQCw+6c3m6ECGiAV5mwqtnutWLfjhS52mTeLJ4rRQam
+PwmjIfqQtQ2KLHeU/BzbqFGtP5Xc3TjEtlVH/peaE5/mrc1K0NPoi/SCHO5iE9j4
+Im6aMm/qlEZDVZaqV+EQypRDZ9JQjhXWv+HdXdvKjCkYhMeifhAwGniVjiPuoV6Z
+D9U54ZTGN9Se6aospRkCVSyGL/DD+c2pb+5EtOnplwhfUYDOzTutdAWbKR+sUcmB
+CNk34RKE2/ypIafULo8ljRBxJ0mwOyb/ABeAIePORuFDpv0dk7SIdFcm/qSEcy7g
+Lyu/CZpBIbwiXAgyj01HZVLp9E7Q3VMyfdTqLWsrCdLoFoJRZh9WwESjOH1m5dkd
+WxUgwFGVfDTwVT6b5NGGFCE6vytTnns1O0OcG7BQ7FxQfVacRzjW+yOiAx0iCflN
+cetw+0/4U6v5lIQbUFx9U001ChTlCmflQTPpkBORIVVIaF1MViMzG6bSkpw/apKD
+opacqjqtRWQk1OwTvo4rgNwQj/yMJutzaQtbaHui4+WVobEmoWIoDaqcQw1Q0gjm
+UA1zZQ1HqHGUKh0nlQXa+xU9UcQukQp1oIFhgii0mCsUuqGg07wgdUyK0WkdXqh0
+wU9zpnYKhxAFpiCNwquePdNLTq08ppLQJEyh2WH+3UEwgRMqyotgpJn18VD4H+i0
+7lYhERUKZbZCLDZUQug5tin0nhSU0x2Vd1JMhMIi4Kw+xP67nI7tKMlTsBlS6hjq
+J5PmThXsmkICbUR0wtTjUbLCeOR+qVLl9PDtuVSF8FdNsqq6LQIVVF04m6lBfRNR
+Mg8eKufbwFNC6d90dIVN0AiN0Z5yc5zN0SLZXgLS11zRV+N008+B2m61bZUVfhN1
+X8NEdX5WmupBx2XBlXlGu6sEa0N8nutAUSg/V7LDnv4tLlUU5Wp9GKjRlfMpzstJ
+kRv2VInlB+qXb9lKdFqI0VF9ygGl1dV8qoaqYsEOyMLyk+i6qequoKiV5lddDTHK
+6s4FKCqidk6aBb90PRTReqMt+VSkhRVeipsmge6kgp1OE97R0N8xz6gpwzKrIVA5
+y/mO0qXnV2QjOApZ5sNkLUfLC0j9pso1CZQqy26ABCePwneqBHC90aogqnBUSmsF
+tz2WLhM6W6CU1wzp+FL2/hSwN90XOMnwFNJsKogrSHRG6dpr0rDpTdDqA2hTqZ7q
+Q4H0Rg09VPaPlArrE/7RNiuqwoqHUdggPvPmKOA0/wByjv4OV5VXOEGrUnu4CDjU
+bjsixxppltLhNNd0+tLQvt90KNUaQtNgAtQ8qInyqLEXRa1pqpjU8fcn4nARc65q
+nu4UHKqt4ZQ/qQAssY/05YWoT0wsMAy0FBxNdc+qkHdCdivv9kJqFZe8QoaOt/8A
+hfQwa4xTWuMvu4903Ab/AHOUp8+Wy7bKHK/hqo+3davxlp5dlHBKc0prZ8vyrwJX
+qqH4TTiCDH5R0myF55X1HAf8rFs39qOK+unqk7lFzrASn4hu4zlq/qKg+yLXXC6T
+ndVQYwJuGPc54I7k5Yre8oFAmeKJwK0tIHquh7QOCvNB7oT6IfxOIJeaYbP9o4mI
+ZeVq3c5DDF8Q/GbPU5am+cfPhDW1JUfcblPxNvK32zwR2OWIOwyJ4qgIC1T3U9SM
+3MVWrFb9R32tWvEMuKGG2guTwgzD8oRbswRm7D4M56m9L1YKwVYCm7uUdPndRqYz
+gRnh/wBuT/7f95P/ALfAJFVLqkqGDp3dsFowx6nlOcbASnONyZz1NuuH8eMD7GGP
+A0f05P8ARdk/38LBiu0sJqUG4YAYLZOG7+nxRidQ+VOG6cpKjD6z8KroHAyY8bjN
+3YDLE9Mu7soy/8QAJxABAAICAgEDBQEBAQEAAAAAAQARITFBUWFxgaEQkbHB4dHw
+8SD/2gAIAQEAAT8hoKqlklWgP3RAHLsht5qaGVmotKsxqccyzO1tJazqYcI8sqLz
+xZAg6GncqPFNZxzknqNY4YHEz7wnBKMV4Bzw9o9mcPLPMtsM51zKiz7D8yoLPlDD
+h7Jd+Q5gGRj9zXgg5mHNAgRlH5S1i4MvV2oO3phsqVVgQICLPSANGDXmZCqzk3NJ
+BvEsrh5xmZTBTwjgfZl5hIIav1dyk8rFxQJQKfuX2rKLbgEXLJnwxafsU9xKswD9
+maLpoxwFBwuOy8i4EXYPRv75T2tLpmkgtujUBTcIFkrXwlhbfBKCy6ydBhORPsK2
+UA5lVOVw7qNG4FgaFcENDOy58zALMwYorCN56h242DmNEVsLRrqbIdNiDCmC+iBF
+TSH5mP2hNdzLNGRYgQNUnFphum917Qsi/VtlOCOXNnGXwOJZ+1TzCtW3EsTyg8pR
+Tw9kHNfjqG0ozjFPQTNZnPLyPJncWR4I7FJ5BKgwy3fXiWAA5IE/fCRpY0omqLB4
+E9UwRtwXs95i5m7dIubD2PMJnlrax2wsJDzv/wAnACs0ywa5tMmXJ8xBl6QXeZYz
+t4jWoobM4lTw54ubNdM5jCnRuLbTPtMInsGNp3JY9wOI5Vy+JvSttdwCA6lPLcRl
+p0TxB2FVVQeh0GBW+6NQBKsmk2rctH0Sm8Z83z+YuxE4u/aEJ1ypu4QCvxzmoKsq
+x/Yj4Oos5lrlq+ZRgVcw58zTiJTlxPAOSVoLXioCG4C9TLVnI4abhLlwKaL4qWGo
+Mdl3uOgqgRr2mRCot80gJrB4DxXnMstLweZcvRByzp8TBbmUjOJiVgu1/wAQNCR0
+cMHDZAVXpG1LvbVwGIsBaw/qZlt9S8MWCtBQLlWo5+08jBPaN+SUX3xjca0MSwXV
+uPeJhYZ8IdTAwdwheN54qVHMd9xFwUtxGzm9eLZg1vazB35o6pUQnSuvP2i9Nsoj
+7wAV6OAhZYdXFm2nRbL+JashgvDcokLGGIwhd1g8M0BfZBKgttd+0xK2FDQFcRNB
+wCxXYS1iLKg45/5lxURSW7mbLfSPKYVL+Rf3jX6uJouHtHJu/F7jUapIpBWGIjzp
+lyXqJdeIC83LFNlezEC9hONRV4HmnfvG4NtZMYSzGLQiLmcwQ0ey9pe0RoFX6eJg
+Z73yRe6Ft8eJdaBoIGAE9iNWiNtTgvofiA0KZqAK3WhgjVZw41GFYOrUGyuTPctS
++xDsBklizOjmMXTfmVhwPiPrb5hOjMe4DXsjM5iZRY5C5UNb1fcpLMHHcGQ8p/1T
+CZPpGNNrfN8QzsQOT0qW1UpwWlS1VDXyS6IEYr10xFC9SWQsKILGPVMgXmpWHvpK
+1auYpgyMum5cOLD5hMMXk6id0QPeZ0qKI0Ydx6gex6nENiuz3hChueo8jNAdeZUR
+9xFbCzsjZkKp90VGNm1UFuacMpOw7/8AJTiI+tTciErsiLIYGc/MZTLV/LFa8yuG
+ivVCAgOQVNn4Y8CXFHSLadqSqoQEvLFHHRuE1IrVbVQAWt1SjJl6RLoNPPEaflVv
+VSx68nqjqUCZiHqUODxVSgoXhuOxdenhXMJ5yLUjmNlutsW6spTv+Jey1uZVO9XM
+2lhBgyuJZV8xl6j9SBsl7XLiBT0CDvNP5IxDhpzM4HWXkWvxAMpeRRkGlMuCXPWV
+iCoV4VcbpCqlwH4iXiaRn3+7F2feZpVHtKlzdV8SnWYhFj6DuF/SvbKtjhGocQX6
+xPRBSVM0MkAzss1EVCoHt4iSK4mls2raDAveVzMr7J/iQw4mEwmCltrXMNUiYboi
+GtsFw2KzsMvLHfii4j+ggeIDzCKWY0+sbgQzYoSF8pXpNBv5Tf6mHRW1YLqWc1Ux
+HYJSaYG853DTaubn2S3GvvLvCtuQmx/2VTeTieq4S6J2BtTuaRF3US+2C4e/pp9N
+svzEdznBDR9AduPL5jzCe1nfUDl6H3mXDenfH5gCz1riAxqPsKhFueUv8wBcHdtP
+Sv8AJRF9dgfmDgu0a8jETyHvDzelaFo5ixar8TFnmIlE9UJDGGMoBiU9wGRNfN/r
+BmOD5QfLLFmAjUu+DGvYAYjVlfbfBnzZGdIoMwmlswt7K8+amBrFAtxOZg7QHiYS
+11t/PMseCXqogtpNEXMXyxPW2VGFwtcw2yhOwMBIVbx6ywDcrFxnYXiZ4l2XEyii
+bm9d7zKsarZUAL4R4PtLWiuTIcS8BOyEYmnWhnPf8jUTUuP/ACp2YnYYr8t+IeUG
+qg2P8qo/sCS7P+Q5chqw7N/MwhkshwMQpR94trLrKb5YRLODMZ+i0SXOVKiJuCeG
+YX3MwlKlwZwxHZOfpGC1iQTJo1Fa3iVjh0XzxcONZNQALXseUrY3TlzGvULEiqmM
+E2dTS7dVWGX3gFtLLa8X/JfLQ63Hc1SPE0rg/MbSH0w0Nu54dlRyAxWOoXNliMp6
+QG/LMFyzS5dJvhwQtT6J+ZtvqXMEx6qIrQRKLXLvAIrUNREndyENY0/BZeITVDwM
+RLGBa3ucZCyPv+p7+Ksm5BD5IeWFMPLv0nNEpTiIrKQD8RGmgXXlzUvsyJt0u4Nt
+IPmmUsCW8Splx7BOVKKcR1FD1HhcGuok2QruONzIgudEebFek7GA1nU8A+rgxcyS
+lVPJrP4ltSl1eaxDA5F3XMMDBeVmEqlwkrjDi+pfuxt4lVbvDxDWZO8TP9PkTAf/
+AHTxlTJ9A5pj1cG8VMvJRPpipsjVgXqIDYSyEUZqU1GB3Dk6KCBuK6usBKpGXL6T
+i06IS6AFTDWVYl0c735lSjT/AFANYGr4gFbA0eJopU+GOkr9HlM5qgqXU0VKIvcr
+FngjN6EqCTZ+xLu1ta4jkbaMH7lDQ8D/AGewLu7jWbDRAjn5zMCjALuyOGlHMICS
+kq5YbnIC0u4oOC4z6xYw/wCifSCjBn6dNvMyVVCNpspit1ygOE82Zgj1IRMZtYdL
+bL+sAqGM45lFsOPigiVuUedxwZKYlXzVVp9IkKKPaF0tbbLlgYoz47iJ889RWVpz
+4IygTNZlEsMwzWqRr0iATHLPELZmSyIVHwYG7nE+0athjLGnbUJIjnfmY6gymK0D
+MYyBHH6TFGDRHQINFzKG5w7uNXQybvmdyal14dxrQq0Z/wCYp4RZXqHLeHdx0BAe
+7qDIYoJAOCBilSjsWz34xMQt9CIBOS5UGA1ctUrgVw1qZsvEaZipD5hAJ7Swha+E
+Gkb5+gAI7KPu/wCRMlptogvnIt9kPVUjBsLCoVWaXZ1fmLKbXsMufmajAxo/yNaL
+FV6yk3YPsS1qLS4wuq+JxPLJ6zKdivSodFlolWcOFQJCzHDW7Fy6GvqDKqy4BXFy
+wAqa1Jb61ALW+mIJOEaBKjLdEXFNlXcqMy2VhFZzVXlqLQHbuW2ttkzEC2l89Sjs
+P2wxHIW9JdsQO8albLdyhBjjCB9ipXaqryrc2BvzRGxJx+RMh30Q6+mA9UfB32bn
+tK+agXrRE1MeNQ6wDxDKq6UDAAdQkN34je2EsF+TKzAB7VDO5kVKUOhD/wBoqUJE
+Bdq954f0HEZqXDlwy7IGXc40K48wuLZymcsa3Kd4wXVR41nYY4Yqmxm6lngO0NAC
+w99suxuWV3MqYQlz1TjF5ROWhmU3i/aCoeZdS2csUhnv7QCsJUHN1tohFLdmEdc3
+YOoNoQFmXEYgK+RUNVJyuZxizV8RLV+J3lDFOa+Ja0CFeVMaqDOAlnAcjMPNl0GV
+Y6acnk6l2FYsPXEzxxYhFW40X8HvNQKe82iCaEyinMpJjTcTRL5lXgnmhfiV3+W5
+EsWK+U0Uzb6sN81MxyVHepaDcOsfmuwqI6vu4QF2MZ4K6XnEyEaYcSxeBa65Z30m
+8B5Zh9zPfgik7o1traOJyyeJkHcB3hguFzVVS1wMocRaGCUuWtyitcqj0hgqBRL0
+ayPviCCgkbN48yzqO8db+ZvzYPRMEnK0dZYVQUNU8QXULBtjUwLRjucrYsNXKUql
+HkzuNRnV0HuCQxrxp4vz0RrwMjlbl62D+BNmGU8oqPPKiVTBplkIOZK1BrdsBdMv
+KxFpabQMSsV4H0qBxH7juZzxv3+4dNxWtlwzi1j0grsMirNS4YKNeEM/Ua7+ZpEZ
+b+8bqF8j8wrk9gcfb8xyHe5HX7j2U5PifipCO0we/wCqNN3Lpgv0kdtIHtKl6lWm
+LMuDfKcv3PZ3DQBqKiId38CMenx9x/IK72GBXB/T/ZlRXaznAuHkv1kScygYpn3h
+qLzl1/ICAXj2d/Ec02168TtRX7YlqdB9G/19Dyg0m8nrcsamH+nw6iNThPoW8zxg
+IKNQfS/cp32fY2fvf2hDLPIPkjueoG+f7OXqUs0oHs/2CVWc9wOKu4ClsukI2Iu/
+pLq4bTD5fH5ixPMZ8Wg0H6tMp5wj67ZzM0Je1XQ9GNj1mZiKv6xiSKDu4Jr5IKKX
+dzGHaoiFSe9DI4/qeH/mYuZ8Z+EzCHM3b4P5HPhLmWliBJ7QFGdpYUpcggXyOXan
+IynsRdzy95xO2XrwZijNy/Uxalh9Csp4lYmW7OfOcv8A8Luofyzmbvj+Zap0gs9X
+X8ziLUc4YiBMJ8EE8Gkssle7aenMeY7iqybvWKaiJ67wlUHY5JpDYADay0B7NQSn
+sORU3zD0In6+kF8TmaKcfzM3ol9xgPfMY1aQCf/aAAwDAQACAAMAAAAQc4xsWSWo
+SvJfMpr+Bvroauh/2fdbJcyUjWgJy83cqQPGSc1R5Yd3TRjkygo5ow+MNncgMzQS
+cxoofo+/p9V34oXbQorrmCpyN6+N/mvq5T1rSm575nx/gc33mpXv/KMGaW35TzgO
+pALXsmskKPzehsT+AMmECvEExw40xYLdQjQSdhpi+HgkIao4R5E6V0l69xVHiZE+
+KkoVzoMITc/pCyz2USzMamQXn/H2ibWyHyhxIwi/8Aj9g+dcAeCA/8QAIBEBAQEB
+AAIDAAMBAAAAAAAAAQARITFBEFFhcYGx0f/aAAgBAwEBPxB8iEXhO9JOOckU3zOi
+F7mRdelj21SflKzCQH1aekJ1v6qDoZvZ0Q58I92FghhbXWHlwDC17hxtn2sDxBZZ
+buvgdQTrQ4z63SnLGxvLN77tvPyjK6LqTj5s6SW4hsgq8LBPdx6uPEcWmvu3blmz
+MC9L3DryTeWzS6MY66tcWDU0th4QPcyGxwTq1IupHqLad2kI5iEc8Qj9p7/7DTvH
+l5DzdiGE1WTZy0UvY3X1DQIRxnCD3E3qi8Zy5L7oByBPlwXxaGW1jiMiMBtWh4n1
+UhXB7lXwZgNu6kR9r2EZHthK/wBQwEvwX6gDPC5LlultmEddbyNiwb4zxsjCyF+1
+wLR8ymXTkYhdk77cWqQvPZZGCT48OStnnIZcy7JczRqhzMmifiVyrCGkTrxLfafG
+SBkMQIDSNPLZZvB/McZd4QzhIzLiw3lkxgVyJs9WgNj9Eh8s+uyYDC3bNIg6kxyA
+bUB78G/7f8vTmgYZS9Nu6wrj1PUIHvmccgE9ZCH9XnP8yLWDB+TL8h/YBw6yDW8s
+tq2OikXRV367DJEyD6np8AFy7OevnMHq+PBsnqfBFxlIJsebpfKbj8ee8E3J8f/E
+ACYRAQEBAAIBAwQDAAMAAAAAAAEAESExQRBRYXGBsfCRodHB4fH/2gAIAQIBAT8Q
+y1/E2Y5fPvcjO9z38wRRkCexEHgyHB027Ny9xwGwFv5kdlyD0hfu/faM8JKZ/KHe
+5ajbn7QOEEd9y8dtEdRje7LB3YTHPn9+86o/NrDp+YY7ELJeP6tAH0230OPD1dwf
+biFEX6cWOzk/f39YLYYLsqWHrZYZ4n2yMMBcGJuSeHbQM+cjAOX+p8ec2enGXMvT
+J5bNxCMj0EGWizcxw4lwzqzF+kl04wK9yJ3rEpam2wZm3Ng3CxrciJnzza59Xx/k
+PHOhtt46uyDYoRSTxjqUYebWJ3EeDYsfEw9TAt3m5MLxKluCz77F20yTWoeMtPLG
+i8f3Dgb/ANSrUteIB29LMx9N9myOErML3WrzYdW3ri1cNsHG8IWW9WzLhn2R3Y7x
+HKIotR4g7tjuSuWTaZBps4DJkXtscmTYS5t+JVzZVt10hhti3vSPOwOhJnoToRHD
+u12d8QCOVvMVrxCqHssSDzLbQ63hPIa76BpOCNHEJMBwf1tiQ5fFaSZzaYR0Hx/z
+ZjySsJJwkMYA4ujy/P0t3s/Cyv0eBYOZ3ica6L5Eb31ni2MN5WXdEv2Dv5fb6e9v
+wG5/HcI9BPmxn5mdh6if7Ecwz735vqL/ACIvhxfKWT4+9/4nfvtLzDD+30QQjh49
+HtGKPqP49Dn7+bsfBPi+YjrBy5pYTHazNkgayHEHvt9Dn0C5/a/EA33fT//EACYQ
+AQACAgICAgIDAQEBAAAAAAERIQAxQVFhcYGRobHB0fDh8RD/2gAIAQEAAT8QMNh7
+2bAj4wcaR4cyffjJzhsS4jmP05UlYE+9Y1htibHgxmEUK4Jb26wpMQFsRb9bzhIo
+2mIMCk6jQACfGWsQCBKUnWRNVdYMlulmesdykCmRCh8kYNKOupBK247c0GZzi2ng
+S5CLIQLoJ+7GNpogJgG/yReBZYRmJeb/ADzhg4AzQDqHLC+AiJ58+sBREOlAWEYr
+ym7fsyCAPCC0H81j5geLq0SuZJPeGd1Q83z95KwysSZrb1rvJcDVbLe4eMtnZEng
+btd5pyKFqfjIgQgmB8c6wixEAI1Nj+8QuV0iey/jJKD2MIEU8OuMW2TDKRJiRusQ
+NgBocCdlk5tP0UBSPycdSY6bZr0GNq9O1F/ifnCTuibhSjy5GRBSkksrglzcr82U
+CRzSe8pQiORGlTyuFJxF6Ys7iqw6jelXU9LdYQZmQoOw/wBOKkkNEKIv/XiDReJy
+p/HjJgKUFUY1OEE/FACtsvxm4pJdfDlXhBCBeH3E4lBUADA20dRP3gwB2gOBvaBg
+ekkluCeWXR1gOIHANzv1fzkOUJFsjeOK8tQN4CiytxDzHE/3jiIJQANg7MVWAkiS
+Hj5M1cYBLl085HCThkB1Pc7xmxCTLoyPEbPOQqIBTrueBLcJdLkumFHqQeS4MF8E
+WCkunPvFJdgF1X6cfeRgOEQROROZO8pQt4I0PMXfGsEZrmAW7jQC8WFCIpV4NGSe
+YTAHs/2sjJCChb/uEQTxpnEsHrjCt9goR8eN/WDKBBQhPXm3EsTmxaekQwyuSaMT
+CIjR7yBcryIKm/bGJDcHVBXffFGBV5hIMgEdf1kkC8SqImYlYqcdJIzJfX7vKMh4
+sHAhrCkRQURoskygqi0md+dfqsVgKKlQWhXcjPWGIaDEhE76mbxZSRNO4d3e65PO
+KgJCYhcrLhIjIDNeIYiN83HBg0BERIL1U3iTJLGEpRZoHcZw4sGUbCOF464NNH/h
+HGFJiqBEGTIOHhvsBjuVe14WEUHY66wwmcCz3N1FYYtZBweDh3rnAthJDKhMMlm2
+zGYijwSdS7gjfGDOAZM5jXhLyLmRavJ1POA7NINJXeuP7xXowK6CT8c4jbJNiG4O
+97+MJsnFI0Oedaw9ucttjJzGvznERUuUjHHc4wSsCaaG3wzPrGE0oG/zgqeVip6q
+6C8B4uJCxchBgJoNK4M9Ejy9YdywgBM0F0wusjd0CuBMod8eox5CsEcEM3e49YI2
+1D0SCdy0TwmQlOs7I4ck/WGEnS0YIF+wwKjFhGveDVHAN++sgZM6Ec9zgrA3qsRA
+sgNS9eMAbZpPd/njIw2wLl7Dv185QmIYbddk/WKZAwVL2h6/nEZMkB5he56xpShh
+obU/vBwTCghUgPg46xI51Yu/ti4AOABk8U/OV+gVsYYXh+neRBpAEWqfd6x5OpN5
+wa74xtkIDNXzXvExtyS+SCDfeBigdE2hPa+MG3QmSDSXeGocqAtJKasyf4li8ayB
+P+25TdUUtIw1dE/xlQlKq2L/ADEYi0CBbroyE7Fpax0S1BSyV94rqoUKa29GJOCg
+kCEJQ+WvjjCNJSPo8GEFtIw8kx/uM4MA6uDOCzscIhfesGRt0LG7xURIgIpM1gxT
+yKOfWIZlSnDkvb05ZCoHW4lGV5XC4mMl2VnyRBlYMfMc1wSzWco4MEa1ueZxQtQc
+AhCXAIYwE8pRtQrPPWTfXhE3b2zg3qMEGNY2abSCTl/bJ8rS5Okkbd5qctkc6I2g
+QzvxhhUBMLQkoTPXE4uG+4LWokGor/uLBFTnDidh764xFFDReCCjeWvK5PXaJBju
+Jo/vIy3EElc/cVzGI42IReEkdqKdph69gK88vnDlVDSOg+p/jJQJfAFgr8YTo0ma
+l29jGAeEFF4Md7JpY7yH6dShDh96xchCCn8c+8RjDU03p85CmUUenn1+sSgJMtqH
+bpIwKuQEBtBv1WBUwkniQmEskx4yQKAJCXy/vGg2KwgsKnEsjEGxI36xAGuAAiol
+LxUzUTBuAuskS2hIOJKeayal0gdgheR41zgBMCEENsN0jNHWnI28oa1oJ8ns5woR
+mp3v+byKAoLDMtx2RP13iPPYLCHH3GEQEVNMybJgwgSTUxRHBi1IMjYen4nI2gpN
+gzFZdqAbbO59ZN2gylSP4yPLKqZHhHPlMDr+siaURJJwsymqUUkfnEEOy9o48XiW
+WAmXSvzzkTiRKIk1Edy/6aRqGhYVTWqXeclAQSeHd4FCWEmyYK8UYmbq9fEg8sfG
+VXGT/l8OOmEIAiBsI5P4DACIxCIg8xm4D2klNp0YJ0QoDtI1Kw/O95EQixERDH9Y
+EFLWSVYPdVOvnE3VKhOxXV/fOHc1Oojb9z+Mm9QA9oYDiUmKOT969ZTJZpQ/3eRc
+l1ODyuLnXDFFdGUMUAlCnqnJMFUiD/xWEt9C+CYYWKB0YlmGmxyUklmYbx9GJo1j
+XGqjlxHTrDXDTYvn1gWKsalwj2R841wAM+XZsv8AeDVaccm0XfnxOBluqmxBURzb
+/WBqDRsLEfmX6wIeztw/ZYfGAoQMDCmoY1W8k2xIlCM3goSCRPIsuuDhexwzAASv
+g+OMaijqlXBWq7nsx8RSxdokDz/zFTw5Xyp9xhltJ9ZcI3Xbb9YVi8PDuiTiUU3a
+cJAAOPGMyJRSbv8AoPvI/S4SQqY9bMgCcX1/WQxOwwCtGBE7w5FRqsv4UXy3lFpC
+TFjf4Zy/mZck1XDG/U5HLGa0vc9njEBijb5dnnJRMUDDFseYxYCFGy0g6XvoezCX
++g2HwcywS9e83MrtemoTreGMeA/lX3hWTC0k+O4yvsrHWvBK1BRW73PrEghwqlV9
+VLjMybSXrSUosmz9rAAzFbu/6ycS2LXhxxCLU44CM5ucrtjOFchFU7xBkBMrFxkD
+tyeMmYCCM2cEnjAEi+8ZdoQ2YoBEvyI+krF0em2rQ/TioiEvW8e0A1594OH9IvYE
+8yvhZx1SIZt/qo+MTpWxUxKzAEfreL65cqVHe5jjzjaEdaPnnBkKnUKNdrYPGGQl
+EUJVz+DeCqiUxKaIIZXxOQcQEgFgRFcfnHJbpiLP/GENiYjyOQmCiKyUxjhPEYt+
+MsdRglt4hwIFvnCAS4QlSDAiRnIlGEPDnICRfbWCwCZ43kZama6nWKTYbg0OFYkk
+BcJxjGJBhtwPKjb8ZAdcA2N6+8kqwwaasV9seTDAmEm0TUe53iAgE8hPzlFjEHqI
+KyafDviMnQ/bInoACmXG8MsAIuZIND5yVqx1bauhncBz4ySXR5SfHTOcTRAejINV
+MRJZBWVac8HFeXWd584pMOUiQeIw5EsGXK4w2xjBj85GUlZvrACXx6y1Tf7xqodE
+qJPyYJLlohYz+EH64yJ46J4j/wAyfW2qyjZe5I1iQSZRIiV+Y+XJxolQE+dYziRB
+G9J9zgWPCQrVyhjzrrCo4gz0tlmifsxbrrTREnVRdP4w+PfZhsD7nUOIwUi8HALS
+IzYJrGWKc4AfGABPOUCN+cEBi94DlBzBlhlPUZYUxfWTmCjzmyOS8wLMFMwShxyr
+DM5J/wCsZhy40xQXQ0tZ+vjIiIgINZVDqYRDkz8wgcpGVg1QST6MGYKfNhXv/wBy
+S2HYCamIajBUIUlyKKFipEt/GaWDgKBsewkEGRNS2wIh08k+byI086Rx43Y+vnCM
+KCpSxDvRq0yVCWMj/GHtVqPGQDna8jTOFs5w/leSErswRS3ePYz4xI3XnjGKC55y
+2IOKh2hyl0N4D4i/OOT1b94iLrCmU6Wo/BOErhmZ2SGJHEGMGpL284Y2ALJWBmdS
+SeanK5T2DRuyiNF/OTb+vkzd8jV03JM2/Pqc5bqPuURJxEfHvHlYUoypncjzvIFe
+FCZF9wWc5YEmYmtTAq3gwlAhocDBX9sg4gQkBtjusHwH0ZsRdTWWFI61GP3lE05d
+4YSK6dZXH0OsoKPCxGS5Pi4mKTsmU8YAEjjyf3lhCsJhQhxWi8lRErRtyAiaFSLc
+zziEGGxpILH4/WcXSoAG5j3cN+MLVXAkIiGURHnjJlapAyATMT/tZDAYApB+XE91
+9wGEBkcdvDF1nBRmJRLyDQ+XIEZRNY0mavopDqQEGNVIbMcjFYuMNGGAoKWNzWj/
+ALjmKNFtD9xG6MY52EfOcbbc/nF1R/x1j4YOx/LWNAe9g5FSM44oEyvjE2YBudYk
+DfvGSFiNvzkWiOI8lhG2On3k2WqrAg2NGsEvYAfLHHMlBgljeB4IkutEesKHEVRh
+RVk7K+oxUxdRL6ATfGpyNJ3pXitzXxjZpD0LIt2QP2axpBkKyY5mc4daQDMUciS7
+yDKDdFEjZ5rebHgS4gCbQKvRxiUlRjOBZYtpLtZ7zk1KwmkxHFM5fFVPpIT2k12Z
+F1zFEXNf4wwS0CsgEJM2Q8GKm81hJwJucJmGyBXrxjjmkyb0mODe2ESEiTxgY114
+R0GQtFDC5KybYl9W/OJEynJiK1kcB3RBy81POEy5Jgh5w0DiGzO8EYIQoTh6Nzo9
+47HFKxYADoh6046qgIrrYTuesZkZAjw9eMuLpUt8rqKfLkITAAICSesa6coJrCKs
+OzU4zHZIc80QXpFzZiRcQTFRcmmRcIkEgyCxX1LiIkEgxHAP1eAQ00TB/l6xSM0G
+kh+3J5WrbGD01MgmJok92ZKQJtX8Ydd8UC1D4jFqQLgwhOOV/fJgrQ6nJ9Nc4YOh
+jPW1hiqFg3MwR8uaMoERcNuBicLwxZHq9/eAVsAREsSg8QJXEmEFCQ2V1XBLKo3j
+QICursh+cgylABJsvMz/AMyUlEAE7Phr4wp5KnbbDHFTOEXLd0KdeN5BhEAQaVrn
+zjSS4wphOj4cB2AypIO3vHwhRNyf5WIx0QapAIz8Y9HLJBqDCLF94iusCkXOsUpJ
+Rqcl3DkbdYwnDgdRgBesYLO8idBgAKUfDJjl7k4ttUkMrcnXnCOSSTkaTXRJ5vAC
+xcYKft78S43YlgmQuoOAvJmiBaQkJB95LXvRGIu/zOEOKNbHSvCRLW4xwMpkbltn
+85SyJPABV85ArJSG2CE+5wAnhJnsUuT1TsQIEnzOKMIxOnLWHMZA2TU4x4jAGWo1
+lgJgsVR5jJzJeKRBp1k5RfOIB4jJjpGMo+TDhcMqC4qbmjFAWWSiG94zMGkwfQKC
+GsS4MA3KJ7JVdOSeDAPAFhdTgOGFDNzzrJSqmXYN/wA/jBhCJEmTlBo3HlT08R/e
+KVSQ8Gy/sy4QJC5i6wPIDxBCv5jHBERL+vw4rrpIC+j6vXjGWgwOhMeRE4ILtvIC
+GZwI2k7waFYnJ3BOMbBnjKpSX6wdYUbya20YJDfjBoRLicNY4paiIMr9HSADzxvA
+IcmGxrixUVJziUMCxnls7vNkqc52/aX8YWYSgyta3porzkYojPUJFfnJEstwxPB+
+sFoRoiY7igSk4YlXq53ig4lJKxJfj85CQKFl74JSeFEEPHGoy6qQpkHc+saRDwhM
+mgf36wuyCpVj+cEx8ZWVXN9pF4UZKA2o4jiDYQ/eSYpGzJyTPEo+3C48QERllpqt
+gtfjKOw4Qr0hjKReRTuzDum6alQMLVAUdbJeyPw5ND0xzLEBR461i1DBJVKqEbt+
+vGcVghBidRY8aisO4xEr2fvAGgekTFv5fjAZKJQy0eGC/ZXJACx4/jFSRqggIa/Y
+ZEf+I2MPZtyguAu6uPXGQ+ozEdMzfPWGhCgSSkjwVfzWQa8qrFkavNZRD5MDklNm
+EsW9TkViuMuNCRgrvGE0WNIe8QWTc0+JjrA0527qPOQxBDxxkLmQwh7ZAI9/OM9E
+Aifg+F5J04jjZizxfP7mMchST6S2/j6RNSq+rOQDSPHVZICQMu0Ewr3yGNALhJbk
+A43hh9Lh6CnVPjAQQSIJEV+mKElYoo3Eb+c0gIiuxs+cmdQKRgOQ5DbgATDpWcZd
+MeYXYP4xClwKmFIPHOKDh/ZUN5CkTIdcfjITgKe8DxU9BjA5dCfvJYkdcYDiWgwC
+SkUArEDAeJyNK0wu8RrDo+HeAnKKMgS236yPm3WHoovwMM8St4AW2UkTMJhFKW1A
+dPPOsYEZYc0iq64/zkcaobCk6TsivGIniVI6R9xlPipWZhIHm4y7LCkEiWK9YgB0
+wLmCJwj+sWssiIkp46y5ClIIaV/nGyQIsAIksRxM+sRFFHYSpDorDYMaLQmd124M
+kxElf8MUl0VRIh8r11gFoeIcRRqEQxvEoiQFH2yXiLM6k/GS4rERMNP3we3B7AoK
+uPelOg+84SuiA+MYxGXpoS4psV+ZrJ9JgOBAPZEnyc4QYAOCSpjVRXeENLrJWHR4
+oL4x9S3ubg/e8RmUKXYYRua+8nXzFrNvETc/WR4K8gyFvU794GljIK4vwRhKz5RS
+ZjuUXxMYEKjGVAgfc4KaYyFRJ048KAoCBj1H9YwqChQSCfBg7jBBO8UCCitJD2ai
+O8V9MS0EycshgQgGH3kOdQxqX0uIgHXYZeusJr+EzpRYE+jeSgJbESxpvPfWJb19
+ZEpZdY5K8c5I4lrzt+4yVg9DyJDjNaik9kFdG/owsjKZBNHO3AQUlyBA2vcJWO0o
+ZkiFx4PVYv4sCS8oviP1hBQ4jFjbBVxkySIACVxTxOL1jIEkSz1TjDoXBXcrjnqX
+HqDQExhcJz5l+clpXIYnmldx4xw4EYwOvXnw5ICMLxor5cGAIJz0eCX8vOJE68AS
+/kn1nCyCfcn7xiVM7QJvzicQSwFYDQ6KhmlfzC48NHlNZpi8nK/kL6xkCTMYbBqY
+/OF+eEOf4wXdTfUJw3CSA5q+pfmMWhVnOoI15OGcCQKGbCUNz5cAk4cYFHyQHH3Q
+xbqqEhau4Ji8PpvIDUhvnV4yNoBKbrG2FGPN2/lyASnIUmB/veASIm7UsMeb/OEo
+ttcLSTmIhyvY2TyF9F36MBOIyP8AzVy2zUY54DDy8H3iAEV5ZZcnTUXohE/jHKKU
+HBIgDKgQqz84UQR43kSSxMF4wRBOGMFT94H5PPjFCMrXg7xODd41yf2/GHyCAxQg
+QL2oH7w3SuTHTuLQCStjW/4yVIOsmoA78K5MUKIQaQGva5vaOgMET2kc0mV2cjSb
+PfXzldZebFdVizLkD8jnJU8NCBafoO8AwGK5PJFd+awhphiwYXxpXweTJZNW9TYe
+3SSLeNAmNSulLz18YlysB27vy/Jg1NVgKCBB0tsfWKiO9cnXsx5/RheMRKTgCIko
+HGQ158YfRBgxlZdYziFmMMzlvj6+cPQygR/mcQDAU2mdhP8AAyx5CYy5rifE/wBG
+RtCRVKcQ9mx79uTOYA6ugPpLxolE0lhZvzvIEFtAo79ReG3LMZSgbyQqAFKJmUwF
+XQ4kShRIDLG374nDUjBrLJY8gNdx3nF4kkBy8V9joxvfO2aCX7fGEEeLgEuVvrh0
+4Pgg+M3WpJyQxd7wA/jCzCMw3krGMT+TI8R1glEfThYE9TWM6vZvEEuOptx+Uq00
+HK+MGhwvOBEvyHzgUkEEZNPjBRQ57Afy4AEm8hTECfRmDqhVpFp+H9uKdy02jQ/z
+jE6FhygjffxiJ6YIH151eJbzeHdFGG5yVEoWFCMstr15rERRQPeCzTb4+IxAZEux
+ZbnFd93JMLAOHA6MZksV4qP395QZUPA/Zh945XAPTGKugv2P6zR2nWKxY5h9jz1i
+wVEImsguL7yi1e3FHTI95AYGwYQLXR4wACfFpn7H9GCDJInRgjTX2g/jExisjmP2
+kIwYZWk14RyfxbGymfrK5VKxfkY7galpucj4Q0J9RjS8gkhGWzxPeRsjGObgN+rH
+hFqzClbR0HRroxSIBgTHt8vAduJlNEmVm1XtbxKgyO38jHxkjN4xAMxIuGhkz7gH
+8x947OMb/wAjGQGLQ+0/nFyB5xyGH8hw2Eu0sLAOQC/R0YSSAuZbfgv6w3Amo7An
+8zk4kzOsjDw69v8ArEQOf8ZgOHDIj5MjAQT/AOO8CSdPzhrB95DUY+QAThc2fxim
+Wl1q5HUmHPs5fBltACT3l/RxiPQ70yOSTKlu1P8AOR7ZtX16w1FXvSaR8OCiG41P
+tz+8nP3m0y8rLmjDVfLDgwRyDRpR+5I9GKSZm8Em3HUZHHHb7THJGbCH+/8AGKWR
+Up84rKCGvkGLJHqciZfygBhH784CBAGXuwXTAORO55Xc85ECJk7YPE3K19EfOExZ
+jrFMsIXcJhT2nFxSJpHCETroe+fnIMMjg9hg+GOgNKAA8uKHOoMHzt+Md+1H5Ll+
+cUS1ZPZkru+9xeRJmi8hOyC62/n/AOVKhsEOv+sEaQOZetuMiWHyKpX4x3H/AMQA
+Ak+c/9mIYAQTEQIAIAUCR4fMGQIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJ
+EN9gW7B2Dy1lePAAoJvsLqG0pPecLG/cmOP0zwR25DqLAKCTdBN8KpP1TPcXB5zH
+NQtN9qhlh7QjVGhvbWFzIERyZWliaG9seiA8ZHJlaWJoQHNpbXVsYS5ubz6IYgQT
+EQIAIgUCT6EAEgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ32BbsHYP
+LWUS7gCgy49KhdrdL2i0sXoEQieOk2dfQaUAnAqzpodVl9fb+SGRijiPT2j56e9f
+uQINBDr2cPwQCACkRMTrAREVIDlgxC+io09il/xbfL674Em8PZAx0pcXLv1edgKg
+4HbqrQkrmAbDUZMHf0A06lzfHl2RI0OImm2e0H0NftIRvVX4ZTrZdk6GO7qjgZsu
+WFGzLjRJW/Nn9GV2Shh4JEfUmCFTsSQayfxFwu5EWPsCBb5taQjILc0IZk36Z1z+
+aZHFip4WkxC/b5edvUS4KTqOoMkvoiNUq55hkPle0pdb5ACPVSVGj28ak0uzuhnP
+dBqESB/RLkKf14unYlGv3gMVWgidnDOI5bIQnwGsmjJ0OAIBv/l4R2sBz7uJu49I
+6c7FUfxp73PI1t2KZIkYO3Wmd8TP8LDdxhi/AAMHB/9tX2Ik7bbNMloHlLPx3NtB
+/Bprnl+6CLsO8857l6ITWn39b648lNhntZDFqszyr+HwHO3A4B95QrO3OgZJW8R/
+GFrxae/P/estYsrU6T6/1lUSWsBiYltsRyLUuaTW9fCaNxiiiNiX/bmaGS+5yDzN
+U7xZ81gLAFSQZQZSP5JClt/ES3zR3IabooW/1c7V8DOVReRYE4Nni8M81Fj4DLh6
+8AWRt8oWAdcxQG+1eUZ+5JClNFc23SZ9FVng554gps90IjwNfk0P35whYRAnYA+B
+a1r6HrWTAnlzuTbHFptti3q/2NPM+vnvK9WV7h85XoTFR4JwVpEjO9f7zsUyhpz5
+iEYEGBECAAYFAjr2cPwACgkQ32BbsHYPLWU+nACdHdhBhlE3hai5nAtwal8x8fZf
+lFUAoMJrt3ofCGhrsOs9pMA//3rkg/Js
+=0dBa
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..3bc36a9
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,3 @@
+version=3
+opts=pgpsigurlmangle=s/$/.asc/ \
+https://packages.nntb.no/software/ripe.atlas.cousteau ripe.atlas.cousteau-(.*)\.tar\.bz2
diff --git a/fetch-debian-changelog b/fetch-debian-changelog
new file mode 100755
index 0000000..c202ffb
--- /dev/null
+++ b/fetch-debian-changelog
@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Packaging Scripts
+# Copyright (C) 2021-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: dreibh@simula.no
+#
+
+import glob
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import urllib.error
+import urllib.request
+
+
+# ====== Handle arguments ==================================================
+if len(sys.argv) < 2:
+ sys.stderr.write('Usage: ' + sys.argv[0] + ' package [distribution]\n')
+ sys.exit(1)
+
+debianPackage = sys.argv[1]
+if len(sys.argv) == 2:
+ debianDistribution = 'unstable'
+else:
+ debianDistribution = sys.argv[2]
+if debianDistribution in [ 'unstable', 'testing', 'stable', 'oldstable' ]:
+ # Debian
+ statusPageURL = 'https://packages.debian.org/source/' + debianDistribution + '/' + debianPackage
+else:
+ # Ubuntu
+ statusPageURL = 'https://packages.ubuntu.com/source/' + debianDistribution + '/' + debianPackage
+
+debianVersion = None
+debianLocation = None
+debianArchive = None
+debianArchiveFormat = None
+
+
+# ====== Get package status =================================================
+statusPageContents = None
+sys.stderr.write('Looking for package status on ' + statusPageURL + ' ... ')
+sys.stderr.flush()
+try:
+ statusPage = urllib.request.urlopen(statusPageURL)
+ statusPageContents = statusPage.readlines()
+ statusPage.close()
+
+ re_debian_package = re.compile(r'.*Source Package: ' + debianPackage + ' \(([0-9-+~\.a-z]+)\)')
+ re_debian_archive = re.compile(r'.*href="((http|https)://[a-zA-Z0-9\./+-]+/' + \
+ debianPackage[0:1] + '/' + \
+ debianPackage + '/' + \
+ r')(' + debianPackage + r'_[0-9-+~\.a-z]+\.debian\.tar\.[a-zA-Z]+)"')
+ for line in statusPageContents:
+ line = line.decode('utf-8')
+ match = re_debian_package.match(line)
+ if match != None:
+ debianVersion = match.group(1)
+ else:
+ match = re_debian_archive.match(line)
+ if match != None:
+ debianLocation = match.group(1)
+ debianArchive = match.group(3)
+
+except urllib.error.HTTPError as e:
+ sys.stderr.write('not found (HTTP ' + str(e.code) + ')!\n')
+ sys.exit(1)
+
+if (debianVersion == None) or (debianArchive == None):
+ sys.stderr.write('not found!\n')
+ sys.exit(1)
+
+sys.stderr.write('Version in ' + debianDistribution + ' is ' + debianVersion + '\n')
+
+
+# ====== Determine necessary compression option =============================
+debianArchiveFormat = debianArchive[len(debianArchive) - 2 : len(debianArchive)]
+tarCompressionOption = ''
+if debianArchiveFormat == 'gz':
+ tarCompressionOption = 'z'
+elif debianArchiveFormat == 'bz2':
+ tarCompressionOption = 'j'
+elif debianArchiveFormat == 'xz':
+ tarCompressionOption = 'J'
+
+
+# ====== Fetch debian archive ===============================================
+archiveFileURL = debianLocation + debianArchive
+sys.stderr.write('Looking for \"debian\" archive at ' + archiveFileURL + ' ... ')
+sys.stderr.flush()
+try:
+ archiveFile = urllib.request.urlopen(archiveFileURL)
+ debianArchiveFile = tempfile.NamedTemporaryFile(delete=False)
+ shutil.copyfileobj(archiveFile, debianArchiveFile)
+ debianArchiveFile.close()
+ archiveFile.close()
+ sys.stderr.write('found!\n')
+
+ try:
+
+ process = subprocess.run([ 'tar', 'x' + tarCompressionOption + 'fO', debianArchiveFile.name, 'debian/changelog'],
+ stderr=subprocess.PIPE, check=True, universal_newlines=True)
+
+ os.unlink(debianArchiveFile.name)
+
+ except Exception as e:
+ sys.stderr.write('ERROR: Failed to extract debian/changelog from ' + debianArchiveFile.name + ': ' + str(e) + '\n')
+ sys.exit(1)
+
+except urllib.error.HTTPError as e:
+ sys.stderr.write('not found (HTTP ' + str(e.code) + ')!\n')
+ sys.exit(1)
diff --git a/filter-debian-changelog b/filter-debian-changelog
new file mode 100755
index 0000000..88ecd1e
--- /dev/null
+++ b/filter-debian-changelog
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Debian/Ubuntu Packaging Scripts
+# Copyright (C) 2002-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+
+# This script filters debian/changelog entries:
+# Usage: filter-debian-changelog [regexp_for_last_entry|FIRST]
+# * Empty entries get dropped.
+# * Stop, if entry matches regexp_for_last_entry argument.
+# * Stop after first entry, if regexp_for_last_entry = FIRST.
+# Example: filter-debian-changelog "Mon, 31 Oct 2016 08:08:08 \+0200"
+# Note the \+, otherwise '+' is interpreted as regexp!
+
+
+import glob
+import os
+import re
+import sys
+import time
+
+
+# ====== Handle arguments ==================================================
+if len(sys.argv) < 2:
+ sys.stderr.write('Usage: ' + sys.argv[0] + ' regexp_for_last_entry|FIRST\n')
+ sys.exit(1)
+
+if sys.argv[1] == '':
+ re_last_entry = None
+elif sys.argv[1] == 'FIRST':
+ re_last_entry = re.compile(r'^.*$')
+else:
+ re_last_entry = re.compile(r'^.*' + sys.argv[1])
+
+re_begin_of_entry = re.compile(r'^[a-zA-Z].*$')
+re_end_of_entry = re.compile(r'^ --.*$')
+re_empty = re.compile(r'^$')
+re_item = re.compile(r'^ *')
+re_item_is_itp = re.compile(r'^(.*Closes:.*ITP.*|.*ITP.*Closes:.*)$')
+
+entries = 0
+entryContentLines = 0
+entryContent = ''
+entryIsITP = False
+
+contents = sys.stdin.readlines()
+for line in contents:
+
+ # ====== Begin of entry ==================================================
+ if entryContentLines == 0:
+ if re_begin_of_entry.match(line):
+ entryContent = line
+ entryContentLines = 1
+
+ # ====== Within entry ====================================================
+ else:
+ # ------ End of entry -------------------------------------------------
+ if re_end_of_entry.match(line):
+ entryContent = entryContent + line + '\n'
+ if entryContentLines > 1:
+ entries = entries + 1
+
+ # ------ Print entry --------------------------------------------
+ if not entryIsITP:
+ sys.stdout.write(entryContent)
+ # ------ Print entry with ITP -----------------------------------
+ # Special case: The ITP package for Debian must only contain the
+ # ITP entry with ITP item and nothing else!
+ else:
+ splittedITPEntry = entryContent.splitlines()
+ i = 0
+ for itpLine in splittedITPEntry:
+ i = i + 1
+ if (i <= 2) or (i >= len(splittedITPEntry) - 2):
+ sys.stdout.write(itpLine + '\n')
+ elif re_item_is_itp.match(itpLine) != None:
+ sys.stdout.write(itpLine + '\n')
+ break # ITP -> done!
+
+ entryContent = ''
+ entryIsITP = False
+
+ # ------ Check for match with last entry regexp in argument --------
+ if re_last_entry != None:
+ if re_last_entry.match(line) != None:
+ break
+
+ entryContentLines = 0
+
+ # ------ Part of entry ------------------------------------------------
+ else:
+ if re_item.match(line):
+ entryContent = entryContent + line
+ entryContentLines = entryContentLines + 1
+ if re_item_is_itp.match(line):
+ entryIsITP = True
diff --git a/make-deb b/make-deb
new file mode 100755
index 0000000..3566af5
--- /dev/null
+++ b/make-deb
@@ -0,0 +1,369 @@
+#!/usr/bin/env bash
+#
+# Debian/Ubuntu Packaging Scripts
+# Copyright (C) 2002-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+
+# ---------------------------------------------------------------------------
+# USAGE:
+# ./make-deb default => for Ubuntu REVU
+# Note: Replaces "Maintainer" by Ubuntu Developers and
+# writes original maintainer entry to "XSBC-Original-Maintainer"
+# ./make-deb unstable => for Debian Mentors
+# ./make-deb bionic|disco|... => for Launchpad PPA
+# ---------------------------------------------------------------------------
+
+
+# Set current Debian debhelper version here
+# for building unstable/testing/stable packages
+# (See https://packages.qa.debian.org/d/debhelper.html for latest version!)
+DEBHELPER_LATEST_VERSION="13"
+
+
+# ====== Obtain package and version information =============================
+DISTRIBUTIONS=`\
+( \
+while [ x$1 != "x" ] ; do \
+ echo $1
+ shift
+done \
+) | sort -u`
+if [ "${DISTRIBUTIONS}" == "" ] ; then
+ DISTRIBUTIONS="default"
+fi
+
+
+CHANGELOG_HEADER="`head -n1 debian/changelog`"
+
+# The package name, e.g. MyApplication
+PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"`
+# The package distribution, e.g. precise, raring, ...
+PACKAGE_DISTRIBUTION=`echo ${CHANGELOG_HEADER} | sed -e "s/[^)]*)//" -e "s/;.*//g" -e "s/ //g"`
+# The package's version, e.g. 1.2.3-1ubuntu1
+PACKAGE_VERSION=`echo ${CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"`
+# The package's output version, e.g. 1.2.3-1ubuntu
+OUTPUT_VERSION=`echo ${PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"`
+# The package's Debian version, e.g. 1.2.3-1
+DEBIAN_VERSION=`echo ${OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"`
+# The package's upstream version, e.g. 1.2.3
+UPSTREAM_VERSION=`echo ${DEBIAN_VERSION} | sed -e "s/-[0-9]*$//"`
+# The package's plain upstream version, e.g. 1.2.3 (without e.g. ~svn)
+PLAIN_VERSION=`echo ${UPSTREAM_VERSION} | sed -e "s/\([0-9\.]*\)[-+~].*$/\1/"`
+
+
+echo -e "\x1b[34m######################################################################\x1b[0m"
+echo -e "\x1b[34mCHANGELOG_HEADER: ${CHANGELOG_HEADER}\x1b[0m"
+echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_DISTRIBUTION: ${PACKAGE_DISTRIBUTION}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_VERSION ${PACKAGE_VERSION}\x1b[0m"
+echo -e "\x1b[34mOUTPUT_VERSION: ${OUTPUT_VERSION}\x1b[0m"
+echo -e "\x1b[34mDEBIAN_VERSION: ${DEBIAN_VERSION}\x1b[0m"
+echo -e "\x1b[34mUPSTREAM_VERSION: ${UPSTREAM_VERSION}\x1b[0m"
+echo -e "\x1b[34mPLAIN_VERSION: ${PLAIN_VERSION}\x1b[0m"
+echo -e "\x1b[34m######################################################################\x1b[0m"
+
+if [ ! -e ./packaging.conf ] ; then
+ echo >&2 "ERROR: packaging.conf does not exist -> no configuration for the new package!"
+ exit 1
+fi
+. ./packaging.conf
+
+
+# ====== Run warp-and-sort tool =============================================
+if [ -e /usr/bin/wrap-and-sort ] ; then
+ echo -e ""
+ echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Calling wrap-and-sort ==========================================\x1b[0m"
+ echo -e ""
+ wrap-and-sort -a -v
+fi
+
+
+# ====== Create upstream source package =====================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating upstream package ======================================\x1b[0m"
+echo -e ""
+if [ "${SKIP_PACKAGE_SIGNING}" != "" -a ${SKIP_PACKAGE_SIGNING} -eq 1 -o "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then
+ ./make-upstream-package ${PACKAGE} ${UPSTREAM_VERSION} "${MAKE_DIST}" -skip-signing
+else
+ ./make-upstream-package ${PACKAGE} ${UPSTREAM_VERSION} "${MAKE_DIST}"
+fi
+
+for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do
+ UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-${UPSTREAM_VERSION}.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`"
+ if [ -e "${UPSTREAM_PACKAGE}" ] ; then
+ break
+ fi
+done
+if [ ! -e "${UPSTREAM_PACKAGE}" ] ; then
+ echo -e "\x1b[34mERROR: No upstream package (${PACKAGE}-${UPSTREAM_VERSION}.tar.*) found!\x1b[0m"
+ exit 1
+fi
+
+
+# ====== Build source packages ==============================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Building source packages =======================================\x1b[0m"
+for DISTRIBUTION in ${DISTRIBUTIONS} ; do
+
+ updatedDebhelperVersion=0
+
+ echo -e ""
+ echo -e "\x1b[34m------ Creating package for ${DISTRIBUTION} ------\x1b[0m"
+
+ cp ${UPSTREAM_PACKAGE} ${PACKAGE}_${UPSTREAM_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}
+ cp ${UPSTREAM_PACKAGE} ${PACKAGE}_${OUTPUT_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}
+ cp ${UPSTREAM_PACKAGE} ${PACKAGE}_${DEBIAN_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}
+ if [ ! ${SKIP_PACKAGE_SIGNING} == "1" -a ! "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then
+ cp ${UPSTREAM_PACKAGE}.asc ${PACKAGE}_${UPSTREAM_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc
+ cp ${UPSTREAM_PACKAGE}.asc ${PACKAGE}_${OUTPUT_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc
+ cp ${UPSTREAM_PACKAGE}.asc ${PACKAGE}_${DEBIAN_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc
+ else
+ rm -f ${PACKAGE}_${UPSTREAM_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc
+ rm -f ${PACKAGE}_${OUTPUT_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc
+ rm -f ${PACKAGE}_${DEBIAN_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc
+ fi
+ rm -rf ${PACKAGE}-${UPSTREAM_VERSION}
+ rm -rf ${PACKAGE}-${UPSTREAM_VERSION}.orig
+ if [ "${UPSTREAM_PACKAGE_TYPE}" == "gz" ] ; then
+ tar xzf ${UPSTREAM_PACKAGE}
+ elif [ "${UPSTREAM_PACKAGE_TYPE}" == "bz2" ] ; then
+ tar xjf ${UPSTREAM_PACKAGE}
+ elif [ "${UPSTREAM_PACKAGE_TYPE}" == "xz" ] ; then
+ tar xJf ${UPSTREAM_PACKAGE}
+ else
+ echo 2>&1 "ERROR: Bad archive format: ${UPSTREAM_PACKAGE}"
+ exit 1
+ fi
+ cp -r debian ${PACKAGE}-${UPSTREAM_VERSION}
+ find ${PACKAGE}-${UPSTREAM_VERSION} -name .svn | xargs --no-run-if-empty rm -rf
+ cd ${PACKAGE}-${UPSTREAM_VERSION}
+
+ if [ "${DISTRIBUTION}" != "default" ] ; then
+ if [ "${DISTRIBUTION}" == "unstable" -o "${DISTRIBUTION}" == "testing" -o "${DISTRIBUTION}" == "stable" -o "${DISTRIBUTION}" == "oldstable" ] ; then
+ # Fetch debian/changelog from Debian, if available.
+ # If there is a Debian changelog, merge new entries.
+ if ../fetch-debian-changelog ${PACKAGE} ${DISTRIBUTION} >debian/changelog.dist ; then
+ ../merge-debian-changelogs debian/changelog debian/changelog.dist >debian/changelog.merged && \
+ mv debian/changelog.merged debian/changelog
+ fi
+ rm -f debian/changelog.dist
+
+ # Debian: Also remove Launchpad Bug IDs.
+ sed -e "s/${PACKAGE_DISTRIBUTION};/${DISTRIBUTION};/1" \
+ -e "s/\(ubuntu\|ppa\)[0-9]//1" \
+ -e "/(LP: #/D" \
+ debian/changelog.new
+ else
+ # Ubuntu PPA
+ # Naming example: 2.7.7-1ubuntu~focal1
+ # Ubuntu: Also remove Debian Bug IDs.
+ sed -e "s/${PACKAGE_DISTRIBUTION};/${DISTRIBUTION};/1" \
+ -e "s/${PACKAGE_VERSION}/${OUTPUT_VERSION}~${DISTRIBUTION}1/1" \
+ -e "/(Closes: #/D" \
+ debian/changelog.new
+
+ # ------ Old distributions not supporting c++/regex style symbols --
+ if [ "${DISTRIBUTION}" == "dapper" -o \
+ "${DISTRIBUTION}" == "edgy" -o \
+ "${DISTRIBUTION}" == "feisty" -o \
+ "${DISTRIBUTION}" == "hardy" -o \
+ "${DISTRIBUTION}" == "intrepid" -o \
+ "${DISTRIBUTION}" == "jaunty" -o \
+ "${DISTRIBUTION}" == "karmic" -o \
+ "${DISTRIBUTION}" == "lucid" ] ; then
+ # Just skip the symbols ...
+ find debian/ -maxdepth 1 -name "*.symbols" | xargs --no-run-if-empty rm -f
+ fi
+ fi
+
+ # Remove additional newlines at the end of the file:
+ sed -i -e :a -e '/^\n*$/{$d;N;};/\n$/ba' debian/changelog.new
+
+ mv debian/changelog.new debian/changelog
+
+ # ------ Old distributions not supporting new Debian format -----------
+ if [ "${DISTRIBUTION}" == "dapper" -o \
+ "${DISTRIBUTION}" == "edgy" -o \
+ "${DISTRIBUTION}" == "feisty" -o \
+ "${DISTRIBUTION}" == "hardy" -o \
+ "${DISTRIBUTION}" == "intrepid" -o \
+ "${DISTRIBUTION}" == "jaunty" ] ; then
+ rm -rf debian/source
+ fi
+
+ # ------ Use latest Debhelper for Debian ------------------------------
+ if [ "${DISTRIBUTION}" == "unstable" -o "${DISTRIBUTION}" == "testing" -o "${DISTRIBUTION}" == "stable" -o "${DISTRIBUTION}" == "oldstable" ] ; then
+ # Update debhelper version:
+ # Also get rid of legacy cmake3 dependency alternative.
+ sed -e "s/debhelper (.* [0-9]*)/debhelper-compat (= ${DEBHELPER_LATEST_VERSION})/g" \
+ -e "s/ | cmake3//g" \
+ debian/control.new
+ # Newer debhelper does not need "--parallel" for building:
+ sed -e "s/\(.*dh .. .*--buildsystem=cmake.*\)\(--parallel\)\(.*\)/\1\3/g" -e 's@[[:space:]]*$@@g' \
+ debian/rules.new
+ # There is no need for debian/compat any more:
+ rm -f debian/compat
+ mv debian/control.new debian/control
+ mv debian/rules.new debian/rules
+ updatedDebhelperVersion=1
+ fi
+
+ else
+ # Ubuntu: Remove Debian Bug IDs.
+ sed -e "/(Closes: #/D" \
+ debian/changelog.new
+ mv debian/changelog.new debian/changelog
+ sed -e "s/^Maintainer:/Maintainer: Ubuntu Developers \nXSBC-Original-Maintainer:/g" debian/control.new
+ mv debian/control.new debian/control
+ fi
+
+ echo -e ""
+ echo -e "\x1b[34m------ Creating diff file ${PACKAGE}-${PACKAGE_VERSION}.diff.gz ------\x1b[0m"
+ (
+ cd ..
+ diff -urN "--exclude=*~" "--exclude=.svn" "--exclude=.git" \
+ ${PACKAGE}-${UPSTREAM_VERSION}.orig ${PACKAGE}-${UPSTREAM_VERSION} \
+ | gzip -c >${PACKAGE}-${PACKAGE_VERSION}.diff.gz
+ )
+
+
+ echo -e ""
+ echo -e "\x1b[34m------ Building source package ------\x1b[0m"
+
+ # Without signature:
+ # debuild -us -uc
+ # For sources:
+ # debuild -S
+ # For binaries:
+ # debuild -b
+ # Use -i to ignore .svn files!
+
+ if [ "${SKIP_PACKAGE_SIGNING}" == "" ] ; then
+ SKIP_PACKAGE_SIGNING=0
+ fi
+ if [ $updatedDebhelperVersion -eq 0 ] ; then
+ opt=""
+ else
+ opt="--no-check-builddeps" # Needed for increased debhelper version!
+ fi
+ if [ ${SKIP_PACKAGE_SIGNING} -eq 1 -o "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then
+ # Build source package without signature:
+ debuild ${opt} -us -uc -S -i || exit 1
+ else
+ # Build source package including signature:
+ if [ "${MAINTAINER_KEY}" == "" ] ; then
+ echo >&2 "ERROR: MAINTAINER_KEY is not set!"
+ exit 1
+ fi
+ debuild ${opt} -sa -S "-k${MAINTAINER_KEY}" -i || exit 1
+ fi
+
+ # Important: In /etc/pbuilderrc, set COMPONENTS="main universe"!
+ # Important: After that, update with option "--override-config"!
+ # sudo pbuilder update --override-config
+
+ cd ..
+
+ if [ "${DISTRIBUTION}" == "unstable" -o \
+ "${DISTRIBUTION}" == "testing" -o \
+ "${DISTRIBUTION}" == "stable" -o \
+ "${DISTRIBUTION}" == "oldstable" -o \
+ "${DISTRIBUTION}" == "default" ] ; then
+ if [ "${DISTRIBUTION}" == "default" ] ; then
+ version=${PACKAGE_VERSION}
+ else
+ version=${DEBIAN_VERSION}
+ fi
+ dscFile=`ls ${PACKAGE}_${version}.dsc | tail -n1`
+ else
+ dscFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9].dsc | tail -n1`
+ fi
+ if [ ! -e "${dscFile}" ] ; then
+ echo -e "\x1b[34mERROR: ${dscFile} has not been generated successfully -> Aborting!\x1b[0m"
+ exit 1
+ fi
+
+done
+
+
+# ====== Show results =======================================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Results overview ============================================\x1b[0m"
+echo -e ""
+
+echo -e "\x1b[34mUpload to PPA:\x1b[0m"
+for DISTRIBUTION in ${DISTRIBUTIONS} ; do
+ if [ "${DISTRIBUTION}" == "unstable" -o \
+ "${DISTRIBUTION}" == "testing" -o \
+ "${DISTRIBUTION}" == "stable" -o \
+ "${DISTRIBUTION}" == "oldstable" -o \
+ "${DISTRIBUTION}" == "default" ] ; then
+ if [ "${DISTRIBUTION}" == "default" ] ; then
+ ppa="revu"
+ version=${PACKAGE_VERSION}
+ else
+ ppa="mentors"
+ version=${DEBIAN_VERSION}
+ fi
+ changesFile=`ls ${PACKAGE}_${version}_source.changes | tail -n1`
+ else
+ ppa="ppa"
+ changesFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9]_source.changes | tail -n1`
+ fi
+ echo -e "\x1b[34m dput ${ppa} $changesFile\x1b[0m"
+done
+echo -e ""
+
+if [ -e make-symbols ] ; then
+ echo -e "\x1b[34m################################################################\x1b[0m"
+ echo -e "\x1b[34mDo not forget to run make-symbols after library version changes!\x1b[0m"
+ echo -e "\x1b[34m################################################################\x1b[0m"
+ echo -e ""
+fi
+
+echo -e "\x1b[34mBuild Test Commands:\x1b[0m"
+for DISTRIBUTION in ${DISTRIBUTIONS} ; do
+ if [ "${DISTRIBUTION}" == "unstable" -o \
+ "${DISTRIBUTION}" == "testing" -o \
+ "${DISTRIBUTION}" == "stable" -o \
+ "${DISTRIBUTION}" == "oldstable" -o \
+ "${DISTRIBUTION}" == "default" ] ; then
+ if [ "${DISTRIBUTION}" == "default" ] ; then
+ version=${PACKAGE_VERSION}
+ else
+ version=${DEBIAN_VERSION}
+ fi
+ changesFilesPattern="${PACKAGE}_${version}_*.changes"
+ dscFile=`ls ${PACKAGE}_${version}.dsc | tail -n1`
+ else
+ changesFilesPattern="${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9]_*.changes"
+ dscFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9].dsc | tail -n1`
+ fi
+ profile="ubuntu"
+ if [ "${DISTRIBUTION}" == "unstable" -o \
+ "${DISTRIBUTION}" == "testing" -o \
+ "${DISTRIBUTION}" == "stable" -o \
+ "${DISTRIBUTION}" == "oldstable" ] ; then
+ profile="debian"
+ fi
+ echo -e "\x1b[34m sudo pbuilder build ${dscFile} && lintian -iIEv --profile ${profile} --pedantic /var/cache/pbuilder/result/$changesFilesPattern\x1b[0m"
+done
+echo -e ""
diff --git a/make-dist b/make-dist
new file mode 100755
index 0000000..c883a39
--- /dev/null
+++ b/make-dist
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+mkdir -p dist/
+rm -f dist/*
+python3 setup.py sdist --formats=bztar
+mv dist/*.bz2 .
diff --git a/make-ppa b/make-ppa
new file mode 100755
index 0000000..bd9a93f
--- /dev/null
+++ b/make-ppa
@@ -0,0 +1,130 @@
+#!/usr/bin/env bash
+#
+# Packaging Scripts
+# Copyright (C) 2002-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+COPR=0
+DPUT=0
+
+# NOTE: These are the supported distributions by Ubuntu Launchpad and Debian:
+DPUT_DISTRIBUTIONS="precise trusty xenial bionic focal jammy lunar mantic noble unstable"
+
+while [ $# -gt 0 ] ; do
+ if [ "$1" == "dput" ] ; then
+ DPUT=1
+ elif [ "$1" == "copr" ] ; then
+ COPR=1
+ elif [ "$1" == "all" ] ; then
+ DPUT=1
+ COPR=1
+ else
+ echo >&2 "Usage: $0 [dput] [copr] [all]"
+ exit 1
+ fi
+ shift
+done
+
+if [ ${DPUT} -eq 0 -a ${COPR} -eq 0 ] ; then
+ COPR=1
+ DPUT=1
+fi
+
+if [ ! -e debian/ ] ; then
+ DPUT=0
+fi
+if [ ! -e rpm/ ] ; then
+ COPR=0
+fi
+
+
+# ====== Build source packages ==============================================
+./clean-deb
+if [ ${DPUT} -ne 0 ] ; then
+ . ./packaging.conf
+ if [ "${NOT_TARGET_DISTRIBUTIONS}" == "" ] ; then
+ echo >&2 "ERROR: Define NOT_TARGET_DISTRIBUTIONS in packaging.conf!"
+ exit 1
+ fi
+ buildForDistribution=""
+ for dputDistribution in ${DPUT_DISTRIBUTIONS} ; do
+ notATarget=0
+ for notTargetDistribution in ${NOT_TARGET_DISTRIBUTIONS} ; do
+ if [ "${notTargetDistribution}" == "${dputDistribution}" ] ; then
+ notATarget=1
+ break
+ fi
+ done
+ if [ $notATarget -eq 0 ] ; then
+ buildForDistribution="${buildForDistribution} ${dputDistribution}"
+ fi
+ done
+
+ echo "Building for distributions:${buildForDistribution}"
+ ./make-deb ${buildForDistribution}
+fi
+
+if [ ${COPR} -ne 0 ] ; then
+ if [ -e rpm -o -e ./make-srpm ] ; then
+ ./make-srpm || exit 1
+ else
+ echo >&2 "ERROR: RPM files not found!"
+ exit 1
+ fi
+fi
+
+
+# ====== dput ===============================================================
+if [ ${DPUT} -ne 0 ] ; then
+ changeFiles=`find . -mindepth 1 -maxdepth 1 -name "*.changes"`
+ for changeFile in ${changeFiles} ; do
+ if [[ ${changeFile} =~ -[0-9]_source.changes$ ]] ; then
+ dput mentors ${changeFile}
+ else
+ dput ppa ${changeFile}
+ fi
+ done
+fi
+
+
+# ====== COPR ===============================================================
+if [ ${COPR} -ne 0 ] ; then
+ PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"`
+ SRPM=`find ${HOME}/rpmbuild/SRPMS -name "${PACKAGE}-*.src.rpm"`
+ if [ ! -e "${SRPM}" ] ; then
+ echo >&2 "ERROR: ${PACKAGE}-*.src.rpm not found!"
+ exit 1
+ fi
+
+ COPR_CLI=""
+ for directory in /usr/bin /usr/local/bin ~/.local/bin ; do
+ if [ -x "${directory}/copr-cli" ] ; then
+ COPR_CLI="${directory}/copr-cli"
+ break
+ fi
+ done
+ if [ "${COPR_CLI}" == "" ] ; then
+ echo >&2 "ERROR: copr-cli not found!"
+ exit 1
+ fi
+ echo "Using ${COPR_CLI}"
+
+ ${COPR_CLI} build --nowait ppa ${SRPM}
+fi
diff --git a/make-srpm b/make-srpm
new file mode 100755
index 0000000..3e80c01
--- /dev/null
+++ b/make-srpm
@@ -0,0 +1,120 @@
+#!/usr/bin/env bash
+#
+# Packaging Scripts
+# Copyright (C) 2017-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+
+# ---------------------------------------------------------------------------
+# USAGE:
+# ./make-srpm
+# ---------------------------------------------------------------------------
+
+
+# ====== Obtain package and version information =============================
+PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"`
+PACKAGE_VERSION=`grep "^Version:" rpm/*.spec | head -n1 | sed -e "s/Version://g" -e "s/[ \t]*//g"`
+PACKAGE_RELEASE=`grep "^Release:" rpm/*.spec | head -n1 | sed -e "s/Release://g" -e "s/[ \t]*//g"`
+
+echo -e "\x1b[34m###########################################\x1b[0m"
+echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_VERSION: ${PACKAGE_VERSION}\x1b[0m"
+echo -e "\x1b[34mPACKAGE_RELEASE: ${PACKAGE}_RELEASE\x1b[0m"
+echo -e "\x1b[34m###########################################\x1b[0m"
+
+# ====== Check with Debian package's version ================================
+if [ -e debian/changelog ] ; then
+ DEBIAN_CHANGELOG_HEADER="`head -n1 debian/changelog`"
+
+ # The package name, e.g. MyApplication
+ DEBIAN_PACKAGE=`echo ${DEBIAN_CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"`
+ # The package distribution, e.g. precise, raring, ...
+ DEBIAN_PACKAGE_DISTRIBUTION=`echo ${DEBIAN_CHANGELOG_HEADER} | sed -e "s/[^)]*)//" -e "s/;.*//g" -e "s/ //g"`
+ # The package's version, e.g. 1.2.3-1ubuntu1
+ DEBIAN_PACKAGE_VERSION=`echo ${DEBIAN_CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"`
+ # The package's output version, e.g. 1.2.3-1ubuntu
+ DEBIAN_OUTPUT_VERSION=`echo ${DEBIAN_PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"`
+ # The package's Debian version, e.g. 1.2.3-1
+ DEBIAN_VERSION=`echo ${DEBIAN_OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"`
+ # The package's upstream version, e.g. 1.2.3
+ DEBIAN_UPSTREAM_VERSION=`echo ${DEBIAN_VERSION} | sed -e "s/-[0-9]*$//"`
+
+ if [ "${PACKAGE}-${PACKAGE_VERSION}" != "${DEBIAN_PACKAGE}-${DEBIAN_UPSTREAM_VERSION}" ] ; then
+ echo >&2 "ERROR: RPM version and Debian version do not match -> ${PACKAGE}-${PACKAGE_VERSION} vs. ${DEBIAN_PACKAGE}-${DEBIAN_UPSTREAM_VERSION}!"
+# exit 1
+ fi
+fi
+
+if [ -e packaging.conf ] ; then
+ . ./packaging.conf
+fi
+
+
+# ====== Create upstream source package =====================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating upstream package ======================================\x1b[0m"
+echo -e ""
+if [ "${SKIP_PACKAGE_SIGNING}" != "" -a ${SKIP_PACKAGE_SIGNING} -eq 1 -o "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then
+ ./make-upstream-package ${PACKAGE} ${PACKAGE_VERSION} "${MAKE_DIST}" -skip-signing
+else
+ ./make-upstream-package ${PACKAGE} ${PACKAGE_VERSION} "${MAKE_DIST}"
+fi
+
+for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do
+ UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`"
+ if [ -e "${UPSTREAM_PACKAGE}" ] ; then
+ break
+ fi
+done
+if [ ! -e "${UPSTREAM_PACKAGE}" ] ; then
+ echo -e "\x1b[34mERROR: No upstream package (${PACKAGE}-*.tar.*) found!\x1b[0m"
+ exit 1
+fi
+
+
+# ====== Create source RPM ==================================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating source RPM ============================\x1b[0m"
+echo -e ""
+
+# ------ Initialise RPM build directories -----------------------------------
+for subdir in BUILD BUILDROOT RPMS SOURCES SPECS SRPMS ; do
+ mkdir -p ${HOME}/rpmbuild/${subdir}
+done
+find ${HOME}/rpmbuild/SRPMS -name "${PACKAGE}*.rpm" | xargs --no-run-if-empty rm -f
+find ${HOME}/rpmbuild/RPMS -name "${PACKAGE}*.rpm" | xargs --no-run-if-empty rm -f
+# Copy upstream sources
+cp ${UPSTREAM_PACKAGE} ${HOME}/rpmbuild/SOURCES/
+# Patches
+if [ -e original ] ; then
+ find original -name "*" -type f | grep -v "~$" | grep -v ".spec$" | xargs -i§ -n1 cp "§" ${HOME}/rpmbuild/SOURCES/
+fi
+# Further patches
+find rpm -name "*" -type f | grep -v "~$" | grep -v ".spec$" | xargs -i§ -n1 cp "§" ${HOME}/rpmbuild/SOURCES/
+# The .spec file
+cp rpm/${PACKAGE}.spec ${HOME}/rpmbuild/SPECS/
+
+# ------ Create source RPM --------------------------------------------------
+rpmbuild -bs rpm/${PACKAGE}.spec
+PACKAGE_SRPM=`find ${HOME}/rpmbuild/SRPMS/ -name "${PACKAGE}-*-*.src.rpm"`
+if [ ! -e "${PACKAGE_SRPM}" ] ; then
+ echo >&2 "ERROR: Cannot find SRPM ${PACKAGE_SRPM}!"
+ exit 1
+fi
diff --git a/make-upstream-package b/make-upstream-package
new file mode 100755
index 0000000..56df24f
--- /dev/null
+++ b/make-upstream-package
@@ -0,0 +1,103 @@
+#!/usr/bin/env bash
+#
+# Packaging Scripts
+# Copyright (C) 2017-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: thomas.dreibholz@gmail.com
+
+# Bash options:
+set -e
+
+
+# ---------------------------------------------------------------------------
+# USAGE:
+# ./make-upstream-package package_name version [-skip-signing]
+# ---------------------------------------------------------------------------
+
+
+# ====== Check arguments ====================================================
+if [ $# -lt 3 ] ; then
+ echo >&2 "Usage: $0 package_name version make_dist [-skip-signing]"
+ exit 1
+fi
+PACKAGE="$1"
+UPSTREAM_VERSION="$2"
+MAKE_DIST="$3"
+SKIP_PACKAGE_SIGNING=0
+shift ; shift ; shift
+while [ $# -gt 0 ] ; do
+ if [ "$1" == "-skip-signing" ] ; then
+ SKIP_PACKAGE_SIGNING=1
+ else
+ echo >&2 "ERROR: Bad argument $0!"
+ exit 1
+ fi
+ shift
+done
+
+
+# ====== Create upstream source package =====================================
+echo -e ""
+echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating upstream package ======================================\x1b[0m"
+echo -e ""
+for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do
+ printf "Looking for ${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE} ... "
+ UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`"
+ if [ -e "${UPSTREAM_PACKAGE}" ] ; then
+ echo "found!"
+ break
+ else
+ echo "not found"
+ fi
+done
+if [ ! -e "${UPSTREAM_PACKAGE}" ]; then
+ rm -f ${PACKAGE}-*.gz ${PACKAGE}"_"*.gz ${PACKAGE}-*.bz2 ${PACKAGE}"_"*.bz2 ${PACKAGE}-*.xz ${PACKAGE}"_"*.xz
+
+ echo -e "\x1b[34m------ Running MAKE_DIST ... ------\x1b[0m"
+ echo "\$ $MAKE_DIST"
+ eval "$MAKE_DIST"
+
+ echo -e "\x1b[34m------ Looking for upstream package ... ------\x1b[0m"
+ for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do
+ UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`"
+ if [ -e "${UPSTREAM_PACKAGE}" ] ; then
+ break
+ fi
+ done
+ if [ ! -e "${UPSTREAM_PACKAGE}" ] ; then
+ echo -e "\x1b[34mERROR: No upstream package (${PACKAGE}-*.tar.*) found!\x1b[0m"
+ exit 1
+ fi
+
+ rm -f "${UPSTREAM_PACKAGE}.asc" # Ensure that old signature file is removed!
+ echo -e ""
+fi
+echo -e "\x1b[34m==> Upstream package is ${UPSTREAM_PACKAGE} (type is ${UPSTREAM_PACKAGE_TYPE})\x1b[0m"
+echo -e ""
+
+
+# ====== Sign upstream source package =======================================
+if [ ! -e "${UPSTREAM_PACKAGE}.asc" ] ; then
+ if [ ! ${SKIP_PACKAGE_SIGNING} == "1" -a ! "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then
+ echo -e ""
+ echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Sign upstream package ==========================================\x1b[0m"
+ echo -e ""
+ echo -e "\x1b[34mSigning upstream package ${UPSTREAM_PACKAGE} ...\x1b[0m"
+ gpg -sab "${UPSTREAM_PACKAGE}"
+ else
+ rm -f "${UPSTREAM_PACKAGE}.asc"
+ fi
+fi
diff --git a/merge-debian-changelogs b/merge-debian-changelogs
new file mode 100755
index 0000000..c7f3334
--- /dev/null
+++ b/merge-debian-changelogs
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Packaging Scripts
+# Copyright (C) 2021-2024 by Thomas Dreibholz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact: dreibh@simula.no
+#
+
+import glob
+import os
+import re
+import sys
+import time
+
+
+# ====== Handle arguments ==================================================
+if len(sys.argv) < 3:
+ sys.stderr.write('Usage: ' + sys.argv[0] + ' ppa_changelog distribution_changelog\n')
+ sys.exit(1)
+
+changelogNamePPA = sys.argv[1]
+changelogNameDistribution = sys.argv[2]
+
+changelogFilePPA = open(changelogNamePPA, 'r', encoding='utf-8')
+changelogFileDistribution = open(changelogNameDistribution, 'r', encoding='utf-8')
+
+changelogContentsPPA = changelogFilePPA.readlines()
+changelogContentsDistribution = changelogFileDistribution.readlines()
+
+
+# ====== Merge changelogs ===================================================
+re_entry_header = re.compile(r'^([a-zA-Z0-9-]+ \([0-9a-zA-Z\.~+]+-[0-9]*)')
+re_entry_footer = re.compile(r'^ -- .*')
+re_empty = re.compile(r'^\S*$')
+
+topics = [
+ { 'regexp': re.compile(r'^ \* .*ew upstream (version|release).*$'), 'count': 0, 'max': 1 },
+ { 'regexp': re.compile(r'^ \* .*standards version.*$'), 'count': 0, 'max': 1 },
+ { 'regexp': re.compile(r'^ \* .*debian/compat:.*$'), 'count': 0, 'max': 0 }
+]
+
+# ------ Get latest entry from distribution changelog -----------------------
+match = re_entry_header.match(changelogContentsDistribution[0])
+if match == None:
+ sys.stderr.write('ERROR: Bad header in ' + changelogNameDistribution + '!\n')
+ sys.exit(1)
+latestDistributionEntry = match.group(1)
+
+# ------ Join all new entries from PPA changelog ----------------------------
+result = []
+
+entries = 0
+insideEntry = False
+foundLatestDistributionEntryInPPA = False
+firstFooter = None
+for line in changelogContentsPPA:
+ # ------ Begin of an entry -----------------------------------------------
+ match = re_entry_header.match(line)
+ if match != None:
+
+ entries = entries + 1
+ if entries == 1:
+ result.append(line)
+ result.append('\n')
+
+ # ------ Done? --------------------------------------------------------
+ elif line[0:len(latestDistributionEntry)] == latestDistributionEntry:
+ foundLatestDistributionEntryInPPA = True
+ break
+
+ continue
+
+ # ------ Empty line ------------------------------------------------------
+ match = re_empty.match(line)
+ if match != None:
+ continue
+
+ # ------ End of an entry -------------------------------------------------
+ match = re_entry_footer.match(line)
+ if match != None:
+ if entries == 1:
+ firstFooter = line
+ continue
+
+ # ------ Topics ----------------------------------------------------------
+ skip = False
+ for topic in topics:
+ match = topic['regexp'].match(line)
+ if match != None:
+ topic['count'] = topic['count'] + 1
+ if topic['count'] > topic['max']:
+ skip = True
+ break
+ if skip == True:
+ continue
+
+ # ------ Add line to output ----------------------------------------------
+ if line[0] == ' ':
+ result.append(line)
+ continue
+
+ # ------ Something is wrong ----------------------------------------------
+ sys.stderr.write('ERROR: Unexpected line: ' + line + '!\n')
+ sys.exit(1)
+
+
+result.append('\n')
+result.append(firstFooter)
+
+
+if foundLatestDistributionEntryInPPA == False:
+ sys.stderr.write('ERROR: Did not found the latest distribution entry in the PPA changelog!\n')
+ sys.exit(1)
+
+
+# ------ Print results ------------------------------------------------------
+for line in result:
+ sys.stdout.write(line)
+sys.stdout.write('\n')
+for line in changelogContentsDistribution:
+ sys.stdout.write(line)
diff --git a/packaging.conf b/packaging.conf
new file mode 100644
index 0000000..a32a731
--- /dev/null
+++ b/packaging.conf
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# ---------------------------------------------------------
+MAKE_DIST="./make-dist"
+NOT_TARGET_DISTRIBUTIONS="unstable lucid precise trusty xenial" # <<-- Distrubutions which are *not* supported!
+MAINTAINER="Thomas Dreibholz "
+MAINTAINER_KEY="21412672518D8B2D1862EFEF5CD5D12AA0877B49"
+DEBIAN_LAST_ENTRY=""
+UBUNTU_LAST_ENTRY=""
+SKIP_PACKAGE_SIGNING=0 # <<-- Must be set to 0 (=off) for PPA upload!
+# ---------------------------------------------------------
diff --git a/rpm/ripe.atlas.cousteau.spec b/rpm/ripe.atlas.cousteau.spec
new file mode 100644
index 0000000..4e91c73
--- /dev/null
+++ b/rpm/ripe.atlas.cousteau.spec
@@ -0,0 +1,51 @@
+Name: ripe.atlas.cousteau
+Version: 1.5.0a2.td1
+Release: 1
+Summary: RIPE Atlas Cousteau
+Group: Applications/Internet
+License: GPLv3
+URL: https://github.com/dreibh/ripe-atlas-cousteau
+Source: https://packages.nntb.no/software/ripe.atlas.cousteau/%{name}-%{version}.tar.bz2
+
+AutoReqProv: on
+BuildRequires: gcc
+BuildRequires: python3
+BuildRequires: python3-coverage
+BuildRequires: python3-dateutil
+BuildRequires: python3-funcsigs
+BuildRequires: python3-jsonschema
+BuildRequires: python3-mock
+BuildRequires: python3-nose
+BuildRequires: python3-pip
+BuildRequires: python3-requests
+BuildRequires: python3-setuptools
+BuildRequires: python3-socketio+client
+BuildRequires: python3-websocket-client
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+
+
+# This package does not generate debug information (no executables):
+%global debug_package %{nil}
+
+# TEST ONLY:
+# define _unpackaged_files_terminate_build 0
+
+
+%description
+A python wrapper around the RIPE ATLAS API.
+See https://ripe-atlas-cousteau.readthedocs.io/en/latest/ for details!
+
+%prep
+%setup -n %{name}-%{version} -n %{name}-%{version}
+
+%build
+python3 setup.py build
+
+%install
+python3 setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files -f INSTALLED_FILES
+%defattr(-,root,root)
diff --git a/setup.py b/setup.py
index 2bedaa8..6fff8d4 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,9 @@
# import manually __version__ variable
__version__ = None
-exec(open("ripe/atlas/cousteau/version.py").read())
+exec(open('ripe/atlas/cousteau/version.py').read())
+__version_extra = '.td1'
+__version__ = __version__ + __version_extra
install_requires = [
"python-dateutil",