introduced confdir option
[privoxy.git] / miscutil.c
1 const char miscutil_rcs[] = "$Id: miscutil.c,v 1.5 2001/06/01 10:31:51 oes Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/miscutil.c,v $
5  *
6  * Purpose     :  zalloc, hash_string, safe_strerror, strcmpic,
7  *                strncmpic, strsav, chomp, and MinGW32 strdup
8  *                functions. 
9  *                These are each too small to deserve their own file
10  *                but don't really fit in any other file.
11  *
12  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
13  *                IJBSWA team.  http://ijbswa.sourceforge.net
14  *
15  *                Based on the Internet Junkbuster originally written
16  *                by and Copyright (C) 1997 Anonymous Coders and 
17  *                Junkbusters Corporation.  http://www.junkbusters.com
18  *
19  *                This program is free software; you can redistribute it 
20  *                and/or modify it under the terms of the GNU General
21  *                Public License as published by the Free Software
22  *                Foundation; either version 2 of the License, or (at
23  *                your option) any later version.
24  *
25  *                This program is distributed in the hope that it will
26  *                be useful, but WITHOUT ANY WARRANTY; without even the
27  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
28  *                PARTICULAR PURPOSE.  See the GNU General Public
29  *                License for more details.
30  *
31  *                The GNU General Public License should be included with
32  *                this file.  If not, you can view it at
33  *                http://www.gnu.org/copyleft/gpl.html
34  *                or write to the Free Software Foundation, Inc., 59
35  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
36  *
37  * Revisions   :
38  *    $Log: miscutil.c,v $
39  *    Revision 1.5  2001/06/01 10:31:51  oes
40  *    Added character class matching to trivimatch; renamed to simplematch
41  *
42  *    Revision 1.4  2001/05/31 17:32:31  oes
43  *
44  *     - Enhanced domain part globbing with infix and prefix asterisk
45  *       matching and optional unanchored operation
46  *
47  *    Revision 1.3  2001/05/29 23:10:09  oes
48  *
49  *
50  *     - Introduced chomp()
51  *     - Moved strsav() from showargs to miscutil
52  *
53  *    Revision 1.2  2001/05/29 09:50:24  jongfoster
54  *    Unified blocklist/imagelist/permissionslist.
55  *    File format is still under discussion, but the internal changes
56  *    are (mostly) done.
57  *
58  *    Also modified interceptor behaviour:
59  *    - We now intercept all URLs beginning with one of the following
60  *      prefixes (and *only* these prefixes):
61  *        * http://i.j.b/
62  *        * http://ijbswa.sf.net/config/
63  *        * http://ijbswa.sourceforge.net/config/
64  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
65  *    - Internal changes so that intercepted and fast redirect pages
66  *      are not replaced with an image.
67  *    - Interceptors now have the option to send a binary page direct
68  *      to the client. (i.e. ijb-send-banner uses this)
69  *    - Implemented show-url-info interceptor.  (Which is why I needed
70  *      the above interceptors changes - a typical URL is
71  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
72  *      The previous mechanism would not have intercepted that, and
73  *      if it had been intercepted then it then it would have replaced
74  *      it with an image.)
75  *
76  *    Revision 1.1.1.1  2001/05/15 13:59:00  oes
77  *    Initial import of version 2.9.3 source tree
78  *
79  *
80  *********************************************************************/
81 \f
82
83 #include "config.h"
84
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <string.h>
88 #include <malloc.h>
89 #include <ctype.h>
90
91 #include "miscutil.h"
92 #include "errlog.h"
93
94 const char miscutil_h_rcs[] = MISCUTIL_H_VERSION;
95
96 /* Fix a problem with Solaris.  There should be no effect on other
97  * platforms.
98  * Solaris's isspace() is a macro which uses it's argument directly
99  * as an array index.  Therefore we need to make sure that high-bit
100  * characters generate +ve values, and ideally we also want to make
101  * the argument match the declared parameter type of "int".
102  */
103 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
104 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))   
105
106 /*********************************************************************
107  *
108  * Function    :  zalloc
109  *
110  * Description :  Malloc some memory and set it to '\0'.
111  *                The way calloc() ought to be -acjc
112  *
113  * Parameters  :
114  *          1  :  size = Size of memory chunk to return.
115  *
116  * Returns     :  Pointer to newly malloc'd memory chunk.
117  *
118  *********************************************************************/
119 void *zalloc(int size)
120 {
121    void * ret;
122
123    if ((ret = (void *)malloc(size)) != NULL)
124    {
125       memset(ret, 0, size);
126    }
127
128    return(ret);
129 }
130
131
132 /*********************************************************************
133  *
134  * Function    :  hash_string
135  *
136  * Description :  Take a string and compute a (hopefuly) unique numeric
137  *                integer value.  This has several uses, but being able
138  *                to "switch" a string the one of my favorites.
139  *
140  * Parameters  :
141  *          1  :  s : string to be hashed.
142  *
143  * Returns     :  an unsigned long variable with the hashed value.
144  *
145  *********************************************************************/
146 unsigned long hash_string( const char* s )
147 {
148    unsigned long h = 0ul; 
149
150    for ( ; *s; ++s )
151    {
152       h = 5 * h + *s;
153    }
154
155    return (h);
156
157 }
158
159
160 #ifdef __MINGW32__
161 /*********************************************************************
162  *
163  * Function    :  strdup
164  *
165  * Description :  For some reason (which is beyond me), gcc and WIN32
166  *                don't like strdup.  When a "free" is executed on a
167  *                strdup'd ptr, it can at times freez up!  So I just
168  *                replaced it and problem was solved.
169  *
170  * Parameters  :
171  *          1  :  s = string to duplicate
172  *
173  * Returns     :  Pointer to newly malloc'ed copy of the string.
174  *
175  *********************************************************************/
176 char *strdup( const char *s )
177 {
178    char * result = (char *)malloc( strlen(s)+1 );
179
180    if (result != NULL)
181    {
182       strcpy( result, s );
183    }
184
185    return( result );
186 }
187
188 #endif /* def __MINGW32__ */
189
190
191
192 /*********************************************************************
193  *
194  * Function    :  safe_strerror
195  *
196  * Description :  Variant of the library routine strerror() which will
197  *                work on systems without the library routine, and
198  *                which should never return NULL.
199  *
200  * Parameters  :
201  *          1  :  err = the `errno' of the last operation.
202  *
203  * Returns     :  An "English" string of the last `errno'.  Allocated
204  *                with strdup(), so caller frees.  May be NULL if the
205  *                system is out of memory.
206  *
207  *********************************************************************/
208 char *safe_strerror(int err)
209 {
210    char *s = NULL;
211    char buf[BUFSIZ];
212
213
214 #ifdef HAVE_STRERROR
215    s = strerror(err);
216 #endif /* HAVE_STRERROR */
217
218    if (s == NULL)
219    {
220       sprintf(buf, "(errno = %d)", err);
221       s = buf;
222    }
223
224    return(strdup(s));
225
226 }
227
228
229 /*********************************************************************
230  *
231  * Function    :  strcmpic
232  *
233  * Description :  Case insensitive string comparison
234  *
235  * Parameters  :
236  *          1  :  s1 = string 1 to compare
237  *          2  :  s2 = string 2 to compare
238  *
239  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
240  *
241  *********************************************************************/
242 int strcmpic(const char *s1, const char *s2)
243 {
244    while (*s1 && *s2)
245    {
246       if ( ( *s1 != *s2 ) && ( ijb_tolower(*s1) != ijb_tolower(*s2) ) )
247       {
248          break;
249       }
250       s1++, s2++;
251    }
252    return(ijb_tolower(*s1) - ijb_tolower(*s2));
253
254 }
255
256
257 /*********************************************************************
258  *
259  * Function    :  strncmpic
260  *
261  * Description :  Case insensitive string comparison (upto n characters)
262  *
263  * Parameters  :
264  *          1  :  s1 = string 1 to compare
265  *          2  :  s2 = string 2 to compare
266  *          3  :  n = maximum characters to compare
267  *
268  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
269  *
270  *********************************************************************/
271 int strncmpic(const char *s1, const char *s2, size_t n)
272 {
273    if (n <= 0) return(0);
274
275    while (*s1 && *s2)
276    {
277       if ( ( *s1 != *s2 ) && ( ijb_tolower(*s1) != ijb_tolower(*s2) ) )
278       {
279          break;
280       }
281
282       if (--n <= 0) break;
283
284       s1++, s2++;
285    }
286    return(ijb_tolower(*s1) - ijb_tolower(*s2));
287
288 }
289
290
291 /*********************************************************************
292  *
293  * Function    :  chomp
294  *
295  * Description :  In-situ-eliminate all leading and trailing whitespace
296  *                from a string.
297  *
298  * Parameters  :
299  *          1  :  s : string to be chomped.
300  *
301  * Returns     :  chomped string
302  *
303  *********************************************************************/
304 char *chomp(char *string)
305 {
306    char *p, *q, *r;
307
308    /* 
309     * strip trailing whitespace
310     */
311    p = string + strlen(string);
312    while (p > string && ijb_isspace(*(p-1)))
313    {
314       p--;
315    }
316    *p = '\0';
317
318    /* 
319     * find end of leading whitespace 
320     */
321    q = r = string;
322    while (*q && ijb_isspace(*q))
323    {
324       q++;
325    }
326
327    /*
328     * if there was any, move the rest forwards
329     */
330    if (q != string)
331    {
332       while (q <= p)
333       {
334          *r++ = *q++;
335       }
336    }
337
338    return(string);
339
340 }
341
342 /*********************************************************************
343  *
344  * Function    :  strsav
345  *
346  * Description :  Reallocate "old" and append text to it.  This makes
347  *                it easier to append to malloc'd strings.
348  *
349  * Parameters  :
350  *          1  :  old = Old text that is to be extended.  Will be
351  *                free()d by this routine.
352  *          2  :  text_to_append = Text to be appended to old.
353  *
354  * Returns     :  Pointer to newly malloc'ed appended string.
355  *                If there is no text to append, return old.  Caller
356  *                must free().
357  *
358  *********************************************************************/
359 char *strsav(char *old, const char *text_to_append)
360 {
361    int old_len, new_len;
362    char *p;
363
364    if (( text_to_append == NULL) || (*text_to_append == '\0'))
365    {
366       return(old);
367    }
368
369    if (NULL != old)
370    {
371       old_len = strlen(old);
372    }
373    else
374    {
375       old_len = 0;
376    }
377
378    new_len = old_len + strlen(text_to_append) + 1;
379
380    if (old)
381    {
382       if ((p = realloc(old, new_len)) == NULL)
383       {
384          log_error(LOG_LEVEL_FATAL, "realloc(%d) bytes failed!", new_len);
385          /* Never get here - LOG_LEVEL_FATAL causes program exit */
386       }
387    }
388    else
389    {
390       if ((p = (char *)malloc(new_len)) == NULL)
391       {
392          log_error(LOG_LEVEL_FATAL, "malloc(%d) bytes failed!", new_len);
393          /* Never get here - LOG_LEVEL_FATAL causes program exit */
394       }
395    }
396
397    strcpy(p + old_len, text_to_append);
398    return(p);
399
400 }
401
402
403 /*********************************************************************
404  *
405  * Function    :  simplematch
406  *
407  * Description :  String matching, with a (greedy) '*' wildcard that
408  *                stands for zero or more arbitrary characters and
409  *                character classes in [], which take both enumerations
410  *                and ranges.
411  *
412  * Parameters  :
413  *          1  :  pattern = pattern for matching
414  *          2  :  text    = text to be matched
415  *
416  * Returns     :  0 if match, else nonzero
417  *
418  *********************************************************************/
419 int simplematch(char *pattern, char *text)
420 {
421   char *fallback; 
422   char *pat = pattern;
423   char *txt = text;
424   int wildcard = 0;
425   
426   char lastchar = 'a';
427   unsigned i;
428   unsigned char charmap[32];
429   
430   
431    while (*txt)
432    {
433
434       /* EOF pattern but !EOF text? */
435       if (*pat == '\0')
436       {
437          return 1;
438       }
439
440       /* '*' in the pattern?  */
441       if (*pat == '*') 
442       {
443      
444          /* The pattern ends afterwards? Speed up the return. */
445          if (*++pat == '\0')
446          {
447             return 0;
448          }
449      
450          /* Else, set wildcard mode and remember position after '*' */
451          wildcard = 1;
452          fallback = pat;
453       }
454
455       /* Character range specification? */
456       if (*pat == '[')
457       {
458          memset(charmap, '\0', sizeof(charmap));
459
460          while (*++pat != ']')
461          {
462             if (!*pat)
463             { 
464                return 1;
465             }
466             else if (*pat == '-')
467             {
468                if ((*++pat == ']') || *pat == '\0')
469                {
470                   return(1);
471                }
472                for(i = lastchar; i <= *pat; i++)
473                {
474                   charmap[i / 8] |= (1 << (i % 8));
475                } 
476             }
477             else
478             {
479                charmap[*pat / 8] |= (1 << (*pat % 8));
480                lastchar = *pat;
481             }
482          }
483       } /* -END- if Character range specification */
484
485
486       /* Compare: Char match, or char range match*/
487       if ((*pat == *txt)  
488       || ((*pat == ']') && (charmap[*txt / 8] & (1 << (*txt % 8)))) )
489       {
490          /* Sucess, go ahead */
491          pat++;
492       }
493       else
494       {
495          /* In wildcard mode, just try again after failiure */
496          if(wildcard)
497          {
498             pat = fallback;
499          }
500
501          /* Else, bad luck */
502          else
503          {
504             return 1;
505          }
506       }
507       txt++;
508    }
509
510    /* Cut off extra '*'s */
511    if(*pat == '*')  pat++;
512
513    /* If this is the pattern's end, fine! */
514    return(*pat);
515
516 }
517
518 /*
519   Local Variables:
520   tab-width: 3
521   end:
522 */