Declare HTTPS inspection non-experimental
[privoxy.git] / miscutil.c
1 /*********************************************************************
2  *
3  * File        :  $Source: /cvsroot/ijbswa/current/miscutil.c,v $
4  *
5  * Purpose     :  zalloc, hash_string, strcmpic, strncmpic, and
6  *                MinGW32 strdup functions.  These are each too small
7  *                to deserve their own file but don't really fit in
8  *                any other file.
9  *
10  * Copyright   :  Written by and Copyright (C) 2001-2022 the
11  *                Privoxy team. https://www.privoxy.org/
12  *
13  *                Based on the Internet Junkbuster originally written
14  *                by and Copyright (C) 1997 Anonymous Coders and
15  *                Junkbusters Corporation.  http://www.junkbusters.com
16  *
17  *                The timegm replacement function was taken from GnuPG,
18  *                Copyright (C) 2004 Free Software Foundation, Inc.
19  *
20  *                This program is free software; you can redistribute it
21  *                and/or modify it under the terms of the GNU General
22  *                Public License as published by the Free Software
23  *                Foundation; either version 2 of the License, or (at
24  *                your option) any later version.
25  *
26  *                This program is distributed in the hope that it will
27  *                be useful, but WITHOUT ANY WARRANTY; without even the
28  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
29  *                PARTICULAR PURPOSE.  See the GNU General Public
30  *                License for more details.
31  *
32  *                The GNU General Public License should be included with
33  *                this file.  If not, you can view it at
34  *                http://www.gnu.org/copyleft/gpl.html
35  *                or write to the Free Software Foundation, Inc., 59
36  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
37  *
38  *********************************************************************/
39
40
41 #include "config.h"
42
43 #include <stdio.h>
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #if !defined(_WIN32)
47 #include <unistd.h>
48 #endif /* #if !defined(_WIN32) */
49 #include <string.h>
50 #include <ctype.h>
51 #include <assert.h>
52
53 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
54 #include <time.h>
55 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
56
57 #include "project.h"
58 #include "miscutil.h"
59 #include "jcc.h"
60 #include "errlog.h"
61
62 /*********************************************************************
63  *
64  * Function    :  zalloc
65  *
66  * Description :  Returns allocated memory that is initialized
67  *                with zeros.
68  *
69  * Parameters  :
70  *          1  :  size = Size of memory chunk to return.
71  *
72  * Returns     :  Pointer to newly alloc'd memory chunk.
73  *
74  *********************************************************************/
75 void *zalloc(size_t size)
76 {
77    void * ret;
78
79 #ifdef HAVE_CALLOC
80    ret = calloc(1, size);
81 #else
82 #warning calloc appears to be unavailable. Your platform will become unsupported in the future
83    if ((ret = (void *)malloc(size)) != NULL)
84    {
85       memset(ret, 0, size);
86    }
87 #endif
88
89    return(ret);
90
91 }
92
93
94 /*********************************************************************
95  *
96  * Function    :  zalloc_or_die
97  *
98  * Description :  zalloc wrapper that either succeeds or causes
99  *                program termination.
100  *
101  *                Useful in situations were the string length is
102  *                "small" and zalloc() failures couldn't be handled
103  *                better anyway. In case of debug builds, failures
104  *                trigger an assert().
105  *
106  * Parameters  :
107  *          1  :  size = Size of memory chunk to return.
108  *
109  * Returns     :  Pointer to newly malloc'd memory chunk.
110  *
111  *********************************************************************/
112 void *zalloc_or_die(size_t size)
113 {
114    void *buffer;
115
116    buffer = zalloc(size);
117    if (buffer == NULL)
118    {
119       assert(buffer != NULL);
120       log_error(LOG_LEVEL_FATAL, "Out of memory in zalloc_or_die().");
121       exit(1);
122    }
123
124    return(buffer);
125
126 }
127
128 /*********************************************************************
129  *
130  * Function    :  strdup_or_die
131  *
132  * Description :  strdup wrapper that either succeeds or causes
133  *                program termination.
134  *
135  *                Useful in situations were the string length is
136  *                "small" and strdup() failures couldn't be handled
137  *                better anyway. In case of debug builds, failures
138  *                trigger an assert().
139  *
140  * Parameters  :
141  *          1  :  str = String to duplicate
142  *
143  * Returns     :  Pointer to newly strdup'd copy of the string.
144  *
145  *********************************************************************/
146 char *strdup_or_die(const char *str)
147 {
148    char *new_str;
149
150    new_str = strdup(str);
151
152    if (new_str == NULL)
153    {
154       assert(new_str != NULL);
155       log_error(LOG_LEVEL_FATAL, "Out of memory in strdup_or_die().");
156       exit(1);
157    }
158
159    return(new_str);
160
161 }
162
163
164 /*********************************************************************
165  *
166  * Function    :  malloc_or_die
167  *
168  * Description :  malloc wrapper that either succeeds or causes
169  *                program termination.
170  *
171  *                Useful in situations were the buffer size is "small"
172  *                and malloc() failures couldn't be handled better
173  *                anyway. In case of debug builds, failures trigger
174  *                an assert().
175  *
176  * Parameters  :
177  *          1  :  buffer_size = Size of the space to allocate
178  *
179  * Returns     :  Pointer to newly malloc'd memory
180  *
181  *********************************************************************/
182 void *malloc_or_die(size_t buffer_size)
183 {
184    char *new_buf;
185
186    if (buffer_size == 0)
187    {
188       log_error(LOG_LEVEL_ERROR,
189          "malloc_or_die() called with buffer size 0");
190       assert(buffer_size != 0);
191       buffer_size = 4096;
192    }
193
194    new_buf = malloc(buffer_size);
195
196    if (new_buf == NULL)
197    {
198       assert(new_buf != NULL);
199       log_error(LOG_LEVEL_FATAL, "Out of memory in malloc_or_die().");
200       exit(1);
201    }
202
203    return(new_buf);
204
205 }
206
207
208 #if defined(unix)
209 /*********************************************************************
210  *
211  * Function    :  write_pid_file
212  *
213  * Description :  Writes a pid file with the pid of the main process.
214  *                Exits if the file can't be opened
215  *
216  * Parameters  :
217  *          1  :  pid_file = Path of the pid file that gets created.
218  *
219  * Returns     :  N/A
220  *
221  *********************************************************************/
222 void write_pid_file(const char *pid_file)
223 {
224    FILE   *fp;
225
226    if ((fp = fopen(pid_file, "w")) == NULL)
227    {
228       log_error(LOG_LEVEL_FATAL, "can't open pid file '%s': %E", pid_file);
229    }
230    else
231    {
232       fprintf(fp, "%u\n", (unsigned int) getpid());
233       fclose (fp);
234    }
235    return;
236
237 }
238 #endif /* def unix */
239
240
241 /*********************************************************************
242  *
243  * Function    :  hash_string
244  *
245  * Description :  Take a string and compute a (hopefully) unique numeric
246  *                integer value. This is useful to "switch" a string.
247  *
248  * Parameters  :
249  *          1  :  s : string to be hashed.
250  *
251  * Returns     :  The string's hash
252  *
253  *********************************************************************/
254 unsigned int hash_string(const char* s)
255 {
256    unsigned int h = 0;
257
258    for (; *s; ++s)
259    {
260       h = 5 * h + (unsigned int)*s;
261    }
262
263    return (h);
264
265 }
266
267
268 /*********************************************************************
269  *
270  * Function    :  strcmpic
271  *
272  * Description :  Case insensitive string comparison
273  *
274  * Parameters  :
275  *          1  :  s1 = string 1 to compare
276  *          2  :  s2 = string 2 to compare
277  *
278  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
279  *
280  *********************************************************************/
281 int strcmpic(const char *s1, const char *s2)
282 {
283    if (!s1) s1 = "";
284    if (!s2) s2 = "";
285
286    while (*s1 && *s2)
287    {
288       if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
289       {
290          break;
291       }
292       s1++, s2++;
293    }
294    return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
295
296 }
297
298
299 /*********************************************************************
300  *
301  * Function    :  strncmpic
302  *
303  * Description :  Case insensitive string comparison (up to n characters)
304  *
305  * Parameters  :
306  *          1  :  s1 = string 1 to compare
307  *          2  :  s2 = string 2 to compare
308  *          3  :  n = maximum characters to compare
309  *
310  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
311  *
312  *********************************************************************/
313 int strncmpic(const char *s1, const char *s2, size_t n)
314 {
315    if (n <= (size_t)0) return(0);
316    if (!s1) s1 = "";
317    if (!s2) s2 = "";
318
319    while (*s1 && *s2)
320    {
321       if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
322       {
323          break;
324       }
325
326       if (--n <= (size_t)0) break;
327
328       s1++, s2++;
329    }
330    return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
331
332 }
333
334
335 /*********************************************************************
336  *
337  * Function    :  chomp
338  *
339  * Description :  In-situ-eliminate all leading and trailing whitespace
340  *                from a string.
341  *
342  * Parameters  :
343  *          1  :  s : string to be chomped.
344  *
345  * Returns     :  chomped string
346  *
347  *********************************************************************/
348 char *chomp(char *string)
349 {
350    char *p, *q, *r;
351
352    /*
353     * strip trailing whitespace
354     */
355    p = string + strlen(string);
356    while (p > string && privoxy_isspace(*(p-1)))
357    {
358       p--;
359    }
360    *p = '\0';
361
362    /*
363     * find end of leading whitespace
364     */
365    q = r = string;
366    while (*q && privoxy_isspace(*q))
367    {
368       q++;
369    }
370
371    /*
372     * if there was any, move the rest forwards
373     */
374    if (q != string)
375    {
376       while (q <= p)
377       {
378          *r++ = *q++;
379       }
380    }
381
382    return(string);
383
384 }
385
386
387 /*********************************************************************
388  *
389  * Function    :  string_append
390  *
391  * Description :  Reallocate target_string and append text to it.
392  *                This makes it easier to append to malloc'd strings.
393  *                This is similar to the (removed) strsav(), but
394  *                running out of memory isn't catastrophic.
395  *
396  *                Programming style:
397  *
398  *                The following style provides sufficient error
399  *                checking for this routine, with minimal clutter
400  *                in the source code.  It is recommended if you
401  *                have many calls to this function:
402  *
403  *                char * s = strdup(...); // don't check for error
404  *                string_append(&s, ...);  // don't check for error
405  *                string_append(&s, ...);  // don't check for error
406  *                string_append(&s, ...);  // don't check for error
407  *                if (NULL == s) { ... handle error ... }
408  *
409  *                OR, equivalently:
410  *
411  *                char * s = strdup(...); // don't check for error
412  *                string_append(&s, ...);  // don't check for error
413  *                string_append(&s, ...);  // don't check for error
414  *                if (string_append(&s, ...)) {... handle error ...}
415  *
416  * Parameters  :
417  *          1  :  target_string = Pointer to old text that is to be
418  *                extended.  *target_string will be free()d by this
419  *                routine.  target_string must be non-NULL.
420  *                If *target_string is NULL, this routine will
421  *                do nothing and return with an error - this allows
422  *                you to make many calls to this routine and only
423  *                check for errors after the last one.
424  *          2  :  text_to_append = Text to be appended to old.
425  *                Must not be NULL.
426  *
427  * Returns     :  JB_ERR_OK on success, and sets *target_string
428  *                   to newly malloc'ed appended string.  Caller
429  *                   must free(*target_string).
430  *                JB_ERR_MEMORY on out-of-memory.  (And free()s
431  *                   *target_string and sets it to NULL).
432  *                JB_ERR_MEMORY if *target_string is NULL.
433  *
434  *********************************************************************/
435 jb_err string_append(char **target_string, const char *text_to_append)
436 {
437    size_t old_len;
438    char *new_string;
439    size_t new_size;
440
441    assert(target_string);
442    assert(text_to_append);
443
444    if (*target_string == NULL)
445    {
446       return JB_ERR_MEMORY;
447    }
448
449    if (*text_to_append == '\0')
450    {
451       return JB_ERR_OK;
452    }
453
454    old_len = strlen(*target_string);
455
456    new_size = strlen(text_to_append) + old_len + 1;
457
458    if (NULL == (new_string = realloc(*target_string, new_size)))
459    {
460       free(*target_string);
461
462       *target_string = NULL;
463       return JB_ERR_MEMORY;
464    }
465
466    strlcpy(new_string + old_len, text_to_append, new_size - old_len);
467
468    *target_string = new_string;
469    return JB_ERR_OK;
470 }
471
472
473 /*********************************************************************
474  *
475  * Function    :  string_join
476  *
477  * Description :  Join two strings together.  Frees BOTH the original
478  *                strings.  If either or both input strings are NULL,
479  *                fails as if it had run out of memory.
480  *
481  *                For comparison, string_append requires that the
482  *                second string is non-NULL, and doesn't free it.
483  *
484  *                Rationale: Too often, we want to do
485  *                string_append(s, html_encode(s2)).  That assert()s
486  *                if s2 is NULL or if html_encode() runs out of memory.
487  *                It also leaks memory.  Proper checking is cumbersome.
488  *                The solution: string_join(s, html_encode(s2)) is safe,
489  *                and will free the memory allocated by html_encode().
490  *
491  * Parameters  :
492  *          1  :  target_string = Pointer to old text that is to be
493  *                extended.  *target_string will be free()d by this
494  *                routine.  target_string must be non-NULL.
495  *          2  :  text_to_append = Text to be appended to old.
496  *
497  * Returns     :  JB_ERR_OK on success, and sets *target_string
498  *                   to newly malloc'ed appended string.  Caller
499  *                   must free(*target_string).
500  *                JB_ERR_MEMORY on out-of-memory, or if
501  *                   *target_string or text_to_append is NULL.  (In
502  *                   this case, frees *target_string and text_to_append,
503  *                   sets *target_string to NULL).
504  *
505  *********************************************************************/
506 jb_err string_join(char **target_string, char *text_to_append)
507 {
508    jb_err err;
509
510    assert(target_string);
511
512    if (text_to_append == NULL)
513    {
514       freez(*target_string);
515       return JB_ERR_MEMORY;
516    }
517
518    err = string_append(target_string, text_to_append);
519
520    freez(text_to_append);
521
522    return err;
523 }
524
525
526 /*********************************************************************
527  *
528  * Function    :  string_toupper
529  *
530  * Description :  Produce a copy of string with all convertible
531  *                characters converted to uppercase.
532  *
533  * Parameters  :
534  *          1  :  string = string to convert
535  *
536  * Returns     :  Uppercase copy of string if possible,
537  *                NULL on out-of-memory or if string was NULL.
538  *
539  *********************************************************************/
540 char *string_toupper(const char *string)
541 {
542    char *result, *p;
543    const char *q;
544
545    if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
546    {
547       return NULL;
548    }
549
550    q = string;
551    p = result;
552
553    while (*q != '\0')
554    {
555       *p++ = (char)toupper((int) *q++);
556    }
557
558    return result;
559
560 }
561
562
563 /*********************************************************************
564  *
565  * Function    :  string_tolower
566  *
567  * Description :  Produce a copy of string with all convertible
568  *                characters converted to lowercase.
569  *
570  * Parameters  :
571  *          1  :  string = string to convert
572  *
573  * Returns     :  Lowercase copy of string if possible,
574  *                NULL on out-of-memory or if string was NULL.
575  *
576  *********************************************************************/
577 char *string_tolower(const char *string)
578 {
579    char *result, *p;
580    const char *q;
581
582    if (!string || ((result = (char *)zalloc(strlen(string) + 1)) == NULL))
583    {
584       return NULL;
585    }
586
587    q = string;
588    p = result;
589
590    while (*q != '\0')
591    {
592       *p++ = (char)privoxy_tolower(*q++);
593    }
594
595    return result;
596
597 }
598
599
600 /*********************************************************************
601  *
602  * Function    :  string_move
603  *
604  * Description :  memmove wrapper to move the last part of a string
605  *                towards the beginning, overwriting the part in
606  *                the middle. strlcpy() can't be used here as the
607  *                strings overlap.
608  *
609  * Parameters  :
610  *          1  :  dst = Destination to overwrite
611  *          2  :  src = Source to move.
612  *
613  * Returns     :  N/A
614  *
615  *********************************************************************/
616 void string_move(char *dst, char *src)
617 {
618    assert(dst < src);
619
620    /* +1 to copy the terminating nul as well. */
621    memmove(dst, src, strlen(src)+1);
622 }
623
624
625 /*********************************************************************
626  *
627  * Function    :  bindup
628  *
629  * Description :  Duplicate the first n characters of a string that may
630  *                contain '\0' characters.
631  *
632  * Parameters  :
633  *          1  :  string = string to be duplicated
634  *          2  :  len = number of bytes to duplicate
635  *
636  * Returns     :  pointer to copy, or NULL if failure
637  *
638  *********************************************************************/
639 char *bindup(const char *string, size_t len)
640 {
641    char *duplicate;
642
643    duplicate = (char *)malloc(len);
644    if (NULL != duplicate)
645    {
646       memcpy(duplicate, string, len);
647    }
648
649    return duplicate;
650
651 }
652
653
654 /*********************************************************************
655  *
656  * Function    :  make_path
657  *
658  * Description :  Takes a directory name and a file name, returns
659  *                the complete path.  Handles windows/unix differences.
660  *                If the file name is already an absolute path, or if
661  *                the directory name is NULL or empty, it returns
662  *                the filename.
663  *
664  * Parameters  :
665  *          1  :  dir: Name of directory or NULL for none.
666  *          2  :  file: Name of file.  Should not be NULL or empty.
667  *
668  * Returns     :  "dir/file" (Or on windows, "dir\file").
669  *                It allocates the string on the heap.  Caller frees.
670  *                Returns NULL in error (i.e. NULL file or out of
671  *                memory)
672  *
673  *********************************************************************/
674 char * make_path(const char * dir, const char * file)
675 {
676    if ((file == NULL) || (*file == '\0'))
677    {
678       return NULL; /* Error */
679    }
680
681    if ((dir == NULL) || (*dir == '\0') /* No directory specified */
682 #if defined(_WIN32)
683       || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
684 #else /* ifndef _WIN32 */
685       || (*file == '/') /* Absolute path (U*ix) */
686 #endif /* ifndef _WIN32 */
687       )
688    {
689       return strdup(file);
690    }
691    else
692    {
693       char * path;
694       size_t path_size = strlen(dir) + strlen(file) + 2; /* +2 for trailing (back)slash and \0 */
695
696 #if defined(unix)
697       if (*dir != '/' && basedir && *basedir)
698       {
699          /*
700           * Relative path, so start with the base directory.
701           */
702          path_size += strlen(basedir) + 1; /* +1 for the slash */
703          path = malloc_or_die(path_size);
704          strlcpy(path, basedir, path_size);
705          strlcat(path, "/", path_size);
706          strlcat(path, dir, path_size);
707       }
708       else
709 #endif /* defined unix */
710       {
711          path = malloc_or_die(path_size);
712          strlcpy(path, dir, path_size);
713       }
714
715       assert(NULL != path);
716 #if defined(_WIN32)
717       if (path[strlen(path)-1] != '\\')
718       {
719          strlcat(path, "\\", path_size);
720       }
721 #else /* ifndef _WIN32 */
722       if (path[strlen(path)-1] != '/')
723       {
724          strlcat(path, "/", path_size);
725       }
726 #endif /* ifndef _WIN32 */
727       strlcat(path, file, path_size);
728
729       return path;
730    }
731 }
732
733
734 /*********************************************************************
735  *
736  * Function    :  pick_from_range
737  *
738  * Description :  Pick a positive number out of a given range.
739  *                Should only be used if randomness would be nice,
740  *                but isn't really necessary.
741  *
742  * Parameters  :
743  *          1  :  range: Highest possible number to pick.
744  *
745  * Returns     :  Picked number.
746  *
747  *********************************************************************/
748 long int pick_from_range(long int range)
749 {
750    long int number;
751 #ifdef _WIN32
752    static unsigned long seed = 0;
753 #endif /* def _WIN32 */
754
755    assert(range != 0);
756    assert(range > 0);
757
758    if (range <= 0) return 0;
759
760 #ifdef HAVE_ARC4RANDOM
761    number = arc4random() % range + 1;
762 #elif defined(HAVE_RANDOM)
763    number = random() % range + 1;
764 #elif defined(MUTEX_LOCKS_AVAILABLE)
765    privoxy_mutex_lock(&rand_mutex);
766 #ifdef _WIN32
767    if (!seed)
768    {
769       seed = (unsigned long)(GetCurrentThreadId()+GetTickCount());
770    }
771    srand(seed);
772    seed = (unsigned long)((rand() << 16) + rand());
773 #endif /* def _WIN32 */
774    number = (unsigned long)((rand() << 16) + (rand())) % (unsigned long)(range + 1);
775    privoxy_mutex_unlock(&rand_mutex);
776 #else
777    /*
778     * XXX: Which platforms reach this and are there
779     * better options than just using rand() and hoping
780     * that it's safe?
781     */
782    log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization "
783       "might cause crashes, predictable results or even combine these fine options.");
784    number = rand() % (long int)(range + 1);
785
786 #endif /* (def HAVE_ARC4RANDOM) */
787
788    return number;
789 }
790
791
792 #ifdef USE_PRIVOXY_STRLCPY
793 /*********************************************************************
794  *
795  * Function    :  privoxy_strlcpy
796  *
797  * Description :  strlcpy(3) look-alike for those without decent libc.
798  *
799  * Parameters  :
800  *          1  :  destination: buffer to copy into.
801  *          2  :  source: String to copy.
802  *          3  :  size: Size of destination buffer.
803  *
804  * Returns     :  The length of the string that privoxy_strlcpy() tried to create.
805  *
806  *********************************************************************/
807 size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
808 {
809    if (0 < size)
810    {
811       snprintf(destination, size, "%s", source);
812       /*
813        * Platforms that lack strlcpy() also tend to have
814        * a broken snprintf implementation that doesn't
815        * guarantee nul termination.
816        *
817        * XXX: the configure script should detect and reject those.
818        */
819       destination[size-1] = '\0';
820    }
821    return strlen(source);
822 }
823 #endif /* def USE_PRIVOXY_STRLCPY */
824
825
826 #ifndef HAVE_STRLCAT
827 /*********************************************************************
828  *
829  * Function    :  privoxy_strlcat
830  *
831  * Description :  strlcat(3) look-alike for those without decent libc.
832  *
833  * Parameters  :
834  *          1  :  destination: C string.
835  *          2  :  source: String to copy.
836  *          3  :  size: Size of destination buffer.
837  *
838  * Returns     :  The length of the string that privoxy_strlcat() tried to create.
839  *
840  *********************************************************************/
841 size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
842 {
843    const size_t old_length = strlen(destination);
844    return old_length + strlcpy(destination + old_length, source, size - old_length);
845 }
846 #endif /* ndef HAVE_STRLCAT */
847
848
849 /*********************************************************************
850  *
851  * Function    :  privoxy_millisleep
852  *
853  * Description :  Sleep a number of milliseconds
854  *
855  * Parameters  :
856  *          1  :  delay: Number of milliseconds to sleep
857  *
858  * Returns     :  -1 on error, 0 otherwise
859  *
860  *********************************************************************/
861 int privoxy_millisleep(unsigned milliseconds)
862 {
863 #ifdef HAVE_NANOSLEEP
864    struct timespec rqtp = {0};
865    struct timespec rmtp = {0};
866
867    rqtp.tv_sec = milliseconds / 1000;
868    rqtp.tv_nsec = (milliseconds % 1000) * 1000 * 1000;
869
870    return nanosleep(&rqtp, &rmtp);
871 #elif defined (_WIN32)
872    Sleep(milliseconds);
873
874    return 0;
875 #else
876 #warning Missing privoxy_milisleep() implementation. delay-response{} will not work.
877
878    return -1;
879 #endif /* def HAVE_NANOSLEEP */
880
881 }
882
883
884 /*********************************************************************
885  *
886  * Function    :  privoxy_gmtime_r
887  *
888  * Description :  Behave like gmtime_r() and convert a
889  *                time_t to a struct tm.
890  *
891  * Parameters  :
892  *          1  :  time_spec: The time to convert
893  *          2  :  result: The struct tm to use as storage
894  *
895  * Returns     :  Pointer to the result or NULL on error.
896  *
897  *********************************************************************/
898 struct tm *privoxy_gmtime_r(const time_t *time_spec, struct tm *result)
899 {
900    struct tm *timeptr;
901
902 #ifdef HAVE_GMTIME_R
903    timeptr = gmtime_r(time_spec, result);
904 #elif defined(MUTEX_LOCKS_AVAILABLE)
905    privoxy_mutex_lock(&gmtime_mutex);
906    timeptr = gmtime(time_spec);
907 #else
908 #warning Using unlocked gmtime()
909    timeptr = gmtime(time_spec);
910 #endif
911
912    if (timeptr == NULL)
913    {
914 #if !defined(HAVE_GMTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
915       privoxy_mutex_unlock(&gmtime_mutex);
916 #endif
917       return NULL;
918    }
919
920 #if !defined(HAVE_GMTIME_R)
921    *result = *timeptr;
922    timeptr = result;
923 #ifdef MUTEX_LOCKS_AVAILABLE
924    privoxy_mutex_unlock(&gmtime_mutex);
925 #endif
926 #endif
927
928    return timeptr;
929 }
930
931 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
932 /*********************************************************************
933  *
934  * Function    :  timegm
935  *
936  * Description :  libc replacement function for the inverse of gmtime().
937  *                Copyright (C) 2004 Free Software Foundation, Inc.
938  *
939  *                Code originally copied from GnuPG, modifications done
940  *                for Privoxy: style changed, #ifdefs for _WIN32 added
941  *                to have it work on mingw32.
942  *
943  *                XXX: It's very unlikely to happen, but if the malloc()
944  *                call fails the time zone will be permanently set to UTC.
945  *
946  * Parameters  :
947  *          1  :  tm: Broken-down time struct.
948  *
949  * Returns     :  tm converted into time_t seconds.
950  *
951  *********************************************************************/
952 time_t timegm(struct tm *tm)
953 {
954    time_t answer;
955    char *zone;
956
957    zone = getenv("TZ");
958    putenv("TZ=UTC");
959    tzset();
960    answer = mktime(tm);
961    if (zone)
962    {
963       char *old_zone;
964
965       old_zone = malloc(3 + strlen(zone) + 1);
966       if (old_zone)
967       {
968          strcpy(old_zone, "TZ=");
969          strcat(old_zone, zone);
970          putenv(old_zone);
971 #ifdef _WIN32
972          /* http://man7.org/linux/man-pages/man3/putenv.3.html
973           *   int putenv(char *string);
974           *     The string pointed to by string becomes part of the environment, so altering the
975           *     string changes the environment.
976           * In other words, the memory pointed to by *string is used until
977           *   a) another call to putenv() with the same e-var name
978           *   b) the program exits
979           *
980           * Windows e-vars don't work that way, so let's not leak memory.
981           */
982          free(old_zone);
983 #endif /* def _WIN32 */
984       }
985    }
986    else
987    {
988 #ifdef HAVE_UNSETENV
989       unsetenv("TZ");
990 #elif defined(_WIN32)
991       putenv("TZ=");
992 #else
993       putenv("TZ");
994 #endif
995    }
996    tzset();
997
998    return answer;
999 }
1000 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
1001
1002
1003 /*********************************************************************
1004  *
1005  * Function    :  host_is_ip_address
1006  *
1007  * Description :  Checks whether or not a host is specified by
1008  *                IP address. Does not actually validate the
1009  *                address.
1010  *
1011  * Parameters  :
1012  *          1  :  host = The host name to check
1013  *
1014  * Returns     :   1 => Yes
1015  *                 0 => No
1016  *
1017  *********************************************************************/
1018 extern int host_is_ip_address(const char *host)
1019 {
1020    const char *p;
1021
1022    if (NULL != strstr(host, ":"))
1023    {
1024       /* Assume an IPv6 address. */
1025       return 1;
1026    }
1027
1028    for (p = host; *p; p++)
1029    {
1030       if ((*p != '.') && !privoxy_isdigit(*p))
1031       {
1032          /* Not a dot or digit so it can't be an IPv4 address. */
1033          return 0;
1034       }
1035    }
1036
1037    /*
1038     * Host only consists of dots and digits so
1039     * assume that is an IPv4 address.
1040     */
1041    return 1;
1042
1043 }
1044
1045
1046 /*
1047   Local Variables:
1048   tab-width: 3
1049   end:
1050 */