libdap
Updated for version 3.17.0
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #include <cstdio> 00033 #include <cstring> 00034 #include <cstdlib> 00035 //#include <string> 00036 #include <ctype.h> 00037 00038 #ifndef TM_IN_SYS_TIME 00039 #include <time.h> 00040 #else 00041 #include <sys/time.h> 00042 #endif 00043 00044 #include <sys/types.h> 00045 #include <sys/stat.h> 00046 00047 #include <iostream> 00048 00049 #include "util_mit.h" 00050 00051 using std::cerr; 00052 using std::endl; 00053 using std::string; 00054 00055 #include "debug.h" 00056 00057 namespace libdap { 00058 00059 static const char * months[12] = 00060 { 00061 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 00062 }; 00063 00064 #ifndef HAVE_STRFTIME 00065 static const char * wkdays[7] = 00066 { 00067 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 00068 }; 00069 #endif 00070 00071 /* Upper- and Lowercase macros 00072 00073 The problem here is that toupper(x) is not defined officially unless 00074 isupper(x) is. These macros are CERTAINLY needed on #if defined(pyr) || 00075 define(mips) or BDSI platforms. For safety, we make them mandatory. 00076 */ 00077 00078 #ifndef TOLOWER 00079 #define TOLOWER(c) tolower((int) (c)) 00080 #define TOUPPER(c) toupper((int) (c)) 00081 #endif 00082 00083 static int 00084 strncasecomp(const char *a, const char *b, int n) 00085 { 00086 const char *p = a; 00087 const char *q = b; 00088 00089 for (p = a, q = b;; p++, q++) { 00090 int diff; 00091 if (p == a + n) return 0; /* Match up to n characters */ 00092 if (!(*p && *q)) return *p - *q; 00093 diff = TOLOWER(*p) - TOLOWER(*q); 00094 if (diff) return diff; 00095 } 00096 /*NOTREACHED*/ 00097 return -1; // silence gcc 00098 } 00099 00100 static int 00101 make_month(char * s, char ** ends) 00102 { 00103 char * ptr = s; 00104 while (!isalpha((int) *ptr)) ptr++; 00105 if (*ptr) { 00106 int i; 00107 *ends = ptr + 3; 00108 for (i = 0; i < 12; i++) 00109 if (!strncasecomp(months[i], ptr, 3)) return i; 00110 } 00111 return 0; 00112 } 00113 00128 time_t 00129 parse_time(const char * str, bool expand) 00130 { 00131 char * s; 00132 struct tm tm; 00133 time_t t; 00134 00135 if (!str) return 0; 00136 00137 if ((s = (char *)strchr(str, ','))) { /* Thursday, 10-Jun-93 01:29:59 GMT */ 00138 s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */ 00139 while (*s && *s == ' ') s++; 00140 if (strchr(s, '-')) { /* First format */ 00141 DBG(cerr << "Format...... Weekday, 00-Mon-00 00:00:00 GMT" 00142 << endl); 00143 if ((int)strlen(s) < 18) { 00144 DBG(cerr << "ERROR....... Not a valid time format \"" 00145 << s << "\"" << endl); 00146 return 0; 00147 } 00148 tm.tm_mday = strtol(s, &s, 10); 00149 tm.tm_mon = make_month(s, &s); 00150 ++s; 00151 tm.tm_year = strtol(s, &s, 10); 00152 tm.tm_hour = strtol(s, &s, 10); 00153 ++s; 00154 tm.tm_min = strtol(s, &s, 10); 00155 ++s; 00156 tm.tm_sec = strtol(s, &s, 10); 00157 00158 } 00159 else { /* Second format */ 00160 DBG(cerr << "Format...... Wkd, 00 Mon 0000 00:00:00 GMT" << endl); 00161 if ((int)strlen(s) < 20) { 00162 DBG(cerr << "ERROR....... Not a valid time format \"" 00163 << s << "\"" << endl); 00164 return 0; 00165 } 00166 tm.tm_mday = strtol(s, &s, 10); 00167 tm.tm_mon = make_month(s, &s); 00168 tm.tm_year = strtol(s, &s, 10) - 1900; 00169 tm.tm_hour = strtol(s, &s, 10); 00170 ++s; 00171 tm.tm_min = strtol(s, &s, 10); 00172 ++s; 00173 tm.tm_sec = strtol(s, &s, 10); 00174 } 00175 } 00176 else if (isdigit((int) *str)) { 00177 00178 if (strchr(str, 'T')) { /* ISO (limited format) date string */ 00179 DBG(cerr << "Format...... YYYY.MM.DDThh:mmStzWkd" << endl); 00180 s = (char *) str; 00181 while (*s && *s == ' ') s++; 00182 if ((int)strlen(s) < 21) { 00183 DBG(cerr << "ERROR....... Not a valid time format \"" 00184 << s << "\"" << endl); 00185 return 0; 00186 } 00187 tm.tm_year = strtol(s, &s, 10) - 1900; 00188 ++s; 00189 tm.tm_mon = strtol(s, &s, 10); 00190 ++s; 00191 tm.tm_mday = strtol(s, &s, 10); 00192 ++s; 00193 tm.tm_hour = strtol(s, &s, 10); 00194 ++s; 00195 tm.tm_min = strtol(s, &s, 10); 00196 ++s; 00197 tm.tm_sec = strtol(s, &s, 10); 00198 00199 } 00200 else { /* delta seconds */ 00201 t = expand ? time(NULL) + atol(str) : atol(str); 00202 00203 return t; 00204 } 00205 00206 } 00207 else { /* Try the other format: Wed Jun 9 01:29:59 1993 GMT */ 00208 DBG(cerr << "Format...... Wkd Mon 00 00:00:00 0000 GMT" << endl); 00209 s = (char *) str; 00210 while (*s && *s == ' ') s++; 00211 DBG(cerr << "Trying...... The Wrong time format: " << s << endl); 00212 if ((int)strlen(s) < 24) { 00213 DBG(cerr << "ERROR....... Not a valid time format \"" 00214 << s << "\"" << endl); 00215 return 0; 00216 } 00217 tm.tm_mon = make_month(s, &s); 00218 tm.tm_mday = strtol(s, &s, 10); 00219 tm.tm_hour = strtol(s, &s, 10); 00220 ++s; 00221 tm.tm_min = strtol(s, &s, 10); 00222 ++s; 00223 tm.tm_sec = strtol(s, &s, 10); 00224 tm.tm_year = strtol(s, &s, 10) - 1900; 00225 } 00226 if (tm.tm_sec < 0 || tm.tm_sec > 59 || 00227 tm.tm_min < 0 || tm.tm_min > 59 || 00228 tm.tm_hour < 0 || tm.tm_hour > 23 || 00229 tm.tm_mday < 1 || tm.tm_mday > 31 || 00230 tm.tm_mon < 0 || tm.tm_mon > 11 || 00231 tm.tm_year < 70 || tm.tm_year > 120) { 00232 DBG(cerr << "ERROR....... Parsed illegal time" << endl); 00233 return 0; 00234 } 00235 00236 /* Let mktime decide whether we have DST or not */ 00237 tm.tm_isdst = -1; 00238 00239 #ifdef HAVE_TIMEGM 00240 00241 t = timegm(&tm); 00242 00243 #else 00244 00245 #ifdef HAVE_MKTIME 00246 00247 // Compute offset between localtime and GMT. 00248 time_t offset; 00249 time_t now = time(0); 00250 #ifdef _REENTRANT 00251 struct tm gmt, local; 00252 offset = mktime(gmtime_r(&now, &gmt)) - mktime(localtime_r(&now, &local)); 00253 #else 00254 offset = mktime(gmtime(&now)) - mktime(localtime(&now)); 00255 #endif 00256 00257 t = mktime(&tm) + offset; 00258 00259 #else 00260 00261 #error "Neither mktime nor timegm defined" 00262 00263 #endif /* HAVE_TIMEGM */ 00264 #endif /* HAVE_MKTIME */ 00265 00266 DBG(cerr << "Time string. " << str << " parsed to " << t 00267 << " calendar time or \"" << ctime(&t) << "\" in local time" << endl); 00268 00269 return t; 00270 } 00271 00281 string date_time_str(time_t *calendar, bool local) 00282 { 00283 char buf[40]; 00284 00285 #ifdef HAVE_STRFTIME 00286 if (local) { 00287 /* 00288 ** Solaris 2.3 has a bug so we _must_ use reentrant version 00289 ** Thomas Maslen <tmaslen@verity.com> 00290 */ 00291 #if defined(_REENTRANT) || defined(SOLARIS) 00292 struct tm loctime; 00293 localtime_r(calendar, &loctime); 00294 strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime); 00295 #else 00296 struct tm *loctime = localtime(calendar); 00297 strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime); 00298 #endif /* SOLARIS || _REENTRANT */ 00299 } 00300 else { 00301 #if defined(_REENTRANT) || defined(SOLARIS) 00302 struct tm gmt; 00303 gmtime_r(calendar, &gmt); 00304 strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt); 00305 #else 00306 struct tm *gmt = gmtime(calendar); 00307 strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt); 00308 #endif /* SOLARIS || _REENTRANT */ 00309 } 00310 00311 #else /* !HAVE_STRFTIME */ 00312 00313 if (local) { 00314 #if defined(_REENTRANT) 00315 struct tm loctime; 00316 localtime_r(calendar, &loctime); 00317 snprintf(buf, 40, "%s, %02d %s %04d %02d:%02d:%02d", 00318 wkdays[loctime.tm_wday], 00319 loctime.tm_mday, 00320 months[loctime.tm_mon], 00321 loctime.tm_year + 1900, 00322 loctime.tm_hour, 00323 loctime.tm_min, 00324 loctime.tm_sec); 00325 #else 00326 struct tm *loctime = localtime(calendar); 00327 if (!loctime) 00328 return ""; 00329 snprintf(buf, 40, "%s, %02d %s %04d %02d:%02d:%02d", 00330 wkdays[loctime->tm_wday], 00331 loctime->tm_mday, 00332 months[loctime->tm_mon], 00333 loctime->tm_year + 1900, 00334 loctime->tm_hour, 00335 loctime->tm_min, 00336 loctime->tm_sec); 00337 #endif /* _REENTRANT */ 00338 } 00339 else { 00340 #if defined(_REENTRANT) || defined(SOLARIS) 00341 struct tm gmt; 00342 gmtime_r(calendar, &gmt); 00343 snprintf(buf, 40, "%s, %02d %s %04d %02d:%02d:%02d GMT", 00344 wkdays[gmt.tm_wday], 00345 gmt.tm_mday, 00346 months[gmt.tm_mon], 00347 gmt.tm_year + 1900, 00348 gmt.tm_hour, 00349 gmt.tm_min, 00350 gmt.tm_sec); 00351 #else 00352 struct tm *gmt = gmtime(calendar); 00353 if (!gmt) 00354 return ""; 00355 snprintf(buf, 40, "%s, %02d %s %04d %02d:%02d:%02d GMT", 00356 wkdays[gmt->tm_wday], 00357 gmt->tm_mday, 00358 months[gmt->tm_mon], 00359 gmt->tm_year + 1900, 00360 gmt->tm_hour, 00361 gmt->tm_min, 00362 gmt->tm_sec); 00363 #endif 00364 } 00365 #endif 00366 return string(buf); 00367 } 00368 00369 } // namespace libdap