From 359d5009089b8b9450ab54825c08448f9e51ed64 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 3 Jan 2007 23:04:38 +0000
Subject: [PATCH] - David McCreedy made changes to allow base64
 encoding/decoding to work on   non-ASCII platforms.

---
 CHANGES              |  4 ++
 RELEASE-NOTES        |  1 +
 lib/base64.c         | 96 ++++++++++++++++++++++++++++++++++----------
 lib/base64.h         |  5 ++-
 lib/http.c           |  4 +-
 lib/http_digest.c    |  4 +-
 lib/http_negotiate.c |  5 ++-
 lib/http_ntlm.c      |  6 +--
 lib/krb4.c           |  7 ++--
 lib/ldap.c           |  6 ++-
 10 files changed, 100 insertions(+), 38 deletions(-)

diff --git a/CHANGES b/CHANGES
index d46ed330a7..811122d1dd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,10 @@
 
                                   Changelog
 
+Daniel (4 January 2007)
+- David McCreedy made changes to allow base64 encoding/decoding to work on
+  non-ASCII platforms.
+
 Daniel (3 January 2007)
 - Matt Witherspoon fixed the flaw which made libcurl 7.16.0 always store
   downloaded data in two buffers, just to be able to deal with a special HTTP
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 6ff132e7d8..fe108df674 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -46,6 +46,7 @@ This release includes the following bugfixes:
  o --limit-rate (CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE)
    now work on windows again
  o improved download performance by avoiding the unconditional "double copying"
+ o base64 encoding/decoding works on non-ASCII platforms
 
 Other curl-related news:
 
diff --git a/lib/base64.c b/lib/base64.c
index 2302eb0145..aa03f83462 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -40,28 +40,27 @@
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
 
+#include "urldata.h" /* for the SessionHandle definition */
+#include "easyif.h"  /* for Curl_convert_... prototypes */
 #include "base64.h"
 #include "memory.h"
 
 /* include memdebug.h last */
 #include "memdebug.h"
 
+/* ---- Base64 Encoding/Decoding Table --- */
+static const char table64[]=
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 static void decodeQuantum(unsigned char *dest, const char *src)
 {
   unsigned int x = 0;
   int i;
+  char *found;
+
   for(i = 0; i < 4; i++) {
-    if(src[i] >= 'A' && src[i] <= 'Z')
-      x = (x << 6) + (unsigned int)(src[i] - 'A' + 0);
-    else if(src[i] >= 'a' && src[i] <= 'z')
-      x = (x << 6) + (unsigned int)(src[i] - 'a' + 26);
-    else if(src[i] >= '0' && src[i] <= '9')
-      x = (x << 6) + (unsigned int)(src[i] - '0' + 52);
-    else if(src[i] == '+')
-      x = (x << 6) + 62;
-    else if(src[i] == '/')
-      x = (x << 6) + 63;
+    if((found = strchr(table64, src[i])))
+      x = (x << 6) + (unsigned int)(found - table64);
     else if(src[i] == '=')
       x = (x << 6);
   }
@@ -133,10 +132,6 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
   return rawlen;
 }
 
-/* ---- Base64 Encoding --- */
-static const char table64[]=
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
 /*
  * Curl_base64_encode()
  *
@@ -145,7 +140,8 @@ static const char table64[]=
  * went wrong, -1 is returned.
  *
  */
-size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
+size_t Curl_base64_encode(struct SessionHandle *data,
+                          const char *inp, size_t insize, char **outptr)
 {
   unsigned char ibuf[3];
   unsigned char obuf[4];
@@ -153,6 +149,9 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
   int inputparts;
   char *output;
   char *base64data;
+#ifdef CURL_DOES_CONVERSIONS
+  char *convbuf;
+#endif
 
   char *indata = (char *)inp;
 
@@ -165,6 +164,28 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
   if(NULL == output)
     return 0;
 
+#ifdef CURL_DOES_CONVERSIONS
+  /*
+   * The base64 data needs to be created using the network encoding
+   * not the host encoding.  And we can't change the actual input
+   * so we copy it to a buffer, translate it, and use that instead.
+   */
+  if(data) {
+    convbuf = (char*)malloc(insize);
+    if(!convbuf) {
+      return 0;
+    }
+    memcpy(convbuf, indata, insize);
+    if(CURLE_OK != Curl_convert_to_network(data, convbuf, insize)) {
+      free(convbuf);
+      return 0;
+    }
+    indata = convbuf; /* switch to the converted buffer */
+  }
+#else
+  (void)data;
+#endif
+
   while(insize > 0) {
     for (i = inputparts = 0; i < 3; i++) {
       if(insize > 0) {
@@ -209,6 +230,10 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
   *output=0;
   *outptr = base64data; /* make it return the actual data memory */
 
+#ifdef CURL_DOES_CONVERSIONS
+  if(data)
+    free(convbuf);
+#endif
   return strlen(base64data); /* return the length of the new data */
 }
 /* ---- End of Base64 Encoding ---- */
@@ -231,14 +256,26 @@ int main(int argc, char **argv, char **envp)
   size_t base64Len;
   unsigned char *data;
   int dataLen;
+  struct SessionHandle *handle = NULL;
 
+#ifdef CURL_DOES_CONVERSIONS
+  /* get a Curl handle so Curl_base64_encode can translate properly */
+  handle = curl_easy_init();
+  if(handle == NULL) {
+    fprintf(stderr, "Error: curl_easy_init failed\n");
+    return 0;
+  }
+#endif
   data = (unsigned char *)suck(&dataLen);
-  base64Len = Curl_base64_encode(data, dataLen, &base64);
+  base64Len = Curl_base64_encode(handle, data, dataLen, &base64);
 
   fprintf(stderr, "%d\n", base64Len);
-  fprintf(stdout, "%s",   base64);
+  fprintf(stdout, "%s\n", base64);
 
   free(base64); free(data);
+#ifdef CURL_DOES_CONVERSIONS
+  curl_easy_cleanup(handle);
+#endif
   return 0;
 }
 #endif
@@ -261,10 +298,17 @@ int main(int argc, char **argv, char **envp)
   unsigned char *data;
   int dataLen;
   int i, j;
+#ifdef CURL_DOES_CONVERSIONS
+  /* get a Curl handle so main can translate properly */
+  struct SessionHandle *handle = curl_easy_init();
+  if(handle == NULL) {
+    fprintf(stderr, "Error: curl_easy_init failed\n");
+    return 0;
+  }
+#endif
 
   base64 = (char *)suck(&base64Len);
-  data = (unsigned char *)malloc(base64Len * 3/4 + 8);
-  dataLen = Curl_base64_decode(base64, data);
+  dataLen = Curl_base64_decode(base64, &data);
 
   fprintf(stderr, "%d\n", dataLen);
 
@@ -279,13 +323,21 @@ int main(int argc, char **argv, char **envp)
     printf(" | ");
 
     for(j=0; j < 0x10; j++)
-      if((j+i) < dataLen)
+      if((j+i) < dataLen) {
+#ifdef CURL_DOES_CONVERSIONS
+        if(CURLE_OK !=
+             Curl_convert_from_network(handle, &data[i+j], (size_t)1))
+          data[i+j] = '.';
+#endif /* CURL_DOES_CONVERSIONS */
         printf("%c", ISGRAPH(data[i+j])?data[i+j]:'.');
-      else
+      } else
         break;
     puts("");
   }
 
+#ifdef CURL_DOES_CONVERSIONS
+  curl_easy_cleanup(handle);
+#endif
   free(base64); free(data);
   return 0;
 }
diff --git a/lib/base64.h b/lib/base64.h
index 0754908ca5..59742bcd3a 100644
--- a/lib/base64.h
+++ b/lib/base64.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,7 @@
  *
  * $Id$
  ***************************************************************************/
-size_t Curl_base64_encode(const char *input, size_t size, char **str);
+size_t Curl_base64_encode(struct SessionHandle *data,
+                          const char *input, size_t size, char **str);
 size_t Curl_base64_decode(const char *source, unsigned char **outptr);
 #endif
diff --git a/lib/http.c b/lib/http.c
index 2f8b98e2ef..ae7c3cfbc1 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -149,7 +149,7 @@ static CURLcode Curl_output_basic(struct connectdata *conn, bool proxy)
   }
 
   snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
-  if(Curl_base64_encode(data->state.buffer,
+  if(Curl_base64_encode(data, data->state.buffer,
                         strlen(data->state.buffer),
                         &authorization) > 0) {
     if(*userp)
diff --git a/lib/http_digest.c b/lib/http_digest.c
index 8b605d5c56..e5d8baae55 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -270,7 +270,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
     /* Generate a cnonce */
     now = Curl_tvnow();
     snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", now.tv_sec);
-    if(Curl_base64_encode(cnoncebuf, strlen(cnoncebuf), &cnonce))
+    if(Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce))
       d->cnonce = cnonce;
     else
       return CURLE_OUT_OF_MEMORY;
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index eb5bd92d1b..bdfeefa0a5 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -290,7 +290,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn)
     }
   }
 #endif
-  len = Curl_base64_encode(neg_ctx->output_token.value,
+  len = Curl_base64_encode(conn->data,
+                           neg_ctx->output_token.value,
                            neg_ctx->output_token.length,
                            &encoded);
 
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 4bbd0dda7f..ee6f6eb9b8 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -706,7 +706,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
     });
 
     /* now size is the size of the base64 encoded package size */
-    size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
+    size = Curl_base64_encode(conn->data, (char *)ntlmbuf, size, &base64);
 
     if(size >0 ) {
       Curl_safefree(*allocuserpwd);
@@ -1017,7 +1017,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
 #endif
 
     /* convert the binary blob into base64 */
-    size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
+    size = Curl_base64_encode(conn->data, (char *)ntlmbuf, size, &base64);
 
     if(size >0 ) {
       Curl_safefree(*allocuserpwd);
diff --git a/lib/krb4.c b/lib/krb4.c
index 1659be21da..f2b91df69f 100644
--- a/lib/krb4.c
+++ b/lib/krb4.c
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
- * Copyright (c) 2004 - 2006 Daniel Stenberg
+ * Copyright (c) 2004 - 2007 Daniel Stenberg
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -252,7 +252,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
   }
 #endif
 
-  if(Curl_base64_encode((char *)adat.dat, adat.length, &p) < 1) {
+  if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
     Curl_failf(data, "Out of memory base64-encoding");
     return AUTH_CONTINUE;
   }
@@ -400,7 +400,8 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
   memset(key, 0, sizeof(key));
   memset(schedule, 0, sizeof(schedule));
   memset(passwd, 0, sizeof(passwd));
-  if(Curl_base64_encode((char *)tktcopy.dat, tktcopy.length, &p) < 1) {
+  if(Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, &p)
+     < 1) {
     failf(conn->data, "Out of memory base64-encoding.");
     Curl_set_command_prot(conn, save);
     return CURLE_OUT_OF_MEMORY;
diff --git a/lib/ldap.c b/lib/ldap.c
index 53c7722098..3e1144d4fe 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -402,7 +402,9 @@ CURLcode Curl_ldap(struct connectdata *conn, bool *done)
                       (char *)attribute +
                       (strlen((char *)attribute) - 7)) == 0)) {
             /* Binary attribute, encode to base64. */
-            val_b64_sz = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
+            val_b64_sz = Curl_base64_encode(conn->data,
+                                            vals[i]->bv_val,
+                                            vals[i]->bv_len,
                                             &val_b64);
             if (val_b64_sz > 0) {
               Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
-- 
GitLab