From 8c56e6dfc36495a97ef784aaf626f7a843860903 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Mon, 20 Dec 1999 16:38:39 +0000 Subject: [PATCH] First step in getting Apache to use APR's time libraries. This gets a good number of them, but I think there are more time values still in the Apache code. This works under Linux, but has not been tested anywhere else. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84338 13f79535-47bb-0310-9956-ffa450edef68 --- include/http_protocol.h | 2 +- include/http_request.h | 2 +- include/httpd.h | 11 ++-- include/util_date.h | 3 +- modules/filters/mod_include.c | 26 +++++++-- modules/http/http_core.c | 6 +- modules/http/http_protocol.c | 68 +++++++++++++++------- modules/http/http_request.c | 4 +- modules/loggers/mod_log_config.c | 8 ++- modules/mappers/mod_negotiation.c | 6 +- server/util.c | 76 +++---------------------- server/util_date.c | 95 +++++++++++++++++-------------- server/util_script.c | 2 +- 13 files changed, 154 insertions(+), 155 deletions(-) diff --git a/include/http_protocol.h b/include/http_protocol.h index 24dae34ec1..bb6cd99d73 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -118,7 +118,7 @@ API_EXPORT(void) ap_send_error_response(request_rec *r, int recursive_error); API_EXPORT(int) ap_set_content_length(request_rec *r, long length); API_EXPORT(int) ap_set_keepalive(request_rec *r); -API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime); +API_EXPORT(ap_time_t *) ap_rationalize_mtime(request_rec *r, ap_time_t *mtime); API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak); API_EXPORT(void) ap_set_etag(request_rec *r); API_EXPORT(void) ap_set_last_modified(request_rec *r); diff --git a/include/http_request.h b/include/http_request.h index bf66f868b2..ed51f915fe 100644 --- a/include/http_request.h +++ b/include/http_request.h @@ -104,7 +104,7 @@ API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *); API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *); API_EXPORT(int) ap_some_auth_required(request_rec *r); API_EXPORT(int) ap_is_initial_req(request_rec *r); -API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime); +API_EXPORT(ap_time_t *) ap_update_mtime(request_rec *r, ap_time_t *dependency_mtime); #ifdef CORE_PRIVATE /* Function called by main.c to handle first-level request */ diff --git a/include/httpd.h b/include/httpd.h index a3b816aa52..7f39de0a3a 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -71,6 +71,7 @@ extern "C" { #include "ap_config.h" #include "apr_general.h" #include "apr_lib.h" +#include "apr_time.h" #include "buff.h" #include "ap.h" @@ -667,7 +668,7 @@ struct request_rec { int proto_num; /* Number version of protocol; 1.1 = 1001 */ const char *hostname; /* Host, as set by full URI or Host: */ - time_t request_time; /* When the request started */ + ap_time_t *request_time; /* When the request started */ const char *status_line; /* Status line, if set by script */ int status; /* In any case */ @@ -703,7 +704,7 @@ struct request_rec { int sent_bodyct; /* byte count in stream is for body */ long bytes_sent; /* body byte count, for easy access */ - time_t mtime; /* Time the resource was last modified */ + ap_time_t *mtime; /* Time the resource was last modified */ /* HTTP/1.1 connection-level features */ @@ -913,14 +914,10 @@ struct server_rec { */ /* Time */ -extern API_VAR_EXPORT const char ap_month_snames[12][4]; -extern API_VAR_EXPORT const char ap_day_snames[7][4]; - API_EXPORT(struct tm *) ap_get_gmtoff(int *tz); API_EXPORT(char *) ap_get_time(void); API_EXPORT(char *) ap_field_noparam(ap_context_t *p, const char *intype); -API_EXPORT(char *) ap_ht_time(ap_context_t *p, time_t t, const char *fmt, int gmt); -API_EXPORT(char *) ap_gm_timestr_822(ap_context_t *p, time_t t); +API_EXPORT(char *) ap_ht_time(ap_context_t *p, ap_time_t *t, const char *fmt, int gmt); /* String handling. The *_nc variants allow you to use non-const char **s as arguments (unfortunately C won't automatically convert a char ** to a const diff --git a/include/util_date.h b/include/util_date.h index 8e2051024e..0504e5e5fd 100644 --- a/include/util_date.h +++ b/include/util_date.h @@ -71,12 +71,13 @@ extern "C" { #include #endif #include +#include "apr_time.h" #define BAD_DATE (time_t)0 API_EXPORT(int) ap_checkmask(const char *data, const char *mask); API_EXPORT(time_t) ap_tm2sec(const struct tm *t); -API_EXPORT(time_t) ap_parseHTTPdate(const char *date); +API_EXPORT(ap_time_t *) ap_parseHTTPdate(const char *date, ap_context_t *cont); #ifdef __cplusplus } diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index 984ddd99da..ecb577b211 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -124,12 +124,16 @@ static void add_include_vars(request_rec *r, char *timefmt) #endif /* ndef WIN32 */ ap_table_t *e = r->subprocess_env; char *t; - time_t date = r->request_time; + ap_time_t *date = r->request_time; + ap_time_t *mtime = NULL; + + ap_make_time(&mtime, r->pool); + ap_set_curtime(mtime, r->finfo.st_mtime); ap_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0)); ap_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1)); ap_table_setn(e, "LAST_MODIFIED", - ap_ht_time(r->pool, r->finfo.st_mtime, timefmt, 0)); + ap_ht_time(r->pool, mtime, timefmt, 0)); ap_table_setn(e, "DOCUMENT_URI", r->uri); ap_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info); #ifndef WIN32 @@ -1021,13 +1025,17 @@ static int handle_config(ap_file_t *in, request_rec *r, char *error, char *tf, parse_string(r, tag_val, error, MAX_STRING_LEN, 0); } else if (!strcmp(tag, "timefmt")) { - time_t date = r->request_time; + ap_time_t *date = r->request_time; + ap_time_t *mtime = NULL; + + ap_make_time(&mtime, r->pool); + ap_set_curtime(mtime, r->finfo.st_mtime); parse_string(r, tag_val, tf, MAX_STRING_LEN, 0); ap_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, tf, 0)); ap_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, tf, 1)); ap_table_setn(env, "LAST_MODIFIED", - ap_ht_time(r->pool, r->finfo.st_mtime, tf, 0)); + ap_ht_time(r->pool, mtime, tf, 0)); } else if (!strcmp(tag, "sizefmt")) { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); @@ -1168,6 +1176,7 @@ static int handle_flastmod(ap_file_t *in, request_rec *r, const char *error, con char *tag_val; struct stat finfo; char parsed_string[MAX_STRING_LEN]; + ap_time_t *mtime = NULL; while (1) { if (!(tag_val = get_tag(r->pool, in, tag, sizeof(tag), 1))) { @@ -1179,7 +1188,9 @@ static int handle_flastmod(ap_file_t *in, request_rec *r, const char *error, con else { parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0); if (!find_file(r, "flastmod", tag, parsed_string, &finfo, error)) { - ap_rputs(ap_ht_time(r->pool, finfo.st_mtime, tf, 0), r); + ap_make_time(&mtime, r->pool); + ap_set_curtime(mtime, finfo.st_mtime); + ap_rputs(ap_ht_time(r->pool, mtime, tf, 0), r); } } } @@ -2341,6 +2352,7 @@ static int send_parsed_file(request_rec *r) (enum xbithack *) ap_get_module_config(r->per_dir_config, &includes_module); int errstatus; request_rec *parent; + ap_time_t *mtime = NULL; if (!(ap_allow_options(r) & OPT_INCLUDES)) { return DECLINED; @@ -2372,7 +2384,9 @@ static int send_parsed_file(request_rec *r) && (r->finfo.st_mode & S_IXGRP) #endif ) { - ap_update_mtime(r, r->finfo.st_mtime); + ap_make_time(&mtime, r->pool); + ap_set_curtime(mtime, r->finfo.st_mtime); + ap_update_mtime(r, mtime); ap_set_last_modified(r); } if ((errstatus = ap_meets_conditions(r)) != OK) { diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 9129eaf684..8bc42d3f60 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -2453,6 +2453,7 @@ static int default_handler(request_rec *r) { core_dir_config *d = (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); + ap_time_t *temp; int rangestatus, errstatus; ap_file_t *fd = NULL; ap_status_t status; @@ -2506,8 +2507,9 @@ static int default_handler(request_rec *r) "file permissions deny server access: %s", r->filename); return FORBIDDEN; } - - ap_update_mtime(r, r->finfo.st_mtime); + ap_make_time(&temp, r->pool); + ap_set_curtime(temp, r->finfo.st_mtime); + ap_update_mtime(r, temp); ap_set_last_modified(r); ap_set_etag(r); ap_table_setn(r->headers_out, "Accept-Ranges", "bytes"); diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 21a1bac48d..0e53623bb5 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -368,9 +368,9 @@ API_EXPORT(int) ap_set_keepalive(request_rec *r) * to limit the number of calls to time(). We don't check for futurosity * unless the mtime is at least as new as the reference. */ -API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime) +API_EXPORT(ap_time_t *) ap_rationalize_mtime(request_rec *r, ap_time_t *mtime) { - time_t now; + ap_time_t *now; /* For all static responses, it's almost certain that the file was * last modified before the beginning of the request. So there's @@ -381,15 +381,26 @@ API_EXPORT(time_t) ap_rationalize_mtime(request_rec *r, time_t mtime) * were given a time in the future, we return the current time - the * Last-Modified can't be in the future. */ - now = (mtime < r->request_time) ? r->request_time : time(NULL); - return (mtime > now) ? now : mtime; + if (ap_timecmp(mtime, r->request_time) == APR_LESS) { + now = r->request_time; + } + else { + ap_make_time(&now, r->pool); + ap_current_time(now); + } + if (ap_timecmp(mtime, now) == APR_MORE) { + return now; + } + else { + return mtime; + } } API_EXPORT(int) ap_meets_conditions(request_rec *r) { const char *etag = ap_table_get(r->headers_out, "ETag"); const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch; - time_t mtime; + ap_time_t *mtime; /* Check for conditional requests --- note that we only want to do * this if we are successful so far and we are not processing a @@ -406,7 +417,13 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r) return OK; } - mtime = (r->mtime != 0) ? r->mtime : time(NULL); + if (r->mtime == NULL) { + ap_make_time(&mtime, r->pool); + ap_current_time(mtime); + } + else { + mtime = r->mtime; + } /* If an If-Match request-header field was given * AND the field value is not "*" (meaning match anything) @@ -428,9 +445,9 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r) */ if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since"); if (if_unmodified != NULL) { - time_t ius = ap_parseHTTPdate(if_unmodified); + ap_time_t *ius = ap_parseHTTPdate(if_unmodified, r->pool); - if ((ius != BAD_DATE) && (mtime > ius)) { + if ((ius != NULL) && (ap_timecmp(mtime, ius) == APR_MORE)) { return HTTP_PRECONDITION_FAILED; } } @@ -481,9 +498,10 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r) else if ((r->method_number == M_GET) && ((if_modified_since = ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) { - time_t ims = ap_parseHTTPdate(if_modified_since); + ap_time_t *ims = ap_parseHTTPdate(if_modified_since, r->pool); - if ((ims >= mtime) && (ims <= r->request_time)) { + if (!ap_timecmp(ims, mtime) < APR_LESS && + !ap_timecmp(ims, r->request_time) > APR_MORE) { return HTTP_NOT_MODIFIED; } } @@ -501,6 +519,7 @@ API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak) { char *etag; char *weak; + int diff; /* * Make an ETag header out of various pieces of information. We use @@ -515,7 +534,8 @@ API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak) * would be incorrect. */ - weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/"; + ap_timediff(r->request_time, r->mtime, &diff); + weak = ((diff > 1) && !force_weak) ? "" : "W/"; if (r->finfo.st_mode != 0) { etag = ap_psprintf(r->pool, @@ -583,10 +603,10 @@ API_EXPORT(void) ap_set_etag(request_rec *r) */ API_EXPORT(void) ap_set_last_modified(request_rec *r) { - time_t mod_time = ap_rationalize_mtime(r, r->mtime); - - ap_table_setn(r->headers_out, "Last-Modified", - ap_gm_timestr_822(r->pool, mod_time)); + ap_time_t *mod_time = ap_rationalize_mtime(r, r->mtime); + char *datestr; + ap_gm_timestr_822(&datestr, mod_time, r->pool); + ap_table_setn(r->headers_out, "Last-Modified", datestr); } /* Get the method number associated with the given string, assumed to @@ -802,7 +822,7 @@ static int read_request_line(request_rec *r) /* this is a hack to make sure that request time is set, * it's not perfect, but it's better than nothing */ - r->request_time = time(0); + ap_current_time(r->request_time); return 0; } } @@ -821,7 +841,7 @@ static int read_request_line(request_rec *r) /* //ap_bsetflag(conn->client, B_SAFEREAD, 0); */ - r->request_time = time(NULL); + ap_current_time(r->request_time); r->the_request = ap_pstrdup(r->pool, l); r->method = ap_getword_white(r->pool, &ll); ap_update_connection_status(conn->id, "Method", r->method); @@ -955,6 +975,8 @@ request_rec *ap_read_request(conn_rec *conn) r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */ r->the_request = NULL; + ap_make_time(&r->request_time, r->pool); + ap_make_time(&r->mtime, r->pool); #ifdef CHARSET_EBCDIC ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1); @@ -1306,6 +1328,7 @@ API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r, API_EXPORT(void) ap_basic_http_header(request_rec *r) { char *protocol; + char *date = NULL; #ifdef CHARSET_EBCDIC int convert = ap_bgetflag(r->connection->client, B_EBCDIC2ASCII); #endif /*CHARSET_EBCDIC*/ @@ -1337,7 +1360,8 @@ API_EXPORT(void) ap_basic_http_header(request_rec *r) ap_rvputs(r, protocol, " ", r->status_line, "\015\012", NULL); - ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time)); + ap_gm_timestr_822(&date, r->request_time, r->pool); + ap_send_header_field(r, "Date", date); ap_send_header_field(r, "Server", ap_get_server_version()); ap_table_unset(r->headers_out, "Date"); /* Avoid bogosity */ @@ -1545,6 +1569,7 @@ API_EXPORT(void) ap_send_http_header(request_rec *r) { int i; const long int zero = 0L; + char *date = NULL; #ifdef CHARSET_EBCDIC int convert = ap_bgetflag(r->connection->client, B_EBCDIC2ASCII); #endif /*CHARSET_EBCDIC*/ @@ -1617,9 +1642,10 @@ API_EXPORT(void) ap_send_http_header(request_rec *r) * Control cachability for non-cachable responses if not already set by * some other part of the server configuration. */ - if (r->no_cache && !ap_table_get(r->headers_out, "Expires")) - ap_table_addn(r->headers_out, "Expires", - ap_gm_timestr_822(r->pool, r->request_time)); + if (r->no_cache && !ap_table_get(r->headers_out, "Expires")) { + ap_gm_timestr_822(&date, r->request_time, r->pool); + ap_table_addn(r->headers_out, "Expires", date); + } /* Send the entire ap_table_t of header fields, terminated by an empty line. */ diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 5c7cacfc17..76904bfc2d 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -1374,9 +1374,9 @@ API_EXPORT(int) ap_is_initial_req(request_rec *r) * Function to set the r->mtime field to the specified value if it's later * than what's already there. */ -API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime) +API_EXPORT(ap_time_t *) ap_update_mtime(request_rec *r, ap_time_t *dependency_mtime) { - if (r->mtime < dependency_mtime) { + if (ap_timecmp(r->mtime, dependency_mtime) == APR_LESS) { r->mtime = dependency_mtime; } return r->mtime; diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 4d173862e6..7debb7977e 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -406,7 +406,13 @@ static const char *log_request_time(request_rec *r, char *a) static const char *log_request_duration(request_rec *r, char *a) { - return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time); + ap_time_t *currtime = NULL; + ap_int32_t diff; + ap_make_time(&currtime, r->pool); + ap_current_time(currtime); + + ap_timediff(currtime, r->request_time, &diff); + return ap_psprintf(r->pool, "%ld", diff); } /* These next two routines use the canonical name:port so that log diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c index 162c9971bf..3d69d4564f 100644 --- a/modules/mappers/mod_negotiation.c +++ b/modules/mappers/mod_negotiation.c @@ -284,13 +284,15 @@ static void set_mime_fields(var_rec *var, accept_rec *mime_info) static void set_vlist_validator(request_rec *r, request_rec *vlistr) { + ap_time_t *temp; /* Calculating the variant list validator is similar to * calculating an etag for the source of the variant list * information, so we use ap_make_etag(). Note that this * validator can be 'weak' in extreme case. */ - - ap_update_mtime (vlistr, vlistr->finfo.st_mtime); + ap_make_time(&temp, vlistr->pool); + ap_set_curtime(temp, vlistr->finfo.st_mtime); + ap_update_mtime(vlistr, temp); r->vlist_validator = ap_make_etag(vlistr, 0); /* ap_set_etag will later take r->vlist_validator into account diff --git a/server/util.c b/server/util.c index 28d45b1b79..666d54a6c1 100644 --- a/server/util.c +++ b/server/util.c @@ -92,15 +92,6 @@ extern int fclose(FILE *); */ #define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f)) -API_VAR_EXPORT const char ap_month_snames[12][4] = -{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; -API_VAR_EXPORT const char ap_day_snames[7][4] = -{ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - API_EXPORT(char *) ap_get_time() { time_t t; @@ -132,13 +123,17 @@ API_EXPORT(char *) ap_field_noparam(ap_context_t *p, const char *intype) } } -API_EXPORT(char *) ap_ht_time(ap_context_t *p, time_t t, const char *fmt, int gmt) +API_EXPORT(char *) ap_ht_time(ap_context_t *p, ap_time_t *t, const char *fmt, int gmt) { char ts[MAX_STRING_LEN]; char tf[MAX_STRING_LEN]; - struct tm *tms; - tms = (gmt ? gmtime(&t) : localtime(&t)); + if (gmt) { + ap_explode_time(t, APR_UTCTIME); + } + else { + ap_explode_time(t, APR_LOCALTIME); + } if(gmt) { /* Convert %Z to "GMT" and %z to "+0000"; * on hosts that do not have a time zone string in struct tm, @@ -174,66 +169,11 @@ API_EXPORT(char *) ap_ht_time(ap_context_t *p, time_t t, const char *fmt, int gm } /* check return code? */ - strftime(ts, MAX_STRING_LEN, fmt, tms); + ap_strftime(ts, MAX_STRING_LEN, fmt, t); ts[MAX_STRING_LEN - 1] = '\0'; return ap_pstrdup(p, ts); } -API_EXPORT(char *) ap_gm_timestr_822(ap_context_t *p, time_t sec) -{ - struct tm *tms; - char *date_str = ap_palloc(p, 48 * sizeof(char)); - char *date_str_ptr = date_str; - int real_year; - - tms = gmtime(&sec); - - /* Assumption: this is always 3 */ - /* i = strlen(ap_day_snames[tms->tm_wday]); */ - memcpy(date_str_ptr, ap_day_snames[tms->tm_wday], 3); - date_str_ptr += 3; - *date_str_ptr++ = ','; - *date_str_ptr++ = ' '; - *date_str_ptr++ = tms->tm_mday / 10 + '0'; - *date_str_ptr++ = tms->tm_mday % 10 + '0'; - *date_str_ptr++ = ' '; - /* Assumption: this is also always 3 */ - /* i = strlen(ap_month_snames[tms->tm_mon]); */ - memcpy(date_str_ptr, ap_month_snames[tms->tm_mon], 3); - date_str_ptr += 3; - *date_str_ptr++ = ' '; - real_year = 1900 + tms->tm_year; - /* This routine isn't y10k ready. */ - *date_str_ptr++ = real_year / 1000 + '0'; - *date_str_ptr++ = real_year % 1000 / 100 + '0'; - *date_str_ptr++ = real_year % 100 / 10 + '0'; - *date_str_ptr++ = real_year % 10 + '0'; - *date_str_ptr++ = ' '; - *date_str_ptr++ = tms->tm_hour / 10 + '0'; - *date_str_ptr++ = tms->tm_hour % 10 + '0'; - *date_str_ptr++ = ':'; - *date_str_ptr++ = tms->tm_min / 10 + '0'; - *date_str_ptr++ = tms->tm_min % 10 + '0'; - *date_str_ptr++ = ':'; - *date_str_ptr++ = tms->tm_sec / 10 + '0'; - *date_str_ptr++ = tms->tm_sec % 10 + '0'; - *date_str_ptr++ = ' '; - *date_str_ptr++ = 'G'; - *date_str_ptr++ = 'M'; - *date_str_ptr++ = 'T'; - *date_str_ptr = '\0'; - - return date_str; - /* RFC date format; as strftime '%a, %d %b %Y %T GMT' */ - - /* The equivalent using sprintf. Use this for more legible but slower code - return ap_psprintf(p, - "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[tms->tm_wday], - tms->tm_mday, ap_month_snames[tms->tm_mon], tms->tm_year + 1900, - tms->tm_hour, tms->tm_min, tms->tm_sec); - */ -} - /* What a pain in the ass. */ #if defined(HAVE_GMTOFF) API_EXPORT(struct tm *) ap_get_gmtoff(int *tz) diff --git a/server/util_date.c b/server/util_date.c index 5fb04c013b..78a57af5d4 100644 --- a/server/util_date.c +++ b/server/util_date.c @@ -214,11 +214,16 @@ API_EXPORT(time_t) ap_tm2sec(const struct tm * t) * but many changes since then. * */ -API_EXPORT(time_t) ap_parseHTTPdate(const char *date) +API_EXPORT(ap_time_t *) ap_parseHTTPdate(const char *date, ap_context_t *cont) { - struct tm ds; + ap_int32_t year; + ap_int32_t mday; + ap_int32_t hour; + ap_int32_t min; + ap_int32_t sec; int mint, mon; const char *monstr, *timstr; + ap_time_t *temp; static const int months[12] = { ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b', @@ -229,93 +234,99 @@ API_EXPORT(time_t) ap_parseHTTPdate(const char *date) ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'}; if (!date) - return BAD_DATE; + return NULL; while (*date && ap_isspace(*date)) /* Find first non-whitespace char */ ++date; if (*date == '\0') - return BAD_DATE; + return NULL; if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */ - return BAD_DATE; + return NULL; ++date; /* Now pointing to first char after space, which should be */ /* start of the actual date information for all 3 formats. */ if (ap_checkmask(date, "## @$$ #### ##:##:## *")) { /* RFC 1123 format */ - ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100; - if (ds.tm_year < 0) - return BAD_DATE; + year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100; + if (year < 0) + return NULL; - ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0'); + year += ((date[9] - '0') * 10) + (date[10] - '0'); - ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0'); + mday = ((date[0] - '0') * 10) + (date[1] - '0'); monstr = date + 3; timstr = date + 12; } else if (ap_checkmask(date, "##-@$$-## ##:##:## *")) { /* RFC 850 format */ - ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0'); - if (ds.tm_year < 70) - ds.tm_year += 100; + year = ((date[7] - '0') * 10) + (date[8] - '0'); + if (year < 70) + year += 100; - ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0'); + mday = ((date[0] - '0') * 10) + (date[1] - '0'); monstr = date + 3; timstr = date + 10; } else if (ap_checkmask(date, "@$$ ~# ##:##:## ####*")) { /* asctime format */ - ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100; - if (ds.tm_year < 0) - return BAD_DATE; + year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100; + if (year < 0) + return NULL; - ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0'); + year += ((date[18] - '0') * 10) + (date[19] - '0'); if (date[4] == ' ') - ds.tm_mday = 0; + mday = 0; else - ds.tm_mday = (date[4] - '0') * 10; + mday = (date[4] - '0') * 10; - ds.tm_mday += (date[5] - '0'); + mday += (date[5] - '0'); monstr = date; timstr = date + 7; } else - return BAD_DATE; + return NULL; - if (ds.tm_mday <= 0 || ds.tm_mday > 31) - return BAD_DATE; + if (mday <= 0 || mday > 31) + return NULL; - ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0'); - ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0'); - ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0'); + hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0'); + min = ((timstr[3] - '0') * 10) + (timstr[4] - '0'); + sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0'); - if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61)) - return BAD_DATE; + if ((hour > 23) || (min > 59) || (sec > 61)) + return NULL; mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2]; for (mon = 0; mon < 12; mon++) if (mint == months[mon]) break; if (mon == 12) - return BAD_DATE; + return NULL; - if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10)) - return BAD_DATE; + if ((mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10)) + return NULL; /* February gets special check for leapyear */ if ((mon == 1) && - ((ds.tm_mday > 29) - || ((ds.tm_mday == 29) - && ((ds.tm_year & 3) - || (((ds.tm_year % 100) == 0) - && (((ds.tm_year % 400) != 100))))))) - return BAD_DATE; - - ds.tm_mon = mon; - - return ap_tm2sec(&ds); + ((mday > 29) + || ((mday == 29) + && ((year & 3) + || (((year % 100) == 0) + && (((year % 400) != 100))))))) + return NULL; + + ap_make_time(&temp, cont); + ap_set_year(temp, year); + ap_set_mday(temp, mday); + ap_set_hour(temp, hour); + ap_set_min(temp, min); + ap_set_sec(temp, sec); + ap_set_mon(temp, mon); + + return temp; } diff --git a/server/util_script.c b/server/util_script.c index b38216e6ff..5de8b74a12 100644 --- a/server/util_script.c +++ b/server/util_script.c @@ -589,7 +589,7 @@ API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer, * pass it on blindly because of restrictions on future values. */ else if (!strcasecmp(w, "Last-Modified")) { - time_t mtime = ap_parseHTTPdate(l); + ap_time_t *mtime = ap_parseHTTPdate(l, r->pool); ap_update_mtime(r, mtime); ap_set_last_modified(r); -- 2.40.0