libdap++ Updated for version 3.8.2
|
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