Annotation of embedaddon/thttpd/tdate_parse.c, revision 1.1
1.1 ! misho 1: /* tdate_parse - parse string dates into internal form, stripped-down version
! 2: **
! 3: ** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
! 4: ** All rights reserved.
! 5: **
! 6: ** Redistribution and use in source and binary forms, with or without
! 7: ** modification, are permitted provided that the following conditions
! 8: ** are met:
! 9: ** 1. Redistributions of source code must retain the above copyright
! 10: ** notice, this list of conditions and the following disclaimer.
! 11: ** 2. Redistributions in binary form must reproduce the above copyright
! 12: ** notice, this list of conditions and the following disclaimer in the
! 13: ** documentation and/or other materials provided with the distribution.
! 14: **
! 15: ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 16: ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 17: ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 19: ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: ** SUCH DAMAGE.
! 26: */
! 27:
! 28: /* This is a stripped-down version of date_parse.c, available at
! 29: ** http://www.acme.com/software/date_parse/
! 30: */
! 31:
! 32: #include <sys/types.h>
! 33:
! 34: #include <ctype.h>
! 35: #ifdef HAVE_MEMORY_H
! 36: #include <memory.h>
! 37: #endif
! 38: #include <stdio.h>
! 39: #include <stdlib.h>
! 40: #include <string.h>
! 41: #include <time.h>
! 42:
! 43: #include "tdate_parse.h"
! 44:
! 45:
! 46: struct strlong {
! 47: char* s;
! 48: long l;
! 49: };
! 50:
! 51:
! 52: static void
! 53: pound_case( char* str )
! 54: {
! 55: for ( ; *str != '\0'; ++str )
! 56: {
! 57: if ( isupper( (int) *str ) )
! 58: *str = tolower( (int) *str );
! 59: }
! 60: }
! 61:
! 62: static int
! 63: strlong_compare( v1, v2 )
! 64: char* v1;
! 65: char* v2;
! 66: {
! 67: return strcmp( ((struct strlong*) v1)->s, ((struct strlong*) v2)->s );
! 68: }
! 69:
! 70:
! 71: static int
! 72: strlong_search( char* str, struct strlong* tab, int n, long* lP )
! 73: {
! 74: int i, h, l, r;
! 75:
! 76: l = 0;
! 77: h = n - 1;
! 78: for (;;)
! 79: {
! 80: i = ( h + l ) / 2;
! 81: r = strcmp( str, tab[i].s );
! 82: if ( r < 0 )
! 83: h = i - 1;
! 84: else if ( r > 0 )
! 85: l = i + 1;
! 86: else
! 87: {
! 88: *lP = tab[i].l;
! 89: return 1;
! 90: }
! 91: if ( h < l )
! 92: return 0;
! 93: }
! 94: }
! 95:
! 96:
! 97: static int
! 98: scan_wday( char* str_wday, long* tm_wdayP )
! 99: {
! 100: static struct strlong wday_tab[] = {
! 101: { "sun", 0 }, { "sunday", 0 },
! 102: { "mon", 1 }, { "monday", 1 },
! 103: { "tue", 2 }, { "tuesday", 2 },
! 104: { "wed", 3 }, { "wednesday", 3 },
! 105: { "thu", 4 }, { "thursday", 4 },
! 106: { "fri", 5 }, { "friday", 5 },
! 107: { "sat", 6 }, { "saturday", 6 },
! 108: };
! 109: static int sorted = 0;
! 110:
! 111: if ( ! sorted )
! 112: {
! 113: (void) qsort(
! 114: wday_tab, sizeof(wday_tab)/sizeof(struct strlong),
! 115: sizeof(struct strlong), strlong_compare );
! 116: sorted = 1;
! 117: }
! 118: pound_case( str_wday );
! 119: return strlong_search(
! 120: str_wday, wday_tab, sizeof(wday_tab)/sizeof(struct strlong), tm_wdayP );
! 121: }
! 122:
! 123:
! 124: static int
! 125: scan_mon( char* str_mon, long* tm_monP )
! 126: {
! 127: static struct strlong mon_tab[] = {
! 128: { "jan", 0 }, { "january", 0 },
! 129: { "feb", 1 }, { "february", 1 },
! 130: { "mar", 2 }, { "march", 2 },
! 131: { "apr", 3 }, { "april", 3 },
! 132: { "may", 4 },
! 133: { "jun", 5 }, { "june", 5 },
! 134: { "jul", 6 }, { "july", 6 },
! 135: { "aug", 7 }, { "august", 7 },
! 136: { "sep", 8 }, { "september", 8 },
! 137: { "oct", 9 }, { "october", 9 },
! 138: { "nov", 10 }, { "november", 10 },
! 139: { "dec", 11 }, { "december", 11 },
! 140: };
! 141: static int sorted = 0;
! 142:
! 143: if ( ! sorted )
! 144: {
! 145: (void) qsort(
! 146: mon_tab, sizeof(mon_tab)/sizeof(struct strlong),
! 147: sizeof(struct strlong), strlong_compare );
! 148: sorted = 1;
! 149: }
! 150: pound_case( str_mon );
! 151: return strlong_search(
! 152: str_mon, mon_tab, sizeof(mon_tab)/sizeof(struct strlong), tm_monP );
! 153: }
! 154:
! 155:
! 156: static int
! 157: is_leap( int year )
! 158: {
! 159: return year % 400? ( year % 100 ? ( year % 4 ? 0 : 1 ) : 0 ) : 1;
! 160: }
! 161:
! 162:
! 163: /* Basically the same as mktime(). */
! 164: static time_t
! 165: tm_to_time( struct tm* tmP )
! 166: {
! 167: time_t t;
! 168: static int monthtab[12] = {
! 169: 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
! 170:
! 171: /* Years since epoch, converted to days. */
! 172: t = ( tmP->tm_year - 70 ) * 365;
! 173: /* Leap days for previous years. */
! 174: t += ( tmP->tm_year - 69 ) / 4;
! 175: /* Days for the beginning of this month. */
! 176: t += monthtab[tmP->tm_mon];
! 177: /* Leap day for this year. */
! 178: if ( tmP->tm_mon >= 2 && is_leap( tmP->tm_year + 1900 ) )
! 179: ++t;
! 180: /* Days since the beginning of this month. */
! 181: t += tmP->tm_mday - 1; /* 1-based field */
! 182: /* Hours, minutes, and seconds. */
! 183: t = t * 24 + tmP->tm_hour;
! 184: t = t * 60 + tmP->tm_min;
! 185: t = t * 60 + tmP->tm_sec;
! 186:
! 187: return t;
! 188: }
! 189:
! 190:
! 191: time_t
! 192: tdate_parse( char* str )
! 193: {
! 194: struct tm tm;
! 195: char* cp;
! 196: char str_mon[500], str_wday[500];
! 197: int tm_sec, tm_min, tm_hour, tm_mday, tm_year;
! 198: long tm_mon, tm_wday;
! 199: time_t t;
! 200:
! 201: /* Initialize. */
! 202: (void) memset( (char*) &tm, 0, sizeof(struct tm) );
! 203:
! 204: /* Skip initial whitespace ourselves - sscanf is clumsy at this. */
! 205: for ( cp = str; *cp == ' ' || *cp == '\t'; ++cp )
! 206: continue;
! 207:
! 208: /* And do the sscanfs. WARNING: you can add more formats here,
! 209: ** but be careful! You can easily screw up the parsing of existing
! 210: ** formats when you add new ones. The order is important.
! 211: */
! 212:
! 213: /* DD-mth-YY HH:MM:SS GMT */
! 214: if ( sscanf( cp, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT",
! 215: &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
! 216: &tm_sec ) == 6 &&
! 217: scan_mon( str_mon, &tm_mon ) )
! 218: {
! 219: tm.tm_mday = tm_mday;
! 220: tm.tm_mon = tm_mon;
! 221: tm.tm_year = tm_year;
! 222: tm.tm_hour = tm_hour;
! 223: tm.tm_min = tm_min;
! 224: tm.tm_sec = tm_sec;
! 225: }
! 226:
! 227: /* DD mth YY HH:MM:SS GMT */
! 228: else if ( sscanf( cp, "%d %400[a-zA-Z] %d %d:%d:%d GMT",
! 229: &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
! 230: &tm_sec) == 6 &&
! 231: scan_mon( str_mon, &tm_mon ) )
! 232: {
! 233: tm.tm_mday = tm_mday;
! 234: tm.tm_mon = tm_mon;
! 235: tm.tm_year = tm_year;
! 236: tm.tm_hour = tm_hour;
! 237: tm.tm_min = tm_min;
! 238: tm.tm_sec = tm_sec;
! 239: }
! 240:
! 241: /* HH:MM:SS GMT DD-mth-YY */
! 242: else if ( sscanf( cp, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d",
! 243: &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
! 244: &tm_year ) == 6 &&
! 245: scan_mon( str_mon, &tm_mon ) )
! 246: {
! 247: tm.tm_hour = tm_hour;
! 248: tm.tm_min = tm_min;
! 249: tm.tm_sec = tm_sec;
! 250: tm.tm_mday = tm_mday;
! 251: tm.tm_mon = tm_mon;
! 252: tm.tm_year = tm_year;
! 253: }
! 254:
! 255: /* HH:MM:SS GMT DD mth YY */
! 256: else if ( sscanf( cp, "%d:%d:%d GMT %d %400[a-zA-Z] %d",
! 257: &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon,
! 258: &tm_year ) == 6 &&
! 259: scan_mon( str_mon, &tm_mon ) )
! 260: {
! 261: tm.tm_hour = tm_hour;
! 262: tm.tm_min = tm_min;
! 263: tm.tm_sec = tm_sec;
! 264: tm.tm_mday = tm_mday;
! 265: tm.tm_mon = tm_mon;
! 266: tm.tm_year = tm_year;
! 267: }
! 268:
! 269: /* wdy, DD-mth-YY HH:MM:SS GMT */
! 270: else if ( sscanf( cp, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT",
! 271: str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
! 272: &tm_sec ) == 7 &&
! 273: scan_wday( str_wday, &tm_wday ) &&
! 274: scan_mon( str_mon, &tm_mon ) )
! 275: {
! 276: tm.tm_wday = tm_wday;
! 277: tm.tm_mday = tm_mday;
! 278: tm.tm_mon = tm_mon;
! 279: tm.tm_year = tm_year;
! 280: tm.tm_hour = tm_hour;
! 281: tm.tm_min = tm_min;
! 282: tm.tm_sec = tm_sec;
! 283: }
! 284:
! 285: /* wdy, DD mth YY HH:MM:SS GMT */
! 286: else if ( sscanf( cp, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT",
! 287: str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min,
! 288: &tm_sec ) == 7 &&
! 289: scan_wday( str_wday, &tm_wday ) &&
! 290: scan_mon( str_mon, &tm_mon ) )
! 291: {
! 292: tm.tm_wday = tm_wday;
! 293: tm.tm_mday = tm_mday;
! 294: tm.tm_mon = tm_mon;
! 295: tm.tm_year = tm_year;
! 296: tm.tm_hour = tm_hour;
! 297: tm.tm_min = tm_min;
! 298: tm.tm_sec = tm_sec;
! 299: }
! 300:
! 301: /* wdy mth DD HH:MM:SS GMT YY */
! 302: else if ( sscanf( cp, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d",
! 303: str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec,
! 304: &tm_year ) == 7 &&
! 305: scan_wday( str_wday, &tm_wday ) &&
! 306: scan_mon( str_mon, &tm_mon ) )
! 307: {
! 308: tm.tm_wday = tm_wday;
! 309: tm.tm_mon = tm_mon;
! 310: tm.tm_mday = tm_mday;
! 311: tm.tm_hour = tm_hour;
! 312: tm.tm_min = tm_min;
! 313: tm.tm_sec = tm_sec;
! 314: tm.tm_year = tm_year;
! 315: }
! 316: else
! 317: return (time_t) -1;
! 318:
! 319: if ( tm.tm_year > 1900 )
! 320: tm.tm_year -= 1900;
! 321: else if ( tm.tm_year < 70 )
! 322: tm.tm_year += 100;
! 323:
! 324: t = tm_to_time( &tm );
! 325:
! 326: return t;
! 327: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>