Hello community,

here is the log from the commit of package libfilezilla for openSUSE:Factory 
checked in at 2016-10-18 10:42:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libfilezilla (Old)
 and      /work/SRC/openSUSE:Factory/.libfilezilla.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libfilezilla"

Changes:
--------
--- /work/SRC/openSUSE:Factory/libfilezilla/libfilezilla.changes        
2016-08-05 18:18:15.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.libfilezilla.new/libfilezilla.changes   
2016-10-18 10:42:54.000000000 +0200
@@ -1,0 +2,11 @@
+Sun Oct  2 12:08:54 UTC 2016 - ec...@opensuse.org
+
+- update to 0.7.0
+  * New features:
+    - Add fz::base64_decode and fz::base64_encode
+    - Add fz::strtok string tokenizer
+    - Added non-throwing fz::to_integral
+    - Implemented + (always sign) and - (left align) flags for 
+      fz::sprintf
+
+-------------------------------------------------------------------

Old:
----
  libfilezilla-0.6.1.tar.bz2

New:
----
  libfilezilla-0.7.0.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libfilezilla.spec ++++++
--- /var/tmp/diff_new_pack.DD506c/_old  2016-10-18 10:42:55.000000000 +0200
+++ /var/tmp/diff_new_pack.DD506c/_new  2016-10-18 10:42:55.000000000 +0200
@@ -20,7 +20,7 @@
 %define libname                %{name}%{major}
 %define develname      %{name}-devel
 Name:           libfilezilla
-Version:        0.6.1
+Version:        0.7.0
 Release:        0
 Summary:        C++ library for filezilla
 License:        GPL-2.0+

++++++ libfilezilla-0.6.1.tar.bz2 -> libfilezilla-0.7.0.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/NEWS new/libfilezilla-0.7.0/NEWS
--- old/libfilezilla-0.6.1/NEWS 2016-07-27 14:07:50.000000000 +0200
+++ new/libfilezilla-0.7.0/NEWS 2016-09-24 15:17:31.000000000 +0200
@@ -1,3 +1,10 @@
+0.7.0 (2016-09-24)
+
++ Add fz::base64_decode and fz::base64_encode
++ Add fz::strtok string tokenizer
++ Added non-throwing fz::to_integral
++ Implemented + (always sign) and - (left align) flags for fz::sprintf
+
 0.6.1 (2016-07-27)
 
 - Fix UTF-8 conversion functions and added a testcase
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/configure 
new/libfilezilla-0.7.0/configure
--- old/libfilezilla-0.6.1/configure    2016-07-27 14:08:39.000000000 +0200
+++ new/libfilezilla-0.7.0/configure    2016-09-24 15:18:35.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libfilezilla 0.6.1.
+# Generated by GNU Autoconf 2.69 for libfilezilla 0.7.0.
 #
 # Report bugs to <tim.ko...@filezilla-project.org>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='libfilezilla'
 PACKAGE_TARNAME='libfilezilla'
-PACKAGE_VERSION='0.6.1'
-PACKAGE_STRING='libfilezilla 0.6.1'
+PACKAGE_VERSION='0.7.0'
+PACKAGE_STRING='libfilezilla 0.7.0'
 PACKAGE_BUGREPORT='tim.ko...@filezilla-project.org'
 PACKAGE_URL='https://lib.filezilla-project.org/'
 
@@ -1396,7 +1396,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libfilezilla 0.6.1 to adapt to many kinds of systems.
+\`configure' configures libfilezilla 0.7.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1466,7 +1466,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libfilezilla 0.6.1:";;
+     short | recursive ) echo "Configuration of libfilezilla 0.7.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1591,7 +1591,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libfilezilla configure 0.6.1
+libfilezilla configure 0.7.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2036,7 +2036,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libfilezilla $as_me 0.6.1, which was
+It was created by libfilezilla $as_me 0.7.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2902,7 +2902,7 @@
 
 # Define the identity of the package.
  PACKAGE='libfilezilla'
- VERSION='0.6.1'
+ VERSION='0.7.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -19665,7 +19665,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libfilezilla $as_me 0.6.1, which was
+This file was extended by libfilezilla $as_me 0.7.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -19732,7 +19732,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-libfilezilla config.status 0.6.1
+libfilezilla config.status 0.7.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/configure.ac 
new/libfilezilla-0.7.0/configure.ac
--- old/libfilezilla-0.6.1/configure.ac 2016-07-27 14:04:28.000000000 +0200
+++ new/libfilezilla-0.7.0/configure.ac 2016-09-24 15:14:28.000000000 +0200
@@ -1,4 +1,4 @@
-AC_INIT([libfilezilla],[0.6.1],[tim.ko...@filezilla-project.org],[],[https://lib.filezilla-project.org/])
+AC_INIT([libfilezilla],[0.7.0],[tim.ko...@filezilla-project.org],[],[https://lib.filezilla-project.org/])
 AC_CONFIG_HEADERS([lib/libfilezilla/private/config.hpp])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR(config)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/Makefile.am 
new/libfilezilla-0.7.0/lib/Makefile.am
--- old/libfilezilla-0.6.1/lib/Makefile.am      2016-07-05 09:30:27.000000000 
+0200
+++ new/libfilezilla-0.7.0/lib/Makefile.am      2016-09-24 15:14:12.000000000 
+0200
@@ -12,6 +12,7 @@
        recursive_remove.cpp \
        string.cpp \
        thread.cpp \
+       thread_pool.cpp \
        time.cpp \
        util.cpp \
        version.cpp
@@ -33,6 +34,7 @@
        libfilezilla/shared.hpp \
        libfilezilla/string.hpp \
        libfilezilla/thread.hpp \
+       libfilezilla/thread_pool.hpp \
        libfilezilla/time.hpp \
        libfilezilla/util.hpp \
        libfilezilla/version.hpp \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/Makefile.in 
new/libfilezilla-0.7.0/lib/Makefile.in
--- old/libfilezilla-0.6.1/lib/Makefile.in      2016-07-27 14:08:39.000000000 
+0200
+++ new/libfilezilla-0.7.0/lib/Makefile.in      2016-09-24 15:18:35.000000000 
+0200
@@ -141,8 +141,8 @@
        libfilezilla_la-local_filesys.lo libfilezilla_la-mutex.lo \
        libfilezilla_la-process.lo libfilezilla_la-recursive_remove.lo \
        libfilezilla_la-string.lo libfilezilla_la-thread.lo \
-       libfilezilla_la-time.lo libfilezilla_la-util.lo \
-       libfilezilla_la-version.lo
+       libfilezilla_la-thread_pool.lo libfilezilla_la-time.lo \
+       libfilezilla_la-util.lo libfilezilla_la-version.lo
 libfilezilla_la_OBJECTS = $(am_libfilezilla_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -383,6 +383,7 @@
        recursive_remove.cpp \
        string.cpp \
        thread.cpp \
+       thread_pool.cpp \
        time.cpp \
        util.cpp \
        version.cpp
@@ -404,6 +405,7 @@
        libfilezilla/shared.hpp \
        libfilezilla/string.hpp \
        libfilezilla/thread.hpp \
+       libfilezilla/thread_pool.hpp \
        libfilezilla/time.hpp \
        libfilezilla/util.hpp \
        libfilezilla/version.hpp \
@@ -515,6 +517,7 @@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-recursive_remove.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-string.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-thread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-thread_pool.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-time.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-util.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@./$(DEPDIR)/libfilezilla_la-version.Plo@am__quote@
@@ -617,6 +620,13 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX 
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) 
$(DEFAULT_INCLUDES) $(INCLUDES) $(libfilezilla_la_CPPFLAGS) $(CPPFLAGS) 
$(libfilezilla_la_CXXFLAGS) $(CXXFLAGS) -c -o libfilezilla_la-thread.lo `test 
-f 'thread.cpp' || echo '$(srcdir)/'`thread.cpp
 
+libfilezilla_la-thread_pool.lo: thread_pool.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX 
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) 
$(DEFAULT_INCLUDES) $(INCLUDES) $(libfilezilla_la_CPPFLAGS) $(CPPFLAGS) 
$(libfilezilla_la_CXXFLAGS) $(CXXFLAGS) -MT libfilezilla_la-thread_pool.lo -MD 
-MP -MF $(DEPDIR)/libfilezilla_la-thread_pool.Tpo -c -o 
libfilezilla_la-thread_pool.lo `test -f 'thread_pool.cpp' || echo 
'$(srcdir)/'`thread_pool.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) 
$(DEPDIR)/libfilezilla_la-thread_pool.Tpo 
$(DEPDIR)/libfilezilla_la-thread_pool.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='thread_pool.cpp' 
object='libfilezilla_la-thread_pool.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX 
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) 
$(DEFAULT_INCLUDES) $(INCLUDES) $(libfilezilla_la_CPPFLAGS) $(CPPFLAGS) 
$(libfilezilla_la_CXXFLAGS) $(CXXFLAGS) -c -o libfilezilla_la-thread_pool.lo 
`test -f 'thread_pool.cpp' || echo '$(srcdir)/'`thread_pool.cpp
+
 libfilezilla_la-time.lo: time.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX 
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) 
$(DEFAULT_INCLUDES) $(INCLUDES) $(libfilezilla_la_CPPFLAGS) $(CPPFLAGS) 
$(libfilezilla_la_CXXFLAGS) $(CXXFLAGS) -MT libfilezilla_la-time.lo -MD -MP -MF 
$(DEPDIR)/libfilezilla_la-time.Tpo -c -o libfilezilla_la-time.lo `test -f 
'time.cpp' || echo '$(srcdir)/'`time.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) $(DEPDIR)/libfilezilla_la-time.Tpo 
$(DEPDIR)/libfilezilla_la-time.Plo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/libfilezilla/format.hpp 
new/libfilezilla-0.7.0/lib/libfilezilla/format.hpp
--- old/libfilezilla-0.6.1/lib/libfilezilla/format.hpp  2016-07-20 
10:41:59.000000000 +0200
+++ new/libfilezilla-0.7.0/lib/libfilezilla/format.hpp  2016-09-24 
15:14:12.000000000 +0200
@@ -20,7 +20,9 @@
 enum : char {
        pad_0 = 1,
        pad_blank = 2,
-       with_width = 4
+       with_width = 4,
+       left_align = 8,
+       always_sign = 16
 };
 
 // Converts integral type to desired string type...
@@ -37,11 +39,13 @@
        if (std::is_signed<std::decay_t<Arg>>::value && !(arg >= 0)) {
                lead = '-';
        }
+       else if (std::is_signed<std::decay_t<Arg>>::value && flags & 
always_sign) {
+               lead = '+';
+       }
        else if (flags & pad_blank && arg >= 0) {
                lead = ' ';
        }
 
-
        // max decimal digits in b-bit integer is floor((b-1) * log_10(2)) + 1 
< b * 0.5 + 1
        typename String::value_type buf[sizeof(v) * 4 + 1];
        auto *const end = buf + sizeof(v) * 4 + 1;
@@ -67,17 +71,21 @@
                        if (end - p < width) {
                                ret.append(width - (end - p), '0');
                        }
+                       ret.append(p, end);
                }
                else {
-                       if (end - p < width) {
+                       if (end - p < width && !(flags & left_align)) {
                                ret.append(width - (end - p), ' ');
                        }
                        if (lead) {
                                ret += lead;
                        }
+                       ret.append(p, end);
+                       if (end - p < width && flags & left_align) {
+                               ret.append(width - (end - p), ' ');
+                       }
                }
 
-               ret.append(p, end);
                return ret;
        }
        else {
@@ -164,7 +172,7 @@
 
 
 template<typename String, typename Arg>
-typename std::enable_if_t<!std::is_pointer<std::decay_t<Arg>>::value, String> 
pointer_to_string(Arg&& arg)
+typename std::enable_if_t<!std::is_pointer<std::decay_t<Arg>>::value, String> 
pointer_to_string(Arg&&)
 {
        assert(0);
        return String();
@@ -177,6 +185,19 @@
        return String();
 }
 
+template<typename String>
+void pad_arg(String& s, char flags, size_t width)
+{
+       if (flags & with_width && s.size() < width) {
+               if (flags & left_align) {
+                       s += String(width - s.size(), ' ');
+               }
+               else {
+                       s = String(width - s.size(), ' ') + s;
+               }
+       }
+}
+
 template<typename String, typename Arg, typename... Args>
 String extract_arg(char flags, size_t width, typename String::value_type type, 
size_t arg_n, Arg&& arg, Args&&...args)
 {
@@ -185,9 +206,7 @@
        if (!arg_n) {
                if (type == 's') {
                        ret = arg_to_string<String>(std::forward<Arg>(arg));
-                       if (flags & with_width && ret.size() < width) {
-                               ret = String(width - ret.size(), ' ') + ret;
-                       }
+                       pad_arg(ret, flags, width);
                }
                else if (type == 'd' || type == 'i') {
                        ret = integral_to_string<String, false>(flags, width, 
std::forward<Arg>(arg));
@@ -197,21 +216,15 @@
                }
                else if (type == 'x') {
                        ret = integral_to_hex_string<String, 
true>(std::forward<Arg>(arg));
-                       if (flags & with_width && ret.size() < width) {
-                               ret = String(width - ret.size(), ' ') + ret;
-                       }
+                       pad_arg(ret, flags, width);
                }
                else if (type == 'X') {
                        ret = integral_to_hex_string<String, 
false>(std::forward<Arg>(arg));
-                       if (flags & with_width && ret.size() < width) {
-                               ret = String(width - ret.size(), ' ') + ret;
-                       }
+                       pad_arg(ret, flags, width);
                }
                else if (type == 'p') {
                        ret = pointer_to_string<String>(std::forward<Arg>(arg));
-                       if (flags & with_width && ret.size() < width) {
-                               ret = String(width - ret.size(), ' ') + ret;
-                       }
+                       pad_arg(ret, flags, width);
                }
                else {
                        assert(0);
@@ -245,6 +258,14 @@
                else if (fmt[pos] == ' ') {
                        flags |= pad_blank;
                }
+               else if (fmt[pos] == '-') {
+                       flags &= ~pad_0;
+                       flags |= left_align;
+               }
+               else if (fmt[pos] == '+') {
+                       flags &= ~pad_blank;
+                       flags |= always_sign;
+               }
                else {
                        break;
                }
@@ -303,7 +324,7 @@
 * Only partially implements the format specifiers for the printf family of C 
functions:
 *
 * \li Positional arguments
-* \li Supported flags: 0, ' '
+* \li Supported flags: 0, ' ', -, +
 * \li Field widths are supported as decimal integers not exceeding 10k, longer 
widths are truncated
 * \li precision is ignored
 * \li Supported types: d, i, u, s, x, X, p
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/libfilezilla/string.hpp 
new/libfilezilla-0.7.0/lib/libfilezilla/string.hpp
--- old/libfilezilla-0.6.1/lib/libfilezilla/string.hpp  2016-07-20 
10:41:55.000000000 +0200
+++ new/libfilezilla-0.7.0/lib/libfilezilla/string.hpp  2016-09-24 
15:14:12.000000000 +0200
@@ -4,6 +4,7 @@
 #include "libfilezilla.hpp"
 
 #include <string>
+#include <vector>
 
 /** \file
  * \brief String types and assorted functions.
@@ -200,11 +201,15 @@
 /// Calls either fz::to_string or fz::to_wstring depending on the passed 
template argument
 template<typename String, typename Arg>
 inline auto toString(Arg&& arg) -> typename 
std::enable_if<std::is_same<String, std::string>::value, 
decltype(to_string(std::forward<Arg>(arg)))>::type
-{ return to_string(std::forward<Arg>(arg)); }
+{
+       return to_string(std::forward<Arg>(arg));
+}
 
 template<typename String, typename Arg>
 inline auto toString(Arg&& arg) -> typename 
std::enable_if<std::is_same<String, std::wstring>::value, 
decltype(to_wstring(std::forward<Arg>(arg)))>::type
-{ return to_wstring(std::forward<Arg>(arg)); }
+{
+       return to_wstring(std::forward<Arg>(arg));
+}
 
 #if !defined(fzT) || defined(DOXYGEN)
 #ifdef FZ_WINDOWS
@@ -222,7 +227,7 @@
 #endif
 #endif
 
-/// Returns the function argument of the type matching the template argument. 
\sa fzS
+ /// Returns the function argument of the type matching the template argument. 
\sa fzS
 template<typename Char>
 Char const* choose_string(char const* c, wchar_t const* w);
 
@@ -241,17 +246,78 @@
  *   }
  * \endcode
  */
-#define fzS(Char, s) choose_string<Char>(s, L ## s)
+#define fzS(Char, s) fz::choose_string<Char>(s, L ## s)
 #endif
 
-/// Returns \c in with all occurrences of \c find in the input string replaced 
with \c replacement
-std::string FZ_PUBLIC_SYMBOL replace_substrings(std::string const& in, 
std::string const& find, std::string const& replacement);
-std::wstring FZ_PUBLIC_SYMBOL replace_substrings(std::wstring const& in, 
std::wstring const& find, std::wstring const& replacement);
+ /// Returns \c in with all occurrences of \c find in the input string 
replaced with \c replacement
+std::string FZ_PUBLIC_SYMBOL replaced_substrings(std::string const& in, 
std::string const& find, std::string const& replacement);
+std::wstring FZ_PUBLIC_SYMBOL replaced_substrings(std::wstring const& in, 
std::wstring const& find, std::wstring const& replacement);
 
 /// Modifies \c in, replacing all occurrences of \c find with \c replacement
 void FZ_PUBLIC_SYMBOL replace_substrings(std::string& in, std::string const& 
find, std::string const& replacement);
 void FZ_PUBLIC_SYMBOL replace_substrings(std::wstring& in, std::wstring const& 
find, std::wstring const& replacement);
 
+/// Tokenizes string. Returns all non-empty substrings
+template<typename String, typename Delim, typename Container = 
std::vector<String>>
+Container strtok(String const& s, Delim const& delims)
+{
+       Container ret;
+
+       typename String::size_type start{}, pos{};
+       do {
+               pos = s.find_first_of(delims, start);
+
+               // Not found, we're at ends;
+               if (pos == String::npos) {
+                       if (start + 1 < s.size()) {
+                               ret.emplace_back(s.substr(start));
+                       }
+               }
+               else if (pos > start + 1) {
+                       // Non-empty substring
+                       ret.emplace_back(s.substr(start, pos - start));
+               }
+               start = pos + 1;
+       } while (pos != String::npos);
+
+       return ret;
+}
+
+
+/// \brief Encodes raw input string to base64
+std::string FZ_PUBLIC_SYMBOL base64_encode(std::string const& in);
+
+/// \brief Decodes base64, ignores whitespace. Returns empty string on invalid 
input.
+std::string FZ_PUBLIC_SYMBOL base64_decode(std::string const& in);
+
+// Converts string to integral type T. If string is not convertible, T() is 
returned.
+template<typename T, typename String>
+T to_integral(String const& s)
+{
+       T ret{};
+
+       auto it = s.cbegin();
+       if (it != s.cend() && (*it == '-' || *it == '+')) {
+               ++it;
+       }
+
+       for (; it != s.cend(); ++it) {
+               auto const& c = *it;
+               if (c < '0' || c > '9') {
+                       return T();
+               }
+               ret *= 10;
+               ret += c - '0';
+       }
+
+       if (!s.empty() && s.front() == '-') {
+               return ret *= static_cast<T>(-1);
+       }
+       else {
+               return ret;
+       }
+}
+
 }
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/libfilezilla/thread_pool.hpp 
new/libfilezilla-0.7.0/lib/libfilezilla/thread_pool.hpp
--- old/libfilezilla-0.6.1/lib/libfilezilla/thread_pool.hpp     1970-01-01 
01:00:00.000000000 +0100
+++ new/libfilezilla-0.7.0/lib/libfilezilla/thread_pool.hpp     2016-09-24 
15:14:12.000000000 +0200
@@ -0,0 +1,77 @@
+#ifndef LIBFILEZILLA_THREAD_POOL_HEADER
+#define LIBFILEZILLA_THREAD_POOL_HEADER
+
+#include "libfilezilla.hpp"
+#include "mutex.hpp"
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+/** \file
+ * \brief Declares \ref fz::thread_pool "thread_pool" and \ref fz::async_task 
"async_task"
+ */
+
+namespace fz {
+
+class thread_pool;
+class pooled_thread_impl;
+
+/** \brief Handle for asynchronous tasks
+ */
+class FZ_PUBLIC_SYMBOL async_task final {
+public:
+       async_task() = default;
+       ~async_task();
+
+       async_task(async_task const&) = delete;
+       async_task& operator=(async_task const&) = delete;
+
+       async_task(async_task && other) noexcept;
+       async_task& operator=(async_task && other) noexcept;
+
+       /// Wait for the task to finish
+       void join();
+
+       /// Check whether it's a spawned, unjoined task.
+       explicit operator bool() const { return impl_ != 0; }
+
+private:
+       friend class thread_pool;
+       friend class pooled_thread_impl;
+
+       pooled_thread_impl* impl_{};
+};
+
+/** \brief A dumb thread-pool for asynchronous tasks
+ *
+ * If there are no idle threads, threads are created on-demand if spawning an 
asynchronous task.
+ * Once an asynchronous task finishes, the corresponding thread is kept idle 
until the pool is
+ * destroyed.
+ *
+ * Any number of tasks can be run concurrently.
+ */
+class FZ_PUBLIC_SYMBOL thread_pool final
+{
+public:
+       thread_pool();
+       ~thread_pool();
+
+       thread_pool(thread_pool const&) = delete;
+       thread_pool& operator=(thread_pool const&) = delete;
+
+       /// Spawns a new asynchronous task.
+       async_task spawn(std::function<void()> const& f);
+
+private:
+       friend class async_task;
+       friend class pooled_thread_impl;
+
+       std::vector<pooled_thread_impl*> threads_;
+       std::vector<pooled_thread_impl*> idle_;
+       mutex m_{false};
+};
+
+}
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/libfilezilla/version.hpp 
new/libfilezilla-0.7.0/lib/libfilezilla/version.hpp
--- old/libfilezilla-0.6.1/lib/libfilezilla/version.hpp 2016-07-27 
14:08:41.000000000 +0200
+++ new/libfilezilla-0.7.0/lib/libfilezilla/version.hpp 2016-09-24 
15:18:37.000000000 +0200
@@ -9,15 +9,15 @@
 
 #include <tuple>
 /// \brief Version string of the libfilezilla headers
-#define LIBFILEZILLA_VERSION "0.6.1"
+#define LIBFILEZILLA_VERSION "0.7.0"
 
 #define LIBFILEZILLA_VERSION_MAJOR  0
-#define LIBFILEZILLA_VERSION_MINOR  6
-#define LIBFILEZILLA_VERSION_MICRO  1
+#define LIBFILEZILLA_VERSION_MINOR  7
+#define LIBFILEZILLA_VERSION_MICRO  0
 #define LIBFILEZILLA_VERSION_NANO   0
 
 /// \brief Suffix string, e.g. "rc1"
-#define LIBFILEZILLA_VERSION_SUFFIX "0.6.1"
+#define LIBFILEZILLA_VERSION_SUFFIX "0.7.0"
 
 namespace fz {
 /// \brief Get version string of libfilezilla
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/libfilezilla.vcxproj 
new/libfilezilla-0.7.0/lib/libfilezilla.vcxproj
--- old/libfilezilla-0.6.1/lib/libfilezilla.vcxproj     2016-07-05 
09:30:27.000000000 +0200
+++ new/libfilezilla-0.7.0/lib/libfilezilla.vcxproj     2016-09-24 
15:14:12.000000000 +0200
@@ -196,6 +196,7 @@
     <ClCompile Include="recursive_remove.cpp" />
     <ClCompile Include="string.cpp" />
     <ClCompile Include="thread.cpp" />
+    <ClCompile Include="thread_pool.cpp" />
     <ClCompile Include="time.cpp" />
     <ClCompile Include="util.cpp" />
     <ClCompile Include="version.cpp" />
@@ -220,6 +221,7 @@
     <ClInclude Include="libfilezilla\shared.hpp" />
     <ClInclude Include="libfilezilla\string.hpp" />
     <ClInclude Include="libfilezilla\thread.hpp" />
+    <ClInclude Include="libfilezilla\thread_pool.hpp" />
     <ClInclude Include="libfilezilla\time.hpp" />
     <ClInclude Include="libfilezilla\util.hpp" />
     <ClInclude Include="libfilezilla\version.hpp" />
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/string.cpp 
new/libfilezilla-0.7.0/lib/string.cpp
--- old/libfilezilla-0.6.1/lib/string.cpp       2016-07-27 14:03:01.000000000 
+0200
+++ new/libfilezilla-0.7.0/lib/string.cpp       2016-09-24 15:14:12.000000000 
+0200
@@ -100,7 +100,7 @@
 // On some platforms, e.g. those derived from SunOS, iconv does not understand 
"WCHAR_T", so we
 // need to guess an encoding.
 // On other platforms, WCHAR_T results in iconv() doing endless loops, such as 
OS X.
-char const* const calc_wchar_t_encoding()
+char const* calc_wchar_t_encoding()
 {
        auto try_encoding = [](char const* const encoding) -> bool {
                iconv_t cd = iconv_open(encoding, "UTF-8");
@@ -263,14 +263,14 @@
 }
 }
 
-std::string replace_substrings(std::string const& in, std::string const& find, 
std::string const& replacement)
+std::string replaced_substrings(std::string const& in, std::string const& 
find, std::string const& replacement)
 {
        std::string ret = in;
        do_replace_substrings(ret, find, replacement);
        return ret;
 }
 
-std::wstring replace_substrings(std::wstring const& in, std::wstring const& 
find, std::wstring const& replacement)
+std::wstring replaced_substrings(std::wstring const& in, std::wstring const& 
find, std::wstring const& replacement)
 {
        std::wstring ret = in;
        do_replace_substrings(ret, find, replacement);
@@ -287,4 +287,126 @@
        do_replace_substrings(in, find, replacement);
 }
 
+std::string base64_encode(std::string const& in)
+{
+       std::string::value_type const base64_chars[] = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+       std::string ret;
+
+       size_t len = in.size();
+       size_t pos{};
+
+       ret.reserve(((len + 2) / 3) * 4);
+
+       while (len >= 3) {
+               len -= 3;
+               auto const c1 = static_cast<unsigned char>(in[pos++]);
+               auto const c2 = static_cast<unsigned char>(in[pos++]);
+               auto const c3 = static_cast<unsigned char>(in[pos++]);
+
+               ret += base64_chars[(c1 >> 2) & 0x3fu];
+               ret += base64_chars[((c1 & 0x3u) << 4) | ((c2 >> 4) & 0xfu)];
+               ret += base64_chars[((c2 & 0xfu) << 2) | ((c3 >> 6) & 0x3u)];
+               ret += base64_chars[(c3 & 0x3fu)];
+       }
+       if (len) {
+               auto const c1 = static_cast<unsigned char>(in[pos++]);
+               ret += base64_chars[(c1 >> 2) & 0x3fu];
+               if (len == 2) {
+                       auto const c2 = static_cast<unsigned char>(in[pos++]);
+                       ret += base64_chars[((c1 & 0x3u) << 4) | ((c2 >> 4) & 
0xfu)];
+                       ret += base64_chars[(c2 & 0xfu) << 2];
+               }
+               else {
+                       ret += base64_chars[(c1 & 0x3u) << 4];
+                       ret += '=';
+               }
+               ret += '=';
+       }
+
+       return ret;
+}
+
+std::string base64_decode(std::string const& in)
+{
+       unsigned char const chars[256] =
+       {
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 
0x80, 0xff, 0x80, 0x80, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+               0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 
0xff, 0xff, 0xff, 0x40, 0xff, 0xff,
+               0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+               0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 
0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 
0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+               0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 
0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+       };
+
+       std::string ret;
+       ret.reserve((in.size() / 4) * 3);
+
+       size_t pos{};
+       size_t len = in.size();
+
+       // Trim trailing whitespace
+       while (len && chars[static_cast<unsigned char>(in[len - 1])] == 0x80) {
+               --len;
+       }
+
+       auto next = [&]() {
+               while (pos < len) {
+                       auto c = chars[static_cast<unsigned char>(in[pos++])];
+                       if (c != 0x80u) {
+                               return c;
+                       }
+               }
+               return static_cast<unsigned char>(0xffu);
+       };
+
+       while (pos < len) {
+               auto c1 = next();
+               auto c2 = next();
+               auto c3 = next();
+               auto c4 = next();
+
+               if (c1 == 0xff || c2 == 0xff || c3 == 0xff || c4 == 0xff || c1 
== 0x40 || c2 == 0x40) {
+                       // Bad input
+                       return std::string();
+               }
+
+               if (c4 == 0x40) {
+                       // Pad
+                       if (pos < len) {
+                               // Not at end of string
+                               return std::string();
+                       }
+                       ret += (c1 << 2) | ((c2 >> 4) & 0x3);
+
+                       if (c3 != 0x40) {
+                               ret += ((c2 & 0xf) << 4) | ((c3 >> 2) & 0xf);
+                       }
+               }
+               else {
+                       if (c3 == 0x40) {
+                               // Bad input
+                               return std::string();
+                       }
+
+                       ret += (c1 << 2) | ((c2 >> 4) & 0x3);
+                       ret += ((c2 & 0xf) << 4) | ((c3 >> 2) & 0xf);
+                       ret += ((c3 & 0x3) << 6) | c4;
+               }
+       }
+
+       return ret;
+}
+
+
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/lib/thread_pool.cpp 
new/libfilezilla-0.7.0/lib/thread_pool.cpp
--- old/libfilezilla-0.6.1/lib/thread_pool.cpp  1970-01-01 01:00:00.000000000 
+0100
+++ new/libfilezilla-0.7.0/lib/thread_pool.cpp  2016-09-24 15:14:12.000000000 
+0200
@@ -0,0 +1,129 @@
+#include "libfilezilla/thread_pool.hpp"
+#include "libfilezilla/thread.hpp"
+
+#include <assert.h>
+
+namespace fz {
+
+class pooled_thread_impl final : public thread
+{
+public:
+       pooled_thread_impl(thread_pool & pool)
+               : m_(pool.m_)
+               , pool_(pool)
+       {}
+
+       virtual ~pooled_thread_impl()
+       {
+               join();
+       }
+
+       virtual void entry() {
+               scoped_lock l(m_);
+               while (!quit_) {
+                       thread_cond_.wait(l);
+
+                       if (f_) {
+                               l.unlock();
+                               f_();
+                               l.lock();
+                               task_cond_.signal(l);
+                       }
+               }
+       }
+
+       void quit(scoped_lock & l)
+       {
+               quit_ = true;
+               thread_cond_.signal(l);
+       }
+
+       std::function<void()> f_{};
+       mutex & m_;
+       condition thread_cond_;
+       condition task_cond_;
+       thread_pool& pool_;
+
+private:
+       bool quit_{};
+};
+
+
+async_task::async_task(async_task && other) noexcept
+{
+       std::swap(impl_, other.impl_);
+}
+
+async_task& async_task::operator=(async_task && other) noexcept
+{
+       std::swap(impl_, other.impl_);
+       return *this;
+}
+
+async_task::~async_task()
+{
+       join();
+}
+
+
+void async_task::join()
+{
+       if (impl_) {
+               scoped_lock l(impl_->m_);
+               impl_->task_cond_.wait(l);
+               impl_->f_ = std::function<void()>();
+               impl_->pool_.idle_.push_back(impl_);
+               impl_ = 0;
+       }
+}
+
+
+
+thread_pool::thread_pool()
+{
+}
+
+thread_pool::~thread_pool()
+{
+       std::vector<pooled_thread_impl*> threads;
+       {
+               scoped_lock l(m_);
+               for (auto thread : threads_) {
+                       thread->quit(l);
+               }
+               threads.swap(threads_);
+       }
+
+       for (auto thread : threads) {
+               delete thread;
+       }
+}
+
+async_task thread_pool::spawn(std::function<void()> const& f)
+{
+       async_task ret;
+
+       scoped_lock l(m_);
+
+       pooled_thread_impl *t{};
+       if (idle_.empty()) {
+               t = new pooled_thread_impl(*this);
+               if (!t->run()) {
+                       delete t;
+                       return ret;
+               }
+               threads_.push_back(t);
+       }
+       else {
+               t = idle_.back();
+               idle_.pop_back();
+       }
+
+       ret.impl_ = t;
+       t->f_ = f;
+       t->thread_cond_.signal(l);
+
+       return ret;
+}
+
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/libfilezilla.sln 
new/libfilezilla-0.7.0/libfilezilla.sln
--- old/libfilezilla-0.6.1/libfilezilla.sln     2015-11-19 14:27:40.000000000 
+0100
+++ new/libfilezilla-0.7.0/libfilezilla.sln     2016-09-24 15:18:31.000000000 
+0200
@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.25420.1
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo_events", 
"demos\demo_events.vcxproj", "{59E51CBA-EA1F-448F-9DF5-955EECAB8ACD}"
        ProjectSection(ProjectDependencies) = postProject
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/tests/format.cpp 
new/libfilezilla-0.7.0/tests/format.cpp
--- old/libfilezilla-0.6.1/tests/format.cpp     2016-07-20 10:41:55.000000000 
+0200
+++ new/libfilezilla-0.7.0/tests/format.cpp     2016-09-24 15:14:12.000000000 
+0200
@@ -99,4 +99,18 @@
        CPPUNIT_ASSERT_EQUAL(std::string("23bf0a"), fz::sprintf("%04x", 
2342666));
        CPPUNIT_ASSERT_EQUAL(std::string("23bf0a"), fz::sprintf("% 4x", 
2342666));
        CPPUNIT_ASSERT_EQUAL(std::string("23bf0a"), fz::sprintf("% 04x", 
2342666));
+
+       CPPUNIT_ASSERT_EQUAL(std::string("77     "), fz::sprintf("%-7d", 77));
+       CPPUNIT_ASSERT_EQUAL(std::string("-77    "), fz::sprintf("%-7d", -77));
+       CPPUNIT_ASSERT_EQUAL(std::string(" 77    "), fz::sprintf("% -7d", 77));
+       CPPUNIT_ASSERT_EQUAL(std::string("-77    "), fz::sprintf("% -7d", -77));
+       CPPUNIT_ASSERT_EQUAL(std::string(" 77    "), fz::sprintf("%- 7d", 77));
+       CPPUNIT_ASSERT_EQUAL(std::string("-77    "), fz::sprintf("%- 7d", -77));
+       CPPUNIT_ASSERT_EQUAL(std::string("ok     "), fz::sprintf("%- 7s", 
"ok"));
+       CPPUNIT_ASSERT_EQUAL(std::string("hello"), fz::sprintf("%-3s", 
"hello"));
+
+       CPPUNIT_ASSERT_EQUAL(std::string("    +77"), fz::sprintf("%+7d", 77));
+       CPPUNIT_ASSERT_EQUAL(std::string("    -77"), fz::sprintf("%+7d", -77));
+       CPPUNIT_ASSERT_EQUAL(std::string("+77    "), fz::sprintf("%+-7d", 77));
+       CPPUNIT_ASSERT_EQUAL(std::string("-77    "), fz::sprintf("%+-7d", -77));
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libfilezilla-0.6.1/tests/string.cpp 
new/libfilezilla-0.7.0/tests/string.cpp
--- old/libfilezilla-0.6.1/tests/string.cpp     2016-07-27 14:03:01.000000000 
+0200
+++ new/libfilezilla-0.7.0/tests/string.cpp     2016-09-24 15:14:12.000000000 
+0200
@@ -12,6 +12,7 @@
        CPPUNIT_TEST(test_conversion);
        CPPUNIT_TEST(test_conversion2);
        CPPUNIT_TEST(test_conversion_utf8);
+       CPPUNIT_TEST(test_base64);
        CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -21,6 +22,7 @@
        void test_conversion();
        void test_conversion2();
        void test_conversion_utf8();
+       void test_base64();
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(string_test);
@@ -75,3 +77,34 @@
 
        ASSERT_EQUAL(w, w2);
 }
+
+void string_test::test_base64()
+{
+       CPPUNIT_ASSERT_EQUAL(std::string(""),         fz::base64_encode(""));
+       CPPUNIT_ASSERT_EQUAL(std::string("Zg=="),     fz::base64_encode("f"));
+       CPPUNIT_ASSERT_EQUAL(std::string("Zm8="),     fz::base64_encode("fo"));
+       CPPUNIT_ASSERT_EQUAL(std::string("Zm9v"),     fz::base64_encode("foo"));
+       CPPUNIT_ASSERT_EQUAL(std::string("Zm9vbA=="), 
fz::base64_encode("fool"));
+       CPPUNIT_ASSERT_EQUAL(std::string("Zm9vbHM="), 
fz::base64_encode("fools"));
+
+       CPPUNIT_ASSERT_EQUAL(std::string("AAECA/3+/w=="), fz::base64_encode({0, 
1, 2, 3, '\xfd', '\xfe', '\xff'}));
+
+       // decode
+       CPPUNIT_ASSERT_EQUAL(std::string(""),      fz::base64_decode(""));
+       CPPUNIT_ASSERT_EQUAL(std::string("f"),     fz::base64_decode("Zg=="));
+       CPPUNIT_ASSERT_EQUAL(std::string("fo"),    fz::base64_decode("Zm8="));
+       CPPUNIT_ASSERT_EQUAL(std::string("foo"),   fz::base64_decode("Zm9v"));
+       CPPUNIT_ASSERT_EQUAL(std::string("fool"),  
fz::base64_decode("Zm9vbA=="));
+       CPPUNIT_ASSERT_EQUAL(std::string("fools"), 
fz::base64_decode("Zm9vbHM="));
+
+       CPPUNIT_ASSERT_EQUAL(std::string({0, 1, 2, 3, '\xfd', '\xfe', '\xff'}), 
fz::base64_decode("AAECA/3+/w=="));
+
+       // with whitespace
+       CPPUNIT_ASSERT_EQUAL(std::string("Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et 
dolore magna aliqua."),
+                                                fz::base64_decode(" 
TG9yZW0gaXBzdW0gZG9sb3Igc2l0I\nGFtZXQsIGNvbnNlY3Rld\rHVyIGFkaXBpc2NpbmcgZWxpd 
\tCwgc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEu
 "));
+
+       // invalid
+       CPPUNIT_ASSERT_EQUAL(std::string(""), fz::base64_decode("Zm9vbHM=="));
+       CPPUNIT_ASSERT_EQUAL(std::string(""), fz::base64_decode("Zm9vb==="));
+       CPPUNIT_ASSERT_EQUAL(std::string(""), 
fz::base64_decode("Zm9vbHM=Zg=="));
+}


Reply via email to