evolution-data-server r9016 - trunk/camel



Author: fejj
Date: Sat Jun 21 13:21:10 2008
New Revision: 9016
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=9016&view=rev

Log:
2008-06-21  Jeffrey Stedfast  <fejj novell com>

	* broken-date-parser.[c,h]: Removed, more-or-less moved into
	camel-mime-utils.c (this code was basically the same as the GMime
	date parser code except that it might not have been as
	up-to-date).

	* camel-mime-utils.c (camel_header_decode_date): Copy/pasted
	GMime's decode_date() code to replace really nasty code.



Removed:
   trunk/camel/broken-date-parser.c
   trunk/camel/broken-date-parser.h
Modified:
   trunk/camel/ChangeLog
   trunk/camel/Makefile.am
   trunk/camel/camel-file-utils.c
   trunk/camel/camel-mime-utils.c

Modified: trunk/camel/Makefile.am
==============================================================================
--- trunk/camel/Makefile.am	(original)
+++ trunk/camel/Makefile.am	Sat Jun 21 13:21:10 2008
@@ -149,7 +149,6 @@
 	$(REGEX_LIBS)
 
 libcamel_1_2_la_SOURCES = 			\
-	broken-date-parser.c			\
 	camel-address.c				\
 	camel-arg.c				\
 	camel-block-file.c			\
@@ -220,7 +219,6 @@
 	$(LIBCAMEL_PLATFORM_DEP_SOURCES)
 
 libcamelinclude_HEADERS =			\
-	broken-date-parser.h			\
 	camel-address.h				\
 	camel-arg.h				\
 	camel-block-file.h			\
@@ -356,7 +354,6 @@
 	fi
 
 noinst_HEADERS =				\
-	broken-date-parser.h			\
 	camel-charset-map-private.h		\
 	camel-private.h				
 

Modified: trunk/camel/camel-file-utils.c
==============================================================================
--- trunk/camel/camel-file-utils.c	(original)
+++ trunk/camel/camel-file-utils.c	Sat Jun 21 13:21:10 2008
@@ -56,7 +56,7 @@
  * 
  * Utility function to save an uint32 to a file.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_encode_uint32 (FILE *out, guint32 value)
@@ -81,7 +81,7 @@
  * 
  * Retrieve an encoded uint32 from a file.
  * 
- * Return value: 0 on success, -1 on error.  @*dest will contain the
+ * Return value: %0 on success, %-1 on error.  @*dest will contain the
  * decoded value.
  **/
 int
@@ -113,7 +113,7 @@
  * Encode a gint32, performing no compression, but converting
  * to network order.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_encode_fixed_int32 (FILE *out, gint32 value)
@@ -134,7 +134,7 @@
  * 
  * Retrieve a gint32.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest)
@@ -188,7 +188,7 @@
  * 
  * Encode a time_t value to the file.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 CFU_ENCODE_T(time_t)
 
@@ -199,7 +199,7 @@
  * 
  * Decode a time_t value.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 CFU_DECODE_T(time_t)
 
@@ -210,7 +210,7 @@
  * 
  * Encode an off_t type.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 CFU_ENCODE_T(off_t)
 
@@ -222,7 +222,7 @@
  * 
  * Decode an off_t type.
  * 
- * Return value: 0 on success, -1 on failure.
+ * Return value: %0 on success, %-1 on failure.
  **/
 CFU_DECODE_T(off_t)
 
@@ -233,7 +233,7 @@
  * 
  * Encode an size_t type.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 CFU_ENCODE_T(size_t)
 
@@ -245,7 +245,7 @@
  * 
  * Decode an size_t type.
  * 
- * Return value: 0 on success, -1 on failure.
+ * Return value: %0 on success, %-1 on failure.
  **/
 CFU_DECODE_T(size_t)
 
@@ -257,7 +257,7 @@
  * 
  * Encode a normal string and save it in the output file.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_encode_string (FILE *out, const char *str)
@@ -285,7 +285,7 @@
  * 
  * Decode a normal string from the input file.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_decode_string (FILE *in, char **str)
@@ -326,7 +326,7 @@
  * Unlike @camel_file_util_encode_string, it pads the
  * @str with "NULL" bytes, if @len is > strlen(str)
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_encode_fixed_string (FILE *out, const char *str, size_t len)
@@ -359,7 +359,7 @@
  * 
  * Decode a normal string from the input file.
  * 
- * Return value: 0 on success, -1 on error.
+ * Return value: %0 on success, %-1 on error.
  **/
 int
 camel_file_util_decode_fixed_string (FILE *in, char **str, size_t len)

Modified: trunk/camel/camel-mime-utils.c
==============================================================================
--- trunk/camel/camel-mime-utils.c	(original)
+++ trunk/camel/camel-mime-utils.c	Sat Jun 21 13:21:10 2008
@@ -52,8 +52,6 @@
 #include "camel-net-utils.h"
 #include "camel-utf8.h"
 
-#include "broken-date-parser.h"
-
 #ifdef G_OS_WIN32
 /* Undef the similar macro from pthread.h, it doesn't check if
  * gmtime() returns NULL.
@@ -3616,6 +3614,43 @@
 	return ret;
 }
 
+
+/* date parser macros */
+#define NUMERIC_CHARS          "1234567890"
+#define WEEKDAY_CHARS          "SundayMondayTuesdayWednesdayThursdayFridaySaturday"
+#define MONTH_CHARS            "JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember"
+#define TIMEZONE_ALPHA_CHARS   "UTCGMTESTEDTCSTCDTMSTPSTPDTZAMNY()"
+#define TIMEZONE_NUMERIC_CHARS "-+1234567890"
+#define TIME_CHARS             "1234567890:"
+
+#define DATE_TOKEN_NON_NUMERIC          (1 << 0)
+#define DATE_TOKEN_NON_WEEKDAY          (1 << 1)
+#define DATE_TOKEN_NON_MONTH            (1 << 2)
+#define DATE_TOKEN_NON_TIME             (1 << 3)
+#define DATE_TOKEN_HAS_COLON            (1 << 4)
+#define DATE_TOKEN_NON_TIMEZONE_ALPHA   (1 << 5)
+#define DATE_TOKEN_NON_TIMEZONE_NUMERIC (1 << 6)
+#define DATE_TOKEN_HAS_SIGN             (1 << 7)
+
+static unsigned char camel_datetok_table[256] = {
+	128,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111, 79, 79,111,175,111,175,111,111,
+	 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,119,111,111,111,111,111,
+	111, 75,111, 79, 75, 79,105, 79,111,111,107,111,111, 73, 75,107,
+	 79,111,111, 73, 77, 79,111,109,111, 79, 79,111,111,111,111,111,
+	111,105,107,107,109,105,111,107,105,105,111,111,107,107,105,105,
+	107,111,105,105,105,105,107,111,111,105,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+	111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+};
+
 /* hrm, is there a library for this shit? */
 static struct {
 	char *name;
@@ -3638,172 +3673,526 @@
 	{ "Y", 1200 },
 };
 
-static const char tz_months [][4] = {
+static const char tm_months [][4] = {
 	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
 	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
 
-static const char tz_days [][4] = {
+static const char tm_days [][4] = {
 	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 };
 
+
+/**
+ * camel_header_format_date:
+ * @date: time_t date representation
+ * @tz_offset: Timezone offset
+ *
+ * Allocates a string buffer containing the rfc822 formatted date
+ * string represented by @time and @tz_offset.
+ *
+ * Return value: a valid string representation of the date.
+ **/
 char *
-camel_header_format_date(time_t time, int offset)
+camel_header_format_date (time_t date, int tz_offset)
 {
 	struct tm tm;
+	
+	d(printf("offset = %d\n", tz_offset));
+	
+	d(printf("converting date %s", ctime(&date)));
+	
+	date += ((tz_offset / 100) * (60 * 60)) + (tz_offset % 100) * 60;
+	
+	d(printf("converting date %s", ctime(&date)));
+	
+	gmtime_r (&date, &tm);
+	
+	return g_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %+05d",
+			       tm_days[tm.tm_wday],
+			       tm.tm_mday, tm_months[tm.tm_mon],
+			       tm.tm_year + 1900,
+			       tm.tm_hour, tm.tm_min, tm.tm_sec,
+			       tz_offset);
+}
 
-	d(printf("offset = %d\n", offset));
+/* This is where it gets ugly... */
 
-	d(printf("converting date %s", ctime(&time)));
+struct _date_token {
+	struct _date_token *next;
+	unsigned char mask;
+	const char *start;
+	size_t len;
+};
 
-	time += ((offset / 100) * (60*60)) + (offset % 100)*60;
+static struct _date_token *
+datetok (const char *date)
+{
+	struct _date_token *tokens = NULL, *token, *tail = (struct _date_token *) &tokens;
+	const char *start, *end;
+        unsigned char mask;
+	
+	start = date;
+	while (*start) {
+		/* kill leading whitespace */
+		while (*start == ' ' || *start == '\t')
+			start++;
+		
+		if (*start == '\0')
+			break;
+		
+		mask = camel_datetok_table[(unsigned char) *start];
+		
+		/* find the end of this token */
+		end = start + 1;
+		while (*end && !strchr ("-/,\t\r\n ", *end))
+			mask |= camel_datetok_table[(unsigned char) *end++];
+		
+		if (end != start) {
+			token = g_malloc (sizeof (struct _date_token));
+			token->next = NULL;
+			token->start = start;
+			token->len = end - start;
+			token->mask = mask;
+			
+			tail->next = token;
+			tail = token;
+		}
+		
+		if (*end)
+			start = end + 1;
+		else
+			break;
+	}
+	
+	return tokens;
+}
 
-	d(printf("converting date %s", ctime(&time)));
+static int
+decode_int (const char *in, size_t inlen)
+{
+	register const char *inptr;
+	int sign = 1, val = 0;
+	const char *inend;
 	
-	gmtime_r (&time, &tm);
+	inptr = in;
+	inend = in + inlen;
 	
-	return g_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %+05d",
-			       tz_days[tm.tm_wday],
-			       tm.tm_mday, tz_months[tm.tm_mon],
-			       tm.tm_year + 1900,
-			       tm.tm_hour, tm.tm_min, tm.tm_sec,
-			       offset);
+	if (*inptr == '-') {
+		sign = -1;
+		inptr++;
+	} else if (*inptr == '+')
+		inptr++;
+	
+	for ( ; inptr < inend; inptr++) {
+		if (!(*inptr >= '0' && *inptr <= '9'))
+			return -1;
+		else
+			val = (val * 10) + (*inptr - '0');
+	}
+	
+	val *= sign;
+	
+	return val;
 }
 
-/* convert a date to time_t representation */
-/* this is an awful mess oh well */
-time_t
-camel_header_decode_date(const char *in, int *saveoffset)
+#if 0
+static int
+get_days_in_month (int month, int year)
 {
-	const char *inptr = in;
-	char *monthname;
-	gboolean foundmonth;
-	int year, offset = 0;
-	struct tm tm;
-	int i;
-	time_t t;
+        switch (month) {
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+	case 8:
+	case 10:
+	case 12:
+	        return 31;
+	case 4:
+	case 6:
+	case 9:
+	case 11:
+	        return 30;
+	case 2:
+	        if (g_date_is_leap_year (year))
+		        return 29;
+		else
+		        return 28;
+	default:
+	        return 0;
+	}
+}
+#endif
 
-	if (in == NULL) {
-		if (saveoffset)
-			*saveoffset = 0;
-		return 0;
+static int
+get_wday (const char *in, size_t inlen)
+{
+	int wday;
+	
+	g_return_val_if_fail (in != NULL, -1);
+	
+	if (inlen < 3)
+		return -1;
+	
+	for (wday = 0; wday < 7; wday++) {
+		if (!g_ascii_strncasecmp (in, tm_days[wday], 3))
+			return wday;
 	}
+	
+	return -1;  /* unknown week day */
+}
 
-	d(printf ("\ndecoding date '%s'\n", inptr));
+static int
+get_mday (const char *in, size_t inlen)
+{
+	int mday;
+	
+	g_return_val_if_fail (in != NULL, -1);
+	
+	mday = decode_int (in, inlen);
+	
+	if (mday < 0 || mday > 31)
+		mday = -1;
+	
+	return mday;
+}
 
-	memset (&tm, 0, sizeof(tm));
+static int
+get_month (const char *in, size_t inlen)
+{
+	int i;
+	
+	g_return_val_if_fail (in != NULL, -1);
+	
+	if (inlen < 3)
+		return -1;
+	
+	for (i = 0; i < 12; i++) {
+		if (!g_ascii_strncasecmp (in, tm_months[i], 3))
+			return i;
+	}
+	
+	return -1;  /* unknown month */
+}
 
-	header_decode_lwsp (&inptr);
-	if (!isdigit (*inptr)) {
-		char *day = decode_token (&inptr);
-		/* we dont really care about the day, it's only for display */
-		if (day) {
-			d(printf ("got day: %s\n", day));
-			g_free (day);
-			header_decode_lwsp (&inptr);
-			if (*inptr == ',') {
+static int
+get_year (const char *in, size_t inlen)
+{
+	int year;
+	
+	g_return_val_if_fail (in != NULL, -1);
+	
+	if ((year = decode_int (in, inlen)) == -1)
+		return -1;
+	
+	if (year < 100)
+		year += (year < 70) ? 2000 : 1900;
+	
+	if (year < 1969)
+		return -1;
+	
+	return year;
+}
+
+static gboolean
+get_time (const char *in, size_t inlen, int *hour, int *min, int *sec)
+{
+	register const char *inptr;
+	int *val, colons = 0;
+	const char *inend;
+	
+	*hour = *min = *sec = 0;
+	
+	inend = in + inlen;
+	val = hour;
+	for (inptr = in; inptr < inend; inptr++) {
+		if (*inptr == ':') {
+			colons++;
+			switch (colons) {
+			case 1:
+				val = min;
+				break;
+			case 2:
+				val = sec;
+				break;
+			default:
+				return FALSE;
+			}
+		} else if (!(*inptr >= '0' && *inptr <= '9'))
+			return FALSE;
+		else
+			*val = (*val * 10) + (*inptr - '0');
+	}
+	
+	return TRUE;
+}
+
+static int
+get_tzone (struct _date_token **token)
+{
+	const char *inptr, *inend;
+	size_t inlen;
+	int i, t;
+	
+	for (i = 0; *token && i < 2; *token = (*token)->next, i++) {
+		inptr = (*token)->start;
+		inlen = (*token)->len;
+		inend = inptr + inlen;
+		
+		if (*inptr == '+' || *inptr == '-') {
+			return decode_int (inptr, inlen);
+		} else {
+			if (*inptr == '(') {
 				inptr++;
-			} else {
-				return parse_broken_date (in, saveoffset);
+				if (*(inend - 1) == ')')
+					inlen -= 2;
+				else
+					inlen--;
+			}
+			
+			for (t = 0; t < 15; t++) {
+				size_t len = strlen (tz_offsets[t].name);
+				
+				if (len != inlen)
+					continue;
+				
+				if (!strncmp (inptr, tz_offsets[t].name, len))
+					return tz_offsets[t].offset;
 			}
 		}
 	}
 	
-	if ((tm.tm_mday = camel_header_decode_int (&inptr)) == 0)
-		return parse_broken_date (in, saveoffset);
+	return -1;
+}
+
+static time_t
+parse_rfc822_date (struct _date_token *tokens, int *tzone)
+{
+	int hour, min, sec, offset, n;
+	struct _date_token *token;
+	struct tm tm;
+	time_t t;
 	
-	monthname = decode_token(&inptr);
-	foundmonth = FALSE;
-	if (monthname) {
-		for (i = 0; i < G_N_ELEMENTS (tz_months); i++) {
-			if (!g_ascii_strcasecmp(tz_months[i], monthname)) {
-				tm.tm_mon = i;
-				foundmonth = TRUE;
-				break;
-			}
-		}
-		g_free(monthname);
+	g_return_val_if_fail (tokens != NULL, (time_t) 0);
+	
+	token = tokens;
+	
+	memset ((void *) &tm, 0, sizeof (struct tm));
+	
+	if ((n = get_wday (token->start, token->len)) != -1) {
+		/* not all dates may have this... */
+		tm.tm_wday = n;
+		token = token->next;
 	}
 	
-	if (!foundmonth)
-		return parse_broken_date (in, saveoffset);
+	/* get the mday */
+	if (!token || (n = get_mday (token->start, token->len)) == -1)
+		return (time_t) 0;
 	
-	year = camel_header_decode_int(&inptr);
-	if (year < 69) {
-		tm.tm_year = 100 + year;
-	} else if (year < 100) {
-		tm.tm_year = year;
-	} else if (year >= 100 && year < 1900) {
-		tm.tm_year = year;
+	tm.tm_mday = n;
+	token = token->next;
+	
+	/* get the month */
+	if (!token || (n = get_month (token->start, token->len)) == -1)
+		return (time_t) 0;
+	
+	tm.tm_mon = n;
+	token = token->next;
+	
+	/* get the year */
+	if (!token || (n = get_year (token->start, token->len)) == -1)
+		return (time_t) 0;
+	
+	tm.tm_year = n - 1900;
+	token = token->next;
+	
+	/* get the hour/min/sec */
+	if (!token || !get_time (token->start, token->len, &hour, &min, &sec))
+		return (time_t) 0;
+	
+	tm.tm_hour = hour;
+	tm.tm_min = min;
+	tm.tm_sec = sec;
+	token = token->next;
+	
+	/* get the timezone */
+	if (!token || (n = get_tzone (&token)) == -1) {
+		/* I guess we assume tz is GMT? */
+		offset = 0;
 	} else {
-		tm.tm_year = year - 1900;
+		offset = n;
 	}
-	/* get the time ... yurck */
-	tm.tm_hour = camel_header_decode_int(&inptr);
-	header_decode_lwsp(&inptr);
-	if (*inptr == ':')
-		inptr++;
-	tm.tm_min = camel_header_decode_int(&inptr);
-	header_decode_lwsp(&inptr);
-	if (*inptr == ':')
-		inptr++;
-	tm.tm_sec = camel_header_decode_int(&inptr);
-	header_decode_lwsp(&inptr);
-	if (*inptr == '+'
-	    || *inptr == '-') {
-		offset = (*inptr++)=='-'?-1:1;
-		offset = offset * camel_header_decode_int(&inptr);
-		d(printf("abs signed offset = %d\n", offset));
-		if (offset < -1200 || offset > 1400)
-			offset = 0;
-	} else if (isdigit(*inptr)) {
-		offset = camel_header_decode_int(&inptr);
-		d(printf("abs offset = %d\n", offset));
-		if (offset < -1200 || offset > 1400)
-			offset = 0;
-	} else {
-		char *tz = decode_token(&inptr);
+	
+	t = e_mktime_utc (&tm);
+	
+	/* t is now GMT of the time we want, but not offset by the timezone ... */
+	
+	/* this should convert the time to the GMT equiv time */
+	t -= ((offset / 100) * 60 * 60) + (offset % 100) * 60;
+	
+	if (tzone)
+		*tzone = offset;
+	
+	return t;
+}
 
-		if (tz) {
-			for (i=0;i<sizeof(tz_offsets)/sizeof(tz_offsets[0]);i++) {
-				if (!g_ascii_strcasecmp(tz_offsets[i].name, tz)) {
-					offset = tz_offsets[i].offset;
-					break;
-				}
+
+#define date_token_mask(t)  (((struct _date_token *) t)->mask)
+#define is_numeric(t)       ((date_token_mask (t) & DATE_TOKEN_NON_NUMERIC) == 0)
+#define is_weekday(t)       ((date_token_mask (t) & DATE_TOKEN_NON_WEEKDAY) == 0)
+#define is_month(t)         ((date_token_mask (t) & DATE_TOKEN_NON_MONTH) == 0)
+#define is_time(t)          (((date_token_mask (t) & DATE_TOKEN_NON_TIME) == 0) && (date_token_mask (t) & DATE_TOKEN_HAS_COLON))
+#define is_tzone_alpha(t)   ((date_token_mask (t) & DATE_TOKEN_NON_TIMEZONE_ALPHA) == 0)
+#define is_tzone_numeric(t) (((date_token_mask (t) & DATE_TOKEN_NON_TIMEZONE_NUMERIC) == 0) && (date_token_mask (t) & DATE_TOKEN_HAS_SIGN))
+#define is_tzone(t)         (is_tzone_alpha (t) || is_tzone_numeric (t))
+
+static time_t
+parse_broken_date (struct _date_token *tokens, int *tzone)
+{
+	gboolean got_wday, got_month, got_tzone;
+	int hour, min, sec, offset, n;
+	struct _date_token *token;
+	struct tm tm;
+	time_t t;
+	
+	memset ((void *) &tm, 0, sizeof (struct tm));
+	got_wday = got_month = got_tzone = FALSE;
+	offset = 0;
+	
+	token = tokens;
+	while (token) {
+		if (is_weekday (token) && !got_wday) {
+			if ((n = get_wday (token->start, token->len)) != -1) {
+				d(printf ("weekday; "));
+				got_wday = TRUE;
+				tm.tm_wday = n;
+				goto next;
 			}
-			g_free(tz);
 		}
-		/* some broken mailers seem to put in things like GMT+1030 instead of just +1030 */
-		header_decode_lwsp(&inptr);
-		if (*inptr == '+' || *inptr == '-') {
-			int sign = (*inptr++)=='-'?-1:1;
-			offset = offset + (camel_header_decode_int(&inptr)*sign);
+		
+		if (is_month (token) && !got_month) {
+			if ((n = get_month (token->start, token->len)) != -1) {
+				d(printf ("month; "));
+				got_month = TRUE;
+				tm.tm_mon = n;
+				goto next;
+			}
+		}
+		
+		if (is_time (token) && !tm.tm_hour && !tm.tm_min && !tm.tm_sec) {
+			if (get_time (token->start, token->len, &hour, &min, &sec)) {
+				d(printf ("time; "));
+				tm.tm_hour = hour;
+				tm.tm_min = min;
+				tm.tm_sec = sec;
+				goto next;
+			}
+		}
+		
+		if (is_tzone (token) && !got_tzone) {
+			struct _date_token *t = token;
+			
+			if ((n = get_tzone (&t)) != -1) {
+				d(printf ("tzone; "));
+				got_tzone = TRUE;
+				offset = n;
+				goto next;
+			}
 		}
-		d(printf("named offset = %d\n", offset));
+		
+		if (is_numeric (token)) {
+			if (token->len == 4 && !tm.tm_year) {
+				if ((n = get_year (token->start, token->len)) != -1) {
+					d(printf ("year; "));
+					tm.tm_year = n - 1900;
+					goto next;
+				}
+			} else {
+				/* Note: assumes MM-DD-YY ordering if '0 < MM < 12' holds true */
+				if (!got_month && token->next && is_numeric (token->next)) {
+					if ((n = decode_int (token->start, token->len)) > 12) {
+						goto mday;
+					} else if (n > 0) {
+						d(printf ("mon; "));
+						got_month = TRUE;
+						tm.tm_mon = n - 1;
+					}
+					goto next;
+				} else if (!tm.tm_mday && (n = get_mday (token->start, token->len)) != -1) {
+				mday:
+					d(printf ("mday; "));
+					tm.tm_mday = n;
+					goto next;
+				} else if (!tm.tm_year) {
+					if ((n = get_year (token->start, token->len)) != -1) {
+						d(printf ("2-digit year; "));
+						tm.tm_year = n - 1900;
+					}
+					goto next;
+				}
+			}
+		}
+		
+		d(printf ("???; "));
+		
+	next:
+		
+		token = token->next;
 	}
-
-	t = e_mktime_utc(&tm);
-
+	
+	d(printf ("\n"));
+	
+	t = e_mktime_utc (&tm);
+	
 	/* t is now GMT of the time we want, but not offset by the timezone ... */
-
-	d(printf(" gmt normalized? = %s\n", ctime(&t)));
-
+	
 	/* this should convert the time to the GMT equiv time */
-	t -= ( (offset/100) * 60*60) + (offset % 100)*60;
-
-	d(printf(" gmt normalized for timezone? = %s\n", ctime(&t)));
-
-	d({
-		char *tmp;
-		tmp = camel_header_format_date(t, offset);
-		printf(" encoded again: %s\n", tmp);
-		g_free(tmp);
-	});
+	t -= ((offset / 100) * 60 * 60) + (offset % 100) * 60;
+	
+	if (tzone)
+		*tzone = offset;
+	
+	return t;
+}
 
-	if (saveoffset)
-		*saveoffset = offset;
 
-	return t;
+/**
+ * camel_header_decode_date:
+ * @str: input date string
+ * @tz_offset: timezone offset
+ *
+ * Decodes the rfc822 date string and saves the GMT offset into
+ * @tz_offset if non-NULL.
+ *
+ * Returns: the time_t representation of the date string specified by
+ * @str or (time_t) %0 on error. If @tz_offset is non-NULL, the value
+ * of the timezone offset will be stored.
+ **/
+time_t
+camel_header_decode_date (const char *str, int *tz_offset)
+{
+	struct _date_token *token, *tokens;
+	time_t date;
+	
+	if (!(tokens = datetok (str))) {
+		if (tz_offset)
+			*tz_offset = 0;
+		
+		return (time_t) 0;
+	}
+	
+	if (!(date = parse_rfc822_date (tokens, tz_offset)))
+		date = parse_broken_date (tokens, tz_offset);
+	
+	/* cleanup */
+	while (tokens) {
+		token = tokens;
+		tokens = tokens->next;
+		g_free (token);
+	}
+	
+	return date;
 }
 
 char *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]