diff options
Diffstat (limited to 'jnlib')
-rw-r--r-- | jnlib/ChangeLog | 35 | ||||
-rw-r--r-- | jnlib/Makefile.am | 1 | ||||
-rw-r--r-- | jnlib/dotlock.c | 122 | ||||
-rw-r--r-- | jnlib/dotlock.h | 12 | ||||
-rw-r--r-- | jnlib/logging.c | 17 | ||||
-rw-r--r-- | jnlib/logging.h | 1 | ||||
-rw-r--r-- | jnlib/mischelp.h | 13 | ||||
-rw-r--r-- | jnlib/stringhelp.c | 173 | ||||
-rw-r--r-- | jnlib/stringhelp.h | 8 | ||||
-rw-r--r-- | jnlib/strlist.c | 20 | ||||
-rw-r--r-- | jnlib/strlist.h | 5 | ||||
-rw-r--r-- | jnlib/utf8conv.c | 448 | ||||
-rw-r--r-- | jnlib/utf8conv.h | 31 |
13 files changed, 840 insertions, 46 deletions
diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog index 41bf3d3bd..594eb340b 100644 --- a/jnlib/ChangeLog +++ b/jnlib/ChangeLog @@ -1,3 +1,36 @@ +2003-06-18 Werner Koch <[email protected]> + + * strlist.c (strlist_pop): New. + + * dotlock.c (dotlock_remove_lockfiles): Prefixed with dotlock_ and + made global. + +2003-06-17 Werner Koch <[email protected]> + + * stringhelp.c (length_sans_trailing_chars) + (length_sans_trailing_ws): New. + + * logging.c (log_inc_errorcount): New. + + * stringhelp.c (print_sanitized_utf8_buffer): Implement utf8 + conversion. + (sanitize_buffer): New. Based on gnupg 1.3.2 make_printable_string. + + * dotlock.c: Updated to match the version from 1.3.2 + * utf8conv.c: New. Code taken from strgutil.c of gnupg 1.3.2. + * utf8conv.h: New. + +2003-06-16 Werner Koch <[email protected]> + + * logging.c (do_logv): Hack to optionally suppress a leading space. + + * stringhelp.c (ascii_strncasecmp): New. Taken from gnupg 1.3. + (ascii_memistr): New. Taken from gnupg 1.3 + +2003-06-13 Werner Koch <[email protected]> + + * mischelp.h (wipememory2,wipememory): New. Taken from GnuPG 1.3.2. + 2002-06-04 Werner Koch <[email protected]> * stringhelp.c (print_sanitized_utf8_string): New. No real @@ -113,7 +146,7 @@ Mon Jan 24 13:04:28 CET 2000 Werner Koch <[email protected]> * You may find it source-copied in other packages. * *********************************************************** - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am index 303ffe3cb..ae1cf6be2 100644 --- a/jnlib/Makefile.am +++ b/jnlib/Makefile.am @@ -31,6 +31,7 @@ libjnlib_a_SOURCES = \ libjnlib-config.h \ stringhelp.c stringhelp.h \ strlist.c strlist.h \ + utf8conv.c utf8conv.h \ argparse.c argparse.h \ logging.c logging.h \ dotlock.c dotlock.h \ diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c index 772c770e8..7240fafeb 100644 --- a/jnlib/dotlock.c +++ b/jnlib/dotlock.c @@ -1,5 +1,5 @@ /* dotlock.c - dotfile locking - * Copyright (C) 1998,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 1998,2000,2001,2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -42,13 +42,20 @@ struct dotlock_handle { char *tname; /* name of lockfile template */ char *lockname; /* name of the real lockfile */ int locked; /* lock status */ + int disable; /* locking */ }; -static DOTLOCK all_lockfiles; +static volatile DOTLOCK all_lockfiles; +static int never_lock; static int read_lockfile( const char *name ); -static void remove_lockfiles(void); + +void +disable_dotlock(void) +{ + never_lock = 1; +} /**************** * Create a lockfile with the given name and return an object of @@ -81,13 +88,23 @@ create_dotlock( const char *file_to_lock ) int dirpartlen; if( !initialized ) { - atexit( remove_lockfiles ); + atexit( dotlock_remove_lockfiles ); initialized = 1; } if( !file_to_lock ) return NULL; h = jnlib_xcalloc( 1, sizeof *h ); + if( never_lock ) { + h->disable = 1; +#ifdef _REENTRANT + /* fixme: aquire mutex on all_lockfiles */ +#endif + h->next = all_lockfiles; + all_lockfiles = h; + return h; + } + #ifndef HAVE_DOSISH_SYSTEM sprintf( pidstr, "%10d\n", (int)getpid() ); /* fixme: add the hostname to the second line (FQDN or IP addr?) */ @@ -98,8 +115,17 @@ create_dotlock( const char *file_to_lock ) else nodename = utsbuf.nodename; - if( !(dirpart = strrchr( file_to_lock, '/' )) ) { - dirpart = "."; +#ifdef __riscos__ + { + char *iter = (char *) nodename; + for (; iter[0]; iter++) + if (iter[0] == '.') + iter[0] = '/'; + } +#endif /* __riscos__ */ + + if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) { + dirpart = EXTSEP_S; dirpartlen = 1; } else { @@ -114,8 +140,13 @@ create_dotlock( const char *file_to_lock ) all_lockfiles = h; h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); - sprintf( h->tname, "%.*s/.#lk%p.%s.%d", +#ifndef __riscos__ + sprintf( h->tname, "%.*s/.#lk%p.%s.%d", dirpartlen, dirpart, h, nodename, (int)getpid() ); +#else /* __riscos__ */ + sprintf( h->tname, "%.*s.lk%p/%s/%d", + dirpartlen, dirpart, h, nodename, (int)getpid() ); +#endif /* __riscos__ */ do { errno = 0; @@ -147,7 +178,8 @@ create_dotlock( const char *file_to_lock ) #ifdef _REENTRANT /* release mutex */ #endif - log_error( "error closing `%s': %s\n", h->tname, strerror(errno)); + log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) ); + close(fd); unlink(h->tname); jnlib_free(h->tname); jnlib_free(h); @@ -159,7 +191,7 @@ create_dotlock( const char *file_to_lock ) #endif #endif /* !HAVE_DOSISH_SYSTEM */ h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 ); - strcpy(stpcpy(h->lockname, file_to_lock), ".lock"); + strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); return h; } @@ -191,12 +223,19 @@ make_dotlock( DOTLOCK h, long timeout ) const char *maybe_dead=""; int backoff=0; + if( h->disable ) { + return 0; + } + if( h->locked ) { +#ifndef __riscos__ log_debug("oops, `%s' is already locked\n", h->lockname ); +#endif /* !__riscos__ */ return 0; } for(;;) { +#ifndef __riscos__ if( !link(h->tname, h->lockname) ) { /* fixme: better use stat to check the link count */ h->locked = 1; @@ -206,6 +245,16 @@ make_dotlock( DOTLOCK h, long timeout ) log_error( "lock not made: link() failed: %s\n", strerror(errno) ); return -1; } +#else /* __riscos__ */ + if( !renamefile(h->tname, h->lockname) ) { + h->locked = 1; + return 0; /* okay */ + } + if( errno != EEXIST ) { + log_error( "lock not made: rename() failed: %s\n", strerror(errno) ); + return -1; + } +#endif /* __riscos__ */ if( (pid = read_lockfile(h->lockname)) == -1 ) { if( errno != ENOENT ) { log_info("cannot read lockfile\n"); @@ -215,20 +264,27 @@ make_dotlock( DOTLOCK h, long timeout ) continue; } else if( pid == getpid() ) { - log_info( "Oops: lock already hold by us\n"); + log_info( "Oops: lock already held by us\n"); h->locked = 1; return 0; /* okay */ } else if( kill(pid, 0) && errno == ESRCH ) { +#ifndef __riscos__ maybe_dead = " - probably dead"; - #if 0 /* we should not do this without checking the permissions */ +#if 0 /* we should not do this without checking the permissions */ /* and the hostname */ log_info( "removing stale lockfile (created by %d)", pid ); - #endif +#endif +#else /* __riscos__ */ + /* we are *pretty* sure that the other task is dead and therefore + we remove the other lock file */ + maybe_dead = " - probably dead - removing lock"; + unlink(h->lockname); +#endif /* __riscos__ */ } if( timeout == -1 ) { struct timeval tv; - log_info( "waiting for lock (hold by %d%s) %s...\n", + log_info( "waiting for lock (held by %d%s) %s...\n", pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":""); @@ -259,6 +315,10 @@ release_dotlock( DOTLOCK h ) #else int pid; + if( h->disable ) { + return 0; + } + if( !h->locked ) { log_debug("oops, `%s' is not locked\n", h->lockname ); return 0; @@ -273,11 +333,19 @@ release_dotlock( DOTLOCK h ) log_error( "release_dotlock: not our lock (pid=%d)\n", pid); return -1; } +#ifndef __riscos__ if( unlink( h->lockname ) ) { log_error( "release_dotlock: error removing lockfile `%s'", h->lockname); return -1; } +#else /* __riscos__ */ + if( renamefile(h->lockname, h->tname) ) { + log_error( "release_dotlock: error renaming lockfile `%s' to `%s'", + h->lockname, h->tname); + return -1; + } +#endif /* __riscos__ */ /* fixme: check that the link count is now 1 */ h->locked = 0; return 0; @@ -291,9 +359,9 @@ release_dotlock( DOTLOCK h ) static int read_lockfile( const char *name ) { - #ifdef HAVE_DOSISH_SYSTEM +#ifdef HAVE_DOSISH_SYSTEM return 0; - #else +#else int fd, pid; char pidstr[16]; @@ -312,20 +380,24 @@ read_lockfile( const char *name ) pidstr[10] = 0; /* terminate pid string */ close(fd); pid = atoi(pidstr); +#ifndef __riscos__ if( !pid || pid == -1 ) { +#else /* __riscos__ */ + if( (!pid && riscos_getpid()) || pid == -1 ) { +#endif /* __riscos__ */ log_error("invalid pid %d in lockfile `%s'", pid, name ); errno = 0; return -1; } return pid; - #endif +#endif } -static void -remove_lockfiles() +void +dotlock_remove_lockfiles() { - #ifndef HAVE_DOSISH_SYSTEM +#ifndef HAVE_DOSISH_SYSTEM DOTLOCK h, h2; h = all_lockfiles; @@ -333,14 +405,16 @@ remove_lockfiles() while( h ) { h2 = h->next; - if( h->locked ) + if (!h->disable ) { + if( h->locked ) unlink( h->lockname ); - unlink(h->tname); - jnlib_free(h->tname); - jnlib_free(h->lockname); + unlink(h->tname); + jnlib_free(h->tname); + jnlib_free(h->lockname); + } jnlib_free(h); h = h2; } - #endif +#endif } diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h index 7d45c8286..9235687df 100644 --- a/jnlib/dotlock.h +++ b/jnlib/dotlock.h @@ -24,9 +24,13 @@ struct dotlock_handle; typedef struct dotlock_handle *DOTLOCK; -DOTLOCK create_dotlock( const char *file_to_lock ); -int make_dotlock( DOTLOCK h, long timeout ); -int release_dotlock( DOTLOCK h ); - +void disable_dotlock (void); +DOTLOCK create_dotlock(const char *file_to_lock); +int make_dotlock (DOTLOCK h, long timeout); +int release_dotlock (DOTLOCK h); +void dotlock_remove_lockfiles (void); #endif /*LIBJNLIB_DOTLOCK_H*/ + + + diff --git a/jnlib/logging.c b/jnlib/logging.c index 647e757c6..913d01b6f 100644 --- a/jnlib/logging.c +++ b/jnlib/logging.c @@ -1,5 +1,5 @@ /* logging.c - useful logging functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -79,6 +79,12 @@ log_get_errorcount (int clear) } void +log_inc_errorcount (void) +{ + errorcount++; +} + +void log_set_file( const char *name ) { FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr; @@ -194,7 +200,12 @@ do_logv( int level, const char *fmt, va_list arg_ptr ) fprintf (logstream, "[%u]", (unsigned int)getpid ()); if (!with_time) putc (':', logstream); - putc (' ', logstream); + /* A leading backspace suppresses the extra space so that we can + correclty output, programname, filename and linenumber. */ + if (fmt && *fmt == '\b') + fmt++; + else + putc (' ', logstream); } switch (level) @@ -272,7 +283,7 @@ log_fatal( const char *fmt, ... ) va_start( arg_ptr, fmt ) ; do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr ); va_end(arg_ptr); - abort(); /* never called, bugs it makes the compiler happy */ + abort(); /* never called, but it makes the compiler happy */ } void diff --git a/jnlib/logging.h b/jnlib/logging.h index 224db36e5..78d2b020d 100644 --- a/jnlib/logging.h +++ b/jnlib/logging.h @@ -26,6 +26,7 @@ int log_get_errorcount (int clear); +void log_inc_errorcount (void); void log_set_file( const char *name ); void log_set_fd (int fd); void log_set_prefix (const char *text, unsigned int flags); diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h index 58c9250e2..54da4cc1f 100644 --- a/jnlib/mischelp.h +++ b/jnlib/mischelp.h @@ -1,5 +1,5 @@ /* mischelp.h - * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -39,5 +39,16 @@ #endif +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + + + #endif /*LIBJNLIB_MISCHELP_H*/ diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c index 3c9baaef5..e2744a5ac 100644 --- a/jnlib/stringhelp.c +++ b/jnlib/stringhelp.c @@ -1,5 +1,5 @@ /* stringhelp.c - standard string helper functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +25,7 @@ #include <ctype.h> #include "libjnlib-config.h" +#include "utf8conv.h" #include "stringhelp.h" @@ -52,6 +53,25 @@ memistr( const char *buf, size_t buflen, const char *sub ) return NULL ; } +const char * +ascii_memistr( const char *buf, size_t buflen, const char *sub ) +{ + const byte *t, *s ; + size_t n; + + for( t=buf, n=buflen, s=sub ; n ; t++, n-- ) + if( ascii_toupper(*t) == ascii_toupper(*s) ) { + for( buf=t++, buflen = n--, s++; + n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- ) + ; + if( !*s ) + return buf; + t = buf; n = buflen; s = sub ; + } + + return NULL ; +} + /**************** * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein * '\0' angeh�ngt. Ist n = 0, so geschieht nichts, ist Destination @@ -127,7 +147,6 @@ trim_trailing_spaces( char *string ) } - unsigned trim_trailing_chars( byte *line, unsigned len, const char *trimchars ) { @@ -159,6 +178,39 @@ trim_trailing_ws( byte *line, unsigned len ) return trim_trailing_chars( line, len, " \t\r\n" ); } +size_t +length_sans_trailing_chars (const unsigned char *line, size_t len, + const char *trimchars ) +{ + const unsigned char *p, *mark; + size_t n; + + for( mark=NULL, p=line, n=0; n < len; n++, p++ ) + { + if (strchr (trimchars, *p )) + { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + + if (mark) + return mark - line; + return len; +} + +/**************** + * remove trailing white spaces and return the length of the buffer + */ +size_t +length_sans_trailing_ws (const unsigned char *line, size_t len) +{ + return length_sans_trailing_chars (line, len, " \t\r\n"); +} + + /*************** * Extract from a given path the filename component. @@ -256,18 +308,19 @@ compare_filenames( const char *a, const char *b ) /* ? check whether this is an absolute filename and * resolve symlinks? */ - #ifdef HAVE_DRIVE_LETTERS +#ifdef HAVE_DRIVE_LETTERS return stricmp(a,b); - #else +#else return strcmp(a,b); - #endif +#endif } /* Print a BUFFER to stream FP while replacing all control characters - and the character DELIM with standard C eescape sequences. Returns + and the character DELIM with standard C escape sequences. Returns the number of characters printed. */ size_t -print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, int delim) +print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, + int delim) { const unsigned char *p = buffer; size_t count = 0; @@ -307,8 +360,26 @@ size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim) { - /* FIXME: convert to local characterset */ - return print_sanitized_buffer (fp, buffer, length, delim); + const char *p = buffer; + size_t i; + + /* We can handle plain ascii simpler, so check for it first. */ + for (i=0; i < length; i++ ) + { + if ( (p[i] & 0x80) ) + break; + } + if (i < length) + { + char *buf = utf8_to_native (p, length, delim); + /*(utf8 conversion already does the control character quoting)*/ + i = strlen (buf); + fputs (buf, fp); + jnlib_free (buf); + return i; + } + else + return print_sanitized_buffer (fp, p, length, delim); } @@ -325,6 +396,63 @@ print_sanitized_utf8_string (FILE *fp, const char *string, int delim) return print_sanitized_string (fp, string, delim); } +/* Create a string from the buffer P of length N which is suitable for + printing. Caller must release the created string using xfree. */ +char * +sanitize_buffer (const unsigned char *p, size_t n, int delim) +{ + size_t save_n, buflen; + const byte *save_p; + char *buffer, *d; + + /* first count length */ + for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) + { + if ( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim + || (delim && *p=='\\')) + { + if ( *p=='\n' || *p=='\r' || *p=='\f' + || *p=='\v' || *p=='\b' || !*p ) + buflen += 2; + else + buflen += 4; + } + else + buflen++; + } + p = save_p; + n = save_n; + /* and now make the string */ + d = buffer = jnlib_xmalloc( buflen ); + for ( ; n; n--, p++ ) + { + if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim + ||(delim && *p=='\\')) { + *d++ = '\\'; + if( *p == '\n' ) + *d++ = 'n'; + else if( *p == '\r' ) + *d++ = 'r'; + else if( *p == '\f' ) + *d++ = 'f'; + else if( *p == '\v' ) + *d++ = 'v'; + else if( *p == '\b' ) + *d++ = 'b'; + else if( !*p ) + *d++ = '0'; + else { + sprintf(d, "x%02x", *p ); + d += 2; + } + } + else + *d++ = *p; + } + *d = 0; + return buffer; +} + /**************************************************** ******** locale insensitive ctype functions ******** ****************************************************/ @@ -371,6 +499,33 @@ ascii_strcasecmp( const char *a, const char *b ) return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b)); } +int +ascii_strncasecmp (const char *a, const char *b, size_t n) +{ + const unsigned char *p1 = (const unsigned char *)a; + const unsigned char *p2 = (const unsigned char *)b; + unsigned char c1, c2; + + if (p1 == p2 || !n ) + return 0; + + do + { + c1 = ascii_tolower (*p1); + c2 = ascii_tolower (*p2); + + if ( !--n || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + return c1 - c2; +} + + int ascii_memcasecmp( const char *a, const char *b, size_t n ) { diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h index 027d30c72..fe5786e59 100644 --- a/jnlib/stringhelp.h +++ b/jnlib/stringhelp.h @@ -1,5 +1,5 @@ /* stringhelp.h - * Copyright (C) 1998,1999,2000,2001 Free Software Foundation, Inc. + * Copyright (C) 1998,1999,2000,2001,2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +30,9 @@ char *trim_trailing_spaces( char *string ); unsigned int trim_trailing_chars( unsigned char *line, unsigned len, const char *trimchars); unsigned int trim_trailing_ws( unsigned char *line, unsigned len ); +size_t length_sans_trailing_chars (const unsigned char *line, size_t len, + const char *trimchars ); +size_t length_sans_trailing_ws (const unsigned char *line, size_t len); char *make_basename(const char *filepath); @@ -43,6 +46,7 @@ size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer, size_t length, int delim); size_t print_sanitized_string (FILE *fp, const char *string, int delim); size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim); +char *sanitize_buffer (const unsigned char *p, size_t n, int delim); const char *ascii_memistr( const char *buf, size_t buflen, const char *sub ); @@ -51,7 +55,9 @@ int ascii_islower (int c); int ascii_toupper (int c); int ascii_tolower (int c); int ascii_strcasecmp( const char *a, const char *b ); +int ascii_strncasecmp (const char *a, const char *b, size_t n); int ascii_memcasecmp( const char *a, const char *b, size_t n ); +const char *ascii_memistr ( const char *buf, size_t buflen, const char *sub); void *ascii_memcasemem (const void *haystack, size_t nhaystack, const void *needle, size_t nneedle); diff --git a/jnlib/strlist.c b/jnlib/strlist.c index 7cbaf5e02..063c89c7e 100644 --- a/jnlib/strlist.c +++ b/jnlib/strlist.c @@ -56,7 +56,7 @@ add_to_strlist( STRLIST *list, const char *string ) #if 0 /**************** * same as add_to_strlist() but if is_utf8 is *not* set a conversion - * to UTF8 is done + * to UTF8 is done */ STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ) @@ -130,4 +130,22 @@ strlist_last( STRLIST node ) } +char * +strlist_pop (STRLIST *list) +{ + char *str=NULL; + STRLIST sl=*list; + + if(sl) + { + str=jnlib_xmalloc(strlen(sl->d)+1); + strcpy(str,sl->d); + + *list=sl->next; + jnlib_free(sl); + } + + return str; +} + diff --git a/jnlib/strlist.h b/jnlib/strlist.h index 53c0bc750..443408f16 100644 --- a/jnlib/strlist.h +++ b/jnlib/strlist.h @@ -31,11 +31,12 @@ typedef struct string_list *STRLIST; void free_strlist( STRLIST sl ); STRLIST add_to_strlist( STRLIST *list, const char *string ); -STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +/*STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 );*/ STRLIST append_to_strlist( STRLIST *list, const char *string ); -STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 ); +/*STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 );*/ STRLIST strlist_prev( STRLIST head, STRLIST node ); STRLIST strlist_last( STRLIST node ); +char * strlist_pop (STRLIST *list); #define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c new file mode 100644 index 000000000..691176766 --- /dev/null +++ b/jnlib/utf8conv.c @@ -0,0 +1,448 @@ +/* utf8conf.c - UTF8 character set conversion + * Copyright (C) 1994, 1998, 1999, 2000, 2001, + * 2003 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> +#endif + +#include "libjnlib-config.h" +#include "stringhelp.h" +#include "utf8conv.h" + + +static ushort koi8_unicode[128] = { + 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, + 0x252c, 0x2534, 0x253c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590, + 0x2591, 0x2592, 0x2593, 0x2320, 0x25a0, 0x2219, 0x221a, 0x2248, + 0x2264, 0x2265, 0x00a0, 0x2321, 0x00b0, 0x00b2, 0x00b7, 0x00f7, + 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, + 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e, + 0x255f, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, + 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x00a9, + 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, + 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, + 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, + 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a +}; + +static ushort latin2_unicode[128] = { + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, + 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, + 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, + 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +}; + + +static const char *active_charset_name = "iso-8859-1"; +static ushort *active_charset = NULL; +static int no_translation = 0; + +int +set_native_charset (const char *newset) +{ + if (!newset) +#ifdef HAVE_LANGINFO_CODESET + newset = nl_langinfo (CODESET); +#else + newset = "8859-1"; +#endif + + if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) + { + newset += 3; + if (*newset == '-' || *newset == '_') + newset++; + } + + if (!*newset + || !ascii_strcasecmp (newset, "8859-1") + || !ascii_strcasecmp (newset, "8859-15")) + { + active_charset_name = "iso-8859-1"; + no_translation = 0; + active_charset = NULL; + } + else if (!ascii_strcasecmp (newset, "8859-2")) + { + active_charset_name = "iso-8859-2"; + no_translation = 0; + active_charset = latin2_unicode; + } + else if (!ascii_strcasecmp (newset, "koi8-r")) + { + active_charset_name = "koi8-r"; + no_translation = 0; + active_charset = koi8_unicode; + } + else if (!ascii_strcasecmp (newset, "utf8") + || !ascii_strcasecmp (newset, "utf-8")) + { + active_charset_name = "utf-8"; + no_translation = 1; + active_charset = NULL; + } + else + return -1; + return 0; +} + +const char * +get_native_charset () +{ + return active_charset_name; +} + +/**************** + * Convert string, which is in native encoding to UTF8 and return the + * new allocated UTF8 string. + */ +char * +native_to_utf8 (const char *string) +{ + const byte *s; + char *buffer; + byte *p; + size_t length = 0; + + if (no_translation) + { + buffer = jnlib_xstrdup (string); + } + else if (active_charset) + { + for (s = string; *s; s++) + { + length++; + if (*s & 0x80) + length += 2; /* we may need 3 bytes */ + } + buffer = jnlib_xmalloc (length + 1); + for (p = buffer, s = string; *s; s++) + { + if ((*s & 0x80)) + { + ushort val = active_charset[*s & 0x7f]; + if (val < 0x0800) + { + *p++ = 0xc0 | ((val >> 6) & 0x1f); + *p++ = 0x80 | (val & 0x3f); + } + else + { + *p++ = 0xe0 | ((val >> 12) & 0x0f); + *p++ = 0x80 | ((val >> 6) & 0x3f); + *p++ = 0x80 | (val & 0x3f); + } + } + else + *p++ = *s; + } + *p = 0; + } + else + { + for (s = string; *s; s++) + { + length++; + if (*s & 0x80) + length++; + } + buffer = jnlib_xmalloc (length + 1); + for (p = buffer, s = string; *s; s++) + { + if (*s & 0x80) + { + *p++ = 0xc0 | ((*s >> 6) & 3); + *p++ = 0x80 | (*s & 0x3f); + } + else + *p++ = *s; + } + *p = 0; + } + return buffer; +} + + +/* Convert string, which is in UTF8 to native encoding. Replace + * illegal encodings by some "\xnn" and quote all control + * characters. A character with value DELIM will always be quoted, it + * must be a vanilla ASCII character. */ +char * +utf8_to_native (const char *string, size_t length, int delim) +{ + int nleft; + int i; + byte encbuf[8]; + int encidx; + const byte *s; + size_t n; + byte *buffer = NULL, *p = NULL; + unsigned long val = 0; + size_t slen; + int resync = 0; + + /* 1. pass (p==NULL): count the extended utf-8 characters */ + /* 2. pass (p!=NULL): create string */ + for (;;) + { + for (slen = length, nleft = encidx = 0, n = 0, s = string; slen; + s++, slen--) + { + if (resync) + { + if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd))) + { + /* still invalid */ + if (p) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4; + continue; + } + resync = 0; + } + if (!nleft) + { + if (!(*s & 0x80)) + { /* plain ascii */ + if (*s < 0x20 || *s == 0x7f || *s == delim || + (delim && *s == '\\')) + { + n++; + if (p) + *p++ = '\\'; + switch (*s) + { + case '\n': + n++; + if (p) + *p++ = 'n'; + break; + case '\r': + n++; + if (p) + *p++ = 'r'; + break; + case '\f': + n++; + if (p) + *p++ = 'f'; + break; + case '\v': + n++; + if (p) + *p++ = 'v'; + break; + case '\b': + n++; + if (p) + *p++ = 'b'; + break; + case 0: + n++; + if (p) + *p++ = '0'; + break; + default: + n += 3; + if (p) + { + sprintf (p, "x%02x", *s); + p += 3; + } + break; + } + } + else + { + if (p) + *p++ = *s; + n++; + } + } + else if ((*s & 0xe0) == 0xc0) + { /* 110x xxxx */ + val = *s & 0x1f; + nleft = 1; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xf0) == 0xe0) + { /* 1110 xxxx */ + val = *s & 0x0f; + nleft = 2; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xf8) == 0xf0) + { /* 1111 0xxx */ + val = *s & 0x07; + nleft = 3; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xfc) == 0xf8) + { /* 1111 10xx */ + val = *s & 0x03; + nleft = 4; + encidx = 0; + encbuf[encidx++] = *s; + } + else if ((*s & 0xfe) == 0xfc) + { /* 1111 110x */ + val = *s & 0x01; + nleft = 5; + encidx = 0; + encbuf[encidx++] = *s; + } + else + { /* invalid encoding: print as \xnn */ + if (p) + { + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4; + resync = 1; + } + } + else if (*s < 0x80 || *s >= 0xc0) + { /* invalid */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + sprintf (p, "\\x%02x", *s); + p += 4; + } + n += 4 + 4 * encidx; + nleft = 0; + encidx = 0; + resync = 1; + } + else + { + encbuf[encidx++] = *s; + val <<= 6; + val |= *s & 0x3f; + if (!--nleft) + { /* ready */ + if (no_translation) + { + if (p) + { + for (i = 0; i < encidx; i++) + *p++ = encbuf[i]; + } + n += encidx; + encidx = 0; + } + else if (active_charset) + { /* table lookup */ + for (i = 0; i < 128; i++) + { + if (active_charset[i] == val) + break; + } + if (i < 128) + { /* we can print this one */ + if (p) + *p++ = i + 128; + n++; + } + else + { /* we do not have a translation: print utf8 */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + } + n += encidx * 4; + encidx = 0; + } + } + else + { /* native set */ + if (val >= 0x80 && val < 256) + { + n++; /* we can simply print this character */ + if (p) + *p++ = val; + } + else + { /* we do not have a translation: print utf8 */ + if (p) + { + for (i = 0; i < encidx; i++) + { + sprintf (p, "\\x%02x", encbuf[i]); + p += 4; + } + } + n += encidx * 4; + encidx = 0; + } + } + } + + } + } + if (!buffer) + { /* allocate the buffer after the first pass */ + buffer = p = jnlib_xmalloc (n + 1); + } + else + { + *p = 0; /* make a string */ + return buffer; + } + } +} diff --git a/jnlib/utf8conv.h b/jnlib/utf8conv.h new file mode 100644 index 000000000..6e2ce9944 --- /dev/null +++ b/jnlib/utf8conv.h @@ -0,0 +1,31 @@ +/* utf8conf.h + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef LIBJNLIB_UTF8CONF_H +#define LIBJNLIB_UTF8CONF_H + +int set_native_charset (const char *newset); +const char *get_native_charset (void); + +char *native_to_utf8 (const char *string); +char *utf8_to_native (const char *string, size_t length, int delim); + + +#endif /*LIBJNLIB_UTF8CONF_H*/ |