📄 date.c
字号:
/* Parser of HTTP date *//* $Id: date.c,v 1.5.6.2 2005/05/10 12:56:27 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#ifdef TIME_WITH_SYS_TIME#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_TIME_H#include <time.h>#endif#else#if defined(TM_IN_SYS_TIME) && defined(HAVE_SYS_TIME_H)#include <sys/time.h>#elif defined(HAVE_TIME_H)#include <time.h>#endif#endif#include "elinks.h"#include "protocol/date.h"#include "util/conv.h"#include "util/ttime.h"/* * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format */intparse_year(const unsigned char **date_p, unsigned char *end){ const unsigned char *date = *date_p; int year; if ((end && date + 1 >= end) || !isdigit(date[0]) || !isdigit(date[1])) return -1; year = (date[0] - '0') * 10 + date[1] - '0'; if ((!end || date + 3 < end) && isdigit(date[2]) && isdigit(date[3])) { /* Four digits date */ year = year * 10 + date[2] - '0'; year = year * 10 + date[3] - '0' - 1900; date += 4; } else if (year < 70) { /* Assuming the epoch starting at 1.1.1970 so it's already next * century. --wget */ year += 100; date += 2; } *date_p = date; return year;}intparse_month(const unsigned char **buf, unsigned char *end){ const unsigned char *month = *buf; int monthnum; /* Check that the buffer has atleast 3 chars. */ if ((end && month + 2 > end) || !month[0] || !month[1] || !month[2]) return -1; monthnum = month2num(month); if (monthnum != -1) *buf += 3; return monthnum;}/* Return day number. */intparse_day(const unsigned char **date_p, unsigned char *end){ const unsigned char *date = *date_p; int day; if ((end && date >= end) || !isdigit(*date)) return 32; day = *date++ - '0'; if ((!end || date < end) && isdigit(*date)) { day = day * 10 + *date++ - '0'; } *date_p = date; return day;}intparse_time(const unsigned char **time, struct tm *tm, unsigned char *end){ unsigned char h1, h2, m1, m2; const unsigned char *date = *time;#define check_time(tm) \ ((tm)->tm_hour <= 23 && (tm)->tm_min <= 59 && (tm)->tm_sec <= 59) /* Eat HH:MM */ if (end && date + 5 > end) return 0; h1 = *date++; if (!isdigit(h1)) return 0; h2 = *date++; if (!isdigit(h2)) return 0; if (*date++ != ':') return 0; m1 = *date++; if (!isdigit(m1)) return 0; m2 = *date++; if (!isdigit(m2)) return 0; tm->tm_hour = (h1 - '0') * 10 + h2 - '0'; tm->tm_min = (m1 - '0') * 10 + m2 - '0'; /* Eat :SS or [PA]M or nothing */ if (end && date + 2 >= end) { *time = date; return check_time(tm); } if (*date == ':') { unsigned char s1, s2; date++; if (end && date + 2 >= end) return 0; s1 = *date++; if (!isdigit(s1)) return 0; s2 = *date++; if (!isdigit(s2)) return 0; tm->tm_sec = (s1 - '0') * 10 + s2 - '0'; } else if (*date == 'A' || *date == 'P') { /* Adjust hour from AM/PM. The sequence goes 11:00AM, 12:00PM, * 01:00PM ... 11:00PM, 12:00AM, 01:00AM. --wget */ if (tm->tm_hour == 12) tm->tm_hour = 0; if (*date++ == 'P') tm->tm_hour += 12; if (*date++ != 'M') return 0; } *time = date; return check_time(tm);}static time_tmy_timegm(struct tm *tm){ time_t t = 0; /* Okay, the next part of the code is somehow problematic. Now, we use * own code for calculating the number of seconds from 1.1.1970, * brought here by SC from w3m. I don't like it a lot, but it's 100% * portable, it's faster and it's shorter. --pasky */#if 0#ifdef HAVE_TIMEGM t = timegm(tm);#else /* Since mktime thinks we have localtime, we need a wrapper * to handle GMT. */ /* FIXME: It was reported that it doesn't work somewhere :/. */ { unsigned char *tz = getenv("TZ"); if (tz && *tz) { /* Temporary disable timezone in-place. */ unsigned char tmp = *tz; *tz = '\0'; tzset(); t = mktime(tm); *tz = tmp; tzset(); } else { /* Already GMT, cool! */ t = mktime(tm); } }#endif#else /* Following code was borrowed from w3m, and its developers probably * borrowed it from somewhere else as well, altough they didn't bother * to mention that. */ /* Actually, same code appears to be in lynx as * well.. oh well. :) */ /* See README.timegm for explanation about how this works. */ tm->tm_mon -= 2; if (tm->tm_mon < 0) { tm->tm_mon += 12; tm->tm_year--; } tm->tm_mon *= 153; tm->tm_mon += 2; tm->tm_year -= 68; tm->tm_mday += tm->tm_year * 1461 / 4; tm->tm_mday += ((tm->tm_mon / 5) - 672); t = ((tm->tm_mday * 60 * 60 * 24) + (tm->tm_hour * 60 * 60) + (tm->tm_min * 60) + tm->tm_sec);#endif if (t == (time_t) -1) return 0; return t;}ttimeparse_date(unsigned char **date_pos, unsigned char *end, int update_pos, int skip_week_day){#define skip_time_sep(date, end) \ do { \ const unsigned char *start = (date); \ while ((!(end) || (date) < (end)) \ && (*(date) == ' ' || *(date) == '-')) \ (date)++; \ if (date == start) return 0; \ } while (0) struct tm tm; const unsigned char *date = (const unsigned char *) *date_pos; if (!date) return 0; if (skip_week_day) { /* Skip day-of-week */ for (; (!end || date < end) && *date != ' '; date++) if (!*date) return 0; /* As pasky said who cares if we allow '-'s here? */ skip_time_sep(date, end); } if (isdigit(*date)) { /* RFC 1036 / RFC 1123 */ /* Eat day */ /* date++; */ tm.tm_mday = parse_day(&date, end); if (tm.tm_mday > 31) return 0; skip_time_sep(date, end); /* Eat month */ tm.tm_mon = parse_month(&date, end); if (tm.tm_mon < 0) return 0; skip_time_sep(date, end); /* Eat year */ tm.tm_year = parse_year(&date, end); if (tm.tm_year < 0) return 0; skip_time_sep(date, end); /* Eat time */ if (!parse_time(&date, &tm, end)) return 0; } else { /* ANSI C's asctime() format */ /* Eat month */ tm.tm_mon = parse_month(&date, end); if (tm.tm_mon < 0) return 0; /* I know, we shouldn't allow '-', but who cares ;). --pasky */ skip_time_sep(date, end); /* Eat day */ tm.tm_mday = parse_day(&date, end); if (tm.tm_mday > 31) return 0; skip_time_sep(date, end); /* Eat time */ if (!parse_time(&date, &tm, end)) return 0; skip_time_sep(date, end); /* Eat year */ tm.tm_year = parse_year(&date, end); if (tm.tm_year < 0) return 0; }#undef skip_time_sep if (update_pos) *date_pos = (unsigned char *) date; return (ttime) my_timegm(&tm);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -