common: Add meta option ignore-invalid-option.
[gnupg.git] / common / utf8conv.c
1 /* utf8conf.c -  UTF8 character set conversion
2  * Copyright (C) 1994, 1998, 1999, 2000, 2001, 2003, 2006,
3  *               2008, 2010  Free Software Foundation, Inc.
4  *
5  * This file is part of JNLIB, which is a subsystem of GnuPG.
6  *
7  * JNLIB is free software; you can redistribute it and/or modify it
8  * under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * JNLIB is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * General Public License for more details.
26  *
27  * You should have received a copies of the GNU General Public License
28  * and the GNU Lesser General Public License along with this program;
29  * if not, see <http://www.gnu.org/licenses/>.
30  */
31
32 #include <config.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <ctype.h>
37 #ifdef HAVE_LANGINFO_CODESET
38 #include <langinfo.h>
39 #endif
40 #include <errno.h>
41 #if !defined HAVE_W32_SYSTEM && !defined HAVE_ANDROID_SYSTEM
42 # include <iconv.h>
43 #endif
44
45 #include "libjnlib-config.h"
46 #include "stringhelp.h"
47 #include "dynload.h"
48 #include "utf8conv.h"
49
50 #ifndef MB_LEN_MAX
51 #define MB_LEN_MAX 16
52 #endif
53
54 static const char *active_charset_name = "iso-8859-1";
55 static int no_translation;     /* Set to true if we let simply pass through. */
56 static int use_iconv;          /* iconv comversion fucntions required. */
57
58
59 #ifdef HAVE_ANDROID_SYSTEM
60 /* Fake stuff to get things building.  */
61 typedef void *iconv_t;
62 #define ICONV_CONST
63
64 static iconv_t
65 iconv_open (const char *tocode, const char *fromcode)
66 {
67   (void)tocode;
68   (void)fromcode;
69   return (iconv_t)(-1);
70 }
71
72 static size_t
73 iconv (iconv_t cd, char **inbuf, size_t *inbytesleft,
74        char **outbuf, size_t *outbytesleft)
75 {
76   (void)cd;
77   (void)inbuf;
78   (void)inbytesleft;
79   (void)outbuf;
80   (void)outbytesleft;
81   return (size_t)(0);
82 }
83
84 static int
85 iconv_close (iconv_t cd)
86 {
87   (void)cd;
88   return 0;
89 }
90
91
92 static int
93 load_libiconv (void)
94 {
95   return -1;
96 }
97
98 #elif defined HAVE_W32_SYSTEM
99 /* Under W32 we dlopen the iconv dll and don't require any iconv
100    related headers at all.  However we need to define some stuff.  */
101 typedef void *iconv_t;
102 #ifndef ICONV_CONST
103 #define ICONV_CONST
104 #endif
105 static iconv_t (* __stdcall iconv_open) (const char *tocode,
106                                          const char *fromcode);
107 static size_t  (* __stdcall iconv) (iconv_t cd,
108                                     char **inbuf, size_t *inbytesleft,
109                                     char **outbuf, size_t *outbytesleft);
110 static int     (* __stdcall iconv_close) (iconv_t cd);
111
112 static int
113 load_libiconv (void)
114 {
115 #ifdef HAVE_W32CE_SYSTEM
116   return -1; /* FIXME No libiconv yet - Need to investigate whether it
117                 is at all required.  */
118 #else
119   static int done;
120
121   if (!done)
122     {
123       void *handle;
124
125       done = 1; /* Do it right now because we might get called recursivly
126                    through gettext.  */
127
128       handle = dlopen ("iconv.dll", RTLD_LAZY);
129       if (handle)
130         {
131           iconv_open  = dlsym (handle, "libiconv_open");
132           if (iconv_open)
133             iconv = dlsym (handle, "libiconv");
134           if (iconv)
135             iconv_close = dlsym (handle, "libiconv_close");
136         }
137       if (!handle || !iconv_close)
138         {
139           log_info (_("error loading '%s': %s\n"),
140                      "iconv.dll",  dlerror ());
141           log_info (_("please see %s for more information\n"),
142                     "http://www.gnupg.org/download/iconv.html");
143           iconv_open = NULL;
144           iconv = NULL;
145           iconv_close = NULL;
146           if (handle)
147             dlclose (handle);
148         }
149     }
150   return iconv_open? 0: -1;
151 #endif
152 }
153 #endif /*HAVE_W32_SYSTEM*/
154
155
156 /* Error handler for iconv failures. This is needed to not clutter the
157    output with repeated diagnostics about a missing conversion. */
158 static void
159 handle_iconv_error (const char *to, const char *from, int use_fallback)
160 {
161   if (errno == EINVAL)
162     {
163       static int shown1, shown2;
164       int x;
165
166       if (to && !strcmp (to, "utf-8"))
167         {
168           x = shown1;
169           shown1 = 1;
170         }
171       else
172         {
173           x = shown2;
174           shown2 = 1;
175         }
176
177       if (!x)
178         log_info (_("conversion from '%s' to '%s' not available\n"),
179                   from, to);
180     }
181   else
182     {
183       static int shown;
184
185       if (!shown)
186         log_info (_("iconv_open failed: %s\n"), strerror (errno));
187       shown = 1;
188     }
189
190   if (use_fallback)
191     {
192       /* To avoid further error messages we fallback to Latin-1 for the
193          native encoding.  This is justified as one can expect that on a
194          utf-8 enabled system nl_langinfo() will work and thus we won't
195          never get to here.  Thus Latin-1 seems to be a reasonable
196          default.  */
197       active_charset_name = "iso-8859-1";
198       no_translation = 0;
199       use_iconv = 0;
200     }
201 }
202
203
204
205 int
206 set_native_charset (const char *newset)
207 {
208   const char *full_newset;
209
210   if (!newset)
211     {
212 #ifdef HAVE_ANDROID_SYSTEM
213       newset = "utf-8";
214 #elif defined HAVE_W32_SYSTEM
215       static char codepage[30];
216       unsigned int cpno;
217       const char *aliases;
218
219       /* We are a console program thus we need to use the
220          GetConsoleOutputCP function and not the the GetACP which
221          would give the codepage for a GUI program.  Note this is not
222          a bulletproof detection because GetConsoleCP might return a
223          different one for console input.  Not sure how to cope with
224          that.  If the console Code page is not known we fall back to
225          the system code page.  */
226 #ifndef HAVE_W32CE_SYSTEM
227       cpno = GetConsoleOutputCP ();
228       if (!cpno)
229 #endif
230         cpno = GetACP ();
231       sprintf (codepage, "CP%u", cpno );
232       /* Resolve alias.  We use a long string string and not the usual
233          array to optimize if the code is taken to a DSO.  Taken from
234          libiconv 1.9.2. */
235       newset = codepage;
236       for (aliases = ("CP936"   "\0" "GBK" "\0"
237                       "CP1361"  "\0" "JOHAB" "\0"
238                       "CP20127" "\0" "ASCII" "\0"
239                       "CP20866" "\0" "KOI8-R" "\0"
240                       "CP21866" "\0" "KOI8-RU" "\0"
241                       "CP28591" "\0" "ISO-8859-1" "\0"
242                       "CP28592" "\0" "ISO-8859-2" "\0"
243                       "CP28593" "\0" "ISO-8859-3" "\0"
244                       "CP28594" "\0" "ISO-8859-4" "\0"
245                       "CP28595" "\0" "ISO-8859-5" "\0"
246                       "CP28596" "\0" "ISO-8859-6" "\0"
247                       "CP28597" "\0" "ISO-8859-7" "\0"
248                       "CP28598" "\0" "ISO-8859-8" "\0"
249                       "CP28599" "\0" "ISO-8859-9" "\0"
250                       "CP28605" "\0" "ISO-8859-15" "\0"
251                       "CP65001" "\0" "UTF-8" "\0");
252            *aliases;
253            aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
254         {
255           if (!strcmp (codepage, aliases) ||(*aliases == '*' && !aliases[1]))
256             {
257               newset = aliases + strlen (aliases) + 1;
258               break;
259             }
260         }
261
262 #else /*!HAVE_W32_SYSTEM && !HAVE_ANDROID_SYSTEM*/
263
264 #ifdef HAVE_LANGINFO_CODESET
265       newset = nl_langinfo (CODESET);
266 #else /*!HAVE_LANGINFO_CODESET*/
267       /* Try to get the used charset from environment variables.  */
268       static char codepage[30];
269       const char *lc, *dot, *mod;
270
271       strcpy (codepage, "iso-8859-1");
272       lc = getenv ("LC_ALL");
273       if (!lc || !*lc)
274         {
275           lc = getenv ("LC_CTYPE");
276           if (!lc || !*lc)
277             lc = getenv ("LANG");
278         }
279       if (lc && *lc)
280         {
281           dot = strchr (lc, '.');
282           if (dot)
283             {
284               mod = strchr (++dot, '@');
285               if (!mod)
286                 mod = dot + strlen (dot);
287               if (mod - dot < sizeof codepage && dot != mod)
288                 {
289                   memcpy (codepage, dot, mod - dot);
290                   codepage [mod - dot] = 0;
291                 }
292             }
293         }
294       newset = codepage;
295 #endif /*!HAVE_LANGINFO_CODESET*/
296 #endif /*!HAVE_W32_SYSTEM && !HAVE_ANDROID_SYSTEM*/
297     }
298
299   full_newset = newset;
300   if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3))
301     {
302       newset += 3;
303       if (*newset == '-' || *newset == '_')
304         newset++;
305     }
306
307   /* Note that we silently assume that plain ASCII is actually meant
308      as Latin-1.  This makes sense because many Unix system don't have
309      their locale set up properly and thus would get annoying error
310      messages and we have to handle all the "bug" reports. Latin-1 has
311      always been the character set used for 8 bit characters on Unix
312      systems. */
313   if ( !*newset
314        || !ascii_strcasecmp (newset, "8859-1" )
315        || !ascii_strcasecmp (newset, "646" )
316        || !ascii_strcasecmp (newset, "ASCII" )
317        || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" )
318        )
319     {
320       active_charset_name = "iso-8859-1";
321       no_translation = 0;
322       use_iconv = 0;
323     }
324   else if ( !ascii_strcasecmp (newset, "utf8" )
325             || !ascii_strcasecmp(newset, "utf-8") )
326     {
327       active_charset_name = "utf-8";
328       no_translation = 1;
329       use_iconv = 0;
330     }
331   else
332     {
333       iconv_t cd;
334
335 #if defined HAVE_W32_SYSTEM || defined HAVE_ANDROID_SYSTEM
336       if (load_libiconv ())
337         return -1;
338 #endif /*HAVE_W32_SYSTEM || HAVE_ANDROID_SYSTEM*/
339
340       cd = iconv_open (full_newset, "utf-8");
341       if (cd == (iconv_t)-1)
342         {
343           handle_iconv_error (full_newset, "utf-8", 0);
344           return -1;
345         }
346       iconv_close (cd);
347       cd = iconv_open ("utf-8", full_newset);
348       if (cd == (iconv_t)-1)
349         {
350           handle_iconv_error ("utf-8", full_newset, 0);
351           return -1;
352         }
353       iconv_close (cd);
354       active_charset_name = full_newset;
355       no_translation = 0;
356       use_iconv = 1;
357     }
358   return 0;
359 }
360
361 const char *
362 get_native_charset ()
363 {
364   return active_charset_name;
365 }
366
367 /* Return true if the native charset is utf-8.  */
368 int
369 is_native_utf8 (void)
370 {
371   return no_translation;
372 }
373
374
375 /* Convert string, which is in native encoding to UTF8 and return a
376    new allocated UTF-8 string.  This function terminates the process
377    on memory shortage.  */
378 char *
379 native_to_utf8 (const char *orig_string)
380 {
381   const unsigned char *string = (const unsigned char *)orig_string;
382   const unsigned char *s;
383   char *buffer;
384   unsigned char *p;
385   size_t length = 0;
386
387   if (no_translation)
388     {
389       /* Already utf-8 encoded. */
390       buffer = jnlib_xstrdup (orig_string);
391     }
392   else if (!use_iconv)
393     {
394       /* For Latin-1 we can avoid the iconv overhead. */
395       for (s = string; *s; s++)
396         {
397           length++;
398           if (*s & 0x80)
399             length++;
400         }
401       buffer = jnlib_xmalloc (length + 1);
402       for (p = (unsigned char *)buffer, s = string; *s; s++)
403         {
404           if ( (*s & 0x80 ))
405             {
406               *p++ = 0xc0 | ((*s >> 6) & 3);
407               *p++ = 0x80 | (*s & 0x3f);
408             }
409           else
410             *p++ = *s;
411         }
412       *p = 0;
413     }
414   else
415     {
416       /* Need to use iconv.  */
417       iconv_t cd;
418       const char *inptr;
419       char *outptr;
420       size_t inbytes, outbytes;
421
422       cd = iconv_open ("utf-8", active_charset_name);
423       if (cd == (iconv_t)-1)
424         {
425           handle_iconv_error ("utf-8", active_charset_name, 1);
426           return native_to_utf8 (string);
427         }
428
429       for (s=string; *s; s++ )
430         {
431           length++;
432           if ((*s & 0x80))
433             length += 5; /* We may need up to 6 bytes for the utf8 output. */
434         }
435       buffer = jnlib_xmalloc (length + 1);
436
437       inptr = string;
438       inbytes = strlen (string);
439       outptr = buffer;
440       outbytes = length;
441       if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
442                   &outptr, &outbytes) == (size_t)-1)
443         {
444           static int shown;
445
446           if (!shown)
447             log_info (_("conversion from '%s' to '%s' failed: %s\n"),
448                       active_charset_name, "utf-8", strerror (errno));
449           shown = 1;
450           /* We don't do any conversion at all but use the strings as is. */
451           strcpy (buffer, string);
452         }
453       else /* Success.  */
454         {
455           *outptr = 0;
456           /* We could realloc the buffer now but I doubt that it makes
457              much sense given that it will get freed anyway soon
458              after.  */
459         }
460       iconv_close (cd);
461     }
462   return buffer;
463 }
464
465
466
467 static char *
468 do_utf8_to_native (const char *string, size_t length, int delim,
469                    int with_iconv)
470 {
471   int nleft;
472   int i;
473   unsigned char encbuf[8];
474   int encidx;
475   const unsigned char *s;
476   size_t n;
477   char *buffer = NULL;
478   char *p = NULL;
479   unsigned long val = 0;
480   size_t slen;
481   int resync = 0;
482
483   /* First pass (p==NULL): count the extended utf-8 characters.  */
484   /* Second pass (p!=NULL): create string.  */
485   for (;;)
486     {
487       for (slen = length, nleft = encidx = 0, n = 0,
488              s = (const unsigned char *)string;
489            slen;
490            s++, slen--)
491         {
492           if (resync)
493             {
494               if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)))
495                 {
496                   /* Still invalid. */
497                   if (p)
498                     {
499                       sprintf (p, "\\x%02x", *s);
500                       p += 4;
501                     }
502                   n += 4;
503                   continue;
504                 }
505               resync = 0;
506             }
507           if (!nleft)
508             {
509               if (!(*s & 0x80))
510                 {
511                   /* Plain ascii. */
512                   if ( delim != -1
513                        && (*s < 0x20 || *s == 0x7f || *s == delim
514                            || (delim && *s == '\\')))
515                     {
516                       n++;
517                       if (p)
518                         *p++ = '\\';
519                       switch (*s)
520                         {
521                         case '\n': n++; if ( p ) *p++ = 'n'; break;
522                         case '\r': n++; if ( p ) *p++ = 'r'; break;
523                         case '\f': n++; if ( p ) *p++ = 'f'; break;
524                         case '\v': n++; if ( p ) *p++ = 'v'; break;
525                         case '\b': n++; if ( p ) *p++ = 'b'; break;
526                         case    0: n++; if ( p ) *p++ = '0'; break;
527                         default:
528                           n += 3;
529                           if (p)
530                             {
531                               sprintf (p, "x%02x", *s);
532                               p += 3;
533                             }
534                           break;
535                         }
536                     }
537                   else
538                     {
539                       if (p)
540                         *p++ = *s;
541                       n++;
542                     }
543                 }
544               else if ((*s & 0xe0) == 0xc0) /* 110x xxxx */
545                 {
546                   val = *s & 0x1f;
547                   nleft = 1;
548                   encidx = 0;
549                   encbuf[encidx++] = *s;
550                 }
551               else if ((*s & 0xf0) == 0xe0) /* 1110 xxxx */
552                 {
553                   val = *s & 0x0f;
554                   nleft = 2;
555                   encidx = 0;
556                   encbuf[encidx++] = *s;
557                 }
558               else if ((*s & 0xf8) == 0xf0) /* 1111 0xxx */
559                 {
560                   val = *s & 0x07;
561                   nleft = 3;
562                   encidx = 0;
563                   encbuf[encidx++] = *s;
564                 }
565               else if ((*s & 0xfc) == 0xf8) /* 1111 10xx */
566                 {
567                   val = *s & 0x03;
568                   nleft = 4;
569                   encidx = 0;
570                   encbuf[encidx++] = *s;
571                 }
572               else if ((*s & 0xfe) == 0xfc) /* 1111 110x */
573                 {
574                   val = *s & 0x01;
575                   nleft = 5;
576                   encidx = 0;
577                   encbuf[encidx++] = *s;
578                 }
579               else /* Invalid encoding: print as \xNN. */
580                 {
581                   if (p)
582                     {
583                       sprintf (p, "\\x%02x", *s);
584                       p += 4;
585                     }
586                   n += 4;
587                   resync = 1;
588                 }
589             }
590           else if (*s < 0x80 || *s >= 0xc0) /* Invalid utf-8 */
591             {
592               if (p)
593                 {
594                   for (i = 0; i < encidx; i++)
595                     {
596                       sprintf (p, "\\x%02x", encbuf[i]);
597                       p += 4;
598                     }
599                   sprintf (p, "\\x%02x", *s);
600                   p += 4;
601                 }
602               n += 4 + 4 * encidx;
603               nleft = 0;
604               encidx = 0;
605               resync = 1;
606             }
607           else
608             {
609               encbuf[encidx++] = *s;
610               val <<= 6;
611               val |= *s & 0x3f;
612               if (!--nleft)  /* Ready. */
613                 {
614                   if (no_translation)
615                     {
616                       if (p)
617                         {
618                           for (i = 0; i < encidx; i++)
619                             *p++ = encbuf[i];
620                         }
621                       n += encidx;
622                       encidx = 0;
623                     }
624                   else if (with_iconv)
625                     {
626                       /* Our strategy for using iconv is a bit strange
627                          but it better keeps compatibility with
628                          previous versions in regard to how invalid
629                          encodings are displayed.  What we do is to
630                          keep the utf-8 as is and have the real
631                          translation step then at the end.  Yes, I
632                          know that this is ugly.  However we are short
633                          of the 1.4 release and for this branch we
634                          should not mess too much around with iconv
635                          things.  One reason for this is that we don't
636                          know enough about non-GNU iconv
637                          implementation and want to minimize the risk
638                          of breaking the code on too many platforms.  */
639                         if ( p )
640                           {
641                             for (i=0; i < encidx; i++ )
642                               *p++ = encbuf[i];
643                           }
644                         n += encidx;
645                         encidx = 0;
646                     }
647                   else  /* Latin-1 case. */
648                     {
649                       if (val >= 0x80 && val < 256)
650                         {
651                           /* We can simply print this character */
652                           n++;
653                           if (p)
654                             *p++ = val;
655                         }
656                       else
657                         {
658                           /* We do not have a translation: print utf8. */
659                           if (p)
660                             {
661                               for (i = 0; i < encidx; i++)
662                                 {
663                                   sprintf (p, "\\x%02x", encbuf[i]);
664                                   p += 4;
665                                 }
666                             }
667                           n += encidx * 4;
668                           encidx = 0;
669                         }
670                     }
671                 }
672
673             }
674         }
675       if (!buffer)
676         {
677           /* Allocate the buffer after the first pass. */
678           buffer = p = jnlib_xmalloc (n + 1);
679         }
680       else if (with_iconv)
681         {
682           /* Note: See above for comments.  */
683           iconv_t cd;
684           const char *inptr;
685           char *outbuf, *outptr;
686           size_t inbytes, outbytes;
687
688           *p = 0;  /* Terminate the buffer. */
689
690           cd = iconv_open (active_charset_name, "utf-8");
691           if (cd == (iconv_t)-1)
692             {
693               handle_iconv_error (active_charset_name, "utf-8", 1);
694               jnlib_free (buffer);
695               return utf8_to_native (string, length, delim);
696             }
697
698           /* Allocate a new buffer large enough to hold all possible
699              encodings. */
700           n = p - buffer + 1;
701           inbytes = n - 1;;
702           inptr = buffer;
703           outbytes = n * MB_LEN_MAX;
704           if (outbytes / MB_LEN_MAX != n)
705             BUG (); /* Actually an overflow. */
706           outbuf = outptr = jnlib_xmalloc (outbytes);
707           if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
708                       &outptr, &outbytes) == (size_t)-1)
709             {
710               static int shown;
711
712               if (!shown)
713                 log_info (_("conversion from '%s' to '%s' failed: %s\n"),
714                           "utf-8", active_charset_name, strerror (errno));
715               shown = 1;
716               /* Didn't worked out.  Try again but without iconv.  */
717               jnlib_free (buffer);
718               buffer = NULL;
719               jnlib_free (outbuf);
720               outbuf = do_utf8_to_native (string, length, delim, 0);
721             }
722             else /* Success.  */
723               {
724                 *outptr = 0; /* Make sure it is a string. */
725                 /* We could realloc the buffer now but I doubt that it
726                    makes much sense given that it will get freed
727                    anyway soon after.  */
728                 jnlib_free (buffer);
729               }
730           iconv_close (cd);
731           return outbuf;
732         }
733       else /* Not using iconv. */
734         {
735           *p = 0; /* Make sure it is a string. */
736           return buffer;
737         }
738     }
739 }
740
741 /* Convert string, which is in UTF-8 to native encoding.  Replace
742    illegal encodings by some "\xnn" and quote all control
743    characters. A character with value DELIM will always be quoted, it
744    must be a vanilla ASCII character.  A DELIM value of -1 is special:
745    it disables all quoting of control characters.  This function
746    terminates the process on memory shortage.  */
747 char *
748 utf8_to_native (const char *string, size_t length, int delim)
749 {
750   return do_utf8_to_native (string, length, delim, use_iconv);
751 }
752
753
754
755
756 /* Wrapper function for iconv_open, required for W32 as we dlopen that
757    library on that system.  */
758 jnlib_iconv_t
759 jnlib_iconv_open (const char *tocode, const char *fromcode)
760 {
761 #if defined HAVE_W32_SYSTEM || defined HAVE_ANDROID_SYSTEM
762   if (load_libiconv ())
763     return (jnlib_iconv_t)(-1);
764 #endif /*HAVE_W32_SYSTEM || HAVE_ANDROID_SYSTEM*/
765
766   return (jnlib_iconv_t)iconv_open (tocode, fromcode);
767 }
768
769
770 /* Wrapper function for iconv, required for W32 as we dlopen that
771    library on that system.  */
772 size_t
773 jnlib_iconv (jnlib_iconv_t cd,
774              const char **inbuf, size_t *inbytesleft,
775              char **outbuf, size_t *outbytesleft)
776 {
777
778 #if defined HAVE_W32_SYSTEM || defined HAVE_ANDROID_SYSTEM
779   if (load_libiconv ())
780     return 0;
781 #endif /*HAVE_W32_SYSTEM || HAVE_ANDROID_SYSTEM*/
782
783   return iconv ((iconv_t)cd, (char**)inbuf, inbytesleft, outbuf, outbytesleft);
784 }
785
786 /* Wrapper function for iconv_close, required for W32 as we dlopen that
787    library on that system.  */
788 int
789 jnlib_iconv_close (jnlib_iconv_t cd)
790 {
791 #if defined HAVE_W32_SYSTEM || defined HAVE_ANDROID_SYSTEM
792   if (load_libiconv ())
793     return 0;
794 #endif /*HAVE_W32_SYSTEM || HAVE_ANDROID_SYSTEM*/
795
796   return iconv_close ((iconv_t)cd);
797 }
798
799
800 #ifdef HAVE_W32_SYSTEM
801 /* Return a malloced string encoded in UTF-8 from the wide char input
802    string STRING.  Caller must free this value.  Returns NULL and sets
803    ERRNO on failure.  Calling this function with STRING set to NULL is
804    not defined.  */
805 char *
806 wchar_to_utf8 (const wchar_t *string)
807 {
808   int n;
809   char *result;
810
811   n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
812   if (n < 0)
813     {
814       jnlib_set_errno (EINVAL);
815       return NULL;
816     }
817
818   result = jnlib_malloc (n+1);
819   if (!result)
820     return NULL;
821
822   n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
823   if (n < 0)
824     {
825       jnlib_free (result);
826       jnlib_set_errno (EINVAL);
827       result = NULL;
828     }
829   return result;
830 }
831
832
833 /* Return a malloced wide char string from an UTF-8 encoded input
834    string STRING.  Caller must free this value.  Returns NULL and sets
835    ERRNO on failure.  Calling this function with STRING set to NULL is
836    not defined.  */
837 wchar_t *
838 utf8_to_wchar (const char *string)
839 {
840   int n;
841   size_t nbytes;
842   wchar_t *result;
843
844   n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
845   if (n < 0)
846     {
847       jnlib_set_errno (EINVAL);
848       return NULL;
849     }
850
851   nbytes = (size_t)(n+1) * sizeof(*result);
852   if (nbytes / sizeof(*result) != (n+1))
853     {
854       jnlib_set_errno (ENOMEM);
855       return NULL;
856     }
857   result = jnlib_malloc (nbytes);
858   if (!result)
859     return NULL;
860
861   n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
862   if (n < 0)
863     {
864       free (result);
865       jnlib_set_errno (EINVAL);
866       result = NULL;
867     }
868   return result;
869 }
870 #endif /*HAVE_W32_SYSTEM || HAVE_ANDROID_SYSTEM*/