aboutsummaryrefslogtreecommitdiffstats
path: root/jnlib
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2003-06-18 19:56:13 +0000
committerWerner Koch <[email protected]>2003-06-18 19:56:13 +0000
commitc0c2c58054923d506f61ce9a71d509b48a381211 (patch)
treea8f82bffb44eb68eb726ff6db41fa715bcd29193 /jnlib
parentA small step for GnuPG but a huge leap for error codes. (diff)
downloadgnupg-c0c2c58054923d506f61ce9a71d509b48a381211.tar.gz
gnupg-c0c2c58054923d506f61ce9a71d509b48a381211.zip
Finished the bulk of changes for gnupg 1.9. This included switching
to libgcrypt functions, using shared error codes from libgpg-error, replacing the old functions we used to have in ../util by those in ../jnlib and ../common, renaming the malloc functions and a couple of types. Note, that not all changes are listed below becuause they are too similar and done at far too many places. As of today the code builds using the current libgcrypt from CVS but it is very unlikely that it actually works.
Diffstat (limited to 'jnlib')
-rw-r--r--jnlib/ChangeLog35
-rw-r--r--jnlib/Makefile.am1
-rw-r--r--jnlib/dotlock.c122
-rw-r--r--jnlib/dotlock.h12
-rw-r--r--jnlib/logging.c17
-rw-r--r--jnlib/logging.h1
-rw-r--r--jnlib/mischelp.h13
-rw-r--r--jnlib/stringhelp.c173
-rw-r--r--jnlib/stringhelp.h8
-rw-r--r--jnlib/strlist.c20
-rw-r--r--jnlib/strlist.h5
-rw-r--r--jnlib/utf8conv.c448
-rw-r--r--jnlib/utf8conv.h31
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*/