| Summary: | Interpret old-fashioned time zone in email Date header | ||
|---|---|---|---|
| Product: | [Unmaintained] kmail | Reporter: | Jaap Weel <weel> |
| Component: | general | Assignee: | kdepim bugs <pim-bugs-null> |
| Status: | RESOLVED FIXED | ||
| Severity: | normal | CC: | bensberg |
| Priority: | NOR | ||
| Version First Reported In: | 1.8.3 | ||
| Target Milestone: | --- | ||
| Platform: | Ubuntu | ||
| OS: | Linux | ||
| Latest Commit: | Version Fixed In: | ||
| Sentry Crash Report: | |||
|
Description
Jaap Weel
2005-12-07 11:16:05 UTC
SVN commit 494852 by mkoller:
BUG:117848
Improve parsing of non-standard date strings.
It now parses in addition date strings in the format
"WWW MMM dd HH:MM:SS [Z] YYYY" zone is optional
e.g.: Fri Oct 14 09:21:49 CEST 2005
or: Tue Mar 23 18:00:02 2004
M +3 -0 datetime.cpp
M +103 -32 dw_date.cpp [POSSIBLY UNSAFE: scanf]
--- branches/KDE/3.5/kdepim/mimelib/datetime.cpp #494851:494852
@@ -45,6 +45,7 @@
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
extern "C" int ParseRfc822Date(const char *str, struct tm *tms, int *z);
+extern "C" int ParseDate(const char *str, struct tm *tms, int *z);
static DwInt32 ymd_to_jdnl(int year, int mon, int day, int julian);
static void jdnl_to_ymd(DwInt32 jdn, int *year, int *mon, int *day, int julian);
static DwUint32 my_inv_gmtime(struct tm* ptms);
@@ -282,6 +283,8 @@
struct tm tms;
int zone;
int err = ParseRfc822Date(str, &tms, &zone);
+ if ( err == -1 ) // try another format
+ err = ParseDate(str, &tms, &zone);
if (!err) {
mYear = tms.tm_year + 1900;
mMonth = tms.tm_mon+1;
--- branches/KDE/3.5/kdepim/mimelib/dw_date.cpp #494851:494852
@@ -526,10 +526,6 @@
if (str[pos+1] == 'T' || str[pos+1] == 't') {
zone = 0;
}
- else {
- /* Military time zone */
- zone = 480;
- }
break;
case 'G':
case 'g':
@@ -537,10 +533,6 @@
&& (str[pos+2] == 'T' || str[pos+2] == 't')) {
zone = 0;
}
- else {
- /* Military time zone */
- zone = -420;
- }
break;
case 'E':
case 'e':
@@ -552,10 +544,6 @@
&& (str[pos+2] == 'T' || str[pos+2] == 't')) {
zone = -240;
}
- else {
- /* Military time zone */
- zone = -300;
- }
break;
case 'C':
case 'c':
@@ -567,10 +555,15 @@
&& (str[pos+2] == 'T' || str[pos+2] == 't')) {
zone = -300;
}
- else {
- /* Military time zone */
- zone = -180;
+ else if ((str[pos+1] == 'E' || str[pos+1] == 'e') // allow non-RFC822 "CET"
+ && (str[pos+2] == 'T' || str[pos+2] == 't')) {
+ zone = 60;
}
+ else if ((str[pos+1] == 'E' || str[pos+1] == 'e') // allow non-RFC822 "CEST"
+ && (str[pos+2] == 'S' || str[pos+2] == 's')
+ && (str[pos+3] == 'T' || str[pos+3] == 't')) {
+ zone = 120;
+ }
break;
case 'M':
case 'm':
@@ -582,10 +575,6 @@
&& (str[pos+2] == 'T' || str[pos+2] == 't')) {
zone = -360;
}
- else {
- /* Military time zone */
- zone = -720;
- }
break;
case 'P':
case 'p':
@@ -597,10 +586,6 @@
&& (str[pos+2] == 'T' || str[pos+2] == 't')) {
zone = -420;
}
- else {
- /* Military time zone */
- zone = 180;
- }
break;
case 'Z':
/* Military time zone */
@@ -653,7 +638,16 @@
return isValid ? 0 : -1;
}
+const char* wdays[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+const char* months[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+
#ifdef DW_TESTING_DATEPARSER
#include <stdio.h>
@@ -664,15 +658,6 @@
""
};
-const char* wdays[] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-const char* months[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
int main()
{
struct tm *ptms, tms1, tms2;
@@ -723,3 +708,89 @@
}
#endif
+
+// try to parse a date/time string given in a format not
+// correctly specified in RFC822 format
+// Here we detect the following format:
+// "WWW MMM dd HH:MM:SS [Z] YYYY" zone is optional
+// e.g.: Fri Oct 14 09:21:49 CEST 2005
+// or: Tue Mar 23 18:00:02 2004
+
+#include <string.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int ParseDate(const char *str, struct tm *tms, int *z)
+{
+ if ( !str )
+ return -1;
+
+ size_t len = strlen(str);
+
+ if ( len < 24 ) // at least "WWW MMM dd HH:MM:SS YYYY"
+ return -1;
+
+ int day=1, month=0, year=1970, hour=0, minute=0, second=0, zone=0;
+ int i;
+
+ for (i = 0; i < 7; i++)
+ if ( strncmp(str, wdays[i], 3) == 0 )
+ break;
+
+ if ( i == 7 )
+ return -1;
+
+ for (i = 0; i < 12; i++)
+ if ( strncmp(str+4, months[i], 3) == 0 )
+ break;
+
+ if ( i == 12 )
+ return -1;
+
+ month = i;
+
+ if ( sscanf(str+8, "%d %d:%d:%d", &day, &hour, &minute, &second) != 4 )
+ return -1;
+
+ if ( isdigit(str[20]) ) { // year without zone info, as in ctime()
+ if ( sscanf(str+20, "%d", &year) != 1 )
+ return -1;
+ }
+ else {
+ if ( sscanf(str+20, "%*s %d", &year) != 1 )
+ return -1;
+
+ if ( strncmp(str+20, "EST" , 3) == 0 ) zone = -5 * 60;
+ else if ( strncmp(str+20, "EDT" , 3) == 0 ) zone = -4 * 60;
+ else if ( strncmp(str+20, "CST" , 3) == 0 ) zone = -6 * 60;
+ else if ( strncmp(str+20, "CDT" , 3) == 0 ) zone = -5 * 60;
+ else if ( strncmp(str+20, "MST" , 3) == 0 ) zone = -7 * 60;
+ else if ( strncmp(str+20, "MDT" , 3) == 0 ) zone = -6 * 60;
+ else if ( strncmp(str+20, "PST" , 3) == 0 ) zone = -8 * 60;
+ else if ( strncmp(str+20, "PDT" , 3) == 0 ) zone = -7 * 60;
+ else if ( strncmp(str+20, "CET" , 3) == 0 ) zone = 60;
+ else if ( strncmp(str+20, "CEST", 4) == 0 ) zone = 120;
+ }
+
+ if ( (day < 1) || (day > 31) ||
+ (hour < 0) || (hour > 23) ||
+ (minute < 0) || (minute > 59) ||
+ (second < 0) || (second > 59) ||
+ (year < 1900) )
+ return -1;
+
+ if ( tms ) {
+ tms->tm_year = year - 1900;
+ tms->tm_mon = month;
+ tms->tm_mday = day;
+ tms->tm_hour = hour;
+ tms->tm_min = minute;
+ tms->tm_sec = second;
+ }
+
+ if ( z ) *z = zone;
+
+ return 0;
+}
*** Bug 115829 has been marked as a duplicate of this bug. *** |