libdap++ Updated for version 3.8.2

util_mit.cc

Go to the documentation of this file.
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2002 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112
00024 
00025 // This file was derived from the libwww source code of 1998/08/20. The
00026 // copyright for the source of this derivative work can be found in the file
00027 // COPYRIGHT_W3C.
00028 
00029 
00030 #include "config.h"
00031 
00032 static char rcsid[] not_used =
00033     {"$Id: util_mit.cc 21214 2009-08-04 16:15:54Z jimg $"
00034     };
00035 
00036 #include <cstdio>
00037 #include <cstring>
00038 #include <cstdlib>
00039 //#include <string>
00040 #include <ctype.h>
00041 
00042 #ifndef TM_IN_SYS_TIME
00043 #include <time.h>
00044 #else
00045 #include <sys/time.h>
00046 #endif
00047 
00048 #include <sys/types.h>
00049 #include <sys/stat.h>
00050 
00051 #include <iostream>
00052 
00053 #include "util_mit.h"
00054 
00055 using std::cerr;
00056 using std::endl;
00057 using std::string;
00058 
00059 #include "debug.h"
00060 
00061 namespace libdap {
00062 
00063 static const char * months[12] =
00064     {
00065         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00066     };
00067 
00068 #ifndef HAVE_STRFTIME
00069 static const char * wkdays[7] =
00070     {
00071         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00072     };
00073 #endif
00074 
00075 /* Upper- and Lowercase macros
00076 
00077    The problem here is that toupper(x) is not defined officially unless
00078    isupper(x) is. These macros are CERTAINLY needed on #if defined(pyr) ||
00079    define(mips) or BDSI platforms. For safefy, we make them mandatory.
00080 */
00081 
00082 #ifndef TOLOWER
00083 #define TOLOWER(c) tolower((int) (c))
00084 #define TOUPPER(c) toupper((int) (c))
00085 #endif
00086 
00087 static int
00088 strncasecomp(const char *a, const char *b, int n)
00089 {
00090     const char *p = a;
00091     const char *q = b;
00092 
00093     for (p = a, q = b;; p++, q++) {
00094         int diff;
00095         if (p == a + n) return 0; /*   Match up to n characters */
00096         if (!(*p && *q)) return *p - *q;
00097         diff = TOLOWER(*p) - TOLOWER(*q);
00098         if (diff) return diff;
00099     }
00100     /*NOTREACHED*/
00101 }
00102 
00103 static int
00104 make_month(char * s, char ** ends)
00105 {
00106     char * ptr = s;
00107     while (!isalpha((int) *ptr)) ptr++;
00108     if (*ptr) {
00109         int i;
00110         *ends = ptr + 3;
00111         for (i = 0; i < 12; i++)
00112             if (!strncasecomp(months[i], ptr, 3)) return i;
00113     }
00114     return 0;
00115 }
00116 
00131 time_t
00132 parse_time(const char * str, bool expand)
00133 {
00134     char * s;
00135     struct tm tm;
00136     time_t t;
00137 
00138     if (!str) return 0;
00139 
00140     if ((s = (char *)strchr(str, ','))) {  /* Thursday, 10-Jun-93 01:29:59 GMT */
00141         s++;    /* or: Thu, 10 Jan 1993 01:29:59 GMT */
00142         while (*s && *s == ' ') s++;
00143         if (strchr(s, '-')) {         /* First format */
00144             DBG(cerr << "Format...... Weekday, 00-Mon-00 00:00:00 GMT"
00145                 << endl);
00146             if ((int)strlen(s) < 18) {
00147                 DBG(cerr << "ERROR....... Not a valid time format \""
00148                     << s << "\"" << endl);
00149                 return 0;
00150             }
00151             tm.tm_mday = strtol(s, &s, 10);
00152             tm.tm_mon = make_month(s, &s);
00153             ++s;
00154             tm.tm_year = strtol(s, &s, 10);
00155             tm.tm_hour = strtol(s, &s, 10);
00156             ++s;
00157             tm.tm_min = strtol(s, &s, 10);
00158             ++s;
00159             tm.tm_sec = strtol(s, &s, 10);
00160 
00161         }
00162         else {         /* Second format */
00163             DBG(cerr << "Format...... Wkd, 00 Mon 0000 00:00:00 GMT" << endl);
00164             if ((int)strlen(s) < 20) {
00165                 DBG(cerr << "ERROR....... Not a valid time format \""
00166                     << s << "\"" << endl);
00167                 return 0;
00168             }
00169             tm.tm_mday = strtol(s, &s, 10);
00170             tm.tm_mon = make_month(s, &s);
00171             tm.tm_year = strtol(s, &s, 10) - 1900;
00172             tm.tm_hour = strtol(s, &s, 10);
00173             ++s;
00174             tm.tm_min = strtol(s, &s, 10);
00175             ++s;
00176             tm.tm_sec = strtol(s, &s, 10);
00177         }
00178     }
00179     else if (isdigit((int) *str)) {
00180 
00181         if (strchr(str, 'T')) { /* ISO (limited format) date string */
00182             DBG(cerr << "Format...... YYYY.MM.DDThh:mmStzWkd" << endl);
00183             s = (char *) str;
00184             while (*s && *s == ' ') s++;
00185             if ((int)strlen(s) < 21) {
00186                 DBG(cerr << "ERROR....... Not a valid time format \""
00187                     << s << "\"" << endl);
00188                 return 0;
00189             }
00190             tm.tm_year = strtol(s, &s, 10) - 1900;
00191             ++s;
00192             tm.tm_mon  = strtol(s, &s, 10);
00193             ++s;
00194             tm.tm_mday = strtol(s, &s, 10);
00195             ++s;
00196             tm.tm_hour = strtol(s, &s, 10);
00197             ++s;
00198             tm.tm_min  = strtol(s, &s, 10);
00199             ++s;
00200             tm.tm_sec  = strtol(s, &s, 10);
00201 
00202         }
00203         else {         /* delta seconds */
00204             t = expand ? time(NULL) + atol(str) : atol(str);
00205 
00206             return t;
00207         }
00208 
00209     }
00210     else {       /* Try the other format:  Wed Jun  9 01:29:59 1993 GMT */
00211         DBG(cerr << "Format...... Wkd Mon 00 00:00:00 0000 GMT" << endl);
00212         s = (char *) str;
00213         while (*s && *s == ' ') s++;
00214         DBG(cerr << "Trying...... The Wrong time format: " << s << endl);
00215         if ((int)strlen(s) < 24) {
00216             DBG(cerr << "ERROR....... Not a valid time format \""
00217                 << s << "\"" << endl);
00218             return 0;
00219         }
00220         tm.tm_mon = make_month(s, &s);
00221         tm.tm_mday = strtol(s, &s, 10);
00222         tm.tm_hour = strtol(s, &s, 10);
00223         ++s;
00224         tm.tm_min = strtol(s, &s, 10);
00225         ++s;
00226         tm.tm_sec = strtol(s, &s, 10);
00227         tm.tm_year = strtol(s, &s, 10) - 1900;
00228     }
00229     if (tm.tm_sec  < 0  ||  tm.tm_sec  > 59  ||
00230         tm.tm_min  < 0  ||  tm.tm_min  > 59  ||
00231         tm.tm_hour < 0  ||  tm.tm_hour > 23  ||
00232         tm.tm_mday < 1  ||  tm.tm_mday > 31  ||
00233         tm.tm_mon  < 0  ||  tm.tm_mon  > 11  ||
00234         tm.tm_year < 70  ||  tm.tm_year > 120) {
00235         DBG(cerr << "ERROR....... Parsed illegal time" << endl);
00236         return 0;
00237     }
00238 
00239     /* Let mktime decide whether we have DST or not */
00240     tm.tm_isdst = -1;
00241 
00242 #ifdef HAVE_TIMEGM
00243 
00244     t = timegm(&tm);
00245 
00246 #else
00247 
00248 #ifdef HAVE_MKTIME
00249 
00250     // Compute offset between localtime and GMT.
00251     time_t offset;
00252     time_t now = time(0);
00253 #ifdef _REENTRANT
00254     struct tm gmt, local;
00255     offset = mktime(gmtime_r(&now, &gmt)) - mktime(localtime_r(&now, &local));
00256 #else
00257     offset = mktime(gmtime(&now)) - mktime(localtime(&now));
00258 #endif
00259 
00260     t = mktime(&tm) + offset;
00261 
00262 #else
00263 
00264 #error "Neither mktime nor timegm defined"
00265 
00266 #endif /* HAVE_TIMEGM */
00267 #endif /* HAVE_MKTIME */
00268 
00269     DBG(cerr << "Time string. " << str << " parsed to " << t
00270         << " calendar time or \"" << ctime(&t) << "\" in local time" << endl);
00271 
00272     return t;
00273 }
00274 
00284 string date_time_str(time_t *calendar, bool local)
00285 {
00286     char buf[40];
00287 
00288 #ifdef HAVE_STRFTIME
00289     if (local) {
00290         /*
00291         ** Solaris 2.3 has a bug so we _must_ use reentrant version
00292         ** Thomas Maslen <tmaslen@verity.com>
00293         */
00294 #if defined(_REENTRANT) || defined(SOLARIS)
00295         struct tm loctime;
00296         localtime_r(calendar, &loctime);
00297         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
00298 #else
00299         struct tm *loctime = localtime(calendar);
00300         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
00301 #endif /* SOLARIS || _REENTRANT */
00302     }
00303     else {
00304 #if defined(_REENTRANT) || defined(SOLARIS)
00305         struct tm gmt;
00306         gmtime_r(calendar, &gmt);
00307         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
00308 #else
00309         struct tm *gmt = gmtime(calendar);
00310         strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
00311 #endif /* SOLARIS || _REENTRANT */
00312     }
00313 
00314 #else  /* !HAVE_STRFTIME */
00315 
00316     if (local) {
00317 #if defined(_REENTRANT)
00318         struct tm loctime;
00319         localtime_r(calendar, &loctime);
00320         sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
00321                 wkdays[loctime.tm_wday],
00322                 loctime.tm_mday,
00323                 months[loctime.tm_mon],
00324                 loctime.tm_year + 1900,
00325                 loctime.tm_hour,
00326                 loctime.tm_min,
00327                 loctime.tm_sec);
00328 #else
00329     struct tm *loctime = localtime(calendar);
00330     sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
00331             wkdays[loctime->tm_wday],
00332             loctime->tm_mday,
00333             months[loctime->tm_mon],
00334             loctime->tm_year + 1900,
00335             loctime->tm_hour,
00336             loctime->tm_min,
00337             loctime->tm_sec);
00338 #endif /* _REENTRANT */
00339     }
00340     else {
00341 #if defined(_REENTRANT) || defined(SOLARIS)
00342         struct tm gmt;
00343         gmtime_r(calendar, &gmt);
00344         sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
00345                 wkdays[gmt.tm_wday],
00346                 gmt.tm_mday,
00347                 months[gmt.tm_mon],
00348                 gmt.tm_year + 1900,
00349                 gmt.tm_hour,
00350                 gmt.tm_min,
00351                 gmt.tm_sec);
00352 #else
00353     struct tm *gmt = gmtime(calendar);
00354     sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
00355             wkdays[gmt->tm_wday],
00356             gmt->tm_mday,
00357             months[gmt->tm_mon],
00358             gmt->tm_year + 1900,
00359             gmt->tm_hour,
00360             gmt->tm_min,
00361             gmt->tm_sec);
00362 #endif
00363     }
00364 #endif
00365     return string(buf);
00366 }
00367 
00368 } // namespace libdap