Nut/OS  4.10.3
API Reference
rfctime.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00053 #include <stdio.h>
00054 #include <string.h>
00055 #include <ctype.h>
00056 
00057 #include <pro/rfctime.h>
00058 
00059 static char rfc1123_buf[32];
00060 static char *wkdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00061 static char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
00062 
00070 static char *skip_spaces(CONST char *str)
00071 {
00072     while (*str == ' ' || *str == '\t')
00073         str++;
00074     return (char *)str;
00075 }
00076 
00087 static char *parse_digits(CONST char *str, int *val)
00088 {
00089     *val = 0;
00090     while (isdigit((unsigned char)*str)) {
00091         *val *= 10;
00092         *val += *str++ - '0';
00093     }
00094     return (char *)str;
00095 }
00096 
00109 char *TimeParseYear(CONST char *str, int *year)
00110 {
00111     str = parse_digits(str, year);
00112     if (*year < 70) {
00113         *year += 100;
00114     }
00115     else if (*year > 1900) {
00116         *year -= 1900;
00117     }
00118     return (char *)str;
00119 }
00120 
00135 char *TimeParseMonth(CONST char *str, int *month)
00136 {
00137     if (*str == 'A') {
00138         if (*++str == 'p' || *str == 'P') {
00139             /* April */
00140             *month = 3;
00141         }
00142         else {
00143             /* August */
00144             *month = 7;
00145         }
00146     }
00147     else if (*str == 'D') {
00148         /* December */
00149         *month = 11;
00150     }
00151     else if (*str == 'F') {
00152         /* February */
00153         *month = 1;
00154     }
00155     else if (*str == 'J') {
00156         if (*++str == 'a' || *str == 'A') {
00157             /* January */
00158             *month = 0;
00159         }
00160         else if (*str && (*++str == 'l' || *str == 'L')) {
00161             /* July */
00162             *month = 6;
00163         }
00164         else {
00165             /* June */
00166             *month = 5;
00167         }
00168     }
00169     else if (*str == 'M') {
00170         if (*++str == 'a' && (*++str == 'r' || *str == 'R')) {
00171             /* March */
00172             *month = 2;
00173         }
00174         else {
00175             /* May */
00176             *month = 4;
00177         }
00178     }
00179     else if (*str == 'N') {
00180         /* November */
00181         *month = 10;
00182     }
00183     else if (*str == 'O') {
00184         /* October */
00185         *month = 9;
00186     }
00187     else {
00188         /* September */
00189         *month = 8;
00190     }
00191     while (isalpha((unsigned char)*str)) {
00192         str++;
00193     }
00194     return (char *)str;
00195 }
00196 
00210 char *TimeParseDmy(CONST char *str, int *mday, int *mon, int *year)
00211 {
00212     str = parse_digits(str, mday);
00213     while (*str && !isalpha((unsigned char)*str)) {
00214         str++;
00215     }
00216     str = TimeParseMonth(str, mon);
00217     while (*str && !isdigit((unsigned char)*str)) {
00218         str++;
00219     }
00220     str = TimeParseYear(str, year);
00221 
00222     return (char *)str;
00223 }
00224 
00237 char *TimeParseHms(CONST char *str, int *hour, int *min, int *sec)
00238 {
00239     str = parse_digits(str, hour);
00240     if (*str == ':') {
00241         str = parse_digits(str + 1, min);
00242         if (*str == ':') {
00243             str = parse_digits(str + 1, sec);
00244         }
00245         else {
00246             *sec = 0;
00247         }
00248     }
00249     else {
00250         *min = 0;
00251     }
00252     return (char *)str;
00253 }
00254 
00264 time_t RfcTimeParse(CONST char *str)
00265 {
00266     struct _tm dts = { 0, 0, 0, 1, 0, 0, 0, 0, 0 };
00267 
00268     /* Skip leading whitespace. */
00269     str = skip_spaces(str);
00270 
00271     /* Skip weekday, optional in RFC 822. */
00272     if (isalpha((unsigned char)*str)) {
00273         while (*str && *str != ' ' && *str != '\t')
00274             str++;
00275         str = skip_spaces(str);
00276     }
00277 
00278     if (isalpha((unsigned char)*str)) {
00279         /* asctime format 'Fri Feb 2 2007 07:30:05'. */
00280         str = TimeParseMonth(str, &dts.tm_mon);
00281         str = skip_spaces(str);
00282         str = parse_digits(str, &dts.tm_mday);
00283         str = skip_spaces(str);
00284         str = TimeParseYear(str, &dts.tm_year);
00285         str = skip_spaces(str);
00286         str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec);
00287     }
00288     else if (*str) {
00289         /* RFC 850 'Friday, 02-Feb-2007 07:30:05 GMT'. */
00290         /* RFC 1123 'Fri, 02 Feb 2007 07:30:05 GMT'. */
00291         str = TimeParseDmy(str, &dts.tm_mday, &dts.tm_mon, &dts.tm_year);
00292         str = skip_spaces(str);
00293         str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec);
00294     }
00295     str = skip_spaces(str);
00296     if (strcmp(str, "GMT") == 0) {
00297         return mktime(&dts);
00298     }
00299     return _mkgmtime(&dts);
00300 }
00301 
00309 char *Rfc1123TimeString(struct _tm *tm)
00310 {
00311     sprintf(rfc1123_buf, "%s, %02d %s %04d %02d:%02d:%02d",
00312             wkdays[tm->tm_wday],
00313             tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
00314             tm->tm_hour, tm->tm_min, tm->tm_sec);
00315 
00316     return rfc1123_buf;
00317 }