(load_libiconv) [_WIN32]: new.
[gnupg.git] / util / strgutil.c
1 /* strgutil.c -  string utilities
2  * Copyright (C) 1994, 1998, 1999, 2000, 2001,
3  *               2003 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #ifdef HAVE_LANGINFO_CODESET
28 #include <langinfo.h>
29 #endif
30
31 /* For W32 we use dynamic loading of the iconv dll and don't need any
32  * iconv headers at all. */
33 #ifndef _WIN32
34 # ifndef HAVE_ICONV
35 #  undef USE_GNUPG_ICONV
36 # endif
37 #endif
38
39 #ifdef USE_GNUPG_ICONV
40 # include <limits.h>
41 # ifndef _WIN32
42 #  include <iconv.h>
43 # endif
44 #endif
45
46 #include "types.h"
47 #include "util.h"
48 #include "memory.h"
49 #include "i18n.h"
50 #include "dynload.h"
51
52
53 #ifndef USE_GNUPG_ICONV
54 static ushort koi8_unicode[128] = {
55     0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
56     0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
57     0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
58     0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
59     0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
60     0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,
61     0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
62     0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9,
63     0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
64     0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
65     0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
66     0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
67     0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
68     0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
69     0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
70     0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
71 };
72
73 static ushort latin2_unicode[128] = {
74     0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
75     0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
76     0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
77     0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
78     0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,
79     0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,
80     0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,
81     0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
82     0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,
83     0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,
84     0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,
85     0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,
86     0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,
87     0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,
88     0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
89     0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
90 };
91 #endif /*!USE_GNUPG_ICONV*/
92
93
94 #ifndef MB_LEN_MAX
95 #define MB_LEN_MAX 16
96 #endif
97
98
99 static const char *active_charset_name = "iso-8859-1";
100 static ushort *active_charset = NULL;
101 static int no_translation = 0;
102 static int use_iconv = 0;
103
104
105 #ifdef _WIN32
106 typedef void* iconv_t;
107 #ifndef ICONV_CONST
108 #define ICONV_CONST const 
109 #endif
110
111 iconv_t (* __stdcall iconv_open) (const char *tocode, const char *fromcode);
112 size_t  (* __stdcall iconv) (iconv_t cd,
113                              const char **inbuf, size_t *inbytesleft,
114                              char **outbuf, size_t *outbytesleft);
115 int     (* __stdcall iconv_close) (iconv_t cd);
116
117 #endif /*_WIN32*/
118
119
120
121 #ifdef _WIN32
122 static int 
123 load_libiconv (void)
124 {
125   static int done;
126   
127   if (!done)
128     {
129       void *handle;
130
131       done = 1; /* Do it right now because we might get called recursivly
132                    through gettext.  */
133     
134       handle = dlopen ("iconv.dll", RTLD_LAZY);
135       if (handle)
136         {
137           iconv_open  = dlsym (handle, "libiconv_open");
138           if (iconv_open)
139             iconv      = dlsym (handle, "libiconv");
140           if (iconv)    
141             iconv_close = dlsym (handle, "libiconv_close");
142         }
143       if (!handle || !iconv_close)
144         {
145           log_error (_("error loading `%s': %s\n"),
146                      "iconv.dll",  dlerror ());
147           iconv_open = NULL;
148           iconv = NULL;
149           iconv_close = NULL;
150           if (handle)
151               dlclose (handle);
152         }
153     }
154   return iconv_open? 0: -1;
155 }    
156 #endif /* _WIN32 */
157
158
159
160
161 void
162 free_strlist( STRLIST sl )
163 {
164     STRLIST sl2;
165
166     for(; sl; sl = sl2 ) {
167         sl2 = sl->next;
168         m_free(sl);
169     }
170 }
171
172
173 STRLIST
174 add_to_strlist( STRLIST *list, const char *string )
175 {
176     STRLIST sl;
177
178     sl = m_alloc( sizeof *sl + strlen(string));
179     sl->flags = 0;
180     strcpy(sl->d, string);
181     sl->next = *list;
182     *list = sl;
183     return sl;
184 }
185
186 /****************
187  * Same as add_to_strlist() but if is_utf8 is *not* set a conversion
188  * to UTF8 is done
189  */
190 STRLIST
191 add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
192 {
193     STRLIST sl;
194
195     if( is_utf8 )
196         sl = add_to_strlist( list, string );
197     else {
198         char *p = native_to_utf8( string );
199         sl = add_to_strlist( list, p );
200         m_free( p );
201     }
202     return sl;
203 }
204
205 STRLIST
206 append_to_strlist( STRLIST *list, const char *string )
207 {
208     STRLIST r, sl;
209
210     sl = m_alloc( sizeof *sl + strlen(string));
211     sl->flags = 0;
212     strcpy(sl->d, string);
213     sl->next = NULL;
214     if( !*list )
215         *list = sl;
216     else {
217         for( r = *list; r->next; r = r->next )
218             ;
219         r->next = sl;
220     }
221     return sl;
222 }
223
224 STRLIST
225 append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
226 {
227     STRLIST sl;
228
229     if( is_utf8 )
230         sl = append_to_strlist( list, string );
231     else {
232         char *p = native_to_utf8( string );
233         sl = append_to_strlist( list, p );
234         m_free( p );
235     }
236     return sl;
237 }
238
239
240 STRLIST
241 strlist_prev( STRLIST head, STRLIST node )
242 {
243     STRLIST n;
244
245     for(n=NULL; head && head != node; head = head->next )
246         n = head;
247     return n;
248 }
249
250 STRLIST
251 strlist_last( STRLIST node )
252 {
253     if( node )
254         for( ; node->next ; node = node->next )
255             ;
256     return node;
257 }
258
259 char *
260 pop_strlist( STRLIST *list )
261 {
262   char *str=NULL;
263   STRLIST sl=*list;
264
265   if(sl)
266     {
267       str=m_alloc(strlen(sl->d)+1);
268       strcpy(str,sl->d);
269
270       *list=sl->next;
271       m_free(sl);
272     }
273
274   return str;
275 }
276
277 /****************
278  * Look for the substring SUB in buffer and return a pointer to that
279  * substring in BUF or NULL if not found.
280  * Comparison is case-insensitive.
281  */
282 const char *
283 memistr( const char *buf, size_t buflen, const char *sub )
284 {
285     const byte *t, *s ;
286     size_t n;
287
288     for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
289         if( toupper(*t) == toupper(*s) ) {
290             for( buf=t++, buflen = n--, s++;
291                  n && toupper(*t) == toupper(*s); t++, s++, n-- )
292                 ;
293             if( !*s )
294                 return buf;
295             t = buf; n = buflen; s = sub ;
296         }
297
298     return NULL ;
299 }
300
301 const char *
302 ascii_memistr( const char *buf, size_t buflen, const char *sub )
303 {
304     const byte *t, *s ;
305     size_t n;
306
307     for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
308         if( ascii_toupper(*t) == ascii_toupper(*s) ) {
309             for( buf=t++, buflen = n--, s++;
310                  n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
311                 ;
312             if( !*s )
313                 return buf;
314             t = buf; n = buflen; s = sub ;
315         }
316
317     return NULL ;
318 }
319
320
321 /* Like strncpy() but copy at max N-1 bytes and append a '\0'.  With
322  * N given as 0 nothing is copied at all. With DEST given as NULL
323  * sufficient memory is allocated using m_alloc (note that m_alloc is
324  * guaranteed to succeed or to abort the process).  */
325 char *
326 mem2str( char *dest , const void *src , size_t n )
327 {
328     char *d;
329     const char *s;
330
331     if( n ) {
332         if( !dest )
333             dest = m_alloc( n ) ;
334         d = dest;
335         s = src ;
336         for(n--; n && *s; n-- )
337             *d++ = *s++;
338         *d = '\0' ;
339     }
340
341     return dest ;
342 }
343
344
345 /*
346  * Remove leading and trailing white spaces
347  */
348 char *
349 trim_spaces( char *str )
350 {
351     char *string, *p, *mark;
352
353     string = str;
354     /* Find first non space character. */
355     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
356         ;
357     /* Move characters. */
358     for( (mark = NULL); (*string = *p); string++, p++ )
359         if( isspace( *(byte*)p ) ) {
360             if( !mark )
361                 mark = string ;
362         }
363         else
364             mark = NULL ;
365     if( mark )
366         *mark = '\0' ;  /* Remove trailing spaces.  */
367
368     return str ;
369 }
370
371
372
373 unsigned int
374 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
375 {
376     byte *p, *mark;
377     unsigned n;
378
379     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
380         if( strchr(trimchars, *p ) ) {
381             if( !mark )
382                 mark = p;
383         }
384         else
385             mark = NULL;
386     }
387
388     if( mark ) {
389         *mark = 0;
390         return mark - line;
391     }
392     return len;
393 }
394
395 /****************
396  * Remove trailing white spaces and return the length of the buffer
397  */
398 unsigned
399 trim_trailing_ws( byte *line, unsigned len )
400 {
401     return trim_trailing_chars( line, len, " \t\r\n" );
402 }
403
404
405 unsigned int
406 check_trailing_chars( const byte *line, unsigned int len,
407                       const char *trimchars )
408 {
409     const byte *p, *mark;
410     unsigned int n;
411
412     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
413         if( strchr(trimchars, *p ) ) {
414             if( !mark )
415                 mark = p;
416         }
417         else
418             mark = NULL;
419     }
420
421     if( mark ) {
422         return mark - line;
423     }
424     return len;
425 }
426
427
428 /****************
429  * Remove trailing white spaces and return the length of the buffer
430  */
431 unsigned int
432 check_trailing_ws( const byte *line, unsigned int len )
433 {
434     return check_trailing_chars( line, len, " \t\r\n" );
435 }
436
437
438
439 int
440 string_count_chr( const char *string, int c )
441 {
442     int count;
443     for(count=0; *string; string++ )
444         if( *string == c )
445             count++;
446     return count;
447 }
448
449 #ifdef USE_GNUPG_ICONV
450 static void
451 handle_iconv_error (const char *to, const char *from, int use_fallback)
452 {
453   if (errno == EINVAL)
454     log_error (_("conversion from `%s' to `%s' not available\n"),
455                from, to);
456   else
457     log_error (_("iconv_open failed: %s\n"), strerror (errno));
458
459   if (use_fallback)
460     {
461       /* To avoid further error messages we fallback to Latin-1 for the
462          native encoding.  This is justified as one can expect that on a
463          utf-8 enabled system nl_langinfo() will work and thus we won't
464          never get to here.  Thus Latin-1 seems to be a reasonable
465          default.  */
466       active_charset_name = "iso-8859-1";
467       no_translation = 0;
468       active_charset = NULL;
469       use_iconv = 0;
470     }
471 }
472 #endif /*USE_GNUPG_ICONV*/
473
474 int
475 set_native_charset( const char *newset )
476 {
477     const char *full_newset;
478
479     if (!newset) {
480 #ifdef _WIN32
481         static char codepage[30];
482
483         sprintf (codepage, "CP%u", (unsigned int)GetACP ());
484
485         /* If it is the Windows name for Latin-1 we use the
486          * standard name instead to avoid loading of iconv.dll.  */
487         if (!strcmp (codepage, "CP1252"))
488             newset = "iso-8859-1";
489         else
490             newset = codepage;
491 #else
492 #ifdef HAVE_LANGINFO_CODESET
493         newset = nl_langinfo (CODESET);
494 #else
495         newset = "iso-8859-1";
496 #endif
497 #endif
498     }
499
500     full_newset = newset;
501     if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) {
502         newset += 3;
503         if (*newset == '-' || *newset == '_')
504             newset++;
505     }
506
507     if( !*newset
508         || !ascii_strcasecmp (newset, "8859-1" )
509         || !ascii_strcasecmp (newset, "8859-15" ) ) {
510         active_charset_name = "iso-8859-1";
511         no_translation = 0;
512         active_charset = NULL;
513         use_iconv = 0;
514     }
515     else if( !ascii_strcasecmp (newset, "utf8" )
516              || !ascii_strcasecmp(newset, "utf-8") ) {
517         active_charset_name = "utf-8";
518         no_translation = 1;
519         active_charset = NULL;
520         use_iconv = 0;
521     }
522 #ifdef USE_GNUPG_ICONV
523     else {
524       iconv_t cd;
525
526 #ifdef _WIN32
527       if (load_libiconv ())
528           return G10ERR_GENERAL;
529 #endif /*_WIN32*/      
530
531       cd = iconv_open (full_newset, "utf-8");
532       if (cd == (iconv_t)-1) {
533           handle_iconv_error (full_newset, "utf-8", 0);
534           return G10ERR_GENERAL;
535       }
536       iconv_close (cd);
537       cd = iconv_open ("utf-8", full_newset);
538       if (cd == (iconv_t)-1) {
539           handle_iconv_error ("utf-8", full_newset, 0);
540           return G10ERR_GENERAL;
541       }
542       iconv_close (cd);
543       active_charset_name = full_newset;
544       no_translation = 0;
545       active_charset = NULL; 
546       use_iconv = 1;
547     }
548 #else /*!USE_GNUPG_ICONV*/
549     else if( !ascii_strcasecmp( newset, "8859-2" ) ) {
550         active_charset_name = "iso-8859-2";
551         no_translation = 0;
552         active_charset = latin2_unicode;
553         use_iconv = 0;
554     }
555     else if( !ascii_strcasecmp( newset, "koi8-r" ) ) {
556         active_charset_name = "koi8-r";
557         no_translation = 0;
558         active_charset = koi8_unicode;
559         use_iconv = 0;
560     }
561     else
562         return G10ERR_GENERAL;
563 #endif /*!USE_GNUPG_ICONV*/
564     return 0;
565 }
566
567 const char*
568 get_native_charset()
569 {
570     return active_charset_name;
571 }
572
573 /****************
574  * Convert string, which is in native encoding to UTF8 and return the
575  * new allocated UTF8 string.
576  */
577 char *
578 native_to_utf8( const char *string )
579 {
580   const byte *s;
581   char *buffer;
582   byte *p;
583   size_t length=0;
584   
585   if (no_translation)
586     { /* Already utf-8 encoded. */
587       buffer = m_strdup (string);
588     }
589   else if( !active_charset && !use_iconv) /* Shortcut implementation
590                                              for Latin-1.  */
591     { 
592       for(s=string; *s; s++ ) 
593         {
594           length++;
595           if( *s & 0x80 )
596             length++;
597         }
598       buffer = m_alloc( length + 1 );
599       for(p=buffer, s=string; *s; s++ )
600         {
601           if( *s & 0x80 )
602             {
603               *p++ = 0xc0 | ((*s >> 6) & 3);
604               *p++ = 0x80 | ( *s & 0x3f );
605             }
606           else
607             *p++ = *s;
608         }
609       *p = 0;
610     }
611   else       /* Need to use a translation table. */
612     { 
613 #ifdef USE_GNUPG_ICONV
614       iconv_t cd;
615       const char *inptr;
616       char *outptr;
617       size_t inbytes, outbytes;
618      
619       cd = iconv_open ("utf-8", active_charset_name);
620       if (cd == (iconv_t)-1)
621         {
622           handle_iconv_error ("utf-8", active_charset_name, 1);
623           return native_to_utf8 (string);
624         }
625
626       for (s=string; *s; s++ ) 
627         {
628           length++;
629           if ((*s & 0x80))
630             length += 5; /* We may need up to 6 bytes for the utf8 output. */
631         }
632       buffer = m_alloc (length + 1);
633
634       inptr = string;
635       inbytes = strlen (string);
636       outptr = buffer;
637       outbytes = length;
638       if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
639                   &outptr, &outbytes) == (size_t)-1)
640         {
641           log_error (_("conversion from `%s' to `%s' failed: %s\n"),
642                        active_charset_name, "utf-8", strerror (errno));
643           /* We don't do any conversion at all but use the strings as is. */
644           strcpy (buffer, string);
645         }
646       else /* Success.  */
647         {
648           *outptr = 0;
649           /* We could realloc the buffer now but I doubt that it makes
650              much sense given that it will get freed anyway soon
651              after.  */
652         }
653       iconv_close (cd);
654
655 #else /*!USE_GNUPG_ICONV*/
656       for(s=string; *s; s++ ) 
657         {
658           length++;
659           if( *s & 0x80 )
660             length += 2; /* We may need up to 3 bytes. */
661         }
662       buffer = m_alloc( length + 1 );
663       for(p=buffer, s=string; *s; s++ ) {
664         if( *s & 0x80 ) {
665           ushort val = active_charset[ *s & 0x7f ];
666           if( val < 0x0800 ) {
667             *p++ = 0xc0 | ( (val >> 6) & 0x1f );
668             *p++ = 0x80 | (  val & 0x3f );
669           }
670           else {
671             *p++ = 0xe0 | ( (val >> 12) & 0x0f );
672             *p++ = 0x80 | ( (val >>  6) & 0x3f );
673             *p++ = 0x80 | (  val & 0x3f );
674           }
675         }
676         else
677           *p++ = *s;
678       }
679       *p = 0;
680 #endif /*!USE_GNUPG_ICONV*/
681
682     }
683   return buffer;
684 }
685
686
687 /****************
688  * Convert string, which is in UTF8 to native encoding.  illegal
689  * encodings by some "\xnn" and quote all control characters. A
690  * character with value DELIM will always be quoted, it must be a
691  * vanilla ASCII character.  
692   */
693 char *
694 utf8_to_native( const char *string, size_t length, int delim )
695 {
696     int nleft;
697     int i;
698     byte encbuf[8];
699     int encidx;
700     const byte *s;
701     size_t n;
702     byte *buffer = NULL, *p = NULL;
703     unsigned long val = 0;
704     size_t slen;
705     int resync = 0;
706
707     /* 1. pass (p==NULL): count the extended utf-8 characters */
708     /* 2. pass (p!=NULL): create string */
709     for( ;; ) {
710         for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) {
711             if( resync ) {
712                 if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) {
713                     /* still invalid */
714                     if( p ) {
715                         sprintf(p, "\\x%02x", *s );
716                         p += 4;
717                     }
718                     n += 4;
719                     continue;
720                 }
721                 resync = 0;
722             }
723             if( !nleft ) {
724                 if( !(*s & 0x80) ) { /* plain ascii */
725                     if( *s < 0x20 || *s == 0x7f || *s == delim ||
726                         (delim && *s=='\\')) {
727                         n++;
728                         if( p )
729                             *p++ = '\\';
730                         switch( *s ) {
731                           case '\n': n++; if( p ) *p++ = 'n'; break;
732                           case '\r': n++; if( p ) *p++ = 'r'; break;
733                           case '\f': n++; if( p ) *p++ = 'f'; break;
734                           case '\v': n++; if( p ) *p++ = 'v'; break;
735                           case '\b': n++; if( p ) *p++ = 'b'; break;
736                           case   0 : n++; if( p ) *p++ = '0'; break;
737                           default:
738                             n += 3;
739                             if ( p ) {
740                                 sprintf( p, "x%02x", *s );
741                                 p += 3;
742                             }
743                             break;
744                         }
745                     }
746                     else {
747                         if( p ) *p++ = *s;
748                         n++;
749                     }
750                 }
751                 else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */
752                     val = *s & 0x1f;
753                     nleft = 1;
754                     encidx = 0;
755                     encbuf[encidx++] = *s;
756                 }
757                 else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */
758                     val = *s & 0x0f;
759                     nleft = 2;
760                     encidx = 0;
761                     encbuf[encidx++] = *s;
762                 }
763                 else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */
764                     val = *s & 0x07;
765                     nleft = 3;
766                     encidx = 0;
767                     encbuf[encidx++] = *s;
768                 }
769                 else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */
770                     val = *s & 0x03;
771                     nleft = 4;
772                     encidx = 0;
773                     encbuf[encidx++] = *s;
774                 }
775                 else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */
776                     val = *s & 0x01;
777                     nleft = 5;
778                     encidx = 0;
779                     encbuf[encidx++] = *s;
780                 }
781                 else {  /* invalid encoding: print as \xnn */
782                     if( p ) {
783                         sprintf(p, "\\x%02x", *s );
784                         p += 4;
785                     }
786                     n += 4;
787                     resync = 1;
788                 }
789             }
790             else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */
791                 if( p ) {
792                     for(i=0; i < encidx; i++ ) {
793                         sprintf(p, "\\x%02x", encbuf[i] );
794                         p += 4;
795                     }
796                     sprintf(p, "\\x%02x", *s );
797                     p += 4;
798                 }
799                 n += 4 + 4*encidx;
800                 nleft = 0;
801                 encidx = 0;
802                 resync = 1;
803             }
804             else {
805                 encbuf[encidx++] = *s;
806                 val <<= 6;
807                 val |= *s & 0x3f;
808                 if( !--nleft ) { /* ready */
809                     if (no_translation) {
810                         if( p ) {
811                             for(i=0; i < encidx; i++ )
812                                 *p++ = encbuf[i];
813                         }
814                         n += encidx;
815                         encidx = 0;
816                     }
817 #ifdef USE_GNUPG_ICONV
818                     else if(use_iconv) {
819                         /* Our strategy for using iconv is a bit
820                          * strange but it better keeps compatibility
821                          * with previous versions in regard to how
822                          * invalid encodings are displayed.  What we
823                          * do is to keep the utf-8 as is and have the
824                          * real translation step then at the end.
825                          * Yes, I know that this is ugly.  However we
826                          * are short of the 1.4 release and for this
827                          * branch we should not mee too much around
828                          * with iconv things.  One reason for this is
829                          * that we don't know enough about non-GNU
830                          * iconv implementation and want to minimize
831                          * the risk of breaking the code on too many
832                          * platforms.  */
833                         if( p ) {
834                             for(i=0; i < encidx; i++ )
835                                 *p++ = encbuf[i];
836                         }
837                         n += encidx;
838                         encidx = 0;
839                     }
840 #endif /*USE_GNUPG_ICONV*/
841                     else if( active_charset ) { /* table lookup */
842                         for(i=0; i < 128; i++ ) {
843                             if( active_charset[i] == val )
844                                 break;
845                         }
846                         if( i < 128 ) { /* we can print this one */
847                             if( p ) *p++ = i+128;
848                             n++;
849                         }
850                         else { /* we do not have a translation: print utf8 */
851                             if( p ) {
852                                 for(i=0; i < encidx; i++ ) {
853                                     sprintf(p, "\\x%02x", encbuf[i] );
854                                     p += 4;
855                                 }
856                             }
857                             n += encidx*4;
858                             encidx = 0;
859                         }
860                     }
861                     else { /* native set */
862                         if( val >= 0x80 && val < 256 ) {
863                             n++;    /* we can simply print this character */
864                             if( p ) *p++ = val;
865                         }
866                         else { /* we do not have a translation: print utf8 */
867                             if( p ) {
868                                 for(i=0; i < encidx; i++ ) {
869                                     sprintf(p, "\\x%02x", encbuf[i] );
870                                     p += 4;
871                                 }
872                             }
873                             n += encidx*4;
874                             encidx = 0;
875                         }
876                     }
877                 }
878
879             }
880         }
881         if( !buffer ) { /* allocate the buffer after the first pass */
882             buffer = p = m_alloc( n + 1 );
883         }
884 #ifdef USE_GNUPG_ICONV
885         else if(use_iconv) {
886             /* Note: See above for comments.  */
887             iconv_t cd;
888             const char *inptr;
889             char *outbuf, *outptr;
890             size_t inbytes, outbytes;
891             
892             *p = 0;  /* Terminate the buffer. */
893
894             cd = iconv_open (active_charset_name, "utf-8");
895             if (cd == (iconv_t)-1)
896                 {
897                     handle_iconv_error (active_charset_name, "utf-8", 1);
898                     m_free (buffer);
899                     return utf8_to_native (string, length, delim);
900                 }
901
902             /* Allocate a new buffer large enough to hold all possible
903              * encodings. */
904             n = p - buffer + 1;
905             inbytes = n - 1;;
906             inptr = buffer;
907             outbytes = n * MB_LEN_MAX;
908             if (outbytes / MB_LEN_MAX != n) 
909                 BUG (); /* Actually an overflow. */
910             outbuf = outptr = m_alloc (outbytes);
911             if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
912                         &outptr, &outbytes) == (size_t)-1) {
913                 log_error (_("conversion from `%s' to `%s' failed: %s\n"),
914                            "utf-8", active_charset_name, strerror (errno));
915                 /* Didn't worked out.  Temporary disable the use of
916                  * iconv and fall back to our old code. */
917                 m_free (buffer);
918                 buffer = NULL;
919                 m_free (outbuf);
920                 use_iconv = 0;
921                 outbuf = utf8_to_native (string, length, delim);
922                 use_iconv = 1;
923             }
924             else { /* Success.  */
925                 *outptr = 0;
926                 /* We could realloc the buffer now but I doubt that it makes
927                    much sense given that it will get freed anyway soon
928                    after.  */
929                 m_free (buffer);
930             }
931             iconv_close (cd);
932             return outbuf;
933         }
934 #endif /*USE_GNUPG_ICONV*/
935         else {
936             *p = 0; /* make a string */
937             return buffer;
938         }
939     }
940 }
941
942 /****************************************************
943  ******** locale insensitive ctype functions ********
944  ****************************************************/
945 /* FIXME: replace them by a table lookup and macros */
946 int
947 ascii_isupper (int c)
948 {
949     return c >= 'A' && c <= 'Z';
950 }
951
952 int
953 ascii_islower (int c)
954 {
955     return c >= 'a' && c <= 'z';
956 }
957
958 int 
959 ascii_toupper (int c)
960 {
961     if (c >= 'a' && c <= 'z')
962         c &= ~0x20;
963     return c;
964 }
965
966 int 
967 ascii_tolower (int c)
968 {
969     if (c >= 'A' && c <= 'Z')
970         c |= 0x20;
971     return c;
972 }
973
974
975 int
976 ascii_strcasecmp (const char *a, const char *b)
977 {
978   const unsigned char *p1 = (const unsigned char *)a;
979   const unsigned char *p2 = (const unsigned char *)b;
980   unsigned char c1, c2;
981
982   if (p1 == p2)
983     return 0;
984
985   do
986     {
987       c1 = ascii_tolower (*p1);
988       c2 = ascii_tolower (*p2);
989
990       if (c1 == '\0')
991         break;
992
993       ++p1;
994       ++p2;
995     }
996   while (c1 == c2);
997   
998   return c1 - c2;
999 }
1000
1001 int 
1002 ascii_strncasecmp (const char *a, const char *b, size_t n)
1003 {
1004   const unsigned char *p1 = (const unsigned char *)a;
1005   const unsigned char *p2 = (const unsigned char *)b;
1006   unsigned char c1, c2;
1007
1008   if (p1 == p2 || !n )
1009     return 0;
1010
1011   do
1012     {
1013       c1 = ascii_tolower (*p1);
1014       c2 = ascii_tolower (*p2);
1015
1016       if ( !--n || c1 == '\0')
1017         break;
1018
1019       ++p1;
1020       ++p2;
1021     }
1022   while (c1 == c2);
1023   
1024   return c1 - c2;
1025 }
1026
1027
1028 int
1029 ascii_memcasecmp( const char *a, const char *b, size_t n )
1030 {
1031     if (a == b)
1032         return 0;
1033     for ( ; n; n--, a++, b++ ) {
1034         if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
1035             return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
1036     }
1037     return 0;
1038 }
1039
1040
1041
1042 /*********************************************
1043  ********** missing string functions *********
1044  *********************************************/
1045
1046 #ifndef HAVE_STPCPY
1047 char *
1048 stpcpy(char *a,const char *b)
1049 {
1050     while( *b )
1051         *a++ = *b++;
1052     *a = 0;
1053
1054     return (char*)a;
1055 }
1056 #endif
1057
1058
1059 #ifndef HAVE_STRSEP
1060 /* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
1061 char *
1062 strsep (char **stringp, const char *delim)
1063 {
1064   char *begin, *end;
1065
1066   begin = *stringp;
1067   if (begin == NULL)
1068     return NULL;
1069
1070   /* A frequent case is when the delimiter string contains only one
1071      character.  Here we don't need to call the expensive `strpbrk'
1072      function and instead work using `strchr'.  */
1073   if (delim[0] == '\0' || delim[1] == '\0')
1074     {
1075       char ch = delim[0];
1076
1077       if (ch == '\0')
1078         end = NULL;
1079       else
1080         {
1081           if (*begin == ch)
1082             end = begin;
1083           else if (*begin == '\0')
1084             end = NULL;
1085           else
1086             end = strchr (begin + 1, ch);
1087         }
1088     }
1089   else
1090     /* Find the end of the token.  */
1091     end = strpbrk (begin, delim);
1092
1093   if (end)
1094     {
1095       /* Terminate the token and set *STRINGP past NUL character.  */
1096       *end++ = '\0';
1097       *stringp = end;
1098     }
1099   else
1100     /* No more delimiters; this is the last token.  */
1101     *stringp = NULL;
1102
1103   return begin;
1104 }
1105 #endif /*HAVE_STRSEP*/
1106
1107
1108 #ifndef HAVE_STRLWR
1109 char *
1110 strlwr(char *s)
1111 {
1112     char *p;
1113     for(p=s; *p; p++ )
1114         *p = tolower(*(unsigned char *)p);
1115     return s;
1116 }
1117 #endif
1118
1119 #ifndef HAVE_STRCASECMP
1120 int
1121 strcasecmp( const char *a, const char *b )
1122 {
1123     for( ; *a && *b; a++, b++ ) {
1124         if( *a != *b
1125             && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
1126             break;
1127     }
1128     return *(const byte*)a - *(const byte*)b;
1129 }
1130 #endif
1131
1132 #ifndef HAVE_STRNCASECMP
1133 int
1134 strncasecmp( const char *a, const char *b, size_t n )
1135 {
1136     for( ; n && *a && *b; a++, b++, n--) {
1137         if( *a != *b
1138             && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
1139             break;
1140     }
1141     if (!n)
1142       return 0;
1143     return *(const byte*)a - *(const byte*)b;
1144 }
1145 #endif
1146
1147
1148 #ifdef _WIN32
1149 /* 
1150  * Like vsprintf but provides a pointer to malloc'd storage, which
1151  * must be freed by the caller (m_free).  Taken from libiberty as
1152  * found in gcc-2.95.2 and a little bit modernized.
1153  * FIXME: Write a new CRT for W32.
1154  */
1155 int
1156 vasprintf (char **result, const char *format, va_list args)
1157 {
1158   const char *p = format;
1159   /* Add one to make sure that it is never zero, which might cause malloc
1160      to return NULL.  */
1161   int total_width = strlen (format) + 1;
1162   va_list ap;
1163
1164   /* this is not really portable but works under Windows */
1165   memcpy ( &ap, &args, sizeof (va_list));
1166
1167   while (*p != '\0')
1168     {
1169       if (*p++ == '%')
1170         {
1171           while (strchr ("-+ #0", *p))
1172             ++p;
1173           if (*p == '*')
1174             {
1175               ++p;
1176               total_width += abs (va_arg (ap, int));
1177             }
1178           else
1179             {
1180               char *endp;  
1181               total_width += strtoul (p, &endp, 10);
1182               p = endp;
1183             }
1184           if (*p == '.')
1185             {
1186               ++p;
1187               if (*p == '*')
1188                 {
1189                   ++p;
1190                   total_width += abs (va_arg (ap, int));
1191                 }
1192               else
1193                 {
1194                   char *endp;
1195                   total_width += strtoul (p, &endp, 10);
1196                   p = endp;
1197                 }
1198             }
1199           while (strchr ("hlL", *p))
1200             ++p;
1201           /* Should be big enough for any format specifier except %s
1202              and floats.  */
1203           total_width += 30;
1204           switch (*p)
1205             {
1206             case 'd':
1207             case 'i':
1208             case 'o':
1209             case 'u':
1210             case 'x':
1211             case 'X':
1212             case 'c':
1213               (void) va_arg (ap, int);
1214               break;
1215             case 'f':
1216             case 'e':
1217             case 'E':
1218             case 'g':
1219             case 'G':
1220               (void) va_arg (ap, double);
1221               /* Since an ieee double can have an exponent of 307, we'll
1222                  make the buffer wide enough to cover the gross case. */
1223               total_width += 307;
1224             
1225             case 's':
1226               total_width += strlen (va_arg (ap, char *));
1227               break;
1228             case 'p':
1229             case 'n':
1230               (void) va_arg (ap, char *);
1231               break;
1232             }
1233         }
1234     }
1235   *result = m_alloc (total_width);
1236   if (*result != NULL)
1237     return vsprintf (*result, format, args);
1238   else
1239     return 0;
1240 }
1241
1242 int
1243 asprintf (char **buf, const char *fmt, ...)
1244 {
1245   int status;
1246   va_list ap;
1247
1248   va_start (ap, fmt);
1249   status = vasprintf (buf, fmt, ap);
1250   va_end (ap);
1251   return status;  
1252 }
1253
1254 #endif /*_WIN32*/