~ubuntu-branches/ubuntu/jaunty/gnupg2/jaunty

« back to all changes in this revision

Viewing changes to jnlib/stringhelp.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* stringhelp.c -  standard string helper functions
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2003,
 
3
 *               2004  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 <stdarg.h>
 
26
#include <ctype.h>
 
27
#ifdef HAVE_W32_SYSTEM
 
28
#include <windows.h>
 
29
#endif
 
30
 
 
31
#include "libjnlib-config.h"
 
32
#include "utf8conv.h"
 
33
#include "stringhelp.h"
 
34
 
 
35
 
 
36
/*
 
37
 * Look for the substring SUB in buffer and return a pointer to that
 
38
 * substring in BUF or NULL if not found.
 
39
 * Comparison is case-insensitive.
 
40
 */
 
41
const char *
 
42
memistr( const char *buf, size_t buflen, const char *sub )
 
43
{
 
44
    const byte *t, *s ;
 
45
    size_t n;
 
46
 
 
47
    for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
 
48
        if( toupper(*t) == toupper(*s) ) {
 
49
            for( buf=t++, buflen = n--, s++;
 
50
                 n && toupper(*t) == toupper(*s); t++, s++, n-- )
 
51
                ;
 
52
            if( !*s )
 
53
                return buf;
 
54
            t = buf; n = buflen; s = sub ;
 
55
        }
 
56
 
 
57
    return NULL ;
 
58
}
 
59
 
 
60
const char *
 
61
ascii_memistr( const char *buf, size_t buflen, const char *sub )
 
62
{
 
63
    const byte *t, *s ;
 
64
    size_t n;
 
65
 
 
66
    for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
 
67
        if( ascii_toupper(*t) == ascii_toupper(*s) ) {
 
68
            for( buf=t++, buflen = n--, s++;
 
69
                 n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
 
70
                ;
 
71
            if( !*s )
 
72
                return buf;
 
73
            t = buf; n = buflen; s = sub ;
 
74
        }
 
75
 
 
76
    return NULL ;
 
77
}
 
78
 
 
79
/* This function is similar to strncpy().  However it won't copy more
 
80
   than N - 1 characters and makes sure that a '\0' is appended. With
 
81
   N given as 0, nothing will happen.  With DEST given as NULL, memory
 
82
   will be allocated using jnlib_xmalloc (i.e. if it runs out of core
 
83
   the function terminates).  Returns DES or a pointer to the
 
84
   allocated memory.
 
85
 */
 
86
char *
 
87
mem2str( char *dest , const void *src , size_t n )
 
88
{
 
89
    char *d;
 
90
    const char *s;
 
91
 
 
92
    if( n ) {
 
93
        if( !dest )
 
94
            dest = jnlib_xmalloc( n ) ;
 
95
        d = dest;
 
96
        s = src ;
 
97
        for(n--; n && *s; n-- )
 
98
            *d++ = *s++;
 
99
        *d = '\0' ;
 
100
    }
 
101
 
 
102
    return dest ;
 
103
}
 
104
 
 
105
 
 
106
/****************
 
107
 * remove leading and trailing white spaces
 
108
 */
 
109
char *
 
110
trim_spaces( char *str )
 
111
{
 
112
    char *string, *p, *mark;
 
113
 
 
114
    string = str;
 
115
    /* find first non space character */
 
116
    for( p=string; *p && isspace( *(byte*)p ) ; p++ )
 
117
        ;
 
118
    /* move characters */
 
119
    for( (mark = NULL); (*string = *p); string++, p++ )
 
120
        if( isspace( *(byte*)p ) ) {
 
121
            if( !mark )
 
122
                mark = string ;
 
123
        }
 
124
        else
 
125
            mark = NULL ;
 
126
    if( mark )
 
127
        *mark = '\0' ;  /* remove trailing spaces */
 
128
 
 
129
    return str ;
 
130
}
 
131
 
 
132
/****************
 
133
 * remove trailing white spaces
 
134
 */
 
135
char *
 
136
trim_trailing_spaces( char *string )
 
137
{
 
138
    char *p, *mark;
 
139
 
 
140
    for( mark = NULL, p = string; *p; p++ ) {
 
141
        if( isspace( *(byte*)p ) ) {
 
142
            if( !mark )
 
143
                mark = p;
 
144
        }
 
145
        else
 
146
            mark = NULL;
 
147
    }
 
148
    if( mark )
 
149
        *mark = '\0' ;
 
150
 
 
151
    return string ;
 
152
}
 
153
 
 
154
 
 
155
unsigned
 
156
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
 
157
{
 
158
    byte *p, *mark;
 
159
    unsigned n;
 
160
 
 
161
    for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
 
162
        if( strchr(trimchars, *p ) ) {
 
163
            if( !mark )
 
164
                mark = p;
 
165
        }
 
166
        else
 
167
            mark = NULL;
 
168
    }
 
169
 
 
170
    if( mark ) {
 
171
        *mark = 0;
 
172
        return mark - line;
 
173
    }
 
174
    return len;
 
175
}
 
176
 
 
177
/****************
 
178
 * remove trailing white spaces and return the length of the buffer
 
179
 */
 
180
unsigned
 
181
trim_trailing_ws( byte *line, unsigned len )
 
182
{
 
183
    return trim_trailing_chars( line, len, " \t\r\n" );
 
184
}
 
185
 
 
186
size_t
 
187
length_sans_trailing_chars (const unsigned char *line, size_t len,
 
188
                            const char *trimchars )
 
189
{
 
190
  const unsigned char *p, *mark;
 
191
  size_t n;
 
192
  
 
193
  for( mark=NULL, p=line, n=0; n < len; n++, p++ )
 
194
    {
 
195
      if (strchr (trimchars, *p ))
 
196
        {
 
197
          if( !mark )
 
198
            mark = p;
 
199
        }
 
200
      else
 
201
        mark = NULL;
 
202
    }
 
203
  
 
204
  if (mark) 
 
205
    return mark - line;
 
206
  return len;
 
207
}
 
208
 
 
209
/****************
 
210
 * remove trailing white spaces and return the length of the buffer
 
211
 */
 
212
size_t
 
213
length_sans_trailing_ws (const unsigned char *line, size_t len)
 
214
{
 
215
  return length_sans_trailing_chars (line, len, " \t\r\n");
 
216
}
 
217
 
 
218
 
 
219
 
 
220
/***************
 
221
 * Extract from a given path the filename component.
 
222
 *
 
223
 */
 
224
char *
 
225
make_basename(const char *filepath)
 
226
{
 
227
    char *p;
 
228
 
 
229
    if ( !(p=strrchr(filepath, '/')) )
 
230
      #ifdef HAVE_DRIVE_LETTERS
 
231
        if ( !(p=strrchr(filepath, '\\')) )
 
232
            if ( !(p=strrchr(filepath, ':')) )
 
233
      #endif
 
234
              {
 
235
                return jnlib_xstrdup(filepath);
 
236
              }
 
237
 
 
238
    return jnlib_xstrdup(p+1);
 
239
}
 
240
 
 
241
 
 
242
 
 
243
/***************
 
244
 * Extract from a given filename the path prepended to it.
 
245
 * If their isn't a path prepended to the filename, a dot
 
246
 * is returned ('.').
 
247
 *
 
248
 */
 
249
char *
 
250
make_dirname(const char *filepath)
 
251
{
 
252
    char *dirname;
 
253
    int  dirname_length;
 
254
    char *p;
 
255
 
 
256
    if ( !(p=strrchr(filepath, '/')) )
 
257
      #ifdef HAVE_DRIVE_LETTERS
 
258
        if ( !(p=strrchr(filepath, '\\')) )
 
259
            if ( !(p=strrchr(filepath, ':')) )
 
260
      #endif
 
261
              {
 
262
                return jnlib_xstrdup(".");
 
263
              }
 
264
 
 
265
    dirname_length = p-filepath;
 
266
    dirname = jnlib_xmalloc(dirname_length+1);
 
267
    strncpy(dirname, filepath, dirname_length);
 
268
    dirname[dirname_length] = 0;
 
269
 
 
270
    return dirname;
 
271
}
 
272
 
 
273
 
 
274
 
 
275
/****************
 
276
 * Construct a filename from the NULL terminated list of parts.
 
277
 * Tilde expansion is done here.
 
278
 */
 
279
char *
 
280
make_filename( const char *first_part, ... )
 
281
{
 
282
    va_list arg_ptr ;
 
283
    size_t n;
 
284
    const char *s;
 
285
    char *name, *home, *p;
 
286
 
 
287
    va_start( arg_ptr, first_part ) ;
 
288
    n = strlen(first_part)+1;
 
289
    while( (s=va_arg(arg_ptr, const char *)) )
 
290
        n += strlen(s) + 1;
 
291
    va_end(arg_ptr);
 
292
 
 
293
    home = NULL;
 
294
    if( *first_part == '~' && first_part[1] == '/'
 
295
                           && (home = getenv("HOME")) && *home )
 
296
        n += strlen(home);
 
297
 
 
298
    name = jnlib_xmalloc(n);
 
299
    p = home ? stpcpy(stpcpy(name,home), first_part+1)
 
300
             : stpcpy(name, first_part);
 
301
    va_start( arg_ptr, first_part ) ;
 
302
    while( (s=va_arg(arg_ptr, const char *)) )
 
303
        p = stpcpy(stpcpy(p,"/"), s);
 
304
    va_end(arg_ptr);
 
305
 
 
306
    return name;
 
307
}
 
308
 
 
309
 
 
310
int
 
311
compare_filenames( const char *a, const char *b )
 
312
{
 
313
    /* ? check whether this is an absolute filename and
 
314
     * resolve symlinks?
 
315
     */
 
316
#ifdef HAVE_DRIVE_LETTERS
 
317
    return stricmp(a,b);
 
318
#else
 
319
    return strcmp(a,b);
 
320
#endif
 
321
}
 
322
 
 
323
/* Print a BUFFER to stream FP while replacing all control characters
 
324
   and the character DELIM with standard C escape sequences.  Returns
 
325
   the number of characters printed. */
 
326
size_t 
 
327
print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
 
328
                        int delim)
 
329
{
 
330
  const unsigned char *p = buffer;
 
331
  size_t count = 0;
 
332
 
 
333
  for (; length; length--, p++, count++)
 
334
    {
 
335
      if (*p < 0x20 || *p == 0x7f || *p == delim)
 
336
        {
 
337
          putc ('\\', fp);
 
338
          count++;
 
339
          if (*p == '\n')
 
340
            putc ('n', fp);
 
341
          else if (*p == '\r')
 
342
            putc ('r', fp);
 
343
          else if (*p == '\f')
 
344
            putc ('f', fp);
 
345
          else if (*p == '\v')
 
346
            putc ('v', fp);
 
347
          else if (*p == '\b')
 
348
            putc ('b', fp);
 
349
          else if (!*p)
 
350
            putc('0', fp);
 
351
          else
 
352
            {
 
353
              fprintf (fp, "x%02x", *p);
 
354
              count += 2;
 
355
            }
 
356
        }
 
357
      else
 
358
        putc (*p, fp);
 
359
    }
 
360
 
 
361
  return count;
 
362
}
 
363
 
 
364
size_t 
 
365
print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
 
366
                             size_t length, int delim)
 
367
{
 
368
  const char *p = buffer;
 
369
  size_t i;
 
370
 
 
371
  /* We can handle plain ascii simpler, so check for it first. */
 
372
  for (i=0; i < length; i++ ) 
 
373
    {
 
374
      if ( (p[i] & 0x80) )
 
375
        break;
 
376
    }
 
377
  if (i < length)
 
378
    {
 
379
        char *buf = utf8_to_native (p, length, delim);
 
380
        /*(utf8 conversion already does the control character quoting)*/
 
381
        i = strlen (buf);
 
382
        fputs (buf, fp);
 
383
        jnlib_free (buf);
 
384
        return i;
 
385
    }
 
386
  else
 
387
    return print_sanitized_buffer (fp, p, length, delim);
 
388
}
 
389
 
 
390
 
 
391
size_t 
 
392
print_sanitized_string (FILE *fp, const char *string, int delim)
 
393
{
 
394
  return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
 
395
}
 
396
 
 
397
size_t 
 
398
print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
 
399
{
 
400
  return string? print_sanitized_utf8_buffer (fp,
 
401
                                              string, strlen (string),
 
402
                                              delim) : 0;
 
403
}
 
404
 
 
405
/* Create a string from the buffer P of length N which is suitable for
 
406
   printing.  Caller must release the created string using xfree. */
 
407
char *
 
408
sanitize_buffer (const unsigned char *p, size_t n, int delim)
 
409
{
 
410
  size_t save_n, buflen;
 
411
  const byte *save_p;
 
412
  char *buffer, *d;
 
413
 
 
414
  /* first count length */
 
415
  for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) 
 
416
    {
 
417
      if ( *p < 0x20 || *p == 0x7f || *p == delim  || (delim && *p=='\\'))
 
418
        {
 
419
          if ( *p=='\n' || *p=='\r' || *p=='\f'
 
420
               || *p=='\v' || *p=='\b' || !*p )
 
421
            buflen += 2;
 
422
          else
 
423
            buflen += 4;
 
424
        }
 
425
      else
 
426
        buflen++;
 
427
    }
 
428
  p = save_p;
 
429
  n = save_n;
 
430
  /* and now make the string */
 
431
  d = buffer = jnlib_xmalloc( buflen );
 
432
  for ( ; n; n--, p++ )
 
433
    {
 
434
      if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
 
435
        *d++ = '\\';
 
436
        if( *p == '\n' )
 
437
          *d++ = 'n';
 
438
        else if( *p == '\r' )
 
439
          *d++ = 'r';
 
440
        else if( *p == '\f' )
 
441
          *d++ = 'f';
 
442
        else if( *p == '\v' )
 
443
          *d++ = 'v';
 
444
        else if( *p == '\b' )
 
445
          *d++ = 'b';
 
446
        else if( !*p )
 
447
          *d++ = '0';
 
448
        else {
 
449
          sprintf(d, "x%02x", *p );
 
450
          d += 2;
 
451
        }
 
452
      }
 
453
      else
 
454
        *d++ = *p;
 
455
    }
 
456
  *d = 0;
 
457
  return buffer;
 
458
}
 
459
 
 
460
 
 
461
/****************************************************
 
462
 **********  W32 specific functions  ****************
 
463
 ****************************************************/
 
464
 
 
465
#ifdef HAVE_W32_SYSTEM
 
466
const char *
 
467
w32_strerror (int ec)
 
468
{
 
469
  static char strerr[256];
 
470
  
 
471
  if (ec == -1)
 
472
    ec = (int)GetLastError ();
 
473
  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
 
474
                 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
 
475
                 strerr, DIM (strerr)-1, NULL);
 
476
  return strerr;    
 
477
}
 
478
#endif /*HAVE_W32_SYSTEM*/
 
479
 
 
480
 
 
481
/****************************************************
 
482
 ******** Locale insensitive ctype functions ********
 
483
 ****************************************************/
 
484
/* FIXME: replace them by a table lookup and macros */
 
485
int
 
486
ascii_isupper (int c)
 
487
{
 
488
    return c >= 'A' && c <= 'Z';
 
489
}
 
490
 
 
491
int
 
492
ascii_islower (int c)
 
493
{
 
494
    return c >= 'a' && c <= 'z';
 
495
}
 
496
 
 
497
int 
 
498
ascii_toupper (int c)
 
499
{
 
500
    if (c >= 'a' && c <= 'z')
 
501
        c &= ~0x20;
 
502
    return c;
 
503
}
 
504
 
 
505
int 
 
506
ascii_tolower (int c)
 
507
{
 
508
    if (c >= 'A' && c <= 'Z')
 
509
        c |= 0x20;
 
510
    return c;
 
511
}
 
512
 
 
513
 
 
514
int
 
515
ascii_strcasecmp( const char *a, const char *b )
 
516
{
 
517
    if (a == b)
 
518
        return 0;
 
519
 
 
520
    for (; *a && *b; a++, b++) {
 
521
        if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
 
522
            break;
 
523
    }
 
524
    return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
 
525
}
 
526
 
 
527
int 
 
528
ascii_strncasecmp (const char *a, const char *b, size_t n)
 
529
{
 
530
  const unsigned char *p1 = (const unsigned char *)a;
 
531
  const unsigned char *p2 = (const unsigned char *)b;
 
532
  unsigned char c1, c2;
 
533
 
 
534
  if (p1 == p2 || !n )
 
535
    return 0;
 
536
 
 
537
  do
 
538
    {
 
539
      c1 = ascii_tolower (*p1);
 
540
      c2 = ascii_tolower (*p2);
 
541
 
 
542
      if ( !--n || c1 == '\0')
 
543
        break;
 
544
 
 
545
      ++p1;
 
546
      ++p2;
 
547
    }
 
548
  while (c1 == c2);
 
549
  
 
550
  return c1 - c2;
 
551
}
 
552
 
 
553
 
 
554
int
 
555
ascii_memcasecmp( const char *a, const char *b, size_t n )
 
556
{
 
557
    if (a == b)
 
558
        return 0;
 
559
    for ( ; n; n--, a++, b++ ) {
 
560
        if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
 
561
            return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
 
562
    }
 
563
    return 0;
 
564
}
 
565
 
 
566
int
 
567
ascii_strcmp( const char *a, const char *b )
 
568
{
 
569
    if (a == b)
 
570
        return 0;
 
571
 
 
572
    for (; *a && *b; a++, b++) {
 
573
        if (*a != *b )
 
574
            break;
 
575
    }
 
576
    return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
 
577
}
 
578
 
 
579
 
 
580
void *
 
581
ascii_memcasemem (const void *haystack, size_t nhaystack,
 
582
                  const void *needle, size_t nneedle)
 
583
{
 
584
 
 
585
  if (!nneedle)
 
586
    return (void*)haystack; /* finding an empty needle is really easy */
 
587
  if (nneedle <= nhaystack)
 
588
    {
 
589
      const unsigned char *a = haystack;
 
590
      const unsigned char *b = a + nhaystack - nneedle;
 
591
      
 
592
      for (; a <= b; a++)
 
593
        {
 
594
          if ( !ascii_memcasecmp (a, needle, nneedle) )
 
595
            return (void *)a;
 
596
        }
 
597
    }
 
598
  return NULL;
 
599
}
 
600
 
 
601
/*********************************************
 
602
 ********** missing string functions *********
 
603
 *********************************************/
 
604
 
 
605
#ifndef HAVE_STPCPY
 
606
char *
 
607
stpcpy(char *a,const char *b)
 
608
{
 
609
    while( *b )
 
610
        *a++ = *b++;
 
611
    *a = 0;
 
612
 
 
613
    return (char*)a;
 
614
}
 
615
#endif
 
616
 
 
617
#ifndef HAVE_STRLWR
 
618
char *
 
619
strlwr(char *s)
 
620
{
 
621
    char *p;
 
622
    for(p=s; *p; p++ )
 
623
        *p = tolower(*p);
 
624
    return s;
 
625
}
 
626
#endif
 
627
 
 
628
 
 
629
#ifndef HAVE_STRCASECMP
 
630
int
 
631
strcasecmp( const char *a, const char *b )
 
632
{
 
633
    for( ; *a && *b; a++, b++ ) {
 
634
        if( *a != *b && toupper(*a) != toupper(*b) )
 
635
            break;
 
636
    }
 
637
    return *(const byte*)a - *(const byte*)b;
 
638
}
 
639
#endif
 
640
 
 
641
 
 
642
/****************
 
643
 * mingw32/cpd has a memicmp()
 
644
 */
 
645
#ifndef HAVE_MEMICMP
 
646
int
 
647
memicmp( const char *a, const char *b, size_t n )
 
648
{
 
649
    for( ; n; n--, a++, b++ )
 
650
        if( *a != *b  && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
 
651
            return *(const byte *)a - *(const byte*)b;
 
652
    return 0;
 
653
}
 
654
#endif
 
655
 
 
656