]> granicus.if.org Git - transmission/commitdiff
Use libb64 instead of OpenSSL to encode/decode BASE64
authorMike Gelfand <mikedld@mikedld.com>
Thu, 1 Jan 2015 21:16:36 +0000 (21:16 +0000)
committerMike Gelfand <mikedld@mikedld.com>
Thu, 1 Jan 2015 21:16:36 +0000 (21:16 +0000)
Some crypto libraries (like CyaSSL, MatrixSSL and CommonCrypto) either
don't have or expose this functionality at all, expose only part of it,
or (like OpenSSL) have heavyweight API for it. Also, for the task as
easy as BASE64 encoding and decoding it's much better to use small and
simple specialized library.

27 files changed:
CMakeLists.txt
cli/Makefile.am
cmake/FindB64.cmake [new file with mode: 0644]
configure.ac
daemon/Makefile.am
gtk/Makefile.am
libtransmission/CMakeLists.txt
libtransmission/Makefile.am
libtransmission/crypto-utils-openssl.c
libtransmission/crypto-utils.c
libtransmission/crypto-utils.h
qt/config.pri.in
qt/qtr.pro
third-party/Makefile.am
third-party/b64-01-newline.patch [new file with mode: 0644]
third-party/b64.cmake [new file with mode: 0644]
third-party/libb64/AUTHORS [new file with mode: 0644]
third-party/libb64/CHANGELOG [new file with mode: 0644]
third-party/libb64/INSTALL [new file with mode: 0644]
third-party/libb64/LICENSE [new file with mode: 0644]
third-party/libb64/Makefile.am [new file with mode: 0644]
third-party/libb64/README [new file with mode: 0644]
third-party/libb64/b64/cdecode.h [new file with mode: 0644]
third-party/libb64/b64/cencode.h [new file with mode: 0644]
third-party/libb64/cdecode.c [new file with mode: 0644]
third-party/libb64/cencode.c [new file with mode: 0644]
utils/Makefile.am

index 3e8da3de7621b834418f39f20e4fcf5cfcac13ba..b2ea0a9ca635ae8abae91ac2cf59169191521239 100644 (file)
@@ -28,6 +28,7 @@ tr_auto_option(USE_SYSTEM_DHT       "Use system dht library" AUTO)
 tr_auto_option(USE_SYSTEM_MINIUPNPC "Use system miniupnpc library" AUTO)
 tr_auto_option(USE_SYSTEM_NATPMP    "Use system natpmp library" AUTO)
 tr_auto_option(USE_SYSTEM_UTP       "Use system utp library" AUTO)
+tr_auto_option(USE_SYSTEM_B64       "Use system b64 library" AUTO)
 tr_auto_option(WITH_INOTIFY         "Enable inotify support (on systems that support it)" AUTO)
 tr_auto_option(WITH_KQUEUE          "Enable kqueue support (on systems that support it)" AUTO)
 tr_auto_option(WITH_SYSTEMD         "Add support for systemd startup notification (on systems that support it)" AUTO)
@@ -104,6 +105,7 @@ tr_github_upstream(NATPMP    miniupnp/libnatpmp 31ebda6226 7e8deb00a98220622a6f2
 tr_github_upstream(MINIUPNPC miniupnp/miniupnp  c490b42547 f9b7a4715bcd5034abae866e31102888)
 tr_github_upstream(DHT       jech/dht           bf62643a95 0a2a2abe447d8a73f0084c1bc837e566)
 tr_github_upstream(UTP       bittorrent/libutp  7c4f19abdf 8b92aa05abec5f6675cdde6477cd6f51)
+tr_github_upstream(B64       mikedld/libb64     c1e3323498 10128cb30ad768d2c4caf627e0f69db3)
 
 if(WIN32)
     foreach(L C CXX)
@@ -230,6 +232,10 @@ if(ENABLE_UTP)
               COMMAND "${CMAKE_COMMAND}" -E copy "${THIRD_PARTY_DIR}/utp_config.h" "<SOURCE_DIR>/utp_config.h")
 endif()
 
+tr_add_external_auto_library(B64 b64
+    PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${THIRD_PARTY_DIR}/b64.cmake" "<SOURCE_DIR>/CMakeLists.txt"
+          COMMAND "${CMAKE_COMMAND}" -E chdir "<SOURCE_DIR>" patch -p1 -i "${THIRD_PARTY_DIR}/b64-01-newline.patch")
+
 if(WITH_INOTIFY)
     tr_get_required_flag(WITH_INOTIFY INOTIFY_IS_REQUIRED)
 
index 7f16726195a4a9fa980c9ee97c3a2a15069b4998..7a8df41221cffeb61e7a862c9f6e6075fb2f54d0 100644 (file)
@@ -18,6 +18,7 @@ transmission_cli_LDADD = \
     @LIBNATPMP_LIBS@ \
     @LIBUPNP_LIBS@ \
     @DHT_LIBS@ \
+    @LIBB64_LIBS@ \
     @LIBUTP_LIBS@ \
     @LIBEVENT_LIBS@ \
     @LIBCURL_LIBS@ \
diff --git a/cmake/FindB64.cmake b/cmake/FindB64.cmake
new file mode 100644 (file)
index 0000000..206ecc0
--- /dev/null
@@ -0,0 +1,34 @@
+if(B64_PREFER_STATIC_LIB)
+    set(B64_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+    if(WIN32)
+        set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
+    else()
+        set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
+    endif()
+endif()
+
+if(UNIX)
+    find_package(PkgConfig QUIET)
+    pkg_check_modules(_B64 QUIET libb64)
+endif()
+
+find_path(B64_INCLUDE_DIR NAMES b64/cdecode.h b64/cencode.h HINTS ${_B64_INCLUDEDIR})
+find_library(B64_LIBRARY NAMES b64 HINTS ${_B64_LIBDIR})
+
+set(B64_INCLUDE_DIRS ${B64_INCLUDE_DIR})
+set(B64_LIBRARIES ${B64_LIBRARY})
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(B64
+    REQUIRED_VARS
+        B64_LIBRARY
+        B64_INCLUDE_DIR
+)
+
+mark_as_advanced(B64_INCLUDE_DIR B64_LIBRARY)
+
+if(B64_PREFER_STATIC_LIB)
+    set(CMAKE_FIND_LIBRARY_SUFFIXES ${B64_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+    unset(B64_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
+endif()
index dd70d3ba4105be9dab404e91d8e4f2c9240b15fb..5afd03fbcc4cf1832e11a1bda7d06c1e3d8615b4 100644 (file)
@@ -216,6 +216,31 @@ AC_SUBST(DHT_LIBS)
 AC_SUBST(DHT_LIBS_QT)
 
 
+dnl ----------------------------------------------------------------------------
+dnl
+dnl  libb64
+
+LIBB64_CFLAGS="-I\$(top_srcdir)/third-party/libb64"
+LIBB64_LIBS="\$(top_builddir)/third-party/libb64/libb64.a"
+LIBB64_LIBS_QT="\$\${TRANSMISSION_TOP}/third-party/libb64/libb64.a"
+build_bundled_b64="yes"
+AC_ARG_ENABLE([external-b64],
+              AS_HELP_STRING([--enable-external-b64],[Use system libb64]),
+              [want_external_b64=${enableval}],
+              [want_external_b64=no])
+if test "x$want_external_b64" != "xno" ; then
+    LIBB64_CFLAGS=""
+    LIBB64_LIBS="-lb64"
+    LIBB64_LIBS_QT="-lb64"
+    build_bundled_b64="no"
+fi
+
+AM_CONDITIONAL([BUILD_B64],[test "x$build_bundled_b64" = "xyes"])
+AC_SUBST(LIBB64_CFLAGS)
+AC_SUBST(LIBB64_LIBS)
+AC_SUBST(LIBB64_LIBS_QT)
+
+
 dnl ----------------------------------------------------------------------------
 dnl
 dnl  utp
@@ -562,6 +587,7 @@ AC_CONFIG_FILES([Makefile
                  utils/Makefile
                  third-party/Makefile
                  third-party/dht/Makefile
+                 third-party/libb64/Makefile
                  third-party/libutp/Makefile
                  third-party/libnatpmp/Makefile
                  third-party/miniupnp/Makefile
index 4012ef843e287effa200d59f0bb98f9dde1f96bb..ef45a31017d658d6d29b44f374e0e1e0d360a518 100644 (file)
@@ -24,6 +24,7 @@ LDADD = \
     @LIBUPNP_LIBS@ \
     @LIBNATPMP_LIBS@ \
     @DHT_LIBS@ \
+    @LIBB64_LIBS@ \
     @LIBUTP_LIBS@ \
     @LIBEVENT_LIBS@ \
     @LIBCURL_LIBS@ \
index b1c1dfcdd2559caf918beb182f54914352138682..c0924aeac8757251a0ea3907e7c0468652d69437 100644 (file)
@@ -89,6 +89,7 @@ transmission_gtk_LDADD = \
     @LIBUPNP_LIBS@ \
     @LIBNATPMP_LIBS@ \
     @DHT_LIBS@ \
+    @LIBB64_LIBS@ \
     @LIBUTP_LIBS@ \
     @GTK_LIBS@ \
     @LIBAPPINDICATOR_LIBS@ \
index 959e75beda2fe14d058003d4296ffe1324fe14c7..853bb32203d869ce1efc2f352a7181e426815d91 100644 (file)
@@ -171,6 +171,7 @@ include_directories(
     ${MINIUPNPC_INCLUDE_DIRS}
     ${DHT_INCLUDE_DIRS}
     ${UTP_INCLUDE_DIRS}
+    ${B64_INCLUDE_DIRS}
 )
 
 if(ENABLE_UTP)
@@ -187,7 +188,8 @@ foreach(UT ${EVENT2_UPSTREAM_TARGET}
            ${NATPMP_UPSTREAM_TARGET}
            ${MINIUPNPC_UPSTREAM_TARGET}
            ${DHT_UPSTREAM_TARGET}
-           ${UTP_UPSTREAM_TARGET})
+           ${UTP_UPSTREAM_TARGET}
+           ${B64_UPSTREAM_TARGET})
     add_dependencies(${TR_NAME} ${UT})
 endforeach()
 
@@ -202,6 +204,7 @@ target_link_libraries(${TR_NAME}
     ${MINIUPNPC_LIBRARIES}
     ${DHT_LIBRARIES}
     ${UTP_LIBRARIES}
+    ${B64_LIBRARIES}
     ${LIBINTL_LIBRARY}
     ${LIBM_LIBRARY}
 )
index dea667bdfa6e8a15e4a20c7fe910d87bd5e6ebec..e5dca07ac9d1169b30774d4628e10be65c10b583 100644 (file)
@@ -5,6 +5,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
   @DHT_CFLAGS@ \
+  @LIBB64_CFLAGS@ \
   @LIBUTP_CFLAGS@ \
   @LIBUPNP_CFLAGS@ \
   @LIBNATPMP_CFLAGS@ \
@@ -173,6 +174,7 @@ apps_ldadd = \
   @LIBNATPMP_LIBS@ \
   @INTLLIBS@ \
   @DHT_LIBS@ \
+  @LIBB64_LIBS@ \
   @LIBUTP_LIBS@ \
   @LIBCURL_LIBS@ \
   @LIBEVENT_LIBS@ \
index 580071ef8f030d41593b272f959de091e3cb3dad..2245f153f3764bbed4b150b29d07fe2fd9167a84 100644 (file)
@@ -9,9 +9,7 @@
 
 #include <assert.h>
 
-#include <openssl/bio.h>
 #include <openssl/bn.h>
-#include <openssl/buffer.h>
 #include <openssl/dh.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
@@ -303,92 +301,3 @@ tr_rand_buffer (void   * buffer,
 
   return check_result (RAND_bytes (buffer, (int) length));
 }
-
-/***
-****
-***/
-
-void *
-tr_base64_encode_impl (const void * input,
-                       size_t       input_length,
-                       size_t     * output_length)
-{
-  char * ret = NULL;
-  int ret_length = 0;
-  BIO * bmem;
-  BIO * b64;
-
-  assert (input != NULL);
-  assert (input_length > 0);
-
-  bmem = BIO_new (BIO_s_mem ());
-  b64 = BIO_new (BIO_f_base64 ());
-
-  BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
-  b64 = BIO_push (b64, bmem);
-
-  if (check_result_eq (BIO_write (b64, input, input_length), (int) input_length) &&
-      check_result (BIO_flush (b64)))
-    {
-      BUF_MEM * bptr;
-
-      BIO_get_mem_ptr (b64, &bptr);
-      ret = tr_strndup (bptr->data, bptr->length);
-      ret_length = bptr->length;
-    }
-
-  BIO_free_all (b64);
-
-  if (output_length != NULL)
-    *output_length = (size_t) ret_length;
-
-  return ret;
-}
-
-void *
-tr_base64_decode_impl (const void * input,
-                       size_t       input_length,
-                       size_t     * output_length)
-{
-  char * ret;
-  int ret_length;
-  int i;
-
-  assert (input != NULL);
-  assert (input_length > 0);
-
-  ret = tr_new (char, input_length + 1);
-
-  /* try two times, without and with BIO_FLAGS_BASE64_NO_NL flag */
-  for (i = 0; i < 2; ++i)
-    {
-      BIO * bmem = BIO_new_mem_buf ((void *) input, (int) input_length);
-      BIO * b64 = BIO_new (BIO_f_base64 ());
-
-      BIO_set_flags (b64, i == 1 ? BIO_FLAGS_BASE64_NO_NL : 0);
-      bmem = BIO_push (b64, bmem);
-
-      ret_length = BIO_read (bmem, ret, (int) input_length);
-      if (ret_length < 0 && i == 1)
-        log_error ();
-
-      BIO_free_all (bmem);
-
-      /* < 0 - fatal error, > 0 - success*/
-      if (ret_length != 0)
-        break;
-    }
-
-  if (ret_length < 0)
-    {
-      tr_free (ret);
-      return NULL;
-    }
-
-  ret[ret_length] = '\0';
-
-  if (output_length != NULL)
-    *output_length = (size_t) ret_length;
-
-  return ret;
-}
index 7b3bff48d693103cc594c1fe89767efe4c266d77..cb31bf7e7c2cf59fd5f574b40de45d9c230b6493 100644 (file)
@@ -12,6 +12,9 @@
 #include <stdlib.h> /* abs (), srand (), rand () */
 #include <string.h> /* memcpy (), memmove (), memset (), strcmp (), strlen () */
 
+#include <b64/cdecode.h>
+#include <b64/cencode.h>
+
 #include "transmission.h"
 #include "crypto-utils.h"
 #include "utils.h"
@@ -197,8 +200,21 @@ tr_base64_encode (const void * input,
     {
       if (input_length != 0)
         {
-          if ((ret = tr_base64_encode_impl (input, input_length, output_length)) != NULL)
-            return ret;
+          size_t ret_length;
+          base64_encodestate state;
+
+          ret = tr_new (char, 4 * ((input_length + 2) / 3) + 1);
+
+          base64_init_encodestate (&state);
+          ret_length = base64_encode_block (input, input_length, ret, &state);
+          ret_length += base64_encode_blockend (ret + ret_length, &state);
+
+          if (output_length != NULL)
+            *output_length = ret_length;
+
+          ret[ret_length] = '\0';
+
+          return ret;
         }
       else
         ret = tr_strdup ("");
@@ -232,8 +248,20 @@ tr_base64_decode (const void * input,
     {
       if (input_length != 0)
         {
-          if ((ret = tr_base64_decode_impl (input, input_length, output_length)) != NULL)
-            return ret;
+          size_t ret_length;
+          base64_decodestate state;
+
+          ret = tr_new (char, input_length / 4 * 3 + 1);
+
+          base64_init_decodestate (&state);
+          ret_length = base64_decode_block (input, input_length, ret, &state);
+
+          if (output_length != NULL)
+            *output_length = ret_length;
+
+          ret[ret_length] = '\0';
+
+          return ret;
         }
       else
         ret = tr_strdup ("");
index 7078da3f4c412175a2a9233c2f2e1929f9f7c147..d4dc9ecb349d61f4f83695a421e6ec1350198faa 100644 (file)
@@ -181,14 +181,6 @@ void           * tr_base64_encode      (const void     * input,
 void           * tr_base64_encode_str  (const char     * input,
                                         size_t         * output_length) TR_GNUC_MALLOC;
 
-/**
- * @brief Translate a block of bytes into base64 (internal, do not use).
- * @return a newly-allocated null-terminated string that can be freed with tr_free ()
- */
-void           * tr_base64_encode_impl (const void     * input,
-                                        size_t           input_length,
-                                        size_t         * output_length) TR_GNUC_MALLOC;
-
 /**
  * @brief Translate a block of bytes from base64 into raw form.
  * @return a newly-allocated null-terminated string that can be freed with tr_free ()
@@ -204,14 +196,6 @@ void           * tr_base64_decode      (const void     * input,
 void           * tr_base64_decode_str  (const char     * input,
                                         size_t         * output_length) TR_GNUC_MALLOC;
 
-/**
- * @brief Translate null-terminated string from base64 into raw form (internal, do not use).
- * @return a newly-allocated null-terminated string that can be freed with tr_free ()
- */
-void           * tr_base64_decode_impl (const void     * input,
-                                        size_t           input_length,
-                                        size_t         * output_length) TR_GNUC_MALLOC;
-
 /**
  * @brief Wrapper around tr_binary_to_hex () for SHA_DIGEST_LENGTH.
  */
index 900d6b827032ae062b4688d3da26e5aacb54c7ef..df77095cb05465536718a539eee72ea5e8aebc2b 100644 (file)
@@ -1,4 +1,5 @@
 DHT_LIBS = @DHT_LIBS_QT@
+LIBB64_LIBS = @LIBB64_LIBS_QT@
 LIBUTP_LIBS = @LIBUTP_LIBS_QT@ 
 LIBUPNP_LIBS = @LIBUPNP_LIBS_QT@
 LIBNATPMP_LIBS = @LIBNATPMP_LIBS_QT@
index 6ca78e7e22ce6a2b623e7b34a0bf23fa8783535d..bcacceb009e6e109d0b759281721c12394af741d 100644 (file)
@@ -28,6 +28,7 @@ INCLUDEPATH += $${TRANSMISSION_TOP}
 LIBS += $${TRANSMISSION_TOP}/libtransmission/libtransmission.a
 LIBS += $${LIBUTP_LIBS}
 LIBS += $${DHT_LIBS}
+LIBS += $${LIBB64_LIBS}
 LIBS += $${LIBUPNP_LIBS}
 LIBS += $${LIBNATPMP_LIBS}
 unix: LIBS += -L$${EVENT_TOP}/lib -lz -lrt
index 774948d6b7391f202b7e247c8a012d968bf03b63..24e814141491702a7bc33f8ab5df75aa9eaa1ec7 100644 (file)
@@ -1,6 +1,9 @@
 if BUILD_DHT
   DHT_DIR = dht
 endif
+if BUILD_B64
+  B64_DIR = libb64
+endif
 if BUILD_UTP
   UTP_DIR = libutp
 endif
@@ -13,6 +16,7 @@ endif
 
 SUBDIRS = \
   $(DHT_DIR) \
+  $(B64_DIR) \
   $(NATPMP_DIR) \
   $(MINIUPNP_DIR) \
   $(UTP_DIR)
diff --git a/third-party/b64-01-newline.patch b/third-party/b64-01-newline.patch
new file mode 100644 (file)
index 0000000..4df194e
--- /dev/null
@@ -0,0 +1,39 @@
+diff --git a/src/cencode.c b/src/cencode.c
+index 03ba5b6..de3902f 100644
+--- a/src/cencode.c
++++ b/src/cencode.c
+@@ -7,7 +7,9 @@ For details, see http://sourceforge.net/projects/libb64
+ #include <b64/cencode.h>
++/*
+ const int CHARS_PER_LINE = 72;
++*/
+ void base64_init_encodestate(base64_encodestate* state_in)
+ {
+@@ -72,12 +74,14 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out,
+                       result  = (fragment & 0x03f) >> 0;
+                       *codechar++ = base64_encode_value(result);
+                       
++                      /*
+                       ++(state_in->stepcount);
+                       if (state_in->stepcount == CHARS_PER_LINE/4)
+                       {
+                               *codechar++ = '\n';
+                               state_in->stepcount = 0;
+                       }
++                      */
+               }
+       }
+       /* control should not reach here */
+@@ -102,7 +106,9 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
+       case step_A:
+               break;
+       }
++      /*
+       *codechar++ = '\n';
++      */
+       
+       return codechar - code_out;
+ }
diff --git a/third-party/b64.cmake b/third-party/b64.cmake
new file mode 100644 (file)
index 0000000..d51293f
--- /dev/null
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 2.8)
+project(b64 C)
+
+include_directories(include)
+
+add_library(${PROJECT_NAME} STATIC
+    src/cdecode.c
+    src/cencode.c
+)
+
+install(TARGETS ${PROJECT_NAME} DESTINATION lib)
+install(DIRECTORY include/b64 DESTINATION include)
diff --git a/third-party/libb64/AUTHORS b/third-party/libb64/AUTHORS
new file mode 100644 (file)
index 0000000..bf4a9f4
--- /dev/null
@@ -0,0 +1,15 @@
+libb64: Base64 Encoding/Decoding Routines
+======================================
+
+Authors:
+-------
+
+Chris Venter   chris.venter@gmail.com  http://controlaltfire.com
+
+Contributors:
+------------
+
+Mario Rugiero
+Shlok Datye
+Peter K. Lee
+
diff --git a/third-party/libb64/CHANGELOG b/third-party/libb64/CHANGELOG
new file mode 100644 (file)
index 0000000..c1c0844
--- /dev/null
@@ -0,0 +1,33 @@
+libb64: Base64 Encoding/Decoding Routines
+======================================
+
+## Changelog ##
+
+Version 1.2.1 Release
+---------------------
+Fixed a long-standing bug in src/cdecode.c where value_in was not correctly
+checked against the bounds [0..decoding_size)
+Thanks to both Mario Rugiero and Shlok Datye for pointing this out.
+Added some simple example code to answer some of the most common misconceptions
+people have about the library usage.
+
+Version 1.2 Release
+-------------------
+Removed the b64dec, b64enc, encoder and decoder programs in favour of
+a better example, called base64, which encodes and decodes 
+depending on its arguments.
+
+Created a solution for Microsoft Visual Studio C++ Express 2010
+edition, which simply builds the base64 example as a console application.
+
+Version 1.1 Release
+-------------------
+Modified encode.h to (correctly) read from the iostream argument,
+instead of std::cin.
+Thanks to Peter K. Lee for the heads-up.
+
+No API changes.
+
+Version 1.0 Release
+-------------------
+The current content is the changeset.
diff --git a/third-party/libb64/INSTALL b/third-party/libb64/INSTALL
new file mode 100644 (file)
index 0000000..b05f5db
--- /dev/null
@@ -0,0 +1,44 @@
+libb64: Base64 Encoding/Decoding Routines
+======================================
+
+Requirements:
+------------
+This piece of software has minimal requirements.
+
+I have tested it on the following systems:
+
+- a Linux machine, with the following specs:
+(this was the original development machine)
+       * FedoraCore 4
+       * kernel v. 2.6.11 (stock FC4 kernel)
+       * gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
+       * glibc-2.3.5-10
+       * make v. 3.80
+       * some arb version of makedepend
+
+- Windows XP machine
+       * MSYS 1.0
+       * MinGW 5.1.4
+       * gcc version 3.4.5 (mingw-vista special r3)
+
+- Windows XP machine (same as above)
+       * Microsoft Visual Studio 2010, Version 10.0.30319.1 RTMRel
+       
+Barring any serious screwups on my part, this code should compile and run sweetly
+under Cygwin and other systems too. If you DO get it running under some weird arch/os setup,
+send me a mail, please.
+
+Compiling:
+---------
+There is no configure. It would be overkill for something so simple...
+Run make in the root directory.
+
+Installing:
+----------
+Since the current targets are a standalone executable and a static library
+(fancy name for archive) with some headers, an install script has not been implemented yet.
+Simply copy the executable into your path, and use it.
+
+--
+peace out
+Chris
diff --git a/third-party/libb64/LICENSE b/third-party/libb64/LICENSE
new file mode 100644 (file)
index 0000000..a6b5606
--- /dev/null
@@ -0,0 +1,29 @@
+Copyright-Only Dedication (based on United States law) 
+or Public Domain Certification
+
+The person or persons who have associated work with this document (the
+"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of
+his knowledge, the work of authorship identified is in the public domain of the
+country from which the work is published, or (b) hereby dedicates whatever
+copyright the dedicators holds in the work of authorship identified below (the
+"Work") to the public domain. A certifier, moreover, dedicates any copyright
+interest he may have in the associated work, and for these purposes, is
+described as a "dedicator" below.
+
+A certifier has taken reasonable steps to verify the copyright status of this
+work. Certifier recognizes that his good faith efforts may not shield him from
+liability if in fact the work certified is not in the public domain.
+
+Dedicator makes this dedication for the benefit of the public at large and to
+the detriment of the Dedicator's heirs and successors. Dedicator intends this
+dedication to be an overt act of relinquishment in perpetuity of all present
+and future rights under copyright law, whether vested or contingent, in the
+Work. Dedicator understands that such relinquishment of all rights includes
+the relinquishment of all rights to enforce (by lawsuit or otherwise) those
+copyrights in the Work.
+
+Dedicator recognizes that, once placed in the public domain, the Work may be
+freely reproduced, distributed, transmitted, used, modified, built upon, or
+otherwise exploited by anyone for any purpose, commercial or non-commercial,
+and in any way, including by methods that have not yet been invented or
+conceived.
\ No newline at end of file
diff --git a/third-party/libb64/Makefile.am b/third-party/libb64/Makefile.am
new file mode 100644 (file)
index 0000000..4d0cd42
--- /dev/null
@@ -0,0 +1,4 @@
+noinst_LIBRARIES = libb64.a
+libb64_a_SOURCES = cdecode.c cencode.c
+noinst_HEADERS = b64/cdecode.h b64/cencode.h
+EXTRA_DIST = AUTHORS CHANGELOG INSTALL LICENSE README
diff --git a/third-party/libb64/README b/third-party/libb64/README
new file mode 100644 (file)
index 0000000..132f02f
--- /dev/null
@@ -0,0 +1,143 @@
+b64: Base64 Encoding/Decoding Routines
+======================================
+
+Overview:
+--------
+libb64 is a library of ANSI C routines for fast encoding/decoding data into and
+from a base64-encoded format. C++ wrappers are included, as well as the source
+code for standalone encoding and decoding executables.
+
+base64 consists of ASCII text, and is therefore a useful encoding for storing 
+binary data in a text file, such as xml, or sending binary data over text-only
+email.
+
+References:
+----------
+* Wikipedia article:
+       http://en.wikipedia.org/wiki/Base64
+* base64, another implementation of a commandline en/decoder:
+       http://www.fourmilab.ch/webtools/base64/
+
+Why?
+---
+I did this because I need an implementation of base64 encoding and decoding,
+without any licensing problems. Most OS implementations are released under
+either the GNU/GPL, or a BSD-variant, which is not what I require.
+
+Also, the chance to actually use the co-routine implementation in code is rare,
+and its use here is fitting. I couldn't pass up the chance.
+For more information on this technique, see "Coroutines in C", by Simon Tatham,
+which can be found online here: 
+http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+
+So then, under which license do I release this code? On to the next section...
+
+License:
+-------
+This work is released under into the Public Domain.
+It basically boils down to this: I put this work in the public domain, and you
+can take it and do whatever you want with it.
+
+An example of this "license" is the Creative Commons Public Domain License, a
+copy of which can be found in the LICENSE file, and also online at
+http://creativecommons.org/licenses/publicdomain/
+
+Commandline Use:
+---------------
+There is a new executable available, it is simply called base64.
+It can encode and decode files, as instructed by the user.
+
+To encode a file:
+$ ./base64 -e filea fileb
+fileb will now be the base64-encoded version of filea.
+
+To decode a file:
+$ ./base64 -d fileb filec
+filec will now be identical to filea.
+
+Programming:
+-----------
+Some C++ wrappers are provided as well, so you don't have to get your hands
+dirty. Encoding from standard input to standard output is as simple as
+
+       #include <b64/encode.h>
+       #include <iostream>
+       int main()
+       {
+               base64::encoder E;
+               E.encode(std::cin, std::cout);
+               return 0;
+       }
+
+Both standalone executables and a static library is provided in the package,
+
+Example code:
+------------
+The 'examples' directory contains some simple example C code, that demonstrates
+how to use the C interface of the library.
+
+Implementation:
+--------------
+It is DAMN fast, if I may say so myself. The C code uses a little trick which
+has been used to implement coroutines, of which one can say that this
+implementation is an example.
+
+(To see how the libb64 codebase compares with some other BASE64 implementations
+available, see the BENCHMARKS file)
+
+The trick involves the fact that a switch-statement may legally cross into
+sub-blocks. A very thorough and enlightening essay on co-routines in C, using
+this method, can be found in the above mentioned "Coroutines in C", by Simon
+Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+
+For example, an RLE decompressing routine, adapted from the article:
+1      static int STATE = 0;
+2      static int len, c;
+3      switch (STATE)
+4      {
+5              while (1)
+6              {
+7                      c = getchar();
+8                      if (c == EOF) return EOF;
+9                      if (c == 0xFF) {
+10                             len = getchar();
+11                             c = getchar();
+12                             while (len--)
+13                             {
+14                                     STATE = 0;
+15                                     return c;
+16     case 0:
+17                             }
+18                     } else
+19                             STATE = 1;
+20                             return c;
+21     case 1:
+22                     }
+23             }
+24     }
+
+As can be seen from this example, a coroutine depends on a state variable,
+which it sets directly before exiting (lines 14 and 119). The next time the
+routine is entered, the switch moves control to the specific point directly
+after the previous exit (lines 16 and 21).hands
+
+(As an aside, in the mentioned article the combination of the top-level switch,
+the various setting of the state, the return of a value, and the labelling of
+the exit point is wrapped in #define macros, making the structure of the
+routine even clearer.)
+
+The obvious problem with any such routine is the static keyword.
+Any static variables in a function spell doom for multithreaded applications.
+Also, in situations where this coroutine is used by more than one other
+coroutines, the consistency is disturbed.
+
+What is needed is a structure for storing these variabled, which is passed to
+the routine seperately. This obviously breaks the modularity of the function,
+since now the caller has to worry about and care for the internal state of the
+routine (the callee). This allows for a fast, multithreading-enabled
+implementation, which may (obviously) be wrapped in a C++ object for ease of
+use.
+
+The base64 encoding and decoding functionality in this package is implemented
+in exactly this way, providing both a high-speed high-maintanence C interface,
+and a wrapped C++ which is low-maintanence and only slightly less performant.
diff --git a/third-party/libb64/b64/cdecode.h b/third-party/libb64/b64/cdecode.h
new file mode 100644 (file)
index 0000000..5729853
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+cdecode.h - c header for a base64 decoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#ifndef BASE64_CDECODE_H
+#define BASE64_CDECODE_H
+
+typedef enum
+{
+       step_a, step_b, step_c, step_d
+} base64_decodestep;
+
+typedef struct
+{
+       base64_decodestep step;
+       char plainchar;
+} base64_decodestate;
+
+void base64_init_decodestate(base64_decodestate* state_in);
+
+int base64_decode_value(char value_in);
+
+int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
+
+#endif /* BASE64_CDECODE_H */
+
diff --git a/third-party/libb64/b64/cencode.h b/third-party/libb64/b64/cencode.h
new file mode 100644 (file)
index 0000000..cf32131
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+cencode.h - c header for a base64 encoding algorithm
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#ifndef BASE64_CENCODE_H
+#define BASE64_CENCODE_H
+
+typedef enum
+{
+       step_A, step_B, step_C
+} base64_encodestep;
+
+typedef struct
+{
+       base64_encodestep step;
+       char result;
+       int stepcount;
+} base64_encodestate;
+
+void base64_init_encodestate(base64_encodestate* state_in);
+
+char base64_encode_value(char value_in);
+
+int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
+
+int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
+
+#endif /* BASE64_CENCODE_H */
+
diff --git a/third-party/libb64/cdecode.c b/third-party/libb64/cdecode.c
new file mode 100644 (file)
index 0000000..a6c0a42
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+cdecoder.c - c source to a base64 decoding algorithm implementation
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#include <b64/cdecode.h>
+
+int base64_decode_value(char value_in)
+{
+       static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
+       static const char decoding_size = sizeof(decoding);
+       value_in -= 43;
+       if (value_in < 0 || value_in >= decoding_size) return -1;
+       return decoding[(int)value_in];
+}
+
+void base64_init_decodestate(base64_decodestate* state_in)
+{
+       state_in->step = step_a;
+       state_in->plainchar = 0;
+}
+
+int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
+{
+       const char* codechar = code_in;
+       char* plainchar = plaintext_out;
+       char fragment;
+       
+       *plainchar = state_in->plainchar;
+       
+       switch (state_in->step)
+       {
+               while (1)
+               {
+       case step_a:
+                       do {
+                               if (codechar == code_in+length_in)
+                               {
+                                       state_in->step = step_a;
+                                       state_in->plainchar = *plainchar;
+                                       return plainchar - plaintext_out;
+                               }
+                               fragment = (char)base64_decode_value(*codechar++);
+                       } while (fragment < 0);
+                       *plainchar    = (fragment & 0x03f) << 2;
+       case step_b:
+                       do {
+                               if (codechar == code_in+length_in)
+                               {
+                                       state_in->step = step_b;
+                                       state_in->plainchar = *plainchar;
+                                       return plainchar - plaintext_out;
+                               }
+                               fragment = (char)base64_decode_value(*codechar++);
+                       } while (fragment < 0);
+                       *plainchar++ |= (fragment & 0x030) >> 4;
+                       *plainchar    = (fragment & 0x00f) << 4;
+       case step_c:
+                       do {
+                               if (codechar == code_in+length_in)
+                               {
+                                       state_in->step = step_c;
+                                       state_in->plainchar = *plainchar;
+                                       return plainchar - plaintext_out;
+                               }
+                               fragment = (char)base64_decode_value(*codechar++);
+                       } while (fragment < 0);
+                       *plainchar++ |= (fragment & 0x03c) >> 2;
+                       *plainchar    = (fragment & 0x003) << 6;
+       case step_d:
+                       do {
+                               if (codechar == code_in+length_in)
+                               {
+                                       state_in->step = step_d;
+                                       state_in->plainchar = *plainchar;
+                                       return plainchar - plaintext_out;
+                               }
+                               fragment = (char)base64_decode_value(*codechar++);
+                       } while (fragment < 0);
+                       *plainchar++   |= (fragment & 0x03f);
+               }
+       }
+       /* control should not reach here */
+       return plainchar - plaintext_out;
+}
+
diff --git a/third-party/libb64/cencode.c b/third-party/libb64/cencode.c
new file mode 100644 (file)
index 0000000..acd9767
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+cencoder.c - c source to a base64 encoding algorithm implementation
+
+This is part of the libb64 project, and has been placed in the public domain.
+For details, see http://sourceforge.net/projects/libb64
+*/
+
+#include <b64/cencode.h>
+
+const int CHARS_PER_LINE = 72;
+
+void base64_init_encodestate(base64_encodestate* state_in)
+{
+       state_in->step = step_A;
+       state_in->result = 0;
+       state_in->stepcount = 0;
+}
+
+char base64_encode_value(char value_in)
+{
+       static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+       if (value_in > 63) return '=';
+       return encoding[(int)value_in];
+}
+
+int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
+{
+       const char* plainchar = plaintext_in;
+       const char* const plaintextend = plaintext_in + length_in;
+       char* codechar = code_out;
+       char result;
+       char fragment;
+       
+       result = state_in->result;
+       
+       switch (state_in->step)
+       {
+               while (1)
+               {
+       case step_A:
+                       if (plainchar == plaintextend)
+                       {
+                               state_in->result = result;
+                               state_in->step = step_A;
+                               return codechar - code_out;
+                       }
+                       fragment = *plainchar++;
+                       result = (fragment & 0x0fc) >> 2;
+                       *codechar++ = base64_encode_value(result);
+                       result = (fragment & 0x003) << 4;
+       case step_B:
+                       if (plainchar == plaintextend)
+                       {
+                               state_in->result = result;
+                               state_in->step = step_B;
+                               return codechar - code_out;
+                       }
+                       fragment = *plainchar++;
+                       result |= (fragment & 0x0f0) >> 4;
+                       *codechar++ = base64_encode_value(result);
+                       result = (fragment & 0x00f) << 2;
+       case step_C:
+                       if (plainchar == plaintextend)
+                       {
+                               state_in->result = result;
+                               state_in->step = step_C;
+                               return codechar - code_out;
+                       }
+                       fragment = *plainchar++;
+                       result |= (fragment & 0x0c0) >> 6;
+                       *codechar++ = base64_encode_value(result);
+                       result  = (fragment & 0x03f) >> 0;
+                       *codechar++ = base64_encode_value(result);
+                       
+                       /* ++(state_in->stepcount);
+                       if (state_in->stepcount == CHARS_PER_LINE/4)
+                       {
+                               *codechar++ = '\n';
+                               state_in->stepcount = 0;
+                       } */
+               }
+       }
+       /* control should not reach here */
+       return codechar - code_out;
+}
+
+int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
+{
+       char* codechar = code_out;
+       
+       switch (state_in->step)
+       {
+       case step_B:
+               *codechar++ = base64_encode_value(state_in->result);
+               *codechar++ = '=';
+               *codechar++ = '=';
+               break;
+       case step_C:
+               *codechar++ = base64_encode_value(state_in->result);
+               *codechar++ = '=';
+               break;
+       case step_A:
+               break;
+       }
+       /* *codechar++ = '\n'; */
+       
+       return codechar - code_out;
+}
+
index cde4a7b783703d93025268498a60c8199495a9d8..61424c35358a397868b190f9207079b7fa671533 100644 (file)
@@ -31,6 +31,7 @@ transmission_create_LDADD = \
     @LIBNATPMP_LIBS@ \
     @INTLLIBS@ \
     @DHT_LIBS@ \
+    @LIBB64_LIBS@ \
     @LIBUTP_LIBS@ \
     @LIBEVENT_LIBS@ \
     @LIBCURL_LIBS@ \