diff --git a/macros/neon.m4 b/macros/neon.m4 index a7c739af..e7f6cb6d 100644 --- a/macros/neon.m4 +++ b/macros/neon.m4 @@ -675,7 +675,7 @@ NE_LARGEFILE AC_REPLACE_FUNCS(strcasecmp) AC_CHECK_FUNCS([signal setvbuf setsockopt stpcpy poll fcntl getsockopt \ - explicit_bzero sendmsg gettimeofday]) + explicit_bzero sendmsg gettimeofday gmtime_r]) if test "x${ac_cv_func_poll}${ac_cv_header_sys_poll_h}y" = "xyesyesy"; then AC_DEFINE([NE_USE_POLL], 1, [Define if poll() should be used]) diff --git a/src/ne_basic.c b/src/ne_basic.c index a7946736..37f4bf8b 100644 --- a/src/ne_basic.c +++ b/src/ne_basic.c @@ -436,7 +436,7 @@ static int copy_or_move(ne_session *sess, int is_move, int overwrite, { ne_request *req = ne_request_create( sess, is_move?"MOVE":"COPY", src ); - /* 2518 S8.9.2 says only use Depth: infinity with MOVE. */ + /* RFC4918ẞ9.9.2 - "Depth: infinity" is implicit for MOVE. */ if (!is_move) { ne_add_depth_header(req, depth); } @@ -476,7 +476,6 @@ int ne_move(ne_session *sess, int overwrite, return copy_or_move(sess, 1, overwrite, 0, src, dest); } -/* Deletes the specified resource. (and in only two lines of code!) */ int ne_delete(ne_session *sess, const char *path) { ne_request *req = ne_request_create(sess, "DELETE", path); @@ -486,14 +485,7 @@ int ne_delete(ne_session *sess, const char *path) ne_lock_using_parent(req, path); #endif - /* joe: I asked on the DAV WG list about whether we might get a - * 207 error back from a DELETE... conclusion, you shouldn't if - * you don't send the Depth header, since we might be an HTTP/1.1 - * client and a 2xx response indicates success to them. But - * it's all a bit unclear. In any case, DAV servers today do - * return 207 to DELETE even if we don't send the Depth header. - * So we handle 207 errors appropriately. */ - + /* Per RFC4918ẞ9.6.1 DELETE can get a 207 response. */ return ne_simple_request(sess, req); } diff --git a/src/ne_dates.c b/src/ne_dates.c index c82d7103..0835aa9c 100644 --- a/src/ne_dates.c +++ b/src/ne_dates.c @@ -49,8 +49,8 @@ #define ISO8601_FORMAT_M "%04d-%02d-%02dT%02d:%02d:%lf-%02d:%02d" #define ISO8601_FORMAT_P "%04d-%02d-%02dT%02d:%02d:%lf+%02d:%02d" -/* RFC1123: Sun, 06 Nov 1994 08:49:37 GMT */ -#define RFC1123_FORMAT "%3s, %02d %3s %4d %02d:%02d:%02d GMT" +/* IMF-fixdate: Sun, 06 Nov 1994 08:49:37 GMT */ +#define IMFFIX_FORMAT "%3s, %02d %3s %4d %02d:%02d:%02d GMT" /* RFC850: Sunday, 06-Nov-94 08:49:37 GMT */ #define RFC1036_FORMAT "%10s %2d-%3s-%2d %2d:%2d:%2d GMT" /* asctime: Wed Jun 30 21:49:08 1993 */ @@ -98,21 +98,28 @@ time_t gmt_to_local_win32(void) } #endif -/* Returns the time/date GMT, in RFC1123-type format: eg - * Sun, 06 Nov 1994 08:49:37 GMT. */ char *ne_rfc1123_date(time_t anytime) { - struct tm *gmt; + struct tm gmt; + struct tm *rv; char *ret; - gmt = gmtime(&anytime); - if (gmt == NULL) - return NULL; + +#ifdef HAVE_GMTIME_R +#warning fish + if ((rv = gmtime_r(&anytime, &gmt)) == NULL) + return NULL; +#else + if ((rv = gmtime(&anytime)) == NULL) + return NULL; + + gmt = *rv; +#endif + ret = ne_malloc(29 + 1); /* dates are 29 chars long */ -/* it goes: Sun, 06 Nov 1994 08:49:37 GMT */ - ne_snprintf(ret, 30, RFC1123_FORMAT, - rfc1123_weekdays[gmt->tm_wday], gmt->tm_mday, - short_months[gmt->tm_mon], 1900 + gmt->tm_year, - gmt->tm_hour, gmt->tm_min, gmt->tm_sec); - + ne_snprintf(ret, 30, IMFFIX_FORMAT, + rfc1123_weekdays[gmt.tm_wday], gmt.tm_mday, + short_months[gmt.tm_mon], 1900 + gmt.tm_year, + gmt.tm_hour, gmt.tm_min, gmt.tm_sec); + return ret; } @@ -161,8 +168,6 @@ time_t ne_iso8601_parse(const char *date) return result + GMTOFF(gmt); } -/* Takes an RFC1123-formatted date string and returns the time_t. - * Returns (time_t)-1 if the parse fails. */ time_t ne_rfc1123_parse(const char *date) { struct tm gmt = {0}; @@ -171,7 +176,7 @@ time_t ne_rfc1123_parse(const char *date) time_t result; /* it goes: Sun, 06 Nov 1994 08:49:37 GMT */ - if (sscanf(date, RFC1123_FORMAT, + if (sscanf(date, IMFFIX_FORMAT, wkday, &gmt.tm_mday, mon, &gmt.tm_year, &gmt.tm_hour, &gmt.tm_min, &gmt.tm_sec) != 7) return (time_t) -1; @@ -249,7 +254,6 @@ time_t ne_asctime_parse(const char *date) return result + GMTOFF(gmt); } -/* HTTP-date parser */ time_t ne_httpdate_parse(const char *date) { time_t tmp; diff --git a/src/ne_dates.h b/src/ne_dates.h index 484dfdf5..78e68c42 100644 --- a/src/ne_dates.h +++ b/src/ne_dates.h @@ -28,26 +28,35 @@ NE_BEGIN_DECLS -/* Date manipulation routines as per RFC1123 and RFC1036 */ - -/* Return current date/time in RFC1123 format */ -char *ne_rfc1123_date(time_t anytime); - -/* Returns time from date/time using the subset of the ISO8601 format - * referenced in RFC2518 (e.g as used in the creationdate property in - * the DAV: namespace). */ -time_t ne_iso8601_parse(const char *date); - -/* Returns time from date/time in RFC1123 format */ -time_t ne_rfc1123_parse(const char *date); - -time_t ne_rfc1036_parse(const char *date); - -/* Parses asctime date string */ -time_t ne_asctime_parse(const char *date); - -/* Parse an HTTP-date as per RFC2616 */ -time_t ne_httpdate_parse(const char *date); +/* Convert time to a string following the Internet Message Format RFC + * standard (historically known as "RFC1123", currently known as + * RFC5322). Returns a malloc-allocated string, or NULL if there is an + * error converting the time. */ +char *ne_rfc1123_date(time_t anytime) + ne_attribute_malloc; + +/* Parses a date/time using the the ISO8601 format. Returns -1 on + * error. */ +time_t ne_iso8601_parse(const char *date) + ne_attribute((nonnull)); + +/* Parses a date/time using the the IMF-fixdate format (historically + * known as "RFC1123". Returns -1 on error. */ +time_t ne_rfc1123_parse(const char *date) + ne_attribute((nonnull)); + +/* Parses a date/time using the the RFC1036 format. Returns -1 on + * error. */ +time_t ne_rfc1036_parse(const char *date) + ne_attribute((nonnull)); + +/* Parses a libc "asctime" format date. Returns -1 on error. */ +time_t ne_asctime_parse(const char *date) + ne_attribute((nonnull)); + +/* Parse an HTTP-date as perq RFC2616. Returns -1 on error. */ +time_t ne_httpdate_parse(const char *date) + ne_attribute((nonnull)); NE_END_DECLS diff --git a/test/util-tests.c b/test/util-tests.c index 4a8301f6..fd7cc193 100644 --- a/test/util-tests.c +++ b/test/util-tests.c @@ -26,6 +26,9 @@ #ifdef HAVE_STRING_H #include #endif +#ifdef HAVE_STDINT_H +#include +#endif #include "ne_utils.h" #include "ne_md5.h" @@ -254,6 +257,16 @@ static int bad_dates(void) BAD_DATE("asctime", ne_asctime_parse(dates[n])); } +#if SIZEOF_TIME_T == 8 && defined(INT64_MAX) + { + char *rv = ne_rfc1123_date(INT64_MAX); + + ONV(rv != NULL, + ("RFC1123 date conversion surprisingly worked for INT64_MAX: %s", + rv)); + } +#endif + return OK; }