6205910e29c601ce36fd629b55c65f6c8c0e9eaf
[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_info (_("error loading `%s': %s\n"),
146                      "iconv.dll",  dlerror ());
147           log_info(_("please see http://www.gnupg.org/download/iconv.html "
148                      "for more information\n"));
149           iconv_open = NULL;
150           iconv = NULL;
151           iconv_close = NULL;
152           if (handle)
153               dlclose (handle);
154         }
155     }
156   return iconv_open? 0: -1;
157 }    
158 #endif /* _WIN32 */
159
160
161
162
163 void
164 free_strlist( STRLIST sl )
165 {
166     STRLIST sl2;
167
168     for(; sl; sl = sl2 ) {
169         sl2 = sl->next;
170         m_free(sl);
171     }
172 }
173
174
175 STRLIST
176 add_to_strlist( STRLIST *list, const char *string )
177 {
178     STRLIST sl;
179
180     sl = m_alloc( sizeof *sl + strlen(string));
181     sl->flags = 0;
182     strcpy(sl->d, string);
183     sl->next = *list;
184     *list = sl;
185     return sl;
186 }
187
188 /****************
189  * Same as add_to_strlist() but if is_utf8 is *not* set a conversion
190  * to UTF8 is done
191  */
192 STRLIST
193 add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
194 {
195     STRLIST sl;
196
197     if( is_utf8 )
198         sl = add_to_strlist( list, string );
199     else {
200         char *p = native_to_utf8( string );
201         sl = add_to_strlist( list, p );
202         m_free( p );
203     }
204     return sl;
205 }
206
207 STRLIST
208 append_to_strlist( STRLIST *list, const char *string )
209 {
210     STRLIST r, sl;
211
212     sl = m_alloc( sizeof *sl + strlen(string));
213     sl->flags = 0;
214     strcpy(sl->d, string);
215     sl->next = NULL;
216     if( !*list )
217         *list = sl;
218     else {
219         for( r = *list; r->next; r = r->next )
220             ;
221         r->next = sl;
222     }
223     return sl;
224 }
225
226 STRLIST
227 append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
228 {
229     STRLIST sl;
230
231     if( is_utf8 )
232         sl = append_to_strlist( list, string );
233     else {
234         char *p = native_to_utf8( string );
235         sl = append_to_strlist( list, p );
236         m_free( p );
237     }
238     return sl;
239 }
240
241
242 STRLIST
243 strlist_prev( STRLIST head, STRLIST node )
244 {
245     STRLIST n;
246
247     for(n=NULL; head && head != node; head = head->next )
248         n = head;
249     return n;
250 }
251
252 STRLIST
253 strlist_last( STRLIST node )
254 {
255     if( node )
256         for( ; node->next ; node = node->next )
257             ;
258     return node;
259 }
260
261 char *
262 pop_strlist( STRLIST *list )
263 {
264   char *str=NULL;
265   STRLIST sl=*list;
266
267   if(sl)
268     {
269       str=m_alloc(strlen(sl->d)+1);
270       strcpy(str,sl->d);
271
272       *list=sl->next;
273       m_free(sl);
274     }
275
276   return str;
277 }
278
279 /****************
280  * Look for the substring SUB in buffer and return a pointer to that
281  * substring in BUF or NULL if not found.
282  * Comparison is case-insensitive.
283  */
284 const char *
285 memistr( const char *buf, size_t buflen, const char *sub )
286 {
287     const byte *t, *s ;
288     size_t n;
289
290     for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
291         if( toupper(*t) == toupper(*s) ) {
292             for( buf=t++, buflen = n--, s++;
293                  n && toupper(*t) == toupper(*s); t++, s++, n-- )
294                 ;
295             if( !*s )
296                 return buf;
297             t = buf; n = buflen; s = sub ;
298         }
299
300     return NULL ;
301 }
302
303 const char *
304 ascii_memistr( const char *buf, size_t buflen, const char *sub )
305 {
306     const byte *t, *s ;
307     size_t n;
308
309     for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
310         if( ascii_toupper(*t) == ascii_toupper(*s) ) {
311             for( buf=t++, buflen = n--, s++;
312                  n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
313                 ;
314             if( !*s )
315                 return buf;
316             t = buf; n = buflen; s = sub ;
317         }
318
319     return NULL ;
320 }
321
322
323 /* Like strncpy() but copy at max N-1 bytes and append a '\0'.  With
324  * N given as 0 nothing is copied at all. With DEST given as NULL
325  * sufficient memory is allocated using m_alloc (note that m_alloc is
326  * guaranteed to succeed or to abort the process).  */
327 char *
328 mem2str( char *dest , const void *src , size_t n )
329 {
330     char *d;
331     const char *s;
332
333     if( n ) {
334         if( !dest )
335             dest = m_alloc( n ) ;
336         d = dest;
337         s = src ;
338         for(n--; n && *s; n-- )
339             *d++ = *s++;
340         *d = '\0' ;
341     }
342
343     return dest ;
344 }
345
346
347 /*
348  * Remove leading and trailing white spaces
349  */
350 char *
351 trim_spaces( char *str )
352 {
353     char *string, *p, *mark;
354
355     string = str;
356     /* Find first non space character. */
357     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
358         ;
359     /* Move characters. */
360     for( (mark = NULL); (*string = *p); string++, p++ )
361         if( isspace( *(byte*)p ) ) {
362             if( !mark )
363                 mark = string ;
364         }
365         else
366             mark = NULL ;
367     if( mark )
368         *mark = '\0' ;  /* Remove trailing spaces.  */
369
370     return str ;
371 }
372
373
374
375 unsigned int
376 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
377 {
378     byte *p, *mark;
379     unsigned n;
380
381     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
382         if( strchr(trimchars, *p ) ) {
383             if( !mark )
384                 mark = p;
385         }
386         else
387             mark = NULL;
388     }
389
390     if( mark ) {
391         *mark = 0;
392         return mark - line;
393     }
394     return len;
395 }
396
397 /****************
398  * Remove trailing white spaces and return the length of the buffer
399  */
400 unsigned
401 trim_trailing_ws( byte *line, unsigned len )
402 {
403     return trim_trailing_chars( line, len, " \t\r\n" );
404 }
405
406
407 unsigned int
408 check_trailing_chars( const byte *line, unsigned int len,
409                       const char *trimchars )
410 {
411     const byte *p, *mark;
412     unsigned int n;
413
414     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
415         if( strchr(trimchars, *p ) ) {
416             if( !mark )
417                 mark = p;
418         }
419         else
420             mark = NULL;
421     }
422
423     if( mark ) {
424         return mark - line;
425     }
426     return len;
427 }
428
429
430 /****************
431  * Remove trailing white spaces and return the length of the buffer
432  */
433 unsigned int
434 check_trailing_ws( const byte *line, unsigned int len )
435 {
436     return check_trailing_chars( line, len, " \t\r\n" );
437 }
438
439
440
441 int
442 string_count_chr( const char *string, int c )
443 {
444     int count;
445     for(count=0; *string; string++ )
446         if( *string == c )
447             count++;
448     return count;
449 }
450
451 #ifdef USE_GNUPG_ICONV
452 static void
453 handle_iconv_error (const char *to, const char *from, int use_fallback)
454 {
455   if (errno == EINVAL)
456     log_info (_("conversion from `%s' to `%s' not available\n"),
457                from, to);
458   else
459     log_info (_("iconv_open failed: %s\n"), strerror (errno));
460
461   if (use_fallback)
462     {
463       /* To avoid further error messages we fallback to Latin-1 for the
464          native encoding.  This is justified as one can expect that on a
465          utf-8 enabled system nl_langinfo() will work and thus we won't
466          never get to here.  Thus Latin-1 seems to be a reasonable
467          default.  */
468       active_charset_name = "iso-8859-1";
469       no_translation = 0;
470       active_charset = NULL;
471       use_iconv = 0;
472     }
473 }
474 #endif /*USE_GNUPG_ICONV*/
475
476 int
477 set_native_charset( const char *newset )
478 {
479     const char *full_newset;
480
481     if (!newset) {
482 #ifdef _WIN32
483         static char codepage[30];
484         unsigned int cpno;
485
486         /* We are a console program thus we need to use the
487            GetConsoleOutputCP function and not the the GetACP which
488            would give the codepage for a GUI program.  Note this is
489            not a bulletproof detection because GetConsoleCP might
490            return a different one for console input.  Not sure how to
491            cope with that.  If the console Code page is not known we
492            fall back to the system code page.  */
493         cpno = GetConsoleOutputCP ();
494         if (!cpno)
495           cpno = GetACP ();
496         sprintf (codepage, "CP%u", cpno );
497         /* If it is the Windows name for Latin-1 we use the standard
498            name instead to avoid loading of iconv.dll.  Unfortunately
499            it is often CP850 and we don't have a custom translation
500            for it. */
501         if (!strcmp (codepage, "CP1252"))
502             newset = "iso-8859-1";
503         else
504             newset = codepage;
505 #else
506 #ifdef HAVE_LANGINFO_CODESET
507         newset = nl_langinfo (CODESET);
508 #else /* !HAVE_LANGINFO_CODESET */
509         /* Try to get the used charset from environment variables.  */
510         static char codepage[30];
511         const char *lc, *dot, *mod;
512
513         strcpy (codepage, "iso-8859-1");
514         lc = getenv ("LC_ALL");
515         if (!lc || !*lc) {
516             lc = getenv ("LC_CTYPE");
517             if (!lc || !*lc)
518                 lc = getenv ("LANG");
519         }
520         if (lc && *lc) {
521             dot = strchr (lc, '.');
522             if (dot) {
523                 mod = strchr (++dot, '@');
524                 if (!mod)
525                     mod = dot + strlen (dot);
526                 if (mod - dot < sizeof codepage && dot != mod) {
527                     memcpy (codepage, dot, mod - dot);
528                     codepage [mod - dot] = 0;
529                 }
530             }
531         }
532         newset = codepage;
533 #endif  /* !HAVE_LANGINFO_CODESET */
534 #endif
535     }
536
537     full_newset = newset;
538     if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) {
539         newset += 3;
540         if (*newset == '-' || *newset == '_')
541             newset++;
542     }
543
544     /* Note that we silently assume that plain ASCII is actually meant
545        as Latin-1.  This makes sense because many Unix system don't
546        have their locale set up properly and thus would get annoying
547        error messages and we have to handle all the "bug"
548        reports. Latin-1 has always been the character set used for 8
549        bit characters on Unix systems. */
550     if( !*newset
551         || !ascii_strcasecmp (newset, "8859-1" )
552         || !ascii_strcasecmp (newset, "646" )
553         || !ascii_strcasecmp (newset, "ASCII" )
554         || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" )
555         ) {
556         active_charset_name = "iso-8859-1";
557         no_translation = 0;
558         active_charset = NULL;
559         use_iconv = 0;
560     }
561     else if( !ascii_strcasecmp (newset, "utf8" )
562              || !ascii_strcasecmp(newset, "utf-8") ) {
563         active_charset_name = "utf-8";
564         no_translation = 1;
565         active_charset = NULL;
566         use_iconv = 0;
567     }
568 #ifdef USE_GNUPG_ICONV
569     else {
570       iconv_t cd;
571
572 #ifdef _WIN32
573       if (load_libiconv ())
574           return G10ERR_GENERAL;
575 #endif /*_WIN32*/      
576
577       cd = iconv_open (full_newset, "utf-8");
578       if (cd == (iconv_t)-1) {
579           handle_iconv_error (full_newset, "utf-8", 0);
580           return G10ERR_GENERAL;
581       }
582       iconv_close (cd);
583       cd = iconv_open ("utf-8", full_newset);
584       if (cd == (iconv_t)-1) {
585           handle_iconv_error ("utf-8", full_newset, 0);
586           return G10ERR_GENERAL;
587       }
588       iconv_close (cd);
589       active_charset_name = full_newset;
590       no_translation = 0;
591       active_charset = NULL; 
592       use_iconv = 1;
593     }
594 #else /*!USE_GNUPG_ICONV*/
595     else if( !ascii_strcasecmp( newset, "8859-2" ) ) {
596         active_charset_name = "iso-8859-2";
597         no_translation = 0;
598         active_charset = latin2_unicode;
599         use_iconv = 0;
600     }
601     else if( !ascii_strcasecmp( newset, "koi8-r" ) ) {
602         active_charset_name = "koi8-r";
603         no_translation = 0;
604         active_charset = koi8_unicode;
605         use_iconv = 0;
606     }
607     else
608         return G10ERR_GENERAL;
609 #endif /*!USE_GNUPG_ICONV*/
610     return 0;
611 }
612
613 const char*
614 get_native_charset()
615 {
616     return active_charset_name;
617 }
618
619 /****************
620  * Convert string, which is in native encoding to UTF8 and return the
621  * new allocated UTF8 string.
622  */
623 char *
624 native_to_utf8( const char *string )
625 {
626   const byte *s;
627   char *buffer;
628   byte *p;
629   size_t length=0;
630   
631   if (no_translation)
632     { /* Already utf-8 encoded. */
633       buffer = m_strdup (string);
634     }
635   else if( !active_charset && !use_iconv) /* Shortcut implementation
636                                              for Latin-1.  */
637     { 
638       for(s=string; *s; s++ ) 
639         {
640           length++;
641           if( *s & 0x80 )
642             length++;
643         }
644       buffer = m_alloc( length + 1 );
645       for(p=buffer, s=string; *s; s++ )
646         {
647           if( *s & 0x80 )
648             {
649               *p++ = 0xc0 | ((*s >> 6) & 3);
650               *p++ = 0x80 | ( *s & 0x3f );
651             }
652           else
653             *p++ = *s;
654         }
655       *p = 0;
656     }
657   else       /* Need to use a translation table. */
658     { 
659 #ifdef USE_GNUPG_ICONV
660       iconv_t cd;
661       const char *inptr;
662       char *outptr;
663       size_t inbytes, outbytes;
664      
665       cd = iconv_open ("utf-8", active_charset_name);
666       if (cd == (iconv_t)-1)
667         {
668           handle_iconv_error ("utf-8", active_charset_name, 1);
669           return native_to_utf8 (string);
670         }
671
672       for (s=string; *s; s++ ) 
673         {
674           length++;
675           if ((*s & 0x80))
676             length += 5; /* We may need up to 6 bytes for the utf8 output. */
677         }
678       buffer = m_alloc (length + 1);
679
680       inptr = string;
681       inbytes = strlen (string);
682       outptr = buffer;
683       outbytes = length;
684       if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
685                   &outptr, &outbytes) == (size_t)-1)
686         {
687           log_info (_("conversion from `%s' to `%s' failed: %s\n"),
688                        active_charset_name, "utf-8", strerror (errno));
689           /* We don't do any conversion at all but use the strings as is. */
690           strcpy (buffer, string);
691         }
692       else /* Success.  */
693         {
694           *outptr = 0;
695           /* We could realloc the buffer now but I doubt that it makes
696              much sense given that it will get freed anyway soon
697              after.  */
698         }
699       iconv_close (cd);
700
701 #else /*!USE_GNUPG_ICONV*/
702       for(s=string; *s; s++ ) 
703         {
704           length++;
705           if( *s & 0x80 )
706             length += 2; /* We may need up to 3 bytes. */
707         }
708       buffer = m_alloc( length + 1 );
709       for(p=buffer, s=string; *s; s++ ) {
710         if( *s & 0x80 ) {
711           ushort val = active_charset[ *s & 0x7f ];
712           if( val < 0x0800 ) {
713             *p++ = 0xc0 | ( (val >> 6) & 0x1f );
714             *p++ = 0x80 | (  val & 0x3f );
715           }
716           else {
717             *p++ = 0xe0 | ( (val >> 12) & 0x0f );
718             *p++ = 0x80 | ( (val >>  6) & 0x3f );
719             *p++ = 0x80 | (  val & 0x3f );
720           }
721         }
722         else
723           *p++ = *s;
724       }
725       *p = 0;
726 #endif /*!USE_GNUPG_ICONV*/
727
728     }
729   return buffer;
730 }
731
732
733 /****************
734  * Convert string, which is in UTF8 to native encoding.  illegal
735  * encodings by some "\xnn" and quote all control characters. A
736  * character with value DELIM will always be quoted, it must be a
737  * vanilla ASCII character.  A DELIM value of -1 is special: it disables 
738  * all quoting of control characters.
739  */
740 char *
741 utf8_to_native( const char *string, size_t length, int delim )
742 {
743     int nleft;
744     int i;
745     byte encbuf[8];
746     int encidx;
747     const byte *s;
748     size_t n;
749     byte *buffer = NULL, *p = NULL;
750     unsigned long val = 0;
751     size_t slen;
752     int resync = 0;
753
754     /* 1. pass (p==NULL): count the extended utf-8 characters */
755     /* 2. pass (p!=NULL): create string */
756     for( ;; ) {
757         for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) {
758             if( resync ) {
759                 if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) {
760                     /* still invalid */
761                     if( p ) {
762                         sprintf(p, "\\x%02x", *s );
763                         p += 4;
764                     }
765                     n += 4;
766                     continue;
767                 }
768                 resync = 0;
769             }
770             if( !nleft ) {
771                 if( !(*s & 0x80) ) { /* plain ascii */
772                     if( delim != -1 
773                         && (*s < 0x20 || *s == 0x7f || *s == delim
774                             || (delim && *s=='\\'))) {
775                         n++;
776                         if( p )
777                             *p++ = '\\';
778                         switch( *s ) {
779                           case '\n': n++; if( p ) *p++ = 'n'; break;
780                           case '\r': n++; if( p ) *p++ = 'r'; break;
781                           case '\f': n++; if( p ) *p++ = 'f'; break;
782                           case '\v': n++; if( p ) *p++ = 'v'; break;
783                           case '\b': n++; if( p ) *p++ = 'b'; break;
784                           case   0 : n++; if( p ) *p++ = '0'; break;
785                           default:
786                             n += 3;
787                             if ( p ) {
788                                 sprintf( p, "x%02x", *s );
789                                 p += 3;
790                             }
791                             break;
792                         }
793                     }
794                     else {
795                         if( p ) *p++ = *s;
796                         n++;
797                     }
798                 }
799                 else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */
800                     val = *s & 0x1f;
801                     nleft = 1;
802                     encidx = 0;
803                     encbuf[encidx++] = *s;
804                 }
805                 else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */
806                     val = *s & 0x0f;
807                     nleft = 2;
808                     encidx = 0;
809                     encbuf[encidx++] = *s;
810                 }
811                 else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */
812                     val = *s & 0x07;
813                     nleft = 3;
814                     encidx = 0;
815                     encbuf[encidx++] = *s;
816                 }
817                 else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */
818                     val = *s & 0x03;
819                     nleft = 4;
820                     encidx = 0;
821                     encbuf[encidx++] = *s;
822                 }
823                 else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */
824                     val = *s & 0x01;
825                     nleft = 5;
826                     encidx = 0;
827                     encbuf[encidx++] = *s;
828                 }
829                 else {  /* invalid encoding: print as \xnn */
830                     if( p ) {
831                         sprintf(p, "\\x%02x", *s );
832                         p += 4;
833                     }
834                     n += 4;
835                     resync = 1;
836                 }
837             }
838             else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */
839                 if( p ) {
840                     for(i=0; i < encidx; i++ ) {
841                         sprintf(p, "\\x%02x", encbuf[i] );
842                         p += 4;
843                     }
844                     sprintf(p, "\\x%02x", *s );
845                     p += 4;
846                 }
847                 n += 4 + 4*encidx;
848                 nleft = 0;
849                 encidx = 0;
850                 resync = 1;
851             }
852             else {
853                 encbuf[encidx++] = *s;
854                 val <<= 6;
855                 val |= *s & 0x3f;
856                 if( !--nleft ) { /* ready */
857                     if (no_translation) {
858                         if( p ) {
859                             for(i=0; i < encidx; i++ )
860                                 *p++ = encbuf[i];
861                         }
862                         n += encidx;
863                         encidx = 0;
864                     }
865 #ifdef USE_GNUPG_ICONV
866                     else if(use_iconv) {
867                         /* Our strategy for using iconv is a bit
868                          * strange but it better keeps compatibility
869                          * with previous versions in regard to how
870                          * invalid encodings are displayed.  What we
871                          * do is to keep the utf-8 as is and have the
872                          * real translation step then at the end.
873                          * Yes, I know that this is ugly.  However we
874                          * are short of the 1.4 release and for this
875                          * branch we should not mee too much around
876                          * with iconv things.  One reason for this is
877                          * that we don't know enough about non-GNU
878                          * iconv implementation and want to minimize
879                          * the risk of breaking the code on too many
880                          * platforms.  */
881                         if( p ) {
882                             for(i=0; i < encidx; i++ )
883                                 *p++ = encbuf[i];
884                         }
885                         n += encidx;
886                         encidx = 0;
887                     }
888 #endif /*USE_GNUPG_ICONV*/
889                     else if( active_charset ) { /* table lookup */
890                         for(i=0; i < 128; i++ ) {
891                             if( active_charset[i] == val )
892                                 break;
893                         }
894                         if( i < 128 ) { /* we can print this one */
895                             if( p ) *p++ = i+128;
896                             n++;
897                         }
898                         else { /* we do not have a translation: print utf8 */
899                             if( p ) {
900                                 for(i=0; i < encidx; i++ ) {
901                                     sprintf(p, "\\x%02x", encbuf[i] );
902                                     p += 4;
903                                 }
904                             }
905                             n += encidx*4;
906                             encidx = 0;
907                         }
908                     }
909                     else { /* native set */
910                         if( val >= 0x80 && val < 256 ) {
911                             n++;    /* we can simply print this character */
912                             if( p ) *p++ = val;
913                         }
914                         else { /* we do not have a translation: print utf8 */
915                             if( p ) {
916                                 for(i=0; i < encidx; i++ ) {
917                                     sprintf(p, "\\x%02x", encbuf[i] );
918                                     p += 4;
919                                 }
920                             }
921                             n += encidx*4;
922                             encidx = 0;
923                         }
924                     }
925                 }
926
927             }
928         }
929         if( !buffer ) { /* allocate the buffer after the first pass */
930             buffer = p = m_alloc( n + 1 );
931         }
932 #ifdef USE_GNUPG_ICONV
933         else if(use_iconv) {
934             /* Note: See above for comments.  */
935             iconv_t cd;
936             const char *inptr;
937             char *outbuf, *outptr;
938             size_t inbytes, outbytes;
939             
940             *p = 0;  /* Terminate the buffer. */
941
942             cd = iconv_open (active_charset_name, "utf-8");
943             if (cd == (iconv_t)-1)
944                 {
945                     handle_iconv_error (active_charset_name, "utf-8", 1);
946                     m_free (buffer);
947                     return utf8_to_native (string, length, delim);
948                 }
949
950             /* Allocate a new buffer large enough to hold all possible
951              * encodings. */
952             n = p - buffer + 1;
953             inbytes = n - 1;;
954             inptr = buffer;
955             outbytes = n * MB_LEN_MAX;
956             if (outbytes / MB_LEN_MAX != n) 
957                 BUG (); /* Actually an overflow. */
958             outbuf = outptr = m_alloc (outbytes);
959             if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
960                         &outptr, &outbytes) == (size_t)-1) {
961                 log_info (_("conversion from `%s' to `%s' failed: %s\n"),
962                            "utf-8", active_charset_name, strerror (errno));
963                 /* Didn't worked out.  Temporary disable the use of
964                  * iconv and fall back to our old code. */
965                 m_free (buffer);
966                 buffer = NULL;
967                 m_free (outbuf);
968                 use_iconv = 0;
969                 outbuf = utf8_to_native (string, length, delim);
970                 use_iconv = 1;
971             }
972             else { /* Success.  */
973                 *outptr = 0;
974                 /* We could realloc the buffer now but I doubt that it makes
975                    much sense given that it will get freed anyway soon
976                    after.  */
977                 m_free (buffer);
978             }
979             iconv_close (cd);
980             return outbuf;
981         }
982 #endif /*USE_GNUPG_ICONV*/
983         else {
984             *p = 0; /* make a string */
985             return buffer;
986         }
987     }
988 }
989
990 /****************************************************
991  ******** locale insensitive ctype functions ********
992  ****************************************************/
993 /* FIXME: replace them by a table lookup and macros */
994 int
995 ascii_isupper (int c)
996 {
997     return c >= 'A' && c <= 'Z';
998 }
999
1000 int
1001 ascii_islower (int c)
1002 {
1003     return c >= 'a' && c <= 'z';
1004 }
1005
1006 int 
1007 ascii_toupper (int c)
1008 {
1009     if (c >= 'a' && c <= 'z')
1010         c &= ~0x20;
1011     return c;
1012 }
1013
1014 int 
1015 ascii_tolower (int c)
1016 {
1017     if (c >= 'A' && c <= 'Z')
1018         c |= 0x20;
1019     return c;
1020 }
1021
1022
1023 int
1024 ascii_strcasecmp (const char *a, const char *b)
1025 {
1026   const unsigned char *p1 = (const unsigned char *)a;
1027   const unsigned char *p2 = (const unsigned char *)b;
1028   unsigned char c1, c2;
1029
1030   if (p1 == p2)
1031     return 0;
1032
1033   do
1034     {
1035       c1 = ascii_tolower (*p1);
1036       c2 = ascii_tolower (*p2);
1037
1038       if (c1 == '\0')
1039         break;
1040
1041       ++p1;
1042       ++p2;
1043     }
1044   while (c1 == c2);
1045   
1046   return c1 - c2;
1047 }
1048
1049 int 
1050 ascii_strncasecmp (const char *a, const char *b, size_t n)
1051 {
1052   const unsigned char *p1 = (const unsigned char *)a;
1053   const unsigned char *p2 = (const unsigned char *)b;
1054   unsigned char c1, c2;
1055
1056   if (p1 == p2 || !n )
1057     return 0;
1058
1059   do
1060     {
1061       c1 = ascii_tolower (*p1);
1062       c2 = ascii_tolower (*p2);
1063
1064       if ( !--n || c1 == '\0')
1065         break;
1066
1067       ++p1;
1068       ++p2;
1069     }
1070   while (c1 == c2);
1071   
1072   return c1 - c2;
1073 }
1074
1075
1076 int
1077 ascii_memcasecmp( const char *a, const char *b, size_t n )
1078 {
1079     if (a == b)
1080         return 0;
1081     for ( ; n; n--, a++, b++ ) {
1082         if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
1083             return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
1084     }
1085     return 0;
1086 }
1087
1088
1089
1090 /*********************************************
1091  ********** missing string functions *********
1092  *********************************************/
1093
1094 #ifndef HAVE_STPCPY
1095 char *
1096 stpcpy(char *a,const char *b)
1097 {
1098     while( *b )
1099         *a++ = *b++;
1100     *a = 0;
1101
1102     return (char*)a;
1103 }
1104 #endif
1105
1106
1107 #ifndef HAVE_STRSEP
1108 /* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
1109 char *
1110 strsep (char **stringp, const char *delim)
1111 {
1112   char *begin, *end;
1113
1114   begin = *stringp;
1115   if (begin == NULL)
1116     return NULL;
1117
1118   /* A frequent case is when the delimiter string contains only one
1119      character.  Here we don't need to call the expensive `strpbrk'
1120      function and instead work using `strchr'.  */
1121   if (delim[0] == '\0' || delim[1] == '\0')
1122     {
1123       char ch = delim[0];
1124
1125       if (ch == '\0')
1126         end = NULL;
1127       else
1128         {
1129           if (*begin == ch)
1130             end = begin;
1131           else if (*begin == '\0')
1132             end = NULL;
1133           else
1134             end = strchr (begin + 1, ch);
1135         }
1136     }
1137   else
1138     /* Find the end of the token.  */
1139     end = strpbrk (begin, delim);
1140
1141   if (end)
1142     {
1143       /* Terminate the token and set *STRINGP past NUL character.  */
1144       *end++ = '\0';
1145       *stringp = end;
1146     }
1147   else
1148     /* No more delimiters; this is the last token.  */
1149     *stringp = NULL;
1150
1151   return begin;
1152 }
1153 #endif /*HAVE_STRSEP*/
1154
1155
1156 #ifndef HAVE_STRLWR
1157 char *
1158 strlwr(char *s)
1159 {
1160     char *p;
1161     for(p=s; *p; p++ )
1162         *p = tolower(*(unsigned char *)p);
1163     return s;
1164 }
1165 #endif
1166
1167 #ifndef HAVE_STRCASECMP
1168 int
1169 strcasecmp( const char *a, const char *b )
1170 {
1171     for( ; *a && *b; a++, b++ ) {
1172         if( *a != *b
1173             && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
1174             break;
1175     }
1176     return *(const byte*)a - *(const byte*)b;
1177 }
1178 #endif
1179
1180 #ifndef HAVE_STRNCASECMP
1181 int
1182 strncasecmp( const char *a, const char *b, size_t n )
1183 {
1184     for( ; n && *a && *b; a++, b++, n--) {
1185         if( *a != *b
1186             && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
1187             break;
1188     }
1189     if (!n)
1190       return 0;
1191     return *(const byte*)a - *(const byte*)b;
1192 }
1193 #endif
1194
1195
1196 #ifdef _WIN32
1197 /* 
1198  * Like vsprintf but provides a pointer to malloc'd storage, which
1199  * must be freed by the caller (m_free).  Taken from libiberty as
1200  * found in gcc-2.95.2 and a little bit modernized.
1201  * FIXME: Write a new CRT for W32.
1202  */
1203 int
1204 vasprintf (char **result, const char *format, va_list args)
1205 {
1206   const char *p = format;
1207   /* Add one to make sure that it is never zero, which might cause malloc
1208      to return NULL.  */
1209   int total_width = strlen (format) + 1;
1210   va_list ap;
1211
1212   /* this is not really portable but works under Windows */
1213   memcpy ( &ap, &args, sizeof (va_list));
1214
1215   while (*p != '\0')
1216     {
1217       if (*p++ == '%')
1218         {
1219           while (strchr ("-+ #0", *p))
1220             ++p;
1221           if (*p == '*')
1222             {
1223               ++p;
1224               total_width += abs (va_arg (ap, int));
1225             }
1226           else
1227             {
1228               char *endp;  
1229               total_width += strtoul (p, &endp, 10);
1230               p = endp;
1231             }
1232           if (*p == '.')
1233             {
1234               ++p;
1235               if (*p == '*')
1236                 {
1237                   ++p;
1238                   total_width += abs (va_arg (ap, int));
1239                 }
1240               else
1241                 {
1242                   char *endp;
1243                   total_width += strtoul (p, &endp, 10);
1244                   p = endp;
1245                 }
1246             }
1247           while (strchr ("hlL", *p))
1248             ++p;
1249           /* Should be big enough for any format specifier except %s
1250              and floats.  */
1251           total_width += 30;
1252           switch (*p)
1253             {
1254             case 'd':
1255             case 'i':
1256             case 'o':
1257             case 'u':
1258             case 'x':
1259             case 'X':
1260             case 'c':
1261               (void) va_arg (ap, int);
1262               break;
1263             case 'f':
1264             case 'e':
1265             case 'E':
1266             case 'g':
1267             case 'G':
1268               (void) va_arg (ap, double);
1269               /* Since an ieee double can have an exponent of 307, we'll
1270                  make the buffer wide enough to cover the gross case. */
1271               total_width += 307;
1272             
1273             case 's':
1274               total_width += strlen (va_arg (ap, char *));
1275               break;
1276             case 'p':
1277             case 'n':
1278               (void) va_arg (ap, char *);
1279               break;
1280             }
1281         }
1282     }
1283   *result = m_alloc (total_width);
1284   if (*result != NULL)
1285     return vsprintf (*result, format, args);
1286   else
1287     return 0;
1288 }
1289
1290 int
1291 asprintf (char **buf, const char *fmt, ...)
1292 {
1293   int status;
1294   va_list ap;
1295
1296   va_start (ap, fmt);
1297   status = vasprintf (buf, fmt, ap);
1298   va_end (ap);
1299   return status;  
1300 }
1301
1302 const char *
1303 w32_strerror (int w32_errno)
1304 {
1305   static char strerr[256];
1306   int ec = (int)GetLastError ();
1307   
1308   if (w32_errno == 0)
1309     w32_errno = ec;
1310   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, w32_errno,
1311                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
1312                  strerr, DIM (strerr)-1, NULL);
1313   return strerr;    
1314 }
1315 #endif /*_WIN32*/
1316
1317
1318