1/* Replacements for routines missing on some systems.
2   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
4   Foundation, Inc.
5
6This file is part of GNU Wget.
7
8GNU Wget is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
12
13GNU Wget is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with Wget.  If not, see <http://www.gnu.org/licenses/>.
20
21Additional permission under GNU GPL version 3 section 7
22
23If you modify this program, or any covered work, by linking or
24combining it with the OpenSSL project's OpenSSL library (or a
25modified version of that library), containing parts covered by the
26terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27grants you additional permission to convey the resulting work.
28Corresponding Source for a non-source form of such a combination
29shall include the source code for the parts of OpenSSL used as well
30as that of the covered work.  */
31
32#include "wget.h"
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <time.h>
38
39#include <unistd.h>
40
41#include <errno.h>
42
43/* Some systems lack certain functions normally taken for granted.
44   For example, Windows doesn't have strptime, and some systems don't
45   have a usable fnmatch.  This file should contain fallback
46   implementations of such missing functions.  It should *not* define
47   new Wget-specific interfaces -- those should be placed in utils.c
48   or elsewhere.  */
49
50/* strcasecmp and strncasecmp apparently originated with BSD 4.4.
51   SUSv3 seems to be the only standard out there (that I can find)
52   that requires their existence, so in theory there might be systems
53   still in use that lack them.  Note that these don't get defined
54   under Windows because mswindows.h defines them to the equivalent
55   Windows functions stricmp and strnicmp.  */
56
57#ifndef HAVE_STRCASECMP
58/* From GNU libc.  */
59/* Compare S1 and S2, ignoring case, returning less than, equal to or
60   greater than zero if S1 is lexiographically less than,
61   equal to or greater than S2.  */
62int
63strcasecmp (const char *s1, const char *s2)
64{
65  register const unsigned char *p1 = (const unsigned char *) s1;
66  register const unsigned char *p2 = (const unsigned char *) s2;
67  unsigned char c1, c2;
68
69  if (p1 == p2)
70    return 0;
71
72  do
73    {
74      c1 = c_tolower (*p1++);
75      c2 = c_tolower (*p2++);
76      if (c1 == '\0')
77        break;
78    }
79  while (c1 == c2);
80
81  return c1 - c2;
82}
83#endif /* not HAVE_STRCASECMP */
84
85#ifndef HAVE_STRNCASECMP
86/* From GNU libc.  */
87/* Compare no more than N characters of S1 and S2,
88   ignoring case, returning less than, equal to or
89   greater than zero if S1 is lexicographically less
90   than, equal to or greater than S2.  */
91int
92strncasecmp (const char *s1, const char *s2, size_t n)
93{
94  register const unsigned char *p1 = (const unsigned char *) s1;
95  register const unsigned char *p2 = (const unsigned char *) s2;
96  unsigned char c1, c2;
97
98  if (p1 == p2 || n == 0)
99    return 0;
100
101  do
102    {
103      c1 = c_tolower (*p1++);
104      c2 = c_tolower (*p2++);
105      if (c1 == '\0' || c1 != c2)
106        return c1 - c2;
107    } while (--n > 0);
108
109  return c1 - c2;
110}
111#endif /* not HAVE_STRNCASECMP */
112
113#ifndef HAVE_MEMRCHR
114/* memrchr is a GNU extension.  It is like the memchr function, except
115   that it searches backwards from the end of the n bytes pointed to
116   by s instead of forwards from the front.  */
117
118void *
119memrchr (const void *s, int c, size_t n)
120{
121  const char *b = s;
122  const char *e = b + n;
123  while (e > b)
124    if (*--e == c)
125      return (void *) e;
126  return NULL;
127}
128#endif
129
130/* strptime is required by POSIX, but it is missing from Windows,
131   which means we must keep a fallback implementation.  It is
132   reportedly missing or broken on many older Unix systems as well, so
133   it's good to have around.  */
134
135#ifndef HAVE_STRPTIME
136/* From GNU libc 2.1.3.  */
137/* Ulrich, thanks for helping me out with this!  --hniksic  */
138
139/* strptime - Convert a string representation of time to a time value.
140   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
141   This file is part of the GNU C Library.
142   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.  */
143
144/* XXX This version of the implementation is not really complete.
145   Some of the fields cannot add information alone.  But if seeing
146   some of them in the same format (such as year, week and weekday)
147   this is enough information for determining the date.  */
148
149#ifndef __P
150# define __P(args) args
151#endif /* not __P */
152
153#if ! HAVE_LOCALTIME_R && ! defined localtime_r
154# ifdef _LIBC
155#  define localtime_r __localtime_r
156# else
157/* Approximate localtime_r as best we can in its absence.  */
158#  define localtime_r my_localtime_r
159static struct tm *localtime_r __P ((const time_t *, struct tm *));
160static struct tm *
161localtime_r (t, tp)
162     const time_t *t;
163     struct tm *tp;
164{
165  struct tm *l = localtime (t);
166  if (! l)
167    return 0;
168  *tp = *l;
169  return tp;
170}
171# endif /* ! _LIBC */
172#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
173
174
175#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
176#if defined __GNUC__ && __GNUC__ >= 2
177# define match_string(cs1, s2) \
178  ({ size_t len = strlen (cs1);                                               \
179     int result = strncasecmp ((cs1), (s2), len) == 0;                        \
180     if (result) (s2) += len;                                                 \
181     result; })
182#else
183/* Oh come on.  Get a reasonable compiler.  */
184# define match_string(cs1, s2) \
185  (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
186#endif
187/* We intentionally do not use isdigit() for testing because this will
188   lead to problems with the wide character version.  */
189#define get_number(from, to, n) \
190  do {                                                                        \
191    int __n = n;                                                              \
192    val = 0;                                                                  \
193    while (*rp == ' ')                                                        \
194      ++rp;                                                                   \
195    if (*rp < '0' || *rp > '9')                                               \
196      return NULL;                                                            \
197    do {                                                                      \
198      val *= 10;                                                              \
199      val += *rp++ - '0';                                                     \
200    } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');        \
201    if (val < from || val > to)                                               \
202      return NULL;                                                            \
203  } while (0)
204#ifdef _NL_CURRENT
205/* Added check for __GNUC__ extensions here for Wget. --abbotti */
206# if defined __GNUC__ && __GNUC__ >= 2
207#  define get_alt_number(from, to, n) \
208  ({                                                                          \
209    __label__ do_normal;                                                      \
210    if (*decided != raw)                                                      \
211      {                                                                       \
212        const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
213        int __n = n;                                                          \
214        int any = 0;                                                          \
215        while (*rp == ' ')                                                    \
216          ++rp;                                                               \
217        val = 0;                                                              \
218        do {                                                                  \
219          val *= 10;                                                          \
220          while (*alts != '\0')                                               \
221            {                                                                 \
222              size_t len = strlen (alts);                                     \
223              if (strncasecmp (alts, rp, len) == 0)                           \
224                break;                                                        \
225              alts += len + 1;                                                \
226              ++val;                                                          \
227            }                                                                 \
228          if (*alts == '\0')                                                  \
229            {                                                                 \
230              if (*decided == not && ! any)                                   \
231                goto do_normal;                                               \
232              /* If we haven't read anything it's an error.  */               \
233              if (! any)                                                      \
234                return NULL;                                                  \
235              /* Correct the premature multiplication.  */                    \
236              val /= 10;                                                      \
237              break;                                                          \
238            }                                                                 \
239          else                                                                \
240            *decided = loc;                                                   \
241        } while (--__n > 0 && val * 10 <= to);                                \
242        if (val < from || val > to)                                           \
243          return NULL;                                                        \
244      }                                                                       \
245    else                                                                      \
246      {                                                                       \
247       do_normal:                                                             \
248        get_number (from, to, n);                                             \
249      }                                                                       \
250    0;                                                                        \
251  })
252# else
253#  define get_alt_number(from, to, n) \
254  do {
255    if (*decided != raw)                                                      \
256      {                                                                       \
257        const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                 \
258        int __n = n;                                                          \
259        int any = 0;                                                          \
260        while (*rp == ' ')                                                    \
261          ++rp;                                                               \
262        val = 0;                                                              \
263        do {                                                                  \
264          val *= 10;                                                          \
265          while (*alts != '\0')                                               \
266            {                                                                 \
267              size_t len = strlen (alts);                                     \
268              if (strncasecmp (alts, rp, len) == 0)                           \
269                break;                                                        \
270              alts += len + 1;                                                \
271              ++val;                                                          \
272            }                                                                 \
273          if (*alts == '\0')                                                  \
274            {                                                                 \
275              if (*decided == not && ! any)                                   \
276                goto do_normal;                                               \
277              /* If we haven't read anything it's an error.  */               \
278              if (! any)                                                      \
279                return NULL;                                                  \
280              /* Correct the premature multiplication.  */                    \
281              val /= 10;                                                      \
282              break;                                                          \
283            }                                                                 \
284          else                                                                \
285            *decided = loc;                                                   \
286        } while (--__n > 0 && val * 10 <= to);                                \
287        if (val < from || val > to)                                           \
288          return NULL;                                                        \
289      }                                                                       \
290    else                                                                      \
291      {                                                                       \
292       do_normal:                                                             \
293        get_number (from, to, n);                                             \
294      }                                                                       \
295  } while (0)
296# endif /* defined __GNUC__ && __GNUC__ >= 2 */
297#else
298# define get_alt_number(from, to, n) \
299  /* We don't have the alternate representation.  */                          \
300  get_number(from, to, n)
301#endif
302#define recursive(new_fmt) \
303  (*(new_fmt) != '\0'                                                         \
304   && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL)
305
306
307#ifdef _LIBC
308/* This is defined in locale/C-time.c in the GNU libc.  */
309extern const struct locale_data _nl_C_LC_TIME;
310extern const unsigned short int __mon_yday[2][13];
311
312# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
313# define ab_weekday_name \
314  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
315# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
316# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
317# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
318# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
319# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
320# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
321# define HERE_T_FMT_AMPM \
322  (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
323# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
324
325# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
326#else
327static char const weekday_name[][10] =
328  {
329    "Sunday", "Monday", "Tuesday", "Wednesday",
330    "Thursday", "Friday", "Saturday"
331  };
332static char const ab_weekday_name[][4] =
333  {
334    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
335  };
336static char const month_name[][10] =
337  {
338    "January", "February", "March", "April", "May", "June",
339    "July", "August", "September", "October", "November", "December"
340  };
341static char const ab_month_name[][4] =
342  {
343    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
344    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
345  };
346# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
347# define HERE_D_FMT "%m/%d/%y"
348# define HERE_AM_STR "AM"
349# define HERE_PM_STR "PM"
350# define HERE_T_FMT_AMPM "%I:%M:%S %p"
351# define HERE_T_FMT "%H:%M:%S"
352
353const unsigned short int __mon_yday[2][13];
354# ifndef NEED_MON_YDAY
355#  define NEED_MON_YDAY
356# endif
357#endif
358
359/* Status of lookup: do we use the locale data or the raw data?  */
360enum locale_status { not, loc, raw };
361
362
363#ifndef __isleap
364/* Nonzero if YEAR is a leap year (every 4 years,
365   except every 100th isn't, and every 400th is).  */
366# define __isleap(year) \
367  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
368#endif
369
370/* Compute the day of the week.  */
371static void
372day_of_the_week (struct tm *tm)
373{
374  /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
375     difference between this data in the one on TM and so determine
376     the weekday.  */
377  int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
378  int wday = (-473
379              + (365 * (tm->tm_year - 70))
380              + (corr_year / 4)
381              - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
382              + (((corr_year / 4) / 25) / 4)
383              + __mon_yday[0][tm->tm_mon]
384              + tm->tm_mday - 1);
385  tm->tm_wday = ((wday % 7) + 7) % 7;
386}
387
388/* Compute the day of the year.  */
389static void
390day_of_the_year (struct tm *tm)
391{
392  tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
393                 + (tm->tm_mday - 1));
394}
395
396static char *
397#ifdef _LIBC
398internal_function
399#endif
400strptime_internal __P ((const char *buf, const char *format, struct tm *tm,
401                        enum locale_status *decided));
402
403static char *
404#ifdef _LIBC
405internal_function
406#endif
407strptime_internal (rp, fmt, tm, decided)
408     const char *rp;
409     const char *fmt;
410     struct tm *tm;
411     enum locale_status *decided;
412{
413#ifdef _NL_CURRENT
414  const char *rp_backup;
415#endif
416  int cnt;
417  size_t val;
418  int have_I, is_pm;
419  int century, want_century;
420  int have_wday, want_xday;
421  int have_yday;
422  int have_mon, have_mday;
423
424  have_I = is_pm = 0;
425  century = -1;
426  want_century = 0;
427  have_wday = want_xday = have_yday = have_mon = have_mday = 0;
428
429  while (*fmt != '\0')
430    {
431      /* A white space in the format string matches 0 more or white
432         space in the input string.  */
433      if (c_isspace (*fmt))
434        {
435          while (c_isspace (*rp))
436            ++rp;
437          ++fmt;
438          continue;
439        }
440
441      /* Any character but `%' must be matched by the same character
442         in the iput string.  */
443      if (*fmt != '%')
444        {
445          match_char (*fmt++, *rp++);
446          continue;
447        }
448
449      ++fmt;
450#ifndef _NL_CURRENT
451      /* We need this for handling the `E' modifier.  */
452    start_over:
453#endif
454
455#ifdef _NL_CURRENT
456      /* Make back up of current processing pointer.  */
457      rp_backup = rp;
458#endif
459
460      switch (*fmt++)
461        {
462        case '%':
463          /* Match the `%' character itself.  */
464          match_char ('%', *rp++);
465          break;
466        case 'a':
467        case 'A':
468          /* Match day of week.  */
469          for (cnt = 0; cnt < 7; ++cnt)
470            {
471#ifdef _NL_CURRENT
472              if (*decided !=raw)
473                {
474                  if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
475                    {
476                      if (*decided == not
477                          && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
478                                     weekday_name[cnt]))
479                        *decided = loc;
480                      break;
481                    }
482                  if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
483                    {
484                      if (*decided == not
485                          && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
486                                     ab_weekday_name[cnt]))
487                        *decided = loc;
488                      break;
489                    }
490                }
491#endif
492              if (*decided != loc
493                  && (match_string (weekday_name[cnt], rp)
494                      || match_string (ab_weekday_name[cnt], rp)))
495                {
496                  *decided = raw;
497                  break;
498                }
499            }
500          if (cnt == 7)
501            /* Does not match a weekday name.  */
502            return NULL;
503          tm->tm_wday = cnt;
504          have_wday = 1;
505          break;
506        case 'b':
507        case 'B':
508        case 'h':
509          /* Match month name.  */
510          for (cnt = 0; cnt < 12; ++cnt)
511            {
512#ifdef _NL_CURRENT
513              if (*decided !=raw)
514                {
515                  if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
516                    {
517                      if (*decided == not
518                          && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
519                                     month_name[cnt]))
520                        *decided = loc;
521                      break;
522                    }
523                  if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
524                    {
525                      if (*decided == not
526                          && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
527                                     ab_month_name[cnt]))
528                        *decided = loc;
529                      break;
530                    }
531                }
532#endif
533              if (match_string (month_name[cnt], rp)
534                  || match_string (ab_month_name[cnt], rp))
535                {
536                  *decided = raw;
537                  break;
538                }
539            }
540          if (cnt == 12)
541            /* Does not match a month name.  */
542            return NULL;
543          tm->tm_mon = cnt;
544          want_xday = 1;
545          break;
546        case 'c':
547          /* Match locale's date and time format.  */
548#ifdef _NL_CURRENT
549          if (*decided != raw)
550            {
551              if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
552                {
553                  if (*decided == loc)
554                    return NULL;
555                  else
556                    rp = rp_backup;
557                }
558              else
559                {
560                  if (*decided == not &&
561                      strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
562                    *decided = loc;
563                  want_xday = 1;
564                  break;
565                }
566              *decided = raw;
567            }
568#endif
569          if (!recursive (HERE_D_T_FMT))
570            return NULL;
571          want_xday = 1;
572          break;
573        case 'C':
574          /* Match century number.  */
575          get_number (0, 99, 2);
576          century = val;
577          want_xday = 1;
578          break;
579        case 'd':
580        case 'e':
581          /* Match day of month.  */
582          get_number (1, 31, 2);
583          tm->tm_mday = val;
584          have_mday = 1;
585          want_xday = 1;
586          break;
587        case 'F':
588          if (!recursive ("%Y-%m-%d"))
589            return NULL;
590          want_xday = 1;
591          break;
592        case 'x':
593#ifdef _NL_CURRENT
594          if (*decided != raw)
595            {
596              if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
597                {
598                  if (*decided == loc)
599                    return NULL;
600                  else
601                    rp = rp_backup;
602                }
603              else
604                {
605                  if (*decided == not
606                      && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
607                    *decided = loc;
608                  want_xday = 1;
609                  break;
610                }
611              *decided = raw;
612            }
613#endif
614          /* Fall through.  */
615        case 'D':
616          /* Match standard day format.  */
617          if (!recursive (HERE_D_FMT))
618            return NULL;
619          want_xday = 1;
620          break;
621        case 'k':
622        case 'H':
623          /* Match hour in 24-hour clock.  */
624          get_number (0, 23, 2);
625          tm->tm_hour = val;
626          have_I = 0;
627          break;
628        case 'I':
629          /* Match hour in 12-hour clock.  */
630          get_number (1, 12, 2);
631          tm->tm_hour = val % 12;
632          have_I = 1;
633          break;
634        case 'j':
635          /* Match day number of year.  */
636          get_number (1, 366, 3);
637          tm->tm_yday = val - 1;
638          have_yday = 1;
639          break;
640        case 'm':
641          /* Match number of month.  */
642          get_number (1, 12, 2);
643          tm->tm_mon = val - 1;
644          have_mon = 1;
645          want_xday = 1;
646          break;
647        case 'M':
648          /* Match minute.  */
649          get_number (0, 59, 2);
650          tm->tm_min = val;
651          break;
652        case 'n':
653        case 't':
654          /* Match any white space.  */
655          while (c_isspace (*rp))
656            ++rp;
657          break;
658        case 'p':
659          /* Match locale's equivalent of AM/PM.  */
660#ifdef _NL_CURRENT
661          if (*decided != raw)
662            {
663              if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp))
664                {
665                  if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR))
666                    *decided = loc;
667                  break;
668                }
669              if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp))
670                {
671                  if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR))
672                    *decided = loc;
673                  is_pm = 1;
674                  break;
675                }
676              *decided = raw;
677            }
678#endif
679          if (!match_string (HERE_AM_STR, rp))
680            {
681              if (match_string (HERE_PM_STR, rp))
682                is_pm = 1;
683              else
684                return NULL;
685            }
686          break;
687        case 'r':
688#ifdef _NL_CURRENT
689          if (*decided != raw)
690            {
691              if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM)))
692                {
693                  if (*decided == loc)
694                    return NULL;
695                  else
696                    rp = rp_backup;
697                }
698              else
699                {
700                  if (*decided == not &&
701                      strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM),
702                              HERE_T_FMT_AMPM))
703                    *decided = loc;
704                  break;
705                }
706              *decided = raw;
707            }
708#endif
709          if (!recursive (HERE_T_FMT_AMPM))
710            return NULL;
711          break;
712        case 'R':
713          if (!recursive ("%H:%M"))
714            return NULL;
715          break;
716        case 's':
717          {
718            /* The number of seconds may be very high so we cannot use
719               the `get_number' macro.  Instead read the number
720               character for character and construct the result while
721               doing this.  */
722            time_t secs = 0;
723            if (*rp < '0' || *rp > '9')
724              /* We need at least one digit.  */
725              return NULL;
726
727            do
728              {
729                secs *= 10;
730                secs += *rp++ - '0';
731              }
732            while (*rp >= '0' && *rp <= '9');
733
734            if (localtime_r (&secs, tm) == NULL)
735              /* Error in function.  */
736              return NULL;
737          }
738          break;
739        case 'S':
740          get_number (0, 61, 2);
741          tm->tm_sec = val;
742          break;
743        case 'X':
744#ifdef _NL_CURRENT
745          if (*decided != raw)
746            {
747              if (!recursive (_NL_CURRENT (LC_TIME, T_FMT)))
748                {
749                  if (*decided == loc)
750                    return NULL;
751                  else
752                    rp = rp_backup;
753                }
754              else
755                {
756                  if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT))
757                    *decided = loc;
758                  break;
759                }
760              *decided = raw;
761            }
762#endif
763          /* Fall through.  */
764        case 'T':
765          if (!recursive (HERE_T_FMT))
766            return NULL;
767          break;
768        case 'u':
769          get_number (1, 7, 1);
770          tm->tm_wday = val % 7;
771          have_wday = 1;
772          break;
773        case 'g':
774          get_number (0, 99, 2);
775          /* XXX This cannot determine any field in TM.  */
776          break;
777        case 'G':
778          if (*rp < '0' || *rp > '9')
779            return NULL;
780          /* XXX Ignore the number since we would need some more
781             information to compute a real date.  */
782          do
783            ++rp;
784          while (*rp >= '0' && *rp <= '9');
785          break;
786        case 'U':
787        case 'V':
788        case 'W':
789          get_number (0, 53, 2);
790          /* XXX This cannot determine any field in TM without some
791             information.  */
792          break;
793        case 'w':
794          /* Match number of weekday.  */
795          get_number (0, 6, 1);
796          tm->tm_wday = val;
797          have_wday = 1;
798          break;
799        case 'y':
800          /* Match year within century.  */
801          get_number (0, 99, 2);
802          /* The "Year 2000: The Millennium Rollover" paper suggests that
803             values in the range 69-99 refer to the twentieth century.  */
804          tm->tm_year = val >= 69 ? val : val + 100;
805          /* Indicate that we want to use the century, if specified.  */
806          want_century = 1;
807          want_xday = 1;
808          break;
809        case 'Y':
810          /* Match year including century number.  */
811          get_number (0, 9999, 4);
812          tm->tm_year = val - 1900;
813          want_century = 0;
814          want_xday = 1;
815          break;
816        case 'Z':
817          /* XXX How to handle this?  */
818          break;
819        case 'E':
820#ifdef _NL_CURRENT
821          switch (*fmt++)
822            {
823            case 'c':
824              /* Match locale's alternate date and time format.  */
825              if (*decided != raw)
826                {
827                  const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT);
828
829                  if (*fmt == '\0')
830                    fmt = _NL_CURRENT (LC_TIME, D_T_FMT);
831
832                  if (!recursive (fmt))
833                    {
834                      if (*decided == loc)
835                        return NULL;
836                      else
837                        rp = rp_backup;
838                    }
839                  else
840                    {
841                      if (strcmp (fmt, HERE_D_T_FMT))
842                        *decided = loc;
843                      want_xday = 1;
844                      break;
845                    }
846                  *decided = raw;
847                }
848              /* The C locale has no era information, so use the
849                 normal representation.  */
850              if (!recursive (HERE_D_T_FMT))
851                return NULL;
852              want_xday = 1;
853              break;
854            case 'C':
855            case 'y':
856            case 'Y':
857              /* Match name of base year in locale's alternate
858                 representation.  */
859              /* XXX This is currently not implemented.  It should
860                 use the value _NL_CURRENT (LC_TIME, ERA).  */
861              break;
862            case 'x':
863              if (*decided != raw)
864                {
865                  const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT);
866
867                  if (*fmt == '\0')
868                    fmt = _NL_CURRENT (LC_TIME, D_FMT);
869
870                  if (!recursive (fmt))
871                    {
872                      if (*decided == loc)
873                        return NULL;
874                      else
875                        rp = rp_backup;
876                    }
877                  else
878                    {
879                      if (strcmp (fmt, HERE_D_FMT))
880                        *decided = loc;
881                      break;
882                    }
883                  *decided = raw;
884                }
885              if (!recursive (HERE_D_FMT))
886                return NULL;
887              break;
888            case 'X':
889              if (*decided != raw)
890                {
891                  const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT);
892
893                  if (*fmt == '\0')
894                    fmt = _NL_CURRENT (LC_TIME, T_FMT);
895
896                  if (!recursive (fmt))
897                    {
898                      if (*decided == loc)
899                        return NULL;
900                      else
901                        rp = rp_backup;
902                    }
903                  else
904                    {
905                      if (strcmp (fmt, HERE_T_FMT))
906                        *decided = loc;
907                      break;
908                    }
909                  *decided = raw;
910                }
911              if (!recursive (HERE_T_FMT))
912                return NULL;
913              break;
914            default:
915              return NULL;
916            }
917          break;
918#else
919          /* We have no information about the era format.  Just use
920             the normal format.  */
921          if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y'
922              && *fmt != 'x' && *fmt != 'X')
923            /* This is an illegal format.  */
924            return NULL;
925
926          goto start_over;
927#endif
928        case 'O':
929          switch (*fmt++)
930            {
931            case 'd':
932            case 'e':
933              /* Match day of month using alternate numeric symbols.  */
934              get_alt_number (1, 31, 2);
935              tm->tm_mday = val;
936              have_mday = 1;
937              want_xday = 1;
938              break;
939            case 'H':
940              /* Match hour in 24-hour clock using alternate numeric
941                 symbols.  */
942              get_alt_number (0, 23, 2);
943              tm->tm_hour = val;
944              have_I = 0;
945              break;
946            case 'I':
947              /* Match hour in 12-hour clock using alternate numeric
948                 symbols.  */
949              get_alt_number (1, 12, 2);
950              tm->tm_hour = val - 1;
951              have_I = 1;
952              break;
953            case 'm':
954              /* Match month using alternate numeric symbols.  */
955              get_alt_number (1, 12, 2);
956              tm->tm_mon = val - 1;
957              have_mon = 1;
958              want_xday = 1;
959              break;
960            case 'M':
961              /* Match minutes using alternate numeric symbols.  */
962              get_alt_number (0, 59, 2);
963              tm->tm_min = val;
964              break;
965            case 'S':
966              /* Match seconds using alternate numeric symbols.  */
967              get_alt_number (0, 61, 2);
968              tm->tm_sec = val;
969              break;
970            case 'U':
971            case 'V':
972            case 'W':
973              get_alt_number (0, 53, 2);
974              /* XXX This cannot determine any field in TM without
975                 further information.  */
976              break;
977            case 'w':
978              /* Match number of weekday using alternate numeric symbols.  */
979              get_alt_number (0, 6, 1);
980              tm->tm_wday = val;
981              have_wday = 1;
982              break;
983            case 'y':
984              /* Match year within century using alternate numeric symbols.  */
985              get_alt_number (0, 99, 2);
986              tm->tm_year = val >= 69 ? val : val + 100;
987              want_xday = 1;
988              break;
989            default:
990              return NULL;
991            }
992          break;
993        default:
994          return NULL;
995        }
996    }
997
998  if (have_I && is_pm)
999    tm->tm_hour += 12;
1000
1001  if (century != -1)
1002    {
1003      if (want_century)
1004        tm->tm_year = tm->tm_year % 100 + (century - 19) * 100;
1005      else
1006        /* Only the century, but not the year.  Strange, but so be it.  */
1007        tm->tm_year = (century - 19) * 100;
1008    }
1009
1010  if (want_xday && !have_wday) {
1011      if ( !(have_mon && have_mday) && have_yday)  {
1012          /* we don't have tm_mon and/or tm_mday, compute them */
1013          int t_mon = 0;
1014          while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday)
1015              t_mon++;
1016          if (!have_mon)
1017              tm->tm_mon = t_mon - 1;
1018          if (!have_mday)
1019              tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1;
1020      }
1021      day_of_the_week (tm);
1022  }
1023  if (want_xday && !have_yday)
1024    day_of_the_year (tm);
1025
1026  return (char *) rp;
1027}
1028
1029
1030char *
1031strptime (buf, format, tm)
1032     const char *buf;
1033     const char *format;
1034     struct tm *tm;
1035{
1036  enum locale_status decided;
1037#ifdef _NL_CURRENT
1038  decided = not;
1039#else
1040  decided = raw;
1041#endif
1042  return strptime_internal (buf, format, tm, &decided);
1043}
1044#endif /* not HAVE_STRPTIME */
1045
1046#ifdef NEED_MON_YDAY
1047const unsigned short int __mon_yday[2][13] =
1048  {
1049    /* Normal years.  */
1050    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
1051    /* Leap years.  */
1052    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
1053  };
1054#endif
1055
1056/* fnmatch is required by POSIX, but we include an implementation for
1057   the sake of systems that don't have it, most notably Windows.  Some
1058   systems do have fnmatch, but Apache's installation process installs
1059   its own fnmatch.h (incompatible with the system one!) in a system
1060   include directory, effectively rendering fnmatch unusable.  This
1061   has been fixed with Apache 2, where fnmatch has been moved to apr
1062   and given a prefix, but many systems out there are still (as of
1063   this writing in 2005) broken and we must cater to them.
1064
1065   Additionally, according to some conventional wisdom, many
1066   historical implementations of fnmatch are buggy and unreliable.  If
1067   yours is such, undefine SYSTEM_FNMATCH in sysdep.h and tell us
1068   about it.  */
1069
1070#ifndef SYSTEM_FNMATCH
1071
1072#define __FNM_FLAGS     (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD)
1073
1074/* Match STRING against the filename pattern PATTERN, returning zero
1075   if it matches, FNM_NOMATCH if not.  This implementation comes from
1076   an earlier version of GNU Bash.  (It doesn't make sense to update
1077   it with a newer version because those versions add a lot of
1078   features Wget doesn't use or care about.)  */
1079
1080int
1081fnmatch (const char *pattern, const char *string, int flags)
1082{
1083  register const char *p = pattern, *n = string;
1084  register char c;
1085
1086  if ((flags & ~__FNM_FLAGS) != 0)
1087    {
1088      errno = EINVAL;
1089      return (-1);
1090    }
1091
1092  while ((c = *p++) != '\0')
1093    {
1094      switch (c)
1095        {
1096        case '?':
1097          if (*n == '\0')
1098            return (FNM_NOMATCH);
1099          else if ((flags & FNM_PATHNAME) && *n == '/')
1100            return (FNM_NOMATCH);
1101          else if ((flags & FNM_PERIOD) && *n == '.' &&
1102                   (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1103            return (FNM_NOMATCH);
1104          break;
1105
1106        case '\\':
1107          if (!(flags & FNM_NOESCAPE))
1108            c = *p++;
1109          if (*n != c)
1110            return (FNM_NOMATCH);
1111          break;
1112
1113        case '*':
1114          if ((flags & FNM_PERIOD) && *n == '.' &&
1115              (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1116            return (FNM_NOMATCH);
1117
1118          for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1119            if (((flags & FNM_PATHNAME) && *n == '/') ||
1120                (c == '?' && *n == '\0'))
1121              return (FNM_NOMATCH);
1122
1123          if (c == '\0')
1124            return (0);
1125
1126          {
1127            char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1128            for (--p; *n != '\0'; ++n)
1129              if ((c == '[' || *n == c1) &&
1130                  fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1131                return (0);
1132            return (FNM_NOMATCH);
1133          }
1134
1135        case '[':
1136          {
1137            /* Nonzero if the sense of the character class is
1138               inverted.  */
1139            register int not;
1140
1141            if (*n == '\0')
1142              return (FNM_NOMATCH);
1143
1144            if ((flags & FNM_PERIOD) && *n == '.' &&
1145                (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
1146              return (FNM_NOMATCH);
1147
1148            /* Make sure there is a closing `]'.  If there isn't,
1149               the `[' is just a character to be matched.  */
1150            {
1151              register const char *np;
1152
1153              for (np = p; np && *np && *np != ']'; np++)
1154                ;
1155
1156              if (np && !*np)
1157                {
1158                  if (*n != '[')
1159                    return (FNM_NOMATCH);
1160                  goto next_char;
1161                }
1162            }
1163
1164            not = (*p == '!' || *p == '^');
1165            if (not)
1166              ++p;
1167
1168            c = *p++;
1169            while (1)
1170              {
1171                register char cstart = c, cend = c;
1172
1173                if (!(flags & FNM_NOESCAPE) && c == '\\')
1174                  cstart = cend = *p++;
1175
1176                if (c == '\0')
1177                  /* [ (unterminated) loses.  */
1178                  return (FNM_NOMATCH);
1179
1180                c = *p++;
1181
1182                if ((flags & FNM_PATHNAME) && c == '/')
1183                  /* [/] can never match.  */
1184                  return (FNM_NOMATCH);
1185
1186                if (c == '-' && *p != ']')
1187                  {
1188                    cend = *p++;
1189                    if (!(flags & FNM_NOESCAPE) && cend == '\\')
1190                      cend = *p++;
1191                    if (cend == '\0')
1192                      return (FNM_NOMATCH);
1193                    c = *p++;
1194                  }
1195
1196                if (*n >= cstart && *n <= cend)
1197                  goto matched;
1198
1199                if (c == ']')
1200                  break;
1201              }
1202            if (!not)
1203              return (FNM_NOMATCH);
1204
1205          next_char:
1206            break;
1207
1208          matched:
1209            /* Skip the rest of the [...] that already matched.  */
1210            while (c != ']')
1211              {
1212                if (c == '\0')
1213                  /* [... (unterminated) loses.  */
1214                  return (FNM_NOMATCH);
1215
1216                c = *p++;
1217                if (!(flags & FNM_NOESCAPE) && c == '\\')
1218                  /* 1003.2d11 is unclear if this is right.  %%% */
1219                  ++p;
1220              }
1221            if (not)
1222              return (FNM_NOMATCH);
1223          }
1224          break;
1225
1226        default:
1227          if (c != *n)
1228            return (FNM_NOMATCH);
1229        }
1230
1231      ++n;
1232    }
1233
1234  if (*n == '\0')
1235    return (0);
1236
1237  return (FNM_NOMATCH);
1238}
1239
1240#endif /* not SYSTEM_FNMATCH */
1241
1242#ifndef HAVE_TIMEGM
1243/* timegm is a GNU extension, but lately also available on *BSD
1244   systems and possibly elsewhere. */
1245
1246/* True if YEAR is a leap year. */
1247#define ISLEAP(year)                                            \
1248  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
1249
1250/* Number of leap years in the range [y1, y2). */
1251#define LEAPYEARS(y1, y2)                                               \
1252  ((y2-1)/4 - (y1-1)/4) - ((y2-1)/100 - (y1-1)/100) + ((y2-1)/400 - (y1-1)/400)
1253
1254/* Inverse of gmtime: converts struct tm to time_t, assuming the data
1255   in tm is UTC rather than local timezone.  This implementation
1256   returns the number of seconds elapsed since midnight 1970-01-01,
1257   converted to time_t.  */
1258
1259time_t
1260timegm (struct tm *t)
1261{
1262  static const unsigned short int month_to_days[][13] = {
1263    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, /* normal */
1264    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }  /* leap */
1265  };
1266  const int year = 1900 + t->tm_year;
1267  unsigned long secs;  /* until 2106-02-07 for 32-bit unsigned long */
1268  int days;
1269
1270  if (year < 1970)
1271    return (time_t) -1;
1272
1273  days = 365 * (year - 1970);
1274  /* Take into account leap years between 1970 and YEAR, not counting
1275     YEAR itself.  */
1276  days += LEAPYEARS (1970, year);
1277  if (t->tm_mon < 0 || t->tm_mon >= 12)
1278    return (time_t) -1;
1279  days += month_to_days[ISLEAP (year)][t->tm_mon];
1280  days += t->tm_mday - 1;
1281
1282  secs = days * 86400 + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec;
1283  return (time_t) secs;
1284}
1285#endif /* HAVE_TIMEGM */
1286
1287#ifdef NEED_STRTOLL
1288/* strtoll is required by C99 and used by Wget only on systems with
1289   LFS.  Unfortunately, some systems have LFS, but no strtoll or
1290   equivalent.  These include HPUX 11.0 and Windows.
1291
1292   We use #ifdef NEED_STRTOLL instead of #ifndef HAVE_STRTOLL because
1293   of the systems which have a suitable replacement (e.g. _strtoi64 on
1294   Windows), on which Wget's str_to_wgint is instructed to use that
1295   instead.  */
1296
1297static inline int
1298char_value (char c, int base)
1299{
1300  int value;
1301  if (c < '0')
1302    return -1;
1303  if ('0' <= c && c <= '9')
1304    value = c - '0';
1305  else if ('a' <= c && c <= 'z')
1306    value = c - 'a' + 10;
1307  else if ('A' <= c && c <= 'Z')
1308    value = c - 'A' + 10;
1309  else
1310    return -1;
1311  if (value >= base)
1312    return -1;
1313  return value;
1314}
1315
1316#define STRTOLL_MAX TYPE_MAXIMUM (strtoll_type)
1317/* This definition assumes two's complement arithmetic */
1318#define STRTOLL_MIN (-STRTOLL_MAX - 1)
1319
1320/* Like a%b, but always returns a positive number when A is negative.
1321   (C doesn't guarantee the sign of the result.)  */
1322#define MOD(a, b) ((strtoll_type) -1 % 2 == 1 ? (a) % (b) : - ((a) % (b)))
1323
1324/* A strtoll-like replacement for systems that have an integral type
1325   larger than long but don't supply strtoll.  This implementation
1326   makes no assumptions about the size of strtoll_type.  */
1327
1328strtoll_type
1329strtoll (const char *nptr, char **endptr, int base)
1330{
1331  strtoll_type result = 0;
1332  bool negative;
1333
1334  if (base != 0 && (base < 2 || base > 36))
1335    {
1336      errno = EINVAL;
1337      return 0;
1338    }
1339
1340  while (*nptr == ' ' || *nptr == '\t')
1341    ++nptr;
1342  if (*nptr == '-')
1343    {
1344      negative = true;
1345      ++nptr;
1346    }
1347  else if (*nptr == '+')
1348    {
1349      negative = false;
1350      ++nptr;
1351    }
1352  else
1353    negative = false;
1354
1355  /* If BASE is 0, determine the real base based on the beginning on
1356     the number; octal numbers begin with "0", hexadecimal with "0x",
1357     and the others are considered octal.  */
1358  if (*nptr == '0')
1359    {
1360      if ((base == 0 || base == 16)
1361          &&
1362          (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
1363        {
1364          base = 16;
1365          nptr += 2;
1366          /* "0x" must be followed by at least one hex char.  If not,
1367             return 0 and place ENDPTR on 'x'. */
1368          if (!c_isxdigit (*nptr))
1369            {
1370              --nptr;
1371              goto out;
1372            }
1373        }
1374      else if (base == 0)
1375        base = 8;
1376    }
1377  else if (base == 0)
1378    base = 10;
1379
1380  if (!negative)
1381    {
1382      /* Parse positive number, checking for overflow. */
1383      int digit;
1384      /* Overflow watermark.  If RESULT exceeds it, overflow occurs on
1385         this digit.  If result==WATERMARK, current digit may not
1386         exceed the last digit of maximum value. */
1387      const strtoll_type WATERMARK = STRTOLL_MAX / base;
1388      for (; (digit = char_value (*nptr, base)) != -1; ++nptr)
1389        {
1390          if (result > WATERMARK
1391              || (result == WATERMARK && digit > STRTOLL_MAX % base))
1392            {
1393              result = STRTOLL_MAX;
1394              errno = ERANGE;
1395              break;
1396            }
1397          result = base * result + digit;
1398        }
1399    }
1400  else
1401    {
1402      /* Parse negative number, checking for underflow. */
1403      int digit;
1404      const strtoll_type WATERMARK = STRTOLL_MIN / base;
1405      for (; (digit = char_value (*nptr, base)) != -1; ++nptr)
1406        {
1407          if (result < WATERMARK
1408              || (result == WATERMARK && digit > MOD (STRTOLL_MIN, base)))
1409            {
1410              result = STRTOLL_MIN;
1411              errno = ERANGE;
1412              break;
1413            }
1414          result = base * result - digit;
1415        }
1416    }
1417 out:
1418  if (endptr)
1419    *endptr = (char *) nptr;
1420  return result;
1421}
1422
1423#undef STRTOLL_MAX
1424#undef STRTOLL_MIN
1425#undef ABS
1426
1427#endif  /* NEED_STRTOLL */
1428