libdap++  Updated for version 3.8.2
util_mit.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112
24 
25 // This file was derived from the libwww source code of 1998/08/20. The
26 // copyright for the source of this derivative work can be found in the file
27 // COPYRIGHT_W3C.
28 
29 
30 #include "config.h"
31 
32 static char rcsid[] not_used =
33  {"$Id: util_mit.cc 21214 2009-08-04 16:15:54Z jimg $"
34  };
35 
36 #include <cstdio>
37 #include <cstring>
38 #include <cstdlib>
39 //#include <string>
40 #include <ctype.h>
41 
42 #ifndef TM_IN_SYS_TIME
43 #include <time.h>
44 #else
45 #include <sys/time.h>
46 #endif
47 
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 
51 #include <iostream>
52 
53 #include "util_mit.h"
54 
55 using std::cerr;
56 using std::endl;
57 using std::string;
58 
59 #include "debug.h"
60 
61 namespace libdap {
62 
63 static const char * months[12] =
64  {
65  "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
66  };
67 
68 #ifndef HAVE_STRFTIME
69 static const char * wkdays[7] =
70  {
71  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
72  };
73 #endif
74 
75 /* Upper- and Lowercase macros
76 
77  The problem here is that toupper(x) is not defined officially unless
78  isupper(x) is. These macros are CERTAINLY needed on #if defined(pyr) ||
79  define(mips) or BDSI platforms. For safefy, we make them mandatory.
80 */
81 
82 #ifndef TOLOWER
83 #define TOLOWER(c) tolower((int) (c))
84 #define TOUPPER(c) toupper((int) (c))
85 #endif
86 
87 static int
88 strncasecomp(const char *a, const char *b, int n)
89 {
90  const char *p = a;
91  const char *q = b;
92 
93  for (p = a, q = b;; p++, q++) {
94  int diff;
95  if (p == a + n) return 0; /* Match up to n characters */
96  if (!(*p && *q)) return *p - *q;
97  diff = TOLOWER(*p) - TOLOWER(*q);
98  if (diff) return diff;
99  }
100  /*NOTREACHED*/
101 }
102 
103 static int
104 make_month(char * s, char ** ends)
105 {
106  char * ptr = s;
107  while (!isalpha((int) *ptr)) ptr++;
108  if (*ptr) {
109  int i;
110  *ends = ptr + 3;
111  for (i = 0; i < 12; i++)
112  if (!strncasecomp(months[i], ptr, 3)) return i;
113  }
114  return 0;
115 }
116 
131 time_t
132 parse_time(const char * str, bool expand)
133 {
134  char * s;
135  struct tm tm;
136  time_t t;
137 
138  if (!str) return 0;
139 
140  if ((s = (char *)strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */
141  s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */
142  while (*s && *s == ' ') s++;
143  if (strchr(s, '-')) { /* First format */
144  DBG(cerr << "Format...... Weekday, 00-Mon-00 00:00:00 GMT"
145  << endl);
146  if ((int)strlen(s) < 18) {
147  DBG(cerr << "ERROR....... Not a valid time format \""
148  << s << "\"" << endl);
149  return 0;
150  }
151  tm.tm_mday = strtol(s, &s, 10);
152  tm.tm_mon = make_month(s, &s);
153  ++s;
154  tm.tm_year = strtol(s, &s, 10);
155  tm.tm_hour = strtol(s, &s, 10);
156  ++s;
157  tm.tm_min = strtol(s, &s, 10);
158  ++s;
159  tm.tm_sec = strtol(s, &s, 10);
160 
161  }
162  else { /* Second format */
163  DBG(cerr << "Format...... Wkd, 00 Mon 0000 00:00:00 GMT" << endl);
164  if ((int)strlen(s) < 20) {
165  DBG(cerr << "ERROR....... Not a valid time format \""
166  << s << "\"" << endl);
167  return 0;
168  }
169  tm.tm_mday = strtol(s, &s, 10);
170  tm.tm_mon = make_month(s, &s);
171  tm.tm_year = strtol(s, &s, 10) - 1900;
172  tm.tm_hour = strtol(s, &s, 10);
173  ++s;
174  tm.tm_min = strtol(s, &s, 10);
175  ++s;
176  tm.tm_sec = strtol(s, &s, 10);
177  }
178  }
179  else if (isdigit((int) *str)) {
180 
181  if (strchr(str, 'T')) { /* ISO (limited format) date string */
182  DBG(cerr << "Format...... YYYY.MM.DDThh:mmStzWkd" << endl);
183  s = (char *) str;
184  while (*s && *s == ' ') s++;
185  if ((int)strlen(s) < 21) {
186  DBG(cerr << "ERROR....... Not a valid time format \""
187  << s << "\"" << endl);
188  return 0;
189  }
190  tm.tm_year = strtol(s, &s, 10) - 1900;
191  ++s;
192  tm.tm_mon = strtol(s, &s, 10);
193  ++s;
194  tm.tm_mday = strtol(s, &s, 10);
195  ++s;
196  tm.tm_hour = strtol(s, &s, 10);
197  ++s;
198  tm.tm_min = strtol(s, &s, 10);
199  ++s;
200  tm.tm_sec = strtol(s, &s, 10);
201 
202  }
203  else { /* delta seconds */
204  t = expand ? time(NULL) + atol(str) : atol(str);
205 
206  return t;
207  }
208 
209  }
210  else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */
211  DBG(cerr << "Format...... Wkd Mon 00 00:00:00 0000 GMT" << endl);
212  s = (char *) str;
213  while (*s && *s == ' ') s++;
214  DBG(cerr << "Trying...... The Wrong time format: " << s << endl);
215  if ((int)strlen(s) < 24) {
216  DBG(cerr << "ERROR....... Not a valid time format \""
217  << s << "\"" << endl);
218  return 0;
219  }
220  tm.tm_mon = make_month(s, &s);
221  tm.tm_mday = strtol(s, &s, 10);
222  tm.tm_hour = strtol(s, &s, 10);
223  ++s;
224  tm.tm_min = strtol(s, &s, 10);
225  ++s;
226  tm.tm_sec = strtol(s, &s, 10);
227  tm.tm_year = strtol(s, &s, 10) - 1900;
228  }
229  if (tm.tm_sec < 0 || tm.tm_sec > 59 ||
230  tm.tm_min < 0 || tm.tm_min > 59 ||
231  tm.tm_hour < 0 || tm.tm_hour > 23 ||
232  tm.tm_mday < 1 || tm.tm_mday > 31 ||
233  tm.tm_mon < 0 || tm.tm_mon > 11 ||
234  tm.tm_year < 70 || tm.tm_year > 120) {
235  DBG(cerr << "ERROR....... Parsed illegal time" << endl);
236  return 0;
237  }
238 
239  /* Let mktime decide whether we have DST or not */
240  tm.tm_isdst = -1;
241 
242 #ifdef HAVE_TIMEGM
243 
244  t = timegm(&tm);
245 
246 #else
247 
248 #ifdef HAVE_MKTIME
249 
250  // Compute offset between localtime and GMT.
251  time_t offset;
252  time_t now = time(0);
253 #ifdef _REENTRANT
254  struct tm gmt, local;
255  offset = mktime(gmtime_r(&now, &gmt)) - mktime(localtime_r(&now, &local));
256 #else
257  offset = mktime(gmtime(&now)) - mktime(localtime(&now));
258 #endif
259 
260  t = mktime(&tm) + offset;
261 
262 #else
263 
264 #error "Neither mktime nor timegm defined"
265 
266 #endif /* HAVE_TIMEGM */
267 #endif /* HAVE_MKTIME */
268 
269  DBG(cerr << "Time string. " << str << " parsed to " << t
270  << " calendar time or \"" << ctime(&t) << "\" in local time" << endl);
271 
272  return t;
273 }
274 
284 string date_time_str(time_t *calendar, bool local)
285 {
286  char buf[40];
287 
288 #ifdef HAVE_STRFTIME
289  if (local) {
290  /*
291  ** Solaris 2.3 has a bug so we _must_ use reentrant version
292  ** Thomas Maslen <tmaslen@verity.com>
293  */
294 #if defined(_REENTRANT) || defined(SOLARIS)
295  struct tm loctime;
296  localtime_r(calendar, &loctime);
297  strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
298 #else
299  struct tm *loctime = localtime(calendar);
300  strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
301 #endif /* SOLARIS || _REENTRANT */
302  }
303  else {
304 #if defined(_REENTRANT) || defined(SOLARIS)
305  struct tm gmt;
306  gmtime_r(calendar, &gmt);
307  strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
308 #else
309  struct tm *gmt = gmtime(calendar);
310  strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
311 #endif /* SOLARIS || _REENTRANT */
312  }
313 
314 #else /* !HAVE_STRFTIME */
315 
316  if (local) {
317 #if defined(_REENTRANT)
318  struct tm loctime;
319  localtime_r(calendar, &loctime);
320  sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
321  wkdays[loctime.tm_wday],
322  loctime.tm_mday,
323  months[loctime.tm_mon],
324  loctime.tm_year + 1900,
325  loctime.tm_hour,
326  loctime.tm_min,
327  loctime.tm_sec);
328 #else
329  struct tm *loctime = localtime(calendar);
330  sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
331  wkdays[loctime->tm_wday],
332  loctime->tm_mday,
333  months[loctime->tm_mon],
334  loctime->tm_year + 1900,
335  loctime->tm_hour,
336  loctime->tm_min,
337  loctime->tm_sec);
338 #endif /* _REENTRANT */
339  }
340  else {
341 #if defined(_REENTRANT) || defined(SOLARIS)
342  struct tm gmt;
343  gmtime_r(calendar, &gmt);
344  sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
345  wkdays[gmt.tm_wday],
346  gmt.tm_mday,
347  months[gmt.tm_mon],
348  gmt.tm_year + 1900,
349  gmt.tm_hour,
350  gmt.tm_min,
351  gmt.tm_sec);
352 #else
353  struct tm *gmt = gmtime(calendar);
354  sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
355  wkdays[gmt->tm_wday],
356  gmt->tm_mday,
357  months[gmt->tm_mon],
358  gmt->tm_year + 1900,
359  gmt->tm_hour,
360  gmt->tm_min,
361  gmt->tm_sec);
362 #endif
363  }
364 #endif
365  return string(buf);
366 }
367 
368 } // namespace libdap
time_t parse_time(const char *str, bool expand)
Definition: util_mit.cc:132
#define not_used
Definition: config.h:521
#define TOLOWER(c)
Definition: util_mit.cc:83
#define DBG(x)
Definition: debug.h:58
string date_time_str(time_t *calendar, bool local)
Definition: util_mit.cc:284