aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog3
-rw-r--r--camel/Makefile.am2
-rw-r--r--camel/broken-date-parser.c315
-rw-r--r--camel/broken-date-parser.h41
-rw-r--r--camel/camel-mime-utils.c293
-rw-r--r--camel/providers/imap/camel-imap-folder.c3
6 files changed, 367 insertions, 290 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 1c6e1dae8d..f039c30b06 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,8 @@
2000-06-30 Jeffrey Stedfast <fejj@helixcode.com>
+ * broken-date-parser.[c,h]: Utilities for parsing broken
+ date strings.
+
* providers/imap/camel-imap-folder.c (imap_move_message_to):
Implemented.
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 578cd660fa..c398fb55f2 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -45,6 +45,7 @@ libcamel_la_SOURCES = \
hash-table-utils.c \
md5-utils.c \
string-utils.c \
+ broken-date-parser.c \
camel-mime-parser.c \
camel-mime-utils.c \
camel-mime-filter.c \
@@ -90,6 +91,7 @@ libcamelinclude_HEADERS = \
hash-table-utils.h \
md5-utils.h \
string-utils.h \
+ broken-date-parser.h \
camel-exception-list.def \
camel-mime-parser.h \
camel-mime-utils.h \
diff --git a/camel/broken-date-parser.c b/camel/broken-date-parser.c
new file mode 100644
index 0000000000..544dc04e28
--- /dev/null
+++ b/camel/broken-date-parser.c
@@ -0,0 +1,315 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@helixcode.com>
+ *
+ * Copyright 2000 Helix Code, Inc. (www.helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "broken-date-parser.h"
+
+/* prototypes for functions dealing with broken date formats */
+static GList *datetok (const gchar *date);
+static gint get_days_in_month (gint mon, gint year);
+static gint get_weekday (gchar *str);
+static gint get_month (gchar *str);
+
+static char *tz_months [] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+/*****************************************************************************
+ * The following functions are here in the case of badly broken date formats *
+ * *
+ * -- fejj@helixcode.com *
+ *****************************************************************************/
+
+typedef struct {
+ gchar dow[6]; /* day of week (should only need 4 chars) */
+ gint day;
+ gint mon; /* 1->12 or 0 if invalid */
+ gint year;
+ gint hour;
+ gint min;
+ gint sec;
+ gchar zone[6]; /* time zone */
+} date_t;
+
+static
+GList *datetok (const gchar *date)
+{
+ GList *tokens = NULL;
+ gchar *token, *start, *end;
+
+ start = (gchar *) date;
+ while (*start) {
+ /* find the end of this token */
+ for (end = start; *end && *end != ' '; end++);
+
+ token = g_strndup (start, (end - start));
+
+ if (token && *token)
+ tokens = g_list_append (tokens, token);
+ else
+ g_free (token);
+
+ if (*end)
+ start = end + 1;
+ else
+ break;
+ }
+
+ return tokens;
+}
+
+static gint
+get_days_in_month (gint mon, gint year)
+{
+ switch (mon) {
+ 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 ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
+ return 29;
+ return 28;
+ default:
+ return 30;
+ }
+}
+
+static gint
+get_weekday (gchar *str)
+{
+ g_return_val_if_fail ((str != NULL), 0);
+
+ if (strncmp (str, "Mon", 3) == 0) {
+ return 1;
+ } else if (strncmp (str, "Tue", 3) == 0) {
+ return 2;
+ } else if (strncmp (str, "Wed", 3) == 0) {
+ return 3;
+ } else if (strncmp (str, "Thu", 3) == 0) {
+ return 4;
+ } else if (strncmp (str, "Fri", 3) == 0) {
+ return 5;
+ } else if (strncmp (str, "Sat", 3) == 0) {
+ return 6;
+ } else if (strncmp (str, "Sun", 3) == 0) {
+ return 7;
+ }
+
+ return 0; /* unknown week day */
+}
+
+static gint
+get_month (gchar *str)
+{
+ g_return_val_if_fail (str != NULL, 0);
+
+ if (strncmp (str, "Jan", 3) == 0) {
+ return 1;
+ } else if (strncmp (str, "Feb", 3) == 0) {
+ return 2;
+ } else if (strncmp (str, "Mar", 3) == 0) {
+ return 3;
+ } else if (strncmp (str, "Apr", 3) == 0) {
+ return 4;
+ } else if (strncmp (str, "May", 3) == 0) {
+ return 5;
+ } else if (strncmp (str, "Jun", 3) == 0) {
+ return 6;
+ } else if (strncmp (str, "Jul", 3) == 0) {
+ return 7;
+ } else if (strncmp (str, "Aug", 3) == 0) {
+ return 8;
+ } else if (strncmp (str, "Sep", 3) == 0) {
+ return 9;
+ } else if (strncmp (str, "Oct", 3) == 0) {
+ return 10;
+ } else if (strncmp (str, "Nov", 3) == 0) {
+ return 11;
+ } else if (strncmp (str, "Dec", 3) == 0) {
+ return 12;
+ }
+
+ return 0; /* unknown month */
+}
+
+gchar *
+parse_broken_date (const gchar *datestr)
+{
+ GList *tokens;
+ date_t date;
+ gchar *token, *ptr, *newdatestr;
+ guint len, i, retval;
+ gdouble tz = 0.0;
+
+ memset ((void*)&date, 0, sizeof (date_t));
+ g_return_val_if_fail (datestr != NULL, NULL);
+
+ tokens = datetok (datestr);
+ len = g_list_length (tokens);
+ for (i = 0; i < len; i++) {
+ token = g_list_nth_data (tokens, i);
+
+ if ((retval = get_weekday (token))) {
+ strncpy (date.dow, datestr, 4);
+ } else if ((retval = get_month (token))) {
+ date.mon = retval;
+ } else if (strlen (token) <= 2) {
+ /* this could be a 1 or 2 digit day of the month */
+ for (retval = 1, ptr = token; *ptr; ptr++)
+ if (*ptr < '0' || *ptr > '9')
+ retval = 0;
+
+ if (retval && atoi (token) <= 31 && !date.day) /* probably should find a better way */
+ date.day = atoi (token);
+ else /* fubar'd client using a 2-digit year */
+ date.year = atoi (token) < 69 ? 2000 + atoi (token) : 1900 + atoi (token);
+ } else if (strlen (token) == 4) {
+ /* this could be the year... */
+ for (retval = 1, ptr = token; *ptr; ptr++)
+ if (*ptr < '0' || *ptr > '9')
+ retval = 0;
+
+ if (retval)
+ date.year = atoi (token);
+ } else if (strchr (token, ':')) {
+ /* this must be the time: hh:mm:ss */
+ sscanf (token, "%d:%d:%d", &date.hour, &date.min, &date.sec);
+ } else if (*token == '-' || *token == '+') {
+ tz = atoi (token) / 100.0;
+ }
+ }
+
+ g_list_free (tokens);
+
+ /* adjust times based on time zones */
+
+ if (tz != 0) {
+ /* check for time-zone shift */
+ if (tz > 0) {
+ /* correct for positive hours off of UCT */
+ date.hour -= (tz / 100);
+ tz = (gint)tz % 100;
+
+ if (tz > 0) /* correct for positive minutes off of UCT */
+ date.min -= (gint)(((gdouble) tz / 100.0) * 60.0);
+ } else {
+ if (tz < 0) {
+ /* correct for negative hours off of UCT */
+ tz = -tz;
+ date.hour += (tz / 100);
+ tz = -((gint)tz % 100);
+
+ if (tz < 0)
+ date.min -= (gint)(((gdouble) tz / 100.0) * 60.0);
+ }
+ }
+
+ /* adjust seconds to proper range */
+ if (date.sec > 59) {
+ date.min += (date.sec / 60);
+ date.sec = (date.sec % 60);
+ }
+
+ /* adjust minutes to proper range */
+ if (date.min > 59) {
+ date.hour += (date.min / 60);
+ date.min = (date.min % 60);
+ } else {
+ if (date.min < 0) {
+ date.min = -date.min;
+ date.hour -= (date.min / 60) - 1;
+ date.min = 60 - (date.min % 60);
+ }
+ }
+
+ /* adjust hours to the proper randge */
+ if (date.hour > 23) {
+ date.day += (date.hour / 24);
+ date.hour -= (date.hour % 24);
+ } else {
+ if (date.hour < 0) {
+ date.hour = -date.hour;
+ date.day -= (date.hour / 24) - 1;
+ date.hour = 24 - (date.hour % 60);
+ }
+ }
+
+ /* adjust days to the proper range */
+ while (date.day > get_days_in_month (date.mon, date.year)) {
+ date.day -= get_days_in_month (date.mon, date.year);
+ date.mon++;
+ if (date.mon > 12) {
+ date.year += (date.mon / 12);
+ date.mon = (date.mon % 12);
+ if (date.mon == 0) {
+ /* month sanity check */
+ date.mon = 12;
+ date.year -= 1;
+ }
+ }
+ }
+
+ while (date.day < 1) {
+ date.day += get_days_in_month (date.mon, date.year);
+ date.mon--;
+ if (date.mon < 1) {
+ date.mon = -date.mon;
+ date.year -= (date.mon / 12) - 1;
+ date.mon = 12 - (date.mon % 12);
+ }
+ }
+
+ /* adjust months to the proper range */
+ if (date.mon > 12) {
+ date.year += (date.mon / 12);
+ date.mon = (date.mon % 12);
+ if (date.mon == 0) {
+ /* month sanity check */
+ date.mon = 12;
+ date.year -= 1;
+ }
+ } else {
+ if (date.mon < 1) {
+ date.mon = -date.mon;
+ date.year -= (date.mon / 12) - 1;
+ date.mon = 12 - (date.mon % 12);
+ }
+ }
+ }
+
+ /* now lets print this date into a string with the correct format */
+ newdatestr = g_strdup_printf ("%s, %d %s %d %s%d:%s%d:%s%d -0000",
+ date.dow, date.day, tz_months[date.mon-1],
+ date.year,
+ date.hour > 10 ? "" : "0", date.hour,
+ date.min > 10 ? "" : "0", date.min,
+ date.sec > 10 ? "" : "0", date.sec);
+
+ return newdatestr;
+}
+
+/*****************************************************************************
+ * This ends the code for the broken date parser... *
+ * *
+ * -- fejj@helixcode.com *
+ *****************************************************************************/
diff --git a/camel/broken-date-parser.h b/camel/broken-date-parser.h
new file mode 100644
index 0000000000..17000b3299
--- /dev/null
+++ b/camel/broken-date-parser.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@helixcode.com>
+ *
+ * Copyright 2000 Helix Code, Inc. (www.helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <time.h>
+
+#include <ctype.h>
+
+/* prototypes for functions dealing with broken date formats */
+
+gchar *parse_broken_date (const gchar *datestr);
+
+
+
+
+
diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c
index ccf13b4097..12dc48c1b6 100644
--- a/camel/camel-mime-utils.c
+++ b/camel/camel-mime-utils.c
@@ -38,6 +38,8 @@
#include "camel-mime-utils.h"
+#include "broken-date-parser.h"
+
#if 0
int strdup_count = 0;
int malloc_count = 0;
@@ -138,14 +140,6 @@ enum {
#define CHARS_CSPECIAL "()\\\r" /* not in comments */
#define CHARS_DSPECIAL "[]\\\r \t" /* not in domains */
-/* prototypes for functions dealing with broken date formats */
-static GList *datetok (const gchar *date)
-static gint get_days_in_month (gint mon, gint year);
-static gint get_weekday (gchar *str);
-static gint get_month (gchar *str);
-static gchar *parse_date (const gchar *datestr);
-
-
static void
header_init_bits(unsigned char bit, unsigned char bitcopy, int remove, unsigned char *vals, int len)
{
@@ -1939,287 +1933,6 @@ header_format_date(time_t time, int offset)
offset);
}
-/*********************************************************************************
- * The following functions are here in the case of badly broken date formats *
- * *
- * -- fejj@helixcode.com *
- *********************************************************************************/
-
-typedef struct {
- gchar dow[6]; /* day of week (should only need 4 chars) */
- gint day;
- gint mon; /* 1->12 or 0 if invalid */
- gint year;
- gint hour;
- gint min;
- gint sec;
- gchar zone[6]; /* time zone */
-} date_t;
-
-static
-GList *datetok (const gchar *date)
-{
- GList *tokens = NULL;
- gchar *token, *start, *end;
-
- start = (gchar *) date;
- while (*start) {
- /* find the end of this token */
- for (end = start; *end && *end != ' '; end++);
-
- token = g_strndup (start, (end - start));
-
- if (token && *token)
- tokens = g_list_append (tokens, token);
- else
- g_free (token);
-
- if (*end)
- start = end + 1;
- else
- break;
- }
-
- return tokens;
-}
-
-static gint
-get_days_in_month (gint mon, gint year)
-{
- switch (mon) {
- 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 ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
- return 29;
- return 28;
- default:
- return 30;
- }
-}
-
-static gint
-get_weekday (gchar *str)
-{
- g_return_val_if_fail ((str != NULL), 0);
-
- if (strncmp (str, "Mon", 3) == 0) {
- return 1;
- } else if (strncmp (str, "Tue", 3) == 0) {
- return 2;
- } else if (strncmp (str, "Wed", 3) == 0) {
- return 3;
- } else if (strncmp (str, "Thu", 3) == 0) {
- return 4;
- } else if (strncmp (str, "Fri", 3) == 0) {
- return 5;
- } else if (strncmp (str, "Sat", 3) == 0) {
- return 6;
- } else if (strncmp (str, "Sun", 3) == 0) {
- return 7;
- }
-
- return 0; /* unknown week day */
-}
-
-static gint
-get_month (gchar *str)
-{
- g_return_val_if_fail (str != NULL, 0);
-
- if (strncmp (str, "Jan", 3) == 0) {
- return 1;
- } else if (strncmp (str, "Feb", 3) == 0) {
- return 2;
- } else if (strncmp (str, "Mar", 3) == 0) {
- return 3;
- } else if (strncmp (str, "Apr", 3) == 0) {
- return 4;
- } else if (strncmp (str, "May", 3) == 0) {
- return 5;
- } else if (strncmp (str, "Jun", 3) == 0) {
- return 6;
- } else if (strncmp (str, "Jul", 3) == 0) {
- return 7;
- } else if (strncmp (str, "Aug", 3) == 0) {
- return 8;
- } else if (strncmp (str, "Sep", 3) == 0) {
- return 9;
- } else if (strncmp (str, "Oct", 3) == 0) {
- return 10;
- } else if (strncmp (str, "Nov", 3) == 0) {
- return 11;
- } else if (strncmp (str, "Dec", 3) == 0) {
- return 12;
- }
-
- return 0; /* unknown month */
-}
-
-static gchar *
-parse_date (const gchar *datestr)
-{
- GList *tokens;
- date_t date;
- gchar *token, *ptr, *newdatestr;
- guint len, i, retval;
- gdouble tz = 0.0;
-
- memset ((void*)&date, 0, sizeof (date_t));
- g_return_val_if_fail (datestr != NULL, NULL);
-
- tokens = datetok (datestr);
- len = g_list_length (tokens);
- for (i = 0; i < len; i++) {
- token = g_list_nth_data (tokens, i);
-
- if ((retval = get_weekday (token))) {
- strncpy (date.dow, datestr, 4);
- } else if ((retval = get_month (token))) {
- date.mon = retval;
- } else if (strlen (token) <= 2) {
- /* this could be a 1 or 2 digit day of the month */
- for (retval = 1, ptr = token; *ptr; ptr++)
- if (*ptr < '0' || *ptr > '9')
- retval = 0;
-
- if (retval && atoi (token) <= 31 && !date.day) /* probably should find a better way */
- date.day = atoi (token);
- else /* fubar'd client using a 2-digit year */
- date.year = atoi (token) < 69 ? 2000 + atoi (token) : 1900 + atoi (token);
- } else if (strlen (token) == 4) {
- /* this could be the year... */
- for (retval = 1, ptr = token; *ptr; ptr++)
- if (*ptr < '0' || *ptr > '9')
- retval = 0;
-
- if (retval)
- date.year = atoi (token);
- } else if (strchr (token, ':')) {
- /* this must be the time: hh:mm:ss */
- sscanf (token, "%d:%d:%d", &date.hour, &date.min, &date.sec);
- } else if (*token == '-' || *token == '+') {
- tz = atoi (token) / 100.0;
- }
- }
-
- g_list_free (tokens);
-
- /* adjust times based on time zones */
-
- if (tz != 0) {
- /* check for time-zone shift */
- if (tz > 0) {
- /* correct for positive hours off of UCT */
- date.hour -= (tz / 100);
- tz = (gint)tz % 100;
-
- if (tz > 0) /* correct for positive minutes off of UCT */
- date.min -= (gint)(((gdouble) tz / 100.0) * 60.0);
- } else {
- if (tz < 0) {
- /* correct for negative hours off of UCT */
- tz = -tz;
- date.hour += (tz / 100);
- tz = -((gint)tz % 100);
-
- if (tz < 0)
- date.min -= (gint)(((gdouble) tz / 100.0) * 60.0);
- }
- }
-
- /* adjust seconds to proper range */
- if (date.sec > 59) {
- date.min += (date.sec / 60);
- date.sec = (date.sec % 60);
- }
-
- /* adjust minutes to proper range */
- if (date.min > 59) {
- date.hour += (date.min / 60);
- date.min = (date.min % 60);
- } else {
- if (date.min < 0) {
- date.min = -date.min;
- date.hour -= (date.min / 60) - 1;
- date.min = 60 - (date.min % 60);
- }
- }
-
- /* adjust hours to the proper randge */
- if (date.hour > 23) {
- date.day += (date.hour / 24);
- date.hour -= (date.hour % 24);
- } else {
- if (date.hour < 0) {
- date.hour = -date.hour;
- date.day -= (date.hour / 24) - 1;
- date.hour = 24 - (date.hour % 60);
- }
- }
-
- /* adjust days to the proper range */
- while (date.day > get_days_in_month (date.mon, date.year)) {
- date.day -= get_days_in_month (date.mon, date.year);
- date.mon++;
- if (date.mon > 12) {
- date.year += (date.mon / 12);
- date.mon = (date.mon % 12);
- if (date.mon == 0) {
- /* month sanity check */
- date.mon = 12;
- date.year -= 1;
- }
- }
- }
-
- while (date.day < 1) {
- date.day += get_days_in_month (date.mon, date.year);
- date.mon--;
- if (date.mon < 1) {
- date.mon = -date.mon;
- date.year -= (date.mon / 12) - 1;
- date.mon = 12 - (date.mon % 12);
- }
- }
-
- /* adjust months to the proper range */
- if (date.mon > 12) {
- date.year += (date.mon / 12);
- date.mon = (date.mon % 12);
- if (date.mon == 0) {
- /* month sanity check */
- date.mon = 12;
- date.year -= 1;
- }
- } else {
- if (date.mon < 1) {
- date.mon = -date.mon;
- date.year -= (date.mon / 12) - 1;
- date.mon = 12 - (date.mon % 12);
- }
- }
- }
-
- /* now lets print this date into a string with the correct format */
- newdatestr = g_strdup_printf ("%s, %d %s %d %s%d:%s%d:%s%d -0000",
- date.dow, date.day, tz_months[date.mon-1],
- date.year,
- date.hour > 10 ? "" : "0", date.hour,
- date.min > 10 ? "" : "0", date.min,
- date.sec > 10 ? "" : "0", date.sec);
-
- return newdatestr;
-}
-
-/*********************************************************************************
- * This ends the code for the broken date parser... *
- * *
- * -- fejj@helixcode.com *
- *********************************************************************************/
-
/* convert a date to time_t representation */
/* this is an awful mess oh well */
time_t
@@ -2257,7 +1970,7 @@ header_decode_date(const char *in, int *saveoffset)
w(g_warning("day not followed by ',' its probably a broken mail client, so we'll ignore its date entirely"));
printf ("Giving it one last chance...\n");
- newdate = parse_date (in);
+ newdate = parse_broken_date (in);
if (newdate) {
printf ("Got: %s\n", newdate);
if (saveoffset)
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index c90e0cbb3d..2024f9687a 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -539,6 +539,9 @@ imap_move_message_to (CamelFolder *source, const char *uid, CamelFolder *destina
return;
}
+ g_free (result);
+ g_free (folder_path);
+
if (!(info = (CamelMessageInfo *)imap_summary_get_by_uid (source, uid))) {
CamelService *service = CAMEL_SERVICE (store);