/**************************************************************************** * apps/netutils/thttpd/tdate_parse.c * Parse string dates into internal form, stripped-down version * * Copyright (C) 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Derived from the file of the same name in the original THTTPD package: * * Copyright © 1995 by Jef Poskanzer . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include "tdate_parse.h" /**************************************************************************** * Private Types ****************************************************************************/ #undef TDATE_PARSE_WORKS /* tdate_parse() doesn't work */ #undef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ /**************************************************************************** * Private Types ****************************************************************************/ struct strlong { char *s; long l; }; /**************************************************************************** * Private Functions ****************************************************************************/ #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ static void pound_case(char *str) { for (; *str != '\0'; ++str) { if (isupper((int)*str)) { *str = tolower((int)*str); } } } #endif #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ static int strlong_compare(const void *v1, const void *v2) { return strcmp(((struct strlong *)v1)->s, ((struct strlong *)v2)->s); } #endif #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ static int strlong_search(char *str, struct strlong *tab, int n, long *lp) { int i; int h; int l; int r; l = 0; h = n - 1; for (; ; ) { i = (h + l) / 2; r = strcmp(str, tab[i].s); if (r < 0) { h = i - 1; } else if (r > 0) { l = i + 1; } else { *lp = tab[i].l; return 1; } if (h < l) { return 0; } } } #endif #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ static int scan_wday(char *str_wday, long *tm_wdayp) { static struct strlong wday_tab[] = { {"sun", 0}, {"sunday", 0}, {"mon", 1}, {"monday", 1}, {"tue", 2}, {"tuesday", 2}, {"wed", 3}, {"wednesday", 3}, {"thu", 4}, {"thursday", 4}, {"fri", 5}, {"friday", 5}, {"sat", 6}, {"saturday", 6}, }; static int sorted = 0; if (!sorted) { qsort(wday_tab, nitems(wday_tab), sizeof(struct strlong), strlong_compare); sorted = 1; } pound_case(str_wday); return strlong_search(str_wday, wday_tab, nitems(wday_tab), tm_wdayp); } #endif /* Day of week not yet supported by NuttX */ #ifdef TDATE_PARSE_WORKS static int scan_mon(char *str_mon, long *tm_monp) { static struct strlong mon_tab[] = { {"jan", 0}, {"january", 0}, {"feb", 1}, {"february", 1}, {"mar", 2}, {"march", 2}, {"apr", 3}, {"april", 3}, {"may", 4}, {"jun", 5}, {"june", 5}, {"jul", 6}, {"july", 6}, {"aug", 7}, {"august", 7}, {"sep", 8}, {"september", 8}, {"oct", 9}, {"october", 9}, {"nov", 10}, {"november", 10}, {"dec", 11}, {"december", 11}, }; static int sorted = 0; if (!sorted) { qsort(mon_tab, nitems(mon_tab), sizeof(struct strlong), strlong_compare); sorted = 1; } pound_case(str_mon); return strlong_search(str_mon, mon_tab, nitems(mon_tab), tm_monp); } #endif /**************************************************************************** * Public Functions ****************************************************************************/ time_t tdate_parse(char *str) { #ifdef TDATE_PARSE_WORKS /* REVISIT -- doesn't work */ struct tm tm; char *cp; char str_mon[32]; int tm_year; int tm_mday; int tm_hour; int tm_min; int tm_sec; long tm_mon; #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ char str_wday[32]; long tm_wday; #endif ninfo("str: \"%s\"\n", str); /* Initialize. */ memset((char *)&tm, 0, sizeof(struct tm)); /* Skip initial whitespace ourselves - sscanf is clumsy at this. */ for (cp = str; *cp == ' ' || *cp == '\t'; ++cp) { continue; } /* And do the sscanfs. WARNING: you can add more formats here, but be * careful! You can easily screw up the parsing of existing formats when * you add new ones. The order is important. */ /* DD-mth-YY HH:MM:SS GMT */ if (sscanf(cp, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT", &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec) == 6 && scan_mon(str_mon, &tm_mon)) { tm.tm_mday = tm_mday; tm.tm_mon = tm_mon; tm.tm_year = tm_year; tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; } /* DD mth YY HH:MM:SS GMT */ else if (sscanf(cp, "%d %400[a-zA-Z] %d %d:%d:%d GMT", &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec) == 6 && scan_mon(str_mon, &tm_mon)) { tm.tm_mday = tm_mday; tm.tm_mon = tm_mon; tm.tm_year = tm_year; tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; } /* HH:MM:SS GMT DD-mth-YY */ else if (sscanf(cp, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d", &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon, &tm_year) == 6 && scan_mon(str_mon, &tm_mon)) { tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; tm.tm_mday = tm_mday; tm.tm_mon = tm_mon; tm.tm_year = tm_year; } /* HH:MM:SS GMT DD mth YY */ else if (sscanf(cp, "%d:%d:%d GMT %d %400[a-zA-Z] %d", &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon, &tm_year) == 6 && scan_mon(str_mon, &tm_mon)) { tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; tm.tm_mday = tm_mday; tm.tm_mon = tm_mon; tm.tm_year = tm_year; } #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ /* wdy, DD-mth-YY HH:MM:SS GMT */ else if (sscanf(cp, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT", str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 && scan_wday(str_wday, &tm_wday) && scan_mon(str_mon, &tm_mon)) { tm.tm_wday = tm_wday; tm.tm_mday = tm_mday; tm.tm_mon = tm_mon; tm.tm_year = tm_year; tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; } #endif /* Day of week not yet supported by NuttX */ #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ /* wdy, DD mth YY HH:MM:SS GMT */ else if (sscanf(cp, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT", str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 && scan_wday(str_wday, &tm_wday) && scan_mon(str_mon, &tm_mon)) { tm.tm_wday = tm_wday; tm.tm_mday = tm_mday; tm.tm_mon = tm_mon; tm.tm_year = tm_year; tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; } #endif /* Day of week not yet supported by NuttX */ #ifdef HAVE_DAY_OF_WEEK /* Day of week not yet supported by NuttX */ /* wdy mth DD HH:MM:SS GMT YY */ else if (sscanf(cp, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d", str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec, &tm_year) == 7 && scan_wday(str_wday, &tm_wday) && scan_mon(str_mon, &tm_mon)) { tm.tm_wday = tm_wday; tm.tm_mon = tm_mon; tm.tm_mday = tm_mday; tm.tm_hour = tm_hour; tm.tm_min = tm_min; tm.tm_sec = tm_sec; tm.tm_year = tm_year; } #endif /* Day of week not yet supported by NuttX */ else { return (time_t) - 1; } if (tm.tm_year > 1900) { tm.tm_year -= 1900; } else if (tm.tm_year < 70) { tm.tm_year += 100; } return mktime(&tm); #else return 0; /* For now. */ #endif }