[packages/monotone] Up to 1.1
arekm
arekm at pld-linux.org
Sun Aug 16 21:48:04 CEST 2026
commit 3f40c16f2c311e07c034bb0b427ef38719282a9d
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Sun Aug 16 21:47:43 2026 +0200
Up to 1.1
monotone-boost-e-macro.patch | 16 +
monotone-botan2.patch | 1396 ++++++++++++++++++++++++++++++++++++++++++
monotone-pcre.patch | 40 ++
monotone.spec | 60 +-
4 files changed, 1500 insertions(+), 12 deletions(-)
---
diff --git a/monotone.spec b/monotone.spec
index cf0f537..b67b962 100644
--- a/monotone.spec
+++ b/monotone.spec
@@ -1,25 +1,32 @@
# NOTE:
-# - bundled sqlite has local modifications to support large db
-# - bundled lua is stripped, it doesn't contain some features
-# that create security holes in monotone environment
+# - lua 5.1 is not a leftover: monotone uses lua_strlen and LUA_QL, both gone
+# in 5.2
# TODO:
# - subpackage with init-scripts
# - database format is changing - migrate and regenerate options has to be run.
Summary: A free distributed version control system
Summary(pl.UTF-8): Wolnodostępny rozproszony system kontroli wersji
Name: monotone
-Version: 0.42
+Version: 1.1
Release: 1
License: GPL v2
Group: Development/Version Control
-Source0: http://monotone.ca/downloads/%{version}/%{name}-%{version}.tar.gz
-# Source0-md5: c8e916d674b6608369d9f447700a8830
-URL: http://www.venge.net/monotone/
+Source0: http://monotone.ca/downloads/%{version}/%{name}-%{version}.tar.bz2
+# Source0-md5: df3f40ca22120aa142ac9becba9e1bf7
+Patch0: %{name}-botan2.patch
+Patch1: %{name}-boost-e-macro.patch
+Patch2: %{name}-pcre.patch
+URL: http://www.monotone.ca/
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: boost-devel >= 1.35.0
+BuildRequires: botan2-devel
BuildRequires: libidn-devel
-BuildRequires: popt-devel
+BuildRequires: lua51-devel
+BuildRequires: pcre-devel
+BuildRequires: pkgconfig
+BuildRequires: sqlite3-devel
+BuildRequires: zlib-devel
BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
%description
@@ -46,13 +53,21 @@ jest licencjonowany na GNU GPL.
%prep
%setup -q
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+
+# avoid hiding the interpreter dependency behind env
+%{__sed} -i -e '1s,#! */usr/bin/env bash,#!/bin/bash,' extra/mtn-hooks/monotone-mail-notify
+%{__sed} -i -e '1s,#!/usr/bin/env perl,#!%{__perl},' extra/bin/mtn-cleanup
%build
%{__aclocal} -I m4
%{__autoconf}
%{__automake}
-CPPFLAGS="-I%{_includedir}/lua50"; export CPPFLAGS
%configure \
+ lua_CFLAGS="$(pkg-config --cflags lua51)" \
+ lua_LIBS="$(pkg-config --libs lua51)" \
--enable-ipv6
%{__make}
@@ -63,8 +78,21 @@ rm -rf $RPM_BUILD_ROOT
DESTDIR=$RPM_BUILD_ROOT
%find_lang %{name}
-mv $RPM_BUILD_ROOT%{_docdir}/%{name}/monotone.html \
- $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version}
+
+# upstream drops these into an unversioned docdir; ship them as %%doc instead
+%{__rm} -r $RPM_BUILD_ROOT%{_docdir}/%{name}
+
+# python2 notifier for cia.vc, a service shut down in 2011, and the hook
+# that calls it
+%{__rm} $RPM_BUILD_ROOT%{_datadir}/%{name}/scripts/monotone-ciabot.py
+%{__rm} $RPM_BUILD_ROOT%{_datadir}/%{name}/hooks/monotone-ciabot.lua
+
+install -d $RPM_BUILD_ROOT%{bash_compdir}
+%{__mv} $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d/monotone.bash_completion \
+ $RPM_BUILD_ROOT%{bash_compdir}/mtn
+rmdir $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
+
+%{__rm} $RPM_BUILD_ROOT%{_infodir}/dir
%clean
rm -rf $RPM_BUILD_ROOT
@@ -77,6 +105,14 @@ rm -rf $RPM_BUILD_ROOT
%files -f %{name}.lang
%defattr(644,root,root,755)
-%doc AUTHORS NEWS UPGRADE monotone.html
+%doc AUTHORS NEWS README UPGRADE contrib examples
%attr(755,root,root) %{_bindir}/*
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/hooks
+%dir %{_datadir}/%{name}/scripts
+%attr(755,root,root) %{_datadir}/%{name}/scripts/monotone-mail-notify
+%{bash_compdir}/mtn
%{_infodir}/monotone*
+%{_mandir}/man1/mtn.1*
+%{_mandir}/man1/mtn-cleanup.1*
+%{_mandir}/man1/mtnopt.1*
diff --git a/monotone-boost-e-macro.patch b/monotone-boost-e-macro.patch
new file mode 100644
index 0000000..ab2eeca
--- /dev/null
+++ b/monotone-boost-e-macro.patch
@@ -0,0 +1,16 @@
+--- monotone-1.1/src/base.hh
++++ monotone-1.1/src/base.hh
+@@ -29,6 +29,13 @@
+ // than 3.3.14.
+ #define SUPPORT_SQLITE_BEFORE_3003014
+
++// boost >= 1.73 and botan 2 use E as a template parameter and then write
++// E(...) as a base-class initialiser / throw expression; sanity.hh defines a
++// 3-argument E() macro. Pull those headers in here, before any macro exists,
++// so their include guards keep them out of later translation units.
++#include <boost/throw_exception.hpp>
++#include <botan/exceptn.h>
++
+ #include <iosfwd>
+ #include <string> // it would be nice if there were a <stringfwd>
+
diff --git a/monotone-botan2.patch b/monotone-botan2.patch
new file mode 100644
index 0000000..395c306
--- /dev/null
+++ b/monotone-botan2.patch
@@ -0,0 +1,1396 @@
+--- monotone-1.1/m4/library.m4
++++ monotone-1.1/m4/library.m4
+@@ -176,17 +176,50 @@
+ # Checks for specific libraries that can be probed this way.
+
+ AC_DEFUN([MTN_FIND_BOTAN],
+-[MTN_CHECK_MODULE([botan], [1.6.3],
+- [AC_LANG_PROGRAM(
+- [#include <botan/botan.h>
+- #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,6,3)
+- #error too old
+- #endif
+- #if BOTAN_VERSION_CODE == BOTAN_VERSION_CODE_FOR(1,7,14)
+- #error version 1.7.14 is not usable for monotone
+- #endif],
+- [Botan::LibraryInitializer li;])
+- ])
++[AC_REQUIRE([MTN_FULL_PKG_CONFIG_PATH])
++# Try botan-2 (Botan 2.x) first, then fall back to botan 1.x
++_botan_found=false
++if test -n "$PKG_CONFIG"; then
++ AC_MSG_CHECKING([for botan-2 >= 2.0 using pkg-config])
++ if $PKG_CONFIG --exists "botan-2 >= 2.0" 2>/dev/null; then
++ botan_CFLAGS=`$PKG_CONFIG --cflags botan-2`
++ botan_LIBS=`$PKG_CONFIG --libs botan-2`
++ AC_MSG_RESULT([yes])
++ _botan_found=true
++ else
++ AC_MSG_RESULT([no])
++ fi
++fi
++if ! $_botan_found; then
++ MTN_CHECK_MODULE([botan], [1.9.11],
++ [AC_LANG_PROGRAM(
++ [#include <botan/botan.h>
++ #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,11)
++ #error too old
++ #endif],
++ [Botan::LibraryInitializer li;])
++ ])
++ _botan_found=true
++fi
++if $_botan_found && test -n "$botan_CFLAGS$botan_LIBS"; then
++ # Validate the found botan library
++ AC_MSG_CHECKING([whether botan is usable])
++ save_LIBS="$LIBS"
++ save_CPPFLAGS="$CPPFLAGS"
++ LIBS="$LIBS $botan_LIBS"
++ CPPFLAGS="$CPPFLAGS $botan_CFLAGS"
++ AC_LINK_IFELSE(
++ [AC_LANG_PROGRAM(
++ [#include <botan/version.h>],
++ [int v = BOTAN_VERSION_MAJOR;])],
++ [AC_MSG_RESULT([yes])],
++ [AC_MSG_RESULT([no])
++ AC_MSG_FAILURE([Must be able to compile and link programs against botan.])])
++ LIBS="$save_LIBS"
++ CPPFLAGS="$save_CPPFLAGS"
++fi
++AC_SUBST([botan_CFLAGS])
++AC_SUBST([botan_LIBS])
+ ])
+
+ AC_DEFUN([MTN_FIND_IDNA],
+--- monotone-1.1/src/botan_pipe_cache.hh
++++ monotone-1.1/src/botan_pipe_cache.hh
+@@ -10,7 +10,13 @@
+ #ifndef __BOTAN_PIPE_CACHE_HH__
+ #define __BOTAN_PIPE_CACHE_HH__
+
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/pipe.h>
++#include <botan/filters.h>
++#else
+ #include <botan/botan.h>
++#endif
+ #include <boost/scoped_ptr.hpp>
+
+ #include "sanity.hh"
+--- monotone-1.1/src/database.cc
++++ monotone-1.1/src/database.cc
+@@ -25,10 +25,19 @@
+ #include <boost/tuple/tuple.hpp>
+ #include <boost/tuple/tuple_comparison.hpp>
+
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/rsa.h>
++#include <botan/pem.h>
++#include <botan/pubkey.h>
++#include <botan/x509_key.h>
++#include <botan/data_src.h>
++#else
+ #include <botan/botan.h>
+ #include <botan/rsa.h>
+ #include <botan/pem.h>
+ #include <botan/look_pk.h>
++#endif
+ #include "lazy_rng.hh"
+
+ #include <sqlite3.h>
+@@ -98,13 +107,11 @@
+ using boost::tuple;
+ using boost::lexical_cast;
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,5)
+ using Botan::PK_Encryptor_EME;
+-#else
+-using Botan::PK_Encryptor;
+-#endif
+ using Botan::PK_Verifier;
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ using Botan::SecureVector;
++#endif
+ using Botan::X509_PublicKey;
+ using Botan::RSA_PublicKey;
+
+@@ -3428,42 +3435,40 @@
+ rsa_pub_key pub;
+ get_key(pub_id, pub);
+
+- SecureVector<Botan::byte> pub_block
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ Botan::DataSource_Memory ds_pub(
++ reinterpret_cast<uint8_t const *>(pub().data()), pub().size());
++ shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(ds_pub));
++#else
++ Botan::SecureVector<Botan::byte> pub_block
+ (reinterpret_cast<Botan::byte const *>(pub().data()), pub().size());
+-
+ shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(pub_block));
++#endif
+ shared_ptr<RSA_PublicKey> pub_key
+ = dynamic_pointer_cast<RSA_PublicKey>(x509_key);
+ if (!pub_key)
+ throw recoverable_failure(origin::system,
+ "Failed to get RSA encrypting key");
+
+- SecureVector<Botan::byte> ct;
+-
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,5)
+- PK_Encryptor_EME encryptor(*pub_key, "EME1(SHA-1)");
+- ct = encryptor.encrypt(
+- reinterpret_cast<Botan::byte const *>(plaintext.data()),
+- plaintext.size(), lazy_rng::get());
+-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- shared_ptr<PK_Encryptor>
+- encryptor(get_pk_encryptor(*pub_key, "EME1(SHA-1)"));
+-
+- ct = encryptor->encrypt(
+- reinterpret_cast<Botan::byte const *>(plaintext.data()),
+- plaintext.size(), lazy_rng::get());
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ PK_Encryptor_EME encryptor(*pub_key, lazy_rng::get(), "EME1(SHA-1)");
++ std::vector<uint8_t> ct =
++ encryptor.encrypt(
++ reinterpret_cast<uint8_t const *>(plaintext.data()),
++ plaintext.size(), lazy_rng::get());
++ ciphertext = rsa_oaep_sha_data(
++ string(reinterpret_cast<char const *>(ct.data()), ct.size()),
++ origin::database);
+ #else
+- shared_ptr<PK_Encryptor>
+- encryptor(Botan::get_pk_encryptor(*pub_key, "EME1(SHA-1)"));
+-
+- ct = encryptor->encrypt(
+- reinterpret_cast<Botan::byte const *>(plaintext.data()),
+- plaintext.size());
+-#endif
+-
++ PK_Encryptor_EME encryptor(*pub_key, "EME1(SHA-1)");
++ Botan::SecureVector<Botan::byte> ct =
++ encryptor.encrypt(
++ reinterpret_cast<Botan::byte const *>(plaintext.data()),
++ plaintext.size(), lazy_rng::get());
+ ciphertext = rsa_oaep_sha_data(
+ string(reinterpret_cast<char const *>(ct.begin()), ct.size()),
+ origin::database);
++#endif
+ }
+
+ cert_status
+@@ -3487,22 +3492,23 @@
+ return cert_unknown;
+
+ get_key(id, pub);
+- SecureVector<Botan::byte> pub_block
++ L(FL("building verifier for %d-byte pub key") % pub().size());
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ Botan::DataSource_Memory ds_pub(
++ reinterpret_cast<uint8_t const *>(pub().data()), pub().size());
++ shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(ds_pub));
++#else
++ Botan::SecureVector<Botan::byte> pub_block
+ (reinterpret_cast<Botan::byte const *>(pub().data()), pub().size());
+-
+- L(FL("building verifier for %d-byte pub key") % pub_block.size());
+ shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(pub_block));
++#endif
+ shared_ptr<RSA_PublicKey> pub_key
+ = boost::dynamic_pointer_cast<RSA_PublicKey>(x509_key);
+
+ E(pub_key, id.inner().made_from,
+ F("failed to get RSA verifying key for %s") % id);
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+- verifier.reset(new Botan::PK_Verifier(*pub_key, "EMSA3(SHA1)"));
+-#else
+- verifier.reset(Botan::get_pk_verifier(*pub_key, "EMSA3(SHA-1)"));
+-#endif
++ verifier.reset(new Botan::PK_Verifier(*pub_key, "EMSA3(SHA-1)"));
+
+ /* XXX This is ugly. We need to keep the key around
+ * as long as the verifier is around, but the shared_ptr will go
+@@ -3515,9 +3521,9 @@
+ L(FL("checking %d-byte signature") % signature().size());
+
+ if (verifier->verify_message(
+- reinterpret_cast<Botan::byte const*>(alleged_text.data()),
++ reinterpret_cast<uint8_t const*>(alleged_text.data()),
+ alleged_text.size(),
+- reinterpret_cast<Botan::byte const*>(signature().data()),
++ reinterpret_cast<uint8_t const*>(signature().data()),
+ signature().size()))
+ return cert_ok;
+ else
+--- monotone-1.1/src/gzip.cc
++++ monotone-1.1/src/gzip.cc
+@@ -16,9 +16,12 @@
+ #include "base.hh"
+ #include "gzip.hh"
+
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/loadstor.h>
++#include <botan/filters.h>
++#else
+ #include <botan/botan.h>
+-
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ #include <botan/loadstor.h>
+ #include <botan/filters.h>
+ #endif
+@@ -29,44 +32,6 @@
+
+ namespace Botan {
+
+-namespace {
+-
+-/*************************************************
+-* Allocation Information for Zlib *
+-*************************************************/
+-class Zlib_Alloc_Info
+- {
+- public:
+- std::map<void*, u32bit> current_allocs;
+- Allocator* alloc;
+-
+- Zlib_Alloc_Info() { alloc = Allocator::get(false); }
+- };
+-
+-/*************************************************
+-* Allocation Function for Zlib *
+-*************************************************/
+-void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size)
+- {
+- Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+- void* ptr = info->alloc->allocate(n * size);
+- info->current_allocs[ptr] = n * size;
+- return ptr;
+- }
+-
+-/*************************************************
+-* Allocation Function for Zlib *
+-*************************************************/
+-void zlib_free(void* info_ptr, void* ptr)
+- {
+- Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(info_ptr);
+- std::map<void*, u32bit>::const_iterator i = info->current_allocs.find(ptr);
+- if(i == info->current_allocs.end())
+- throw Invalid_Argument("zlib_free: Got pointer not allocated by us");
+- info->alloc->deallocate(ptr, i->second);
+- }
+-}
+-
+ /*************************************************
+ * Wrapper Type for Zlib z_stream *
+ *************************************************/
+@@ -78,14 +43,12 @@
+ Zlib_Stream()
+ {
+ std::memset(&stream, 0, sizeof(z_stream));
+- stream.zalloc = zlib_malloc;
+- stream.zfree = zlib_free;
+- stream.opaque = new Zlib_Alloc_Info;
++ stream.zalloc = Z_NULL;
++ stream.zfree = Z_NULL;
++ stream.opaque = Z_NULL;
+ }
+ ~Zlib_Stream()
+ {
+- Zlib_Alloc_Info* info = static_cast<Zlib_Alloc_Info*>(stream.opaque);
+- delete info;
+ std::memset(&stream, 0, sizeof(z_stream));
+ }
+ };
+@@ -94,7 +57,7 @@
+ * Gzip_Compression Constructor *
+ *************************************************/
+ Gzip_Compression::Gzip_Compression(u32bit l) :
+- level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE),
++ level((l >= 9) ? 9 : l), buffer(BOTAN_DEFAULT_BUFFER_SIZE),
+ pipe(new Hash_Filter("CRC32")), count( 0 )
+ {
+
+@@ -110,7 +73,7 @@
+ if(deflateInit2(&(zlib->stream), level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK)
+ {
+ delete zlib; zlib = 0;
+- throw Memory_Exhaustion();
++ throw std::bad_alloc();
+ }
+ }
+
+@@ -148,12 +111,12 @@
+
+ while(zlib->stream.avail_in != 0)
+ {
+- zlib->stream.next_out = (Bytef*)buffer.begin();
++ zlib->stream.next_out = (Bytef*)buffer.data();
+ zlib->stream.avail_out = buffer.size();
+ int rc = deflate(&(zlib->stream), Z_NO_FLUSH);
+ if (rc != Z_OK && rc != Z_STREAM_END)
+ throw Invalid_State("Internal error in Gzip_Compression deflate.");
+- send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
++ send(buffer.data(), buffer.size() - zlib->stream.avail_out);
+ }
+ }
+
+@@ -168,12 +131,12 @@
+ int rc = Z_OK;
+ while(rc != Z_STREAM_END)
+ {
+- zlib->stream.next_out = (Bytef*)buffer.begin();
++ zlib->stream.next_out = (Bytef*)buffer.data();
+ zlib->stream.avail_out = buffer.size();
+ rc = deflate(&(zlib->stream), Z_FINISH);
+ if (rc != Z_OK && rc != Z_STREAM_END)
+ throw Invalid_State("Internal error in Gzip_Compression finishing deflate.");
+- send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
++ send(buffer.data(), buffer.size() - zlib->stream.avail_out);
+ }
+
+ pipe.end_msg();
+@@ -206,29 +169,29 @@
+ SecureVector<byte> buf(4);
+ SecureVector<byte> tmpbuf(4);
+
+- pipe.read(tmpbuf.begin(), tmpbuf.size(), Pipe::LAST_MESSAGE);
++ pipe.read(tmpbuf.data(), tmpbuf.size(), Pipe::LAST_MESSAGE);
+
+ // CRC32 is the reverse order to what gzip expects.
+ for (int i = 0; i < 4; i++)
+ buf[3-i] = tmpbuf[i];
+
+- send(buf.begin(), buf.size());
++ send(buf.data(), buf.size());
+
+ // Length - LSB first
+ for (int i = 0; i < 4; i++)
+ buf[3-i] = get_byte(i, count);
+
+- send(buf.begin(), buf.size());
++ send(buf.data(), buf.size());
+ }
+
+ /*************************************************
+ * Gzip_Decompression Constructor *
+ *************************************************/
+-Gzip_Decompression::Gzip_Decompression() : buffer(DEFAULT_BUFFERSIZE),
++Gzip_Decompression::Gzip_Decompression() : buffer(BOTAN_DEFAULT_BUFFER_SIZE),
+ no_writes(true), pipe(new Hash_Filter("CRC32")), footer(0)
+ {
+- if (DEFAULT_BUFFERSIZE < sizeof(GZIP::GZIP_HEADER))
+- throw Decoding_Error("DEFAULT_BUFFERSIZE is too small");
++ if (BOTAN_DEFAULT_BUFFER_SIZE < sizeof(GZIP::GZIP_HEADER))
++ throw Decoding_Error("BOTAN_DEFAULT_BUFFER_SIZE is too small");
+
+ zlib = new Zlib_Stream;
+
+@@ -237,7 +200,7 @@
+ if(inflateInit2(&(zlib->stream), -15) != Z_OK)
+ {
+ delete zlib; zlib = 0;
+- throw Memory_Exhaustion();
++ throw std::bad_alloc();
+ }
+ }
+
+@@ -307,7 +270,7 @@
+
+ while(zlib->stream.avail_in != 0)
+ {
+- zlib->stream.next_out = (Bytef*)buffer.begin();
++ zlib->stream.next_out = (Bytef*)buffer.data();
+ zlib->stream.avail_out = buffer.size();
+
+ int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH);
+@@ -318,11 +281,11 @@
+ if(rc == Z_NEED_DICT)
+ throw Decoding_Error("Gzip_Decompression: Need preset dictionary");
+ if(rc == Z_MEM_ERROR)
+- throw Memory_Exhaustion();
++ throw std::bad_alloc();
+ throw Decoding_Error("Gzip_Decompression: Unknown decompress error");
+ }
+- send(buffer.begin(), buffer.size() - zlib->stream.avail_out);
+- pipe.write(buffer.begin(), buffer.size() - zlib->stream.avail_out);
++ send(buffer.data(), buffer.size() - zlib->stream.avail_out);
++ pipe.write(buffer.data(), buffer.size() - zlib->stream.avail_out);
+ datacount += buffer.size() - zlib->stream.avail_out;
+
+ // Reached the end - we now need to check the footer
+@@ -347,14 +310,9 @@
+ if (footer.size() >= GZIP::FOOTER_LENGTH)
+ throw Decoding_Error("Gzip_Decompression: Data integrity error in footer");
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+ size_t eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(),
+ static_cast<size_t>(length));
+- footer += std::make_pair(input, eat_len);
+-#else
+- u32bit eat_len = std::min(GZIP::FOOTER_LENGTH-footer.size(), length);
+- footer.append(input, eat_len);
+-#endif
++ footer.insert(footer.end(), input, input + eat_len);
+
+ if (footer.size() == GZIP::FOOTER_LENGTH)
+ {
+@@ -378,25 +336,20 @@
+ // 4 byte CRC32, and 4 byte length field
+ SecureVector<byte> buf(4);
+ SecureVector<byte> tmpbuf(4);
+- pipe.read(tmpbuf.begin(), tmpbuf.size(), Pipe::LAST_MESSAGE);
++ pipe.read(tmpbuf.data(), tmpbuf.size(), Pipe::LAST_MESSAGE);
+
+ // CRC32 is the reverse order to what gzip expects.
+ for (int i = 0; i < 4; i++)
+ buf[3-i] = tmpbuf[i];
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+- tmpbuf.resize(4);
+- tmpbuf.copy(footer.begin(), 4);
+-#else
+- tmpbuf.set(footer.begin(), 4);
+-#endif
++ std::copy(footer.data(), footer.data() + 4, tmpbuf.data());
+ if (buf != tmpbuf)
+ throw Decoding_Error("Gzip_Decompression: Data integrity error - CRC32 error");
+
+ // Check the length matches - it is encoded LSB-first
+ for (int i = 0; i < 4; i++)
+ {
+- if (footer.begin()[GZIP::FOOTER_LENGTH-1-i] != get_byte(i, datacount))
++ if (footer.data()[GZIP::FOOTER_LENGTH-1-i] != get_byte(i, datacount))
+ throw Decoding_Error("Gzip_Decompression: Data integrity error - incorrect length");
+ }
+
+@@ -424,11 +377,7 @@
+ no_writes = true;
+ inflateReset(&(zlib->stream));
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+ footer.clear();
+-#else
+- footer.destroy();
+-#endif
+ pos = 0;
+ datacount = 0;
+ }
+--- monotone-1.1/src/gzip.hh
++++ monotone-1.1/src/gzip.hh
+@@ -10,6 +10,7 @@
+ #include <botan/version.h>
+ #include <botan/filter.h>
+ #include <botan/pipe.h>
++#include <botan/filters.h>
+
+ namespace Botan {
+
+@@ -26,6 +27,13 @@
+ };
+ #endif
+
++// Compatibility: Botan 2.x removed the byte typedef
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++typedef uint8_t byte;
++typedef uint32_t u32bit;
++template<typename T> using SecureVector = secure_vector<T>;
++#endif
++
+ namespace GZIP {
+
+ /* A basic header - we only need to set the IDs and compression method */
+@@ -44,11 +52,7 @@
+
+ }
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+ typedef size_t filter_length_t;
+-#else
+-typedef u32bit filter_length_t;
+-#endif
+
+ /*************************************************
+ * Gzip Compression Filter *
+--- monotone-1.1/src/inodeprint.cc
++++ monotone-1.1/src/inodeprint.cc
+@@ -13,7 +13,10 @@
+ #include <algorithm>
+ #include <iterator>
+
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ #include <botan/botan.h>
++#endif
+ #include <botan/sha160.h>
+
+ #include "inodeprint.hh"
+--- monotone-1.1/src/key_packet.cc
++++ monotone-1.1/src/key_packet.cc
+@@ -13,8 +13,18 @@
+
+ #include "base.hh"
+ #include <sstream>
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/rsa.h>
++#include <botan/pkcs8.h>
++#include <botan/x509_key.h>
++#include <botan/data_src.h>
++#include <botan/asn1_obj.h>
++#include <botan/ber_dec.h>
++#else
+ #include <botan/botan.h>
+ #include <botan/rsa.h>
++#endif
+
+ #include "cset.hh"
+ #include "constants.hh"
+@@ -72,6 +82,30 @@
+
+
+ // --- reading key_packets from streams ---
++// botan 2 reports "encrypted, and you gave no passphrase" as a Decoding_Error,
++// exactly like real garbage, so structure has to be checked separately: a
++// PKCS#8 EncryptedPrivateKeyInfo is AlgorithmIdentifier + OCTET STRING.
++static bool
++is_encrypted_pkcs8(string const & der)
++{
++ try
++ {
++ Botan::AlgorithmIdentifier alg;
++ std::vector<uint8_t> enc;
++ Botan::BER_Decoder(reinterpret_cast<uint8_t const *>(der.data()),
++ der.size())
++ .start_cons(Botan::SEQUENCE)
++ .decode(alg)
++ .decode(enc, Botan::OCTET_STRING)
++ .end_cons();
++ return true;
++ }
++ catch (std::exception const &)
++ {
++ return false;
++ }
++}
++
+ namespace
+ {
+ struct
+@@ -106,8 +140,8 @@
+ void validate_public_key_data(string const & name, string const & keydata) const
+ {
+ string decoded = decode_base64_as<string>(keydata, origin::user);
+- Botan::SecureVector<Botan::byte> key_block
+- (reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
++ Botan::DataSource_Memory key_block(
++ reinterpret_cast<uint8_t const *>(decoded.c_str()), decoded.size());
+ try
+ {
+ Botan::X509::load_key(key_block);
+@@ -133,7 +167,7 @@
+ }
+ catch (Botan::Decoding_Error const & e)
+ {
+- E(false, origin::user,
++ E(is_encrypted_pkcs8(decoded), origin::user,
+ F("malformed key_packet: invalid private key data for '%s': %s")
+ % name % e.what());
+ }
+--- monotone-1.1/src/key_store.cc
++++ monotone-1.1/src/key_store.cc
+@@ -10,10 +10,23 @@
+ #include "base.hh"
+ #include <sstream>
+
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/rsa.h>
++#include <botan/pem.h>
++#include <botan/pkcs8.h>
++#include <botan/pubkey.h>
++#include <botan/x509_key.h>
++#include <botan/data_src.h>
++#include <botan/pipe.h>
++#include <botan/symkey.h>
++#include <botan/filters.h>
++#else
+ #include <botan/botan.h>
+ #include <botan/rsa.h>
+ #include <botan/pem.h>
+ #include <botan/look_pk.h>
++#endif
+
+ #include "char_classifiers.hh"
+ #include "key_store.hh"
+@@ -47,14 +60,18 @@
+
+ using Botan::RSA_PrivateKey;
+ using Botan::RSA_PublicKey;
+-using Botan::SecureVector;
+ using Botan::X509_PublicKey;
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++using Botan::secure_vector;
++#else
++using Botan::SecureVector;
++using Botan::get_pk_decryptor;
++#endif
++using Botan::get_cipher;
+ using Botan::PKCS8_PrivateKey;
+ using Botan::PK_Decryptor;
+ using Botan::PK_Signer;
+ using Botan::Pipe;
+-using Botan::get_pk_decryptor;
+-using Botan::get_cipher;
+ using Botan::byte;
+
+
+@@ -573,21 +590,9 @@
+ try // with empty passphrase
+ {
+ Botan::DataSource_Memory ds(kp.priv());
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+- pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get(), Dummy_UI()));
+-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get(), ""));
+-#else
+- pkcs8_key.reset(Botan::PKCS8::load_key(ds, ""));
+-#endif
++ pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get(), std::string()));
+ }
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+- catch (Passphrase_Required & e)
+-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,4)
+- catch (Botan::Invalid_Argument & e)
+-#else
+- catch (Botan::Exception & e)
+-#endif
++ catch (std::exception & e)
+ {
+ L(FL("failed to load key with no passphrase: %s") % e.what());
+
+@@ -613,23 +618,15 @@
+ try
+ {
+ Botan::DataSource_Memory ds(kp.priv());
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get(),
+ phrase()));
+-#else
+- pkcs8_key.reset(Botan::PKCS8::load_key(ds, phrase()));
+-#endif
+ break;
+ }
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,4)
+- catch (Botan::Invalid_Argument)
+-#else
+- catch (Botan::Exception & e)
+-#endif
++ catch (std::exception & e2)
+ {
+ cycles++;
+ L(FL("decrypt_private_key: failure %d to load encrypted key: %s")
+- % cycles % e.what());
++ % cycles % e2.what());
+ E(cycles < 3 && !non_interactive, origin::no_fault,
+ F("failed to decrypt old private RSA key, probably incorrect "
+ "passphrase or missing 'get_passphrase' lua hook"));
+@@ -702,38 +699,21 @@
+ {
+ L(FL("generating key-pair '%s'") % ident);
+ }
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ RSA_PrivateKey priv(lazy_rng::get(),
+- static_cast<Botan::u32bit>(constants::keylen));
+-#else
+- RSA_PrivateKey priv(static_cast<Botan::u32bit>(constants::keylen));
+-#endif
++ static_cast<size_t>(constants::keylen));
+
+ // serialize and maybe encrypt the private key
+ keypair kp;
+- SecureVector<byte> pubkey, privkey;
+
+ unfiltered_pipe->start_msg();
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+ if ((*maybe_passphrase)().length())
+ unfiltered_pipe->write(
+ Botan::PKCS8::BER_encode(priv, lazy_rng::get(),
+ (*maybe_passphrase)(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)"));
++ std::chrono::milliseconds(300),
++ "PBE-PKCS5v20(AES-256/CBC,SHA-256)"));
+ else
+ unfiltered_pipe->write(Botan::PKCS8::PEM_encode(priv));
+-#else
+- if ((*maybe_passphrase)().length())
+- Botan::PKCS8::encrypt_key(priv, *unfiltered_pipe,
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- lazy_rng::get(),
+-#endif
+- (*maybe_passphrase)(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)",
+- Botan::RAW_BER);
+- else
+- Botan::PKCS8::encode(priv, *unfiltered_pipe);
+-#endif
+ unfiltered_pipe->end_msg();
+
+ kp.priv = rsa_priv_key(
+@@ -742,11 +722,7 @@
+
+ // serialize the public key
+ unfiltered_pipe->start_msg();
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+ unfiltered_pipe->write(Botan::X509::BER_encode(priv));
+-#else
+- Botan::X509::encode(priv, *unfiltered_pipe, Botan::RAW_BER);
+-#endif
+ unfiltered_pipe->end_msg();
+ kp.pub = rsa_pub_key(unfiltered_pipe->read_all_as_string(Pipe::LAST_MESSAGE),
+ origin::internal);
+@@ -813,26 +789,14 @@
+ get_passphrase(new_phrase, name, id, true, false);
+
+ unfiltered_pipe->start_msg();
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+ if (new_phrase().length())
+ unfiltered_pipe->write(
+ Botan::PKCS8::BER_encode(*priv, lazy_rng::get(),
+ new_phrase(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)"));
++ std::chrono::milliseconds(300),
++ "PBE-PKCS5v20(AES-256/CBC,SHA-256)"));
+ else
+ unfiltered_pipe->write(Botan::PKCS8::PEM_encode(*priv));
+-#else
+- if (new_phrase().length())
+- Botan::PKCS8::encrypt_key(*priv, *unfiltered_pipe,
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- lazy_rng::get(),
+-#endif
+- new_phrase(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)",
+- Botan::RAW_BER);
+- else
+- Botan::PKCS8::encode(*priv, *unfiltered_pipe);
+-#endif
+
+ unfiltered_pipe->end_msg();
+ kp.priv = rsa_priv_key(unfiltered_pipe->read_all_as_string(Pipe::LAST_MESSAGE),
+@@ -853,29 +817,22 @@
+ load_key_pair(*this, id, kp);
+ shared_ptr<RSA_PrivateKey> priv_key = s->decrypt_private_key(id);
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+- Botan::PK_Decryptor_EME decryptor(*priv_key, "EME1(SHA-1)");
+-
+- SecureVector<byte> plain =
+- decryptor.decrypt(reinterpret_cast<byte const *>(ciphertext().data()),
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ Botan::PK_Decryptor_EME decryptor(*priv_key, lazy_rng::get(), "EME1(SHA-1)");
++ Botan::secure_vector<uint8_t> plain =
++ decryptor.decrypt(reinterpret_cast<uint8_t const *>(ciphertext().data()),
+ ciphertext().size());
+ plaintext = string(plain.begin(), plain.end());
+ #else
+- shared_ptr<PK_Decryptor>
+- decryptor(Botan::get_pk_decryptor(*priv_key, "EME1(SHA-1)"));
++ Botan::PK_Decryptor_EME decryptor(*priv_key, "EME1(SHA-1)");
+
+- SecureVector<byte> plain =
+- decryptor->decrypt(reinterpret_cast<byte const *>(ciphertext().data()),
+- ciphertext().size());
+- plaintext = string(reinterpret_cast<char const*>(plain.begin()),
+- plain.size());
++ Botan::SecureVector<Botan::byte> plain =
++ decryptor.decrypt(reinterpret_cast<Botan::byte const *>(ciphertext().data()),
++ ciphertext().size());
++ plaintext = string(plain.begin(), plain.end());
+ #endif
+ }
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,4)
+ catch (std::exception & e)
+-#else
+- catch (Botan::Exception & e)
+-#endif
+ {
+ E(false, ciphertext.made_from,
+ F("Botan error decrypting data: '%s'") % e.what());
+@@ -909,12 +866,19 @@
+ {
+ if (agent.connected()) {
+ //grab the monotone public key as an RSA_PublicKey
+- SecureVector<byte> pub_block
+- (reinterpret_cast<byte const *>(key.pub().data()),
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ Botan::DataSource_Memory ds_pub(
++ reinterpret_cast<uint8_t const *>(key.pub().data()),
++ key.pub().size());
++ shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(ds_pub));
++#else
++ Botan::SecureVector<Botan::byte> pub_block
++ (reinterpret_cast<Botan::byte const *>(key.pub().data()),
+ key.pub().size());
+ L(FL("make_signature: building %d-byte pub key") % pub_block.size());
+ shared_ptr<X509_PublicKey> x509_key =
+ shared_ptr<X509_PublicKey>(Botan::X509::load_key(pub_block));
++#endif
+ shared_ptr<RSA_PublicKey> pub_key =
+ dynamic_pointer_cast<RSA_PublicKey>(x509_key);
+
+@@ -938,8 +902,6 @@
+ || s->ssh_sign_mode == "check"
+ || s->ssh_sign_mode == "no")
+ {
+- SecureVector<byte> sig;
+-
+ // we permit the user to relax security here, by caching a decrypted key
+ // (if they permit it) through the life of a program run. this helps when
+ // you're making a half-dozen certs during a commit or merge or
+@@ -962,13 +924,8 @@
+ L(FL("make_signature: adding private key (%s) to ssh-agent") % id);
+ agent.add_identity(*priv_key, name());
+ }
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+ signer = shared_ptr<PK_Signer>(
+- new PK_Signer(*priv_key, "EMSA3(SHA-1)"));
+-#else
+- signer = shared_ptr<PK_Signer>(
+- get_pk_signer(*priv_key, "EMSA3(SHA-1)"));
+-#endif
++ new PK_Signer(*priv_key, lazy_rng::get(), "EMSA3(SHA-1)"));
+
+ /* If persist_phrase is true, the RSA_PrivateKey object is
+ cached in s->active_keys and will survive as long as the
+@@ -977,16 +934,23 @@
+ s->signer_cache.insert(make_pair(id, signer));
+ }
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- sig = signer->sign_message(
+- reinterpret_cast<byte const *>(tosign.data()),
+- tosign.size(), lazy_rng::get());
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ {
++ std::vector<uint8_t> sig =
++ signer->sign_message(
++ reinterpret_cast<uint8_t const *>(tosign.data()),
++ tosign.size(), lazy_rng::get());
++ sig_string = string(reinterpret_cast<char const*>(sig.data()), sig.size());
++ }
+ #else
+- sig = signer->sign_message(
+- reinterpret_cast<byte const *>(tosign.data()),
+- tosign.size());
++ {
++ Botan::SecureVector<Botan::byte> sig =
++ signer->sign_message(
++ reinterpret_cast<Botan::byte const *>(tosign.data()),
++ tosign.size(), lazy_rng::get());
++ sig_string = string(reinterpret_cast<char const*>(sig.begin()), sig.size());
++ }
+ #endif
+- sig_string = string(reinterpret_cast<char const*>(sig.begin()), sig.size());
+ }
+
+ if (s->ssh_sign_mode == "check" && ssh_sig.length() > 0)
+@@ -1053,7 +1017,8 @@
+ p.write(Botan::PKCS8::PEM_encode(*priv,
+ lazy_rng::get(),
+ new_phrase(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)"));
++ std::chrono::milliseconds(300),
++ "PBE-PKCS5v20(AES-256/CBC,SHA-256)"));
+ else
+ p.write(Botan::PKCS8::PEM_encode(*priv));
+ #else
+@@ -1083,7 +1048,7 @@
+ rsa_pub_key const & pub)
+ {
+ keypair kp;
+- SecureVector<byte> arc4_key;
++ Botan::secure_vector<uint8_t> arc4_key;
+ utf8 phrase;
+ shared_ptr<PKCS8_PrivateKey> pkcs8_key;
+ shared_ptr<RSA_PrivateKey> priv_key;
+@@ -1101,37 +1066,25 @@
+ for (;;)
+ try
+ {
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+- arc4_key.resize(phrase().size());
+- arc4_key.copy(reinterpret_cast<byte const *>(phrase().data()),
+- phrase().size());
+-#else
+- arc4_key.set(reinterpret_cast<byte const *>(phrase().data()),
+- phrase().size());
+-#endif
++ arc4_key.assign(phrase().data(),
++ phrase().data() + phrase().size());
+
+- Pipe arc4_decryptor(get_cipher("ARC4", arc4_key, Botan::DECRYPTION));
++ Pipe arc4_decryptor(Botan::get_cipher("ARC4",
++ Botan::SymmetricKey(arc4_key),
++ Botan::DECRYPTION));
+
+ arc4_decryptor.process_msg(old_priv());
+
+ // This is necessary because PKCS8::load_key() cannot currently
+ // recognize an unencrypted, raw-BER blob as such, but gets it
+ // right if it's PEM-coded.
+- SecureVector<byte> arc4_decrypt(arc4_decryptor.read_all());
++ Botan::secure_vector<uint8_t> arc4_decrypt(arc4_decryptor.read_all());
+ Botan::DataSource_Memory ds(Botan::PEM_Code::encode(arc4_decrypt,
+ "PRIVATE KEY"));
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ pkcs8_key.reset(Botan::PKCS8::load_key(ds, lazy_rng::get()));
+-#else
+- pkcs8_key.reset(Botan::PKCS8::load_key(ds));
+-#endif
+ break;
+ }
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,4)
+ catch (Botan::Invalid_Argument & e)
+-#else
+- catch (Botan::Exception & e)
+-#endif
+ {
+ L(FL("migrate_old_key_pair: failure %d to load old private key: %s")
+ % cycles % e.what());
+@@ -1150,19 +1103,10 @@
+
+ // now we can write out the new key
+ unfiltered_pipe->start_msg();
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+ unfiltered_pipe->write(Botan::PKCS8::BER_encode(
+ *priv_key, lazy_rng::get(), phrase(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)"));
+-#else
+- Botan::PKCS8::encrypt_key(*priv_key, *unfiltered_pipe,
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- lazy_rng::get(),
+-#endif
+- phrase(),
+- "PBE-PKCS5v20(SHA-1,TripleDES/CBC)",
+- Botan::RAW_BER);
+-#endif
++ std::chrono::milliseconds(300),
++ "PBE-PKCS5v20(AES-256/CBC,SHA-256)"));
+ unfiltered_pipe->end_msg();
+ kp.priv = rsa_priv_key(unfiltered_pipe->read_all_as_string(Pipe::LAST_MESSAGE),
+ origin::internal);
+@@ -1171,11 +1115,7 @@
+ // Botan for the X.509 encoding of the private key implies that we want
+ // it to derive and produce the public key)
+ unfiltered_pipe->start_msg();
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
+ unfiltered_pipe->write(Botan::X509::BER_encode(*priv_key));
+-#else
+- Botan::X509::encode(*priv_key, *unfiltered_pipe, Botan::RAW_BER);
+-#endif
+ unfiltered_pipe->end_msg();
+ kp.pub = rsa_pub_key(unfiltered_pipe->read_all_as_string(Pipe::LAST_MESSAGE),
+ origin::internal);
+--- monotone-1.1/src/key_store.hh
++++ monotone-1.1/src/key_store.hh
+@@ -12,10 +12,15 @@
+
+ #include <boost/scoped_ptr.hpp>
+
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/rng.h>
++#include <botan/auto_rng.h>
++#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ #include <botan/botan.h>
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ #include <botan/rng.h>
+ #else
++#include <botan/botan.h>
+ #include <botan/libstate.h>
+ #endif
+
+--- monotone-1.1/src/lazy_rng.hh
++++ monotone-1.1/src/lazy_rng.hh
+@@ -16,7 +16,27 @@
+
+ #include <botan/version.h>
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/auto_rng.h>
++#include <botan/rng.h>
++
++class lazy_rng
++{
++ Botan::AutoSeeded_RNG rng;
++ lazy_rng() {}
++
++public:
++
++ static Botan::RandomNumberGenerator & get()
++ {
++ static lazy_rng * instance = 0;
++ if (!instance)
++ instance = new lazy_rng();
++ return instance->rng;
++ }
++};
++
++#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+ #include <botan/rng.h>
+
+ class lazy_rng
+--- monotone-1.1/src/merkle_tree.cc
++++ monotone-1.1/src/merkle_tree.cc
+@@ -12,7 +12,10 @@
+ #include <sstream>
+
+ #include <boost/dynamic_bitset.hpp>
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ #include <botan/botan.h>
++#endif
+ #include <botan/sha160.h>
+
+ #include "constants.hh"
+--- monotone-1.1/src/monotone.cc
++++ monotone-1.1/src/monotone.cc
+@@ -16,7 +16,10 @@
+ #include <stdlib.h>
+
+ #include <sqlite3.h>
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ #include <botan/botan.h>
++#endif
+
+ #include "app_state.hh"
+ #include "database.hh"
+@@ -109,9 +112,12 @@
+ global_sanity.initialize(argc, argv, localename);
+
+ // Set up secure memory allocation etc
++ // Botan 2.x does not need explicit initialization
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ Botan::LibraryInitializer acquire_botan("thread_safe=0 selftest=0 "
+ "seed_rng=1 use_engines=0 "
+ "secure_memory=1 fips140=0");
++#endif
+
+ // and caching for botan pipes
+ pipe_cache_cleanup acquire_botan_pipe_caching;
+@@ -147,6 +153,11 @@
+ #endif
+
+ // check the botan library version we got linked against.
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ // Built against Botan 2.x - runtime version check only
++ E(Botan::version_major() >= 2, origin::system,
++ F("this monotone binary requires Botan 2.0 or newer"));
++#else
+ u32 linked_botan_version = BOTAN_VERSION_CODE_FOR(
+ Botan::version_major(), Botan::version_minor(),
+ Botan::version_patch());
+@@ -162,41 +173,6 @@
+ E(linked_botan_version != BOTAN_VERSION_CODE_FOR(1,9,9), origin::system,
+ F("monotone does not support Botan 1.9.9"));
+
+-#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,7,7)
+- // motonote binary compiled against botan younger than 1.7.7
+- E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,6,3), origin::system,
+- F("this monotone binary requires Botan 1.6.3 or newer"));
+- E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,7,7), origin::system,
+- F("this monotone binary does not work with Botan 1.7.7 or newer"));
+-
+-#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,7,22)
+- // motonote binary compiled against botan 1.7.7 - 1.7.21
+- E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,7,7), origin::system,
+- F("this monotone binary requires Botan 1.7.7 or newer"));
+- // While compiling against 1.7.22 or newer is recommended, because it
+- // enables new features of Botan, the monotone binary compiled against
+- // Botan 1.7.21 and before should still work with newer Botan version,
+- // including all of the stable branch 1.8.x, up to and including
+- // 1.9.3.
+- E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
+- F("this monotone binary does not work with Botan 1.9.4 or newer"));
+-
+-#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,4)
+- // motonote binary compiled against botan 1.7.22 - 1.9.3
+- E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,7,22), origin::system,
+- F("this monotone binary requires Botan 1.7.22 or newer"));
+- E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
+- F("this monotone binary does not work with Botan 1.9.4 or newer"));
+-
+-#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,11)
+- // motonote binary compiled against botan 1.9.4 - 1.9.10
+-#pragma message ( "The resulting monotone binary won't be able to run with any stable release of botan." )
+- E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
+- F("this monotone binary requires Botan 1.9.4 or newer"));
+- E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
+- F("this monotone binary does not work with Botan 1.9.11 or newer"));
+-
+-#else
+ // motonote binary compiled against botan 1.9.11 and newer
+ E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
+ F("this monotone binary requires Botan 1.9.11 or newer"));
+--- monotone-1.1/src/packet.cc
++++ monotone-1.1/src/packet.cc
+@@ -9,8 +9,19 @@
+
+ #include "base.hh"
+ #include <sstream>
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/rsa.h>
++#include <botan/pkcs8.h>
++#include <botan/pubkey.h>
++#include <botan/x509_key.h>
++#include <botan/data_src.h>
++#include <botan/asn1_obj.h>
++#include <botan/ber_dec.h>
++#else
+ #include <botan/botan.h>
+ #include <botan/rsa.h>
++#endif
+
+ #include "cset.hh"
+ #include "constants.hh"
+@@ -115,6 +126,30 @@
+
+
+ // --- reading packets from streams ---
++// botan 2 reports "encrypted, and you gave no passphrase" as a Decoding_Error,
++// exactly like real garbage, so structure has to be checked separately: a
++// PKCS#8 EncryptedPrivateKeyInfo is AlgorithmIdentifier + OCTET STRING.
++static bool
++is_encrypted_pkcs8(string const & der)
++{
++ try
++ {
++ Botan::AlgorithmIdentifier alg;
++ std::vector<uint8_t> enc;
++ Botan::BER_Decoder(reinterpret_cast<uint8_t const *>(der.data()),
++ der.size())
++ .start_cons(Botan::SEQUENCE)
++ .decode(alg)
++ .decode(enc, Botan::OCTET_STRING)
++ .end_cons();
++ return true;
++ }
++ catch (std::exception const &)
++ {
++ return false;
++ }
++}
++
+ namespace
+ {
+ struct
+@@ -156,11 +191,17 @@
+ void validate_public_key_data(string const & name, string const & keydata) const
+ {
+ string decoded = decode_base64_as<string>(keydata, origin::user);
+- Botan::SecureVector<Botan::byte> key_block
+- (reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
+ try
+ {
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ Botan::DataSource_Memory ds(
++ reinterpret_cast<uint8_t const *>(decoded.c_str()), decoded.size());
++ Botan::X509::load_key(ds);
++#else
++ Botan::SecureVector<Botan::byte> key_block
++ (reinterpret_cast<Botan::byte const *>(decoded.c_str()), decoded.size());
+ Botan::X509::load_key(key_block);
++#endif
+ }
+ catch (Botan::Decoding_Error const & e)
+ {
+@@ -175,27 +216,17 @@
+ Botan::DataSource_Memory ds(decoded);
+ try
+ {
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+- Botan::PKCS8::load_key(ds, lazy_rng::get(), Dummy_UI());
+-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,7)
+- Botan::PKCS8::load_key(ds, lazy_rng::get(), string());
+-#else
+- Botan::PKCS8::load_key(ds, string());
+-#endif
++ Botan::PKCS8::load_key(ds, lazy_rng::get(), std::string());
+ }
+ catch (Botan::Decoding_Error const & e)
+ {
+- E(false, origin::user,
++ E(is_encrypted_pkcs8(decoded), origin::user,
+ F("malformed packet: invalid private key data for '%s': %s")
+ % name % e.what());
+ }
+ // since we do not want to prompt for a password to decode it finally,
+ // we ignore all other exceptions
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
+- catch (Passphrase_Required) {}
+-#else
+- catch (Botan::Invalid_Argument) {}
+-#endif
++ catch (Botan::Invalid_Argument const &) {}
+ }
+ void validate_certname(string const & cn) const
+ {
+@@ -466,8 +497,9 @@
+ return count;
+ }
+
+-// Dummy User_Interface implementation for Botan
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
++// Dummy User_Interface implementation for Botan 1.9.11 - 1.x
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11) && \
++ BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ std::string
+ Dummy_UI::get_passphrase(const std::string &, const std::string &,
+ Botan::User_Interface::UI_Result&) const
+--- monotone-1.1/src/packet.hh
++++ monotone-1.1/src/packet.hh
+@@ -11,8 +11,11 @@
+ #define __PACKET_HH__
+
+ #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ #include <botan/ui.h>
+ #endif
++#endif
+
+ #include "vocab.hh"
+
+@@ -88,7 +91,8 @@
+
+ size_t read_packets(std::istream & in, packet_consumer & cons);
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11)
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,11) && \
++ BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ // A helper class implementing Botan::User_Interface - which doesn't really
+ // interface with the user, but provides the necessary plumbing for Botan.
+ //
+--- monotone-1.1/src/sha1.cc
++++ monotone-1.1/src/sha1.cc
+@@ -11,9 +11,10 @@
+ // benchmark them.
+
+ #include "base.hh"
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ #include <botan/botan.h>
+ #include <botan/sha160.h>
+-
+ // Botan 1.7.23+ and 1.8.x specific sha1 benchmarking code uses botan's
+ // own timer and measures botan's different SHA1 providers, instead of
+ // only measuring one.
+@@ -21,6 +22,7 @@
+ #include <botan/libstate.h>
+ #include <botan/benchmark.h>
+ #endif
++#endif
+
+ #include "sanity.hh"
+ #include "ui.hh"
+@@ -37,7 +39,8 @@
+ {
+ P(F("Benchmarking botan's SHA-1 core"));
+
+-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,23)
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) && \
++ BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,7,23)
+
+ Botan::AutoSeeded_RNG rng;
+ Botan::Algorithm_Factory& af =
+--- monotone-1.1/src/ssh_agent.cc
++++ monotone-1.1/src/ssh_agent.cc
+@@ -11,9 +11,17 @@
+ #include <stdlib.h>
+
+ #include <boost/shared_ptr.hpp>
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/rsa.h>
++#include <botan/numthry.h>
++#include <botan/x509_key.h>
++#include <botan/data_src.h>
++#else
+ #include <botan/botan.h>
+ #include <botan/rsa.h>
+ #include <botan/numthry.h>
++#endif
+
+ #include "ssh_agent.hh"
+ #include "sanity.hh"
+@@ -37,7 +45,9 @@
+ using Botan::RSA_PublicKey;
+ using Botan::RSA_PrivateKey;
+ using Botan::BigInt;
++#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0)
+ using Botan::SecureVector;
++#endif
+ using Botan::X509_PublicKey;
+
+ struct ssh_agent_state : ssh_agent_platform
+@@ -208,11 +218,11 @@
+ L(FL("ssh_agent: put_bigint_into_buf: bigint.bytes(): %u, bigint: %s")
+ % bi.bytes()
+ % bi);
+- SecureVector<Botan::byte> bi_buf = BigInt::encode(bi);
++ std::vector<uint8_t> bi_buf = BigInt::encode(bi);
+ string bi_str;
+- if (*bi_buf.begin() & 0x80)
++ if (*bi_buf.data() & 0x80)
+ bi_str.append(1, static_cast<char>(0));
+- bi_str.append((char *) bi_buf.begin(), bi_buf.size());
++ bi_str.append(reinterpret_cast<char const *>(bi_buf.data()), bi_buf.size());
+ put_string_into_buf(bi_str, buf);
+ L(FL("ssh_agent: put_bigint_into_buf: buf len now %i") % buf.length());
+ }
+@@ -385,12 +395,19 @@
+ ssh_agent::has_key(const keypair & key)
+ {
+ //grab the monotone public key as an RSA_PublicKey
+- SecureVector<Botan::byte> pub_block
++ L(FL("has_key: building %d-byte pub key") % (key.pub)().size());
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++ Botan::DataSource_Memory ds_pub(
++ reinterpret_cast<uint8_t const *>((key.pub)().data()),
++ (key.pub)().size());
++ shared_ptr<X509_PublicKey> x509_key(Botan::X509::load_key(ds_pub));
++#else
++ Botan::SecureVector<Botan::byte> pub_block
+ (reinterpret_cast<Botan::byte const *>((key.pub)().data()),
+ (key.pub)().size());
+- L(FL("has_key: building %d-byte pub key") % pub_block.size());
+ shared_ptr<X509_PublicKey> x509_key =
+ shared_ptr<X509_PublicKey>(Botan::X509::load_key(pub_block));
++#endif
+ shared_ptr<RSA_PublicKey> pub_key =
+ dynamic_pointer_cast<RSA_PublicKey>(x509_key);
+
+--- monotone-1.1/src/transforms.cc
++++ monotone-1.1/src/transforms.cc
+@@ -9,8 +9,14 @@
+
+ #include "base.hh"
+ #include <iterator>
++#include <botan/version.h>
++#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
++#include <botan/pipe.h>
++#include <botan/filters.h>
++#else
+ #include <botan/botan.h>
+ #include <botan/sha160.h>
++#endif
+
+ #include "botan_pipe_cache.hh"
+ #include "gzip.hh"
diff --git a/monotone-pcre.patch b/monotone-pcre.patch
new file mode 100644
index 0000000..d0b463c
--- /dev/null
+++ b/monotone-pcre.patch
@@ -0,0 +1,40 @@
+--- monotone-1.1/src/pcrewrap.cc
++++ monotone-1.1/src/pcrewrap.cc
+@@ -74,7 +74,7 @@
+ namespace pcre
+ {
+ typedef map<char const *,
+- pair<struct real_pcre const *, struct pcre_extra const *> >
++ pair<struct real_pcre8_or_16 const *, struct pcre_extra const *> >
+ regex_cache;
+
+ class regex_cache_manager
+@@ -86,7 +86,7 @@
+ }
+
+ void store(char const * pattern,
+- pair<struct real_pcre const *, struct pcre_extra const *>
++ pair<struct real_pcre8_or_16 const *, struct pcre_extra const *>
+ data)
+ {
+ cache[pattern] = data;
+--- monotone-1.1/src/pcrewrap.hh
++++ monotone-1.1/src/pcrewrap.hh
+@@ -18,7 +18,7 @@
+ // definitions and so we don't actually expose it here. Unfortunately, this
+ // means we have to hope this pair of forward declarations will not change...
+
+-struct real_pcre;
++struct real_pcre8_or_16;
+ struct pcre_extra;
+
+ namespace pcre
+@@ -61,7 +61,7 @@
+ regex & operator=(regex const &);
+
+ // data
+- struct real_pcre const * basedat;
++ struct real_pcre8_or_16 const * basedat;
+ struct pcre_extra const * extradat;
+
+ // used by constructors
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/monotone.git/commitdiff/3f40c16f2c311e07c034bb0b427ef38719282a9d
More information about the pld-cvs-commit
mailing list