gpg: Try to use the passphrase from the primary for --quick-addkey.
[gnupg.git] / common / utf8conv.c
index 16baa0d..83e6eae 100644 (file)
@@ -2,20 +2,31 @@
  * Copyright (C) 1994, 1998, 1999, 2000, 2001, 2003, 2006,
  *               2008, 2010  Free Software Foundation, Inc.
  *
- * This file is part of JNLIB.
+ * This file is part of GnuPG.
  *
- * JNLIB is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 3 of
- * the License, or (at your option) any later version.
+ * GnuPG is free software; you can redistribute it and/or modify it
+ * under the terms of either
  *
- * JNLIB is distributed in the hope that it will be useful, but
+ *   - the GNU Lesser General Public License as published by the Free
+ *     Software Foundation; either version 3 of the License, or (at
+ *     your option) any later version.
+ *
+ * or
+ *
+ *   - the GNU General Public License as published by the Free
+ *     Software Foundation; either version 2 of the License, or (at
+ *     your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * GnuPG is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
+ * General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <langinfo.h>
 #endif
 #include <errno.h>
-#ifndef HAVE_W32_SYSTEM
+
+#if HAVE_W32_SYSTEM
+# /* Tell libgpg-error to provide the iconv macros.  */
+# define GPGRT_ENABLE_W32_ICONV_MACROS 1
+#elif HAVE_ANDROID_SYSTEM
+# /* No iconv support.  */
+#else
 # include <iconv.h>
 #endif
 
-#include "libjnlib-config.h"
+
+#include "util.h"
+#include "common-defs.h"
+#include "i18n.h"
 #include "stringhelp.h"
-#include "dynload.h"
 #include "utf8conv.h"
 
 #ifndef MB_LEN_MAX
 
 static const char *active_charset_name = "iso-8859-1";
 static int no_translation;     /* Set to true if we let simply pass through. */
-static int use_iconv;          /* iconv comversion fucntions required. */
+static int use_iconv;          /* iconv conversion functions required. */
 
 
-/* Under W32 we dlopen the iconv dll and don't require any iconv
-   related headers at all.  However we need to define some stuff.  */
-#ifdef HAVE_W32_SYSTEM
+#ifdef HAVE_ANDROID_SYSTEM
+/* Fake stuff to get things building.  */
 typedef void *iconv_t;
-#ifndef ICONV_CONST
 #define ICONV_CONST
-#endif
-static iconv_t (* __stdcall iconv_open) (const char *tocode,
-                                         const char *fromcode);
-static size_t  (* __stdcall iconv) (iconv_t cd,
-                                    char **inbuf, size_t *inbytesleft,
-                                    char **outbuf, size_t *outbytesleft);
-static int     (* __stdcall iconv_close) (iconv_t cd);
-
-static int 
-load_libiconv (void)
+
+static iconv_t
+iconv_open (const char *tocode, const char *fromcode)
 {
-#ifdef HAVE_W32CE_SYSTEM
-  return -1; /* FIXME No libiconv yet - Need to investigate whether it
-                is at all required.  */
-#else
-  static int done;
-  
-  if (!done)
-    {
-      void *handle;
+  (void)tocode;
+  (void)fromcode;
+  return (iconv_t)(-1);
+}
 
-      done = 1; /* Do it right now because we might get called recursivly
-                   through gettext.  */
-    
-      handle = dlopen ("iconv.dll", RTLD_LAZY);
-      if (handle)
-        {
-          iconv_open  = dlsym (handle, "libiconv_open");
-          if (iconv_open)
-            iconv = dlsym (handle, "libiconv");
-          if (iconv)    
-            iconv_close = dlsym (handle, "libiconv_close");
-        }
-      if (!handle || !iconv_close)
-        {
-          log_info (_("error loading `%s': %s\n"),
-                     "iconv.dll",  dlerror ());
-          log_info (_("please see %s for more information\n"),
-                    "http://www.gnupg.org/download/iconv.html");
-          iconv_open = NULL;
-          iconv = NULL;
-          iconv_close = NULL;
-          if (handle)
-            dlclose (handle);
-        }
-    }
-  return iconv_open? 0: -1;
-#endif
-}    
-#endif /*HAVE_W32_SYSTEM*/
+static size_t
+iconv (iconv_t cd, char **inbuf, size_t *inbytesleft,
+       char **outbuf, size_t *outbytesleft)
+{
+  (void)cd;
+  (void)inbuf;
+  (void)inbytesleft;
+  (void)outbuf;
+  (void)outbytesleft;
+  return (size_t)(0);
+}
+
+static int
+iconv_close (iconv_t cd)
+{
+  (void)cd;
+  return 0;
+}
+#endif /*HAVE_ANDROID_SYSTEM*/
 
 
 /* Error handler for iconv failures. This is needed to not clutter the
@@ -125,7 +120,7 @@ handle_iconv_error (const char *to, const char *from, int use_fallback)
         }
 
       if (!x)
-        log_info (_("conversion from `%s' to `%s' not available\n"),
+        log_info (_("conversion from '%s' to '%s' not available\n"),
                   from, to);
     }
   else
@@ -139,12 +134,10 @@ handle_iconv_error (const char *to, const char *from, int use_fallback)
 
   if (use_fallback)
     {
-      /* To avoid further error messages we fallback to Latin-1 for the
-         native encoding.  This is justified as one can expect that on a
-         utf-8 enabled system nl_langinfo() will work and thus we won't
-         never get to here.  Thus Latin-1 seems to be a reasonable
-         default.  */
-      active_charset_name = "iso-8859-1";
+      /* To avoid further error messages we fallback to UTF-8 for the
+         native encoding.  Nowadays this seems to be the best bet in
+         case of errors from iconv or nl_langinfo.  */
+      active_charset_name = "utf-8";
       no_translation = 0;
       use_iconv = 0;
     }
@@ -157,13 +150,15 @@ set_native_charset (const char *newset)
 {
   const char *full_newset;
 
-  if (!newset) 
+  if (!newset)
     {
-#ifdef HAVE_W32_SYSTEM
+#ifdef HAVE_ANDROID_SYSTEM
+      newset = "utf-8";
+#elif defined HAVE_W32_SYSTEM
       static char codepage[30];
       unsigned int cpno;
       const char *aliases;
-      
+
       /* We are a console program thus we need to use the
          GetConsoleOutputCP function and not the the GetACP which
          would give the codepage for a GUI program.  Note this is not
@@ -207,8 +202,8 @@ set_native_charset (const char *newset)
             }
         }
 
-#else /*!HAVE_W32_SYSTEM*/
-      
+#else /*!HAVE_W32_SYSTEM && !HAVE_ANDROID_SYSTEM*/
+
 #ifdef HAVE_LANGINFO_CODESET
       newset = nl_langinfo (CODESET);
 #else /*!HAVE_LANGINFO_CODESET*/
@@ -232,7 +227,7 @@ set_native_charset (const char *newset)
               mod = strchr (++dot, '@');
               if (!mod)
                 mod = dot + strlen (dot);
-              if (mod - dot < sizeof codepage && dot != mod) 
+              if (mod - dot < sizeof codepage && dot != mod)
                 {
                   memcpy (codepage, dot, mod - dot);
                   codepage [mod - dot] = 0;
@@ -241,7 +236,7 @@ set_native_charset (const char *newset)
         }
       newset = codepage;
 #endif /*!HAVE_LANGINFO_CODESET*/
-#endif /*!HAVE_W32_SYSTEM*/
+#endif /*!HAVE_W32_SYSTEM && !HAVE_ANDROID_SYSTEM*/
     }
 
   full_newset = newset;
@@ -256,8 +251,8 @@ set_native_charset (const char *newset)
      as Latin-1.  This makes sense because many Unix system don't have
      their locale set up properly and thus would get annoying error
      messages and we have to handle all the "bug" reports. Latin-1 has
-     always been the character set used for 8 bit characters on Unix
-     systems. */
+     traditionally been the character set used for 8 bit characters on
+     Unix systems. */
   if ( !*newset
        || !ascii_strcasecmp (newset, "8859-1" )
        || !ascii_strcasecmp (newset, "646" )
@@ -279,21 +274,16 @@ set_native_charset (const char *newset)
   else
     {
       iconv_t cd;
-      
-#ifdef HAVE_W32_SYSTEM
-      if (load_libiconv ())
-        return -1;
-#endif /*HAVE_W32_SYSTEM*/      
 
       cd = iconv_open (full_newset, "utf-8");
-      if (cd == (iconv_t)-1) 
+      if (cd == (iconv_t)-1)
         {
           handle_iconv_error (full_newset, "utf-8", 0);
           return -1;
         }
       iconv_close (cd);
       cd = iconv_open ("utf-8", full_newset);
-      if (cd == (iconv_t)-1) 
+      if (cd == (iconv_t)-1)
         {
           handle_iconv_error ("utf-8", full_newset, 0);
           return -1;
@@ -313,7 +303,7 @@ get_native_charset ()
 }
 
 /* Return true if the native charset is utf-8.  */
-int 
+int
 is_native_utf8 (void)
 {
   return no_translation;
@@ -335,7 +325,7 @@ native_to_utf8 (const char *orig_string)
   if (no_translation)
     {
       /* Already utf-8 encoded. */
-      buffer = jnlib_xstrdup (orig_string);
+      buffer = xstrdup (orig_string);
     }
   else if (!use_iconv)
     {
@@ -346,7 +336,7 @@ native_to_utf8 (const char *orig_string)
          if (*s & 0x80)
            length++;
        }
-      buffer = jnlib_xmalloc (length + 1);
+      buffer = xmalloc (length + 1);
       for (p = (unsigned char *)buffer, s = string; *s; s++)
        {
          if ( (*s & 0x80 ))
@@ -360,13 +350,13 @@ native_to_utf8 (const char *orig_string)
       *p = 0;
     }
   else
-    { 
+    {
       /* Need to use iconv.  */
       iconv_t cd;
       const char *inptr;
       char *outptr;
       size_t inbytes, outbytes;
-     
+
       cd = iconv_open ("utf-8", active_charset_name);
       if (cd == (iconv_t)-1)
         {
@@ -374,14 +364,14 @@ native_to_utf8 (const char *orig_string)
           return native_to_utf8 (string);
         }
 
-      for (s=string; *s; s++ ) 
+      for (s=string; *s; s++ )
         {
           length++;
           if ((*s & 0x80))
             length += 5; /* We may need up to 6 bytes for the utf8 output. */
         }
-      buffer = jnlib_xmalloc (length + 1);
-      
+      buffer = xmalloc (length + 1);
+
       inptr = string;
       inbytes = strlen (string);
       outptr = buffer;
@@ -392,7 +382,7 @@ native_to_utf8 (const char *orig_string)
           static int shown;
 
           if (!shown)
-            log_info (_("conversion from `%s' to `%s' failed: %s\n"),
+            log_info (_("conversion from '%s' to '%s' failed: %s\n"),
                       active_charset_name, "utf-8", strerror (errno));
           shown = 1;
           /* We don't do any conversion at all but use the strings as is. */
@@ -455,10 +445,10 @@ do_utf8_to_native (const char *string, size_t length, int delim,
          if (!nleft)
            {
              if (!(*s & 0x80))
-               {       
+               {
                   /* Plain ascii. */
                  if ( delim != -1
-                       && (*s < 0x20 || *s == 0x7f || *s == delim 
+                       && (*s < 0x20 || *s == 0x7f || *s == delim
                            || (delim && *s == '\\')))
                    {
                      n++;
@@ -497,35 +487,35 @@ do_utf8_to_native (const char *string, size_t length, int delim,
                  encbuf[encidx++] = *s;
                }
              else if ((*s & 0xf0) == 0xe0) /* 1110 xxxx */
-               {       
+               {
                  val = *s & 0x0f;
                  nleft = 2;
                  encidx = 0;
                  encbuf[encidx++] = *s;
                }
              else if ((*s & 0xf8) == 0xf0) /* 1111 0xxx */
-               {       
+               {
                  val = *s & 0x07;
                  nleft = 3;
                  encidx = 0;
                  encbuf[encidx++] = *s;
                }
              else if ((*s & 0xfc) == 0xf8) /* 1111 10xx */
-               {       
+               {
                  val = *s & 0x03;
                  nleft = 4;
                  encidx = 0;
                  encbuf[encidx++] = *s;
                }
              else if ((*s & 0xfe) == 0xfc) /* 1111 110x */
-               {               
+               {
                  val = *s & 0x01;
                  nleft = 5;
                  encidx = 0;
                  encbuf[encidx++] = *s;
                }
              else /* Invalid encoding: print as \xNN. */
-               {               
+               {
                  if (p)
                    {
                      sprintf (p, "\\x%02x", *s);
@@ -558,7 +548,7 @@ do_utf8_to_native (const char *string, size_t length, int delim,
              val <<= 6;
              val |= *s & 0x3f;
              if (!--nleft)  /* Ready. */
-               { 
+               {
                  if (no_translation)
                    {
                      if (p)
@@ -597,12 +587,12 @@ do_utf8_to_native (const char *string, size_t length, int delim,
                      if (val >= 0x80 && val < 256)
                        {
                           /* We can simply print this character */
-                         n++;  
+                         n++;
                          if (p)
                            *p++ = val;
                        }
                      else
-                       {       
+                       {
                           /* We do not have a translation: print utf8. */
                          if (p)
                            {
@@ -623,7 +613,7 @@ do_utf8_to_native (const char *string, size_t length, int delim,
       if (!buffer)
        {
           /* Allocate the buffer after the first pass. */
-         buffer = p = jnlib_xmalloc (n + 1);
+         buffer = p = xmalloc (n + 1);
        }
       else if (with_iconv)
         {
@@ -632,14 +622,14 @@ do_utf8_to_native (const char *string, size_t length, int delim,
           const char *inptr;
           char *outbuf, *outptr;
           size_t inbytes, outbytes;
-          
+
           *p = 0;  /* Terminate the buffer. */
 
           cd = iconv_open (active_charset_name, "utf-8");
           if (cd == (iconv_t)-1)
             {
               handle_iconv_error (active_charset_name, "utf-8", 1);
-              jnlib_free (buffer);
+              xfree (buffer);
               return utf8_to_native (string, length, delim);
             }
 
@@ -649,31 +639,31 @@ do_utf8_to_native (const char *string, size_t length, int delim,
           inbytes = n - 1;;
           inptr = buffer;
           outbytes = n * MB_LEN_MAX;
-          if (outbytes / MB_LEN_MAX != n) 
+          if (outbytes / MB_LEN_MAX != n)
             BUG (); /* Actually an overflow. */
-          outbuf = outptr = jnlib_xmalloc (outbytes);
+          outbuf = outptr = xmalloc (outbytes);
           if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
-                      &outptr, &outbytes) == (size_t)-1) 
+                      &outptr, &outbytes) == (size_t)-1)
             {
               static int shown;
-              
+
               if (!shown)
-                log_info (_("conversion from `%s' to `%s' failed: %s\n"),
+                log_info (_("conversion from '%s' to '%s' failed: %s\n"),
                           "utf-8", active_charset_name, strerror (errno));
               shown = 1;
               /* Didn't worked out.  Try again but without iconv.  */
-              jnlib_free (buffer);
+              xfree (buffer);
               buffer = NULL;
-              jnlib_free (outbuf);
+              xfree (outbuf);
               outbuf = do_utf8_to_native (string, length, delim, 0);
             }
             else /* Success.  */
-              { 
+              {
                 *outptr = 0; /* Make sure it is a string. */
                 /* We could realloc the buffer now but I doubt that it
                    makes much sense given that it will get freed
                    anyway soon after.  */
-                jnlib_free (buffer);
+                xfree (buffer);
               }
           iconv_close (cd);
           return outbuf;
@@ -703,14 +693,9 @@ utf8_to_native (const char *string, size_t length, int delim)
 
 /* Wrapper function for iconv_open, required for W32 as we dlopen that
    library on that system.  */
-jnlib_iconv_t 
+jnlib_iconv_t
 jnlib_iconv_open (const char *tocode, const char *fromcode)
 {
-#ifdef HAVE_W32_SYSTEM
-  if (load_libiconv ())
-    return (jnlib_iconv_t)(-1);
-#endif /*HAVE_W32_SYSTEM*/      
-
   return (jnlib_iconv_t)iconv_open (tocode, fromcode);
 }
 
@@ -722,13 +707,8 @@ jnlib_iconv (jnlib_iconv_t cd,
              const char **inbuf, size_t *inbytesleft,
              char **outbuf, size_t *outbytesleft)
 {
-
-#ifdef HAVE_W32_SYSTEM
-  if (load_libiconv ())
-    return 0;
-#endif /*HAVE_W32_SYSTEM*/      
-
-  return iconv ((iconv_t)cd, (char**)inbuf, inbytesleft, outbuf, outbytesleft);
+  return iconv ((iconv_t)cd, (ICONV_CONST char**)inbuf, inbytesleft,
+                outbuf, outbytesleft);
 }
 
 /* Wrapper function for iconv_close, required for W32 as we dlopen that
@@ -736,83 +716,123 @@ jnlib_iconv (jnlib_iconv_t cd,
 int
 jnlib_iconv_close (jnlib_iconv_t cd)
 {
-#ifdef HAVE_W32_SYSTEM
-  if (load_libiconv ())
-    return 0;
-#endif /*HAVE_W32_SYSTEM*/      
-
   return iconv_close ((iconv_t)cd);
 }
 
 
 #ifdef HAVE_W32_SYSTEM
-/* Return a malloced string encoded in UTF-8 from the wide char input
+/* Return a malloced string encoded for CODEPAGE from the wide char input
    string STRING.  Caller must free this value.  Returns NULL and sets
    ERRNO on failure.  Calling this function with STRING set to NULL is
    not defined.  */
-char *
-wchar_to_utf8 (const wchar_t *string)
+static char *
+wchar_to_cp (const wchar_t *string, unsigned int codepage)
 {
   int n;
   char *result;
 
-  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
+  n = WideCharToMultiByte (codepage, 0, string, -1, NULL, 0, NULL, NULL);
   if (n < 0)
     {
-      jnlib_set_errno (EINVAL);
+      gpg_err_set_errno (EINVAL);
       return NULL;
     }
 
-  result = jnlib_malloc (n+1);
+  result = xtrymalloc (n+1);
   if (!result)
     return NULL;
 
-  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
+  n = WideCharToMultiByte (codepage, 0, string, -1, result, n, NULL, NULL);
   if (n < 0)
     {
-      jnlib_free (result);
-      jnlib_set_errno (EINVAL);
+      xfree (result);
+      gpg_err_set_errno (EINVAL);
       result = NULL;
     }
   return result;
 }
 
 
-/* Return a malloced wide char string from an UTF-8 encoded input
+/* Return a malloced wide char string from a CODEPAGE encoded input
    string STRING.  Caller must free this value.  Returns NULL and sets
    ERRNO on failure.  Calling this function with STRING set to NULL is
    not defined.  */
-wchar_t *
-utf8_to_wchar (const char *string)
+static wchar_t *
+cp_to_wchar (const char *string, unsigned int codepage)
 {
   int n;
   size_t nbytes;
   wchar_t *result;
 
-  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
+  n = MultiByteToWideChar (codepage, 0, string, -1, NULL, 0);
   if (n < 0)
     {
-      jnlib_set_errno (EINVAL);
+      gpg_err_set_errno (EINVAL);
       return NULL;
     }
 
   nbytes = (size_t)(n+1) * sizeof(*result);
-  if (nbytes / sizeof(*result) != (n+1)) 
+  if (nbytes / sizeof(*result) != (n+1))
     {
-      jnlib_set_errno (ENOMEM);
+      gpg_err_set_errno (ENOMEM);
       return NULL;
     }
-  result = jnlib_malloc (nbytes);
+  result = xtrymalloc (nbytes);
   if (!result)
     return NULL;
 
-  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
+  n = MultiByteToWideChar (codepage, 0, string, -1, result, n);
   if (n < 0)
     {
-      free (result);
-      jnlib_set_errno (EINVAL);
+      xfree (result);
+      gpg_err_set_errno (EINVAL);
       result = NULL;
     }
   return result;
 }
+
+
+/* Return a malloced string encoded in the active code page from the
+ * wide char input string STRING.  Caller must free this value.
+ * Returns NULL and sets ERRNO on failure.  Calling this function with
+ * STRING set to NULL is not defined.  */
+char *
+wchar_to_native (const wchar_t *string)
+{
+  return wchar_to_cp (string, CP_ACP);
+}
+
+
+/* Return a malloced wide char string from an UTF-8 encoded input
+ * string STRING.  Caller must free this value.  Returns NULL and sets
+ * ERRNO on failure.  Calling this function with STRING set to NULL is
+ * not defined.  */
+wchar_t *
+native_to_wchar (const char *string)
+{
+  return cp_to_wchar (string, CP_ACP);
+}
+
+
+/* Return a malloced string encoded in UTF-8 from the wide char input
+ * string STRING.  Caller must free this value.  Returns NULL and sets
+ * ERRNO on failure.  Calling this function with STRING set to NULL is
+ * not defined.  */
+char *
+wchar_to_utf8 (const wchar_t *string)
+{
+  return wchar_to_cp (string, CP_UTF8);
+}
+
+
+/* Return a malloced wide char string from an UTF-8 encoded input
+ * string STRING.  Caller must free this value.  Returns NULL and sets
+ * ERRNO on failure.  Calling this function with STRING set to NULL is
+ * not defined.  */
+wchar_t *
+utf8_to_wchar (const char *string)
+{
+  return cp_to_wchar (string, CP_UTF8);
+}
+
 #endif /*HAVE_W32_SYSTEM*/