Moved some generically useful date/time handling functions to mutil.c,
fixed problems with portability of timezone information in struct tm, and moved created a new structure to hold timezone information, since struct tm doesn't do so reliably.
Showing
5 changed files
with
285 additions
and
78 deletions
include/mailutils/mutil.h
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifndef _MAILUTILS_MUTIL_H | ||
19 | #define _MAILUTILS_MUTIL_H | ||
20 | |||
21 | /* | ||
22 | Collection of useful utility routines that are worth sharing, | ||
23 | but don't have a natural home somewhere else. | ||
24 | */ | ||
25 | |||
26 | #include <time.h> | ||
27 | |||
28 | #ifndef __P | ||
29 | # ifdef __STDC__ | ||
30 | # define __P(args) args | ||
31 | # else | ||
32 | # define __P(args) () | ||
33 | # endif | ||
34 | #endif /*__P */ | ||
35 | |||
36 | #ifdef __cplusplus | ||
37 | extern "C" { | ||
38 | #endif | ||
39 | |||
40 | struct mu_timezone | ||
41 | { | ||
42 | int utc_offset; | ||
43 | /* Seconds east of UTC. */ | ||
44 | |||
45 | const char *tz_name; | ||
46 | /* Nickname for this timezone, if known. It is always considered | ||
47 | * to be a pointer to static string, so will never be freed. */ | ||
48 | }; | ||
49 | |||
50 | typedef struct mu_timezone mu_timezone; | ||
51 | |||
52 | extern int mu_parse_imap_date_time __P ((const char **p, struct tm * tm, | ||
53 | mu_timezone * tz)); | ||
54 | extern int mu_parse_ctime_date_time __P ((const char **p, struct tm * tm, | ||
55 | mu_timezone * tz)); | ||
56 | |||
57 | extern time_t mu_utc_offset __P ((void)); | ||
58 | extern time_t mu_tm2time __P ((struct tm * timeptr, mu_timezone * tz)); | ||
59 | |||
60 | #ifdef __cplusplus | ||
61 | } | ||
62 | #endif | ||
63 | |||
64 | #endif /* _MAILUTILS_MUTIL_H */ | ||
65 |
... | @@ -30,12 +30,11 @@ | ... | @@ -30,12 +30,11 @@ |
30 | 30 | ||
31 | #include <mailutils/address.h> | 31 | #include <mailutils/address.h> |
32 | #include <mailutils/error.h> | 32 | #include <mailutils/error.h> |
33 | #include <mailutils/mutil.h> | ||
33 | #include <mailbox0.h> | 34 | #include <mailbox0.h> |
34 | #include <registrar0.h> | 35 | #include <registrar0.h> |
35 | #include <imap0.h> | 36 | #include <imap0.h> |
36 | 37 | ||
37 | extern time_t mu_mktime __P((struct tm *timeptr, int tz)); | ||
38 | |||
39 | /* Functions to overload the mailbox_t API. */ | 38 | /* Functions to overload the mailbox_t API. */ |
40 | static void mailbox_imap_destroy __P ((mailbox_t)); | 39 | static void mailbox_imap_destroy __P ((mailbox_t)); |
41 | static int mailbox_imap_open __P ((mailbox_t, int)); | 40 | static int mailbox_imap_open __P ((mailbox_t, int)); |
... | @@ -91,13 +90,6 @@ static int imap_get_message0 __P ((msg_imap_t, message_t *)); | ... | @@ -91,13 +90,6 @@ static int imap_get_message0 __P ((msg_imap_t, message_t *)); |
91 | static int message_operation __P ((f_imap_t, msg_imap_t, char *, size_t, size_t *)); | 90 | static int message_operation __P ((f_imap_t, msg_imap_t, char *, size_t, size_t *)); |
92 | static void free_subparts __P ((msg_imap_t)); | 91 | static void free_subparts __P ((msg_imap_t)); |
93 | 92 | ||
94 | static const char *MONTHS[] = | ||
95 | { | ||
96 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
97 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | ||
98 | }; | ||
99 | |||
100 | |||
101 | /* Initialize the concrete object mailbox_t by overloading the function of the | 93 | /* Initialize the concrete object mailbox_t by overloading the function of the |
102 | structure. */ | 94 | structure. */ |
103 | int | 95 | int |
... | @@ -1232,67 +1224,6 @@ imap_envelope_sender (envelope_t envelope, char *buffer, size_t buflen, | ... | @@ -1232,67 +1224,6 @@ imap_envelope_sender (envelope_t envelope, char *buffer, size_t buflen, |
1232 | return status; | 1224 | return status; |
1233 | } | 1225 | } |
1234 | 1226 | ||
1235 | int | ||
1236 | imap_parse_date_time (const char **p, struct tm *tm, int *tz) | ||
1237 | { | ||
1238 | int year, mon, day, hour, min, sec; | ||
1239 | char zone[6] = "+0000"; /* ( "+" / "-" ) hhmm */ | ||
1240 | char month[5] = ""; | ||
1241 | int hh = 0; | ||
1242 | int mm = 0; | ||
1243 | int sign = 1; | ||
1244 | int scanned = 0, scanned3; | ||
1245 | int i; | ||
1246 | |||
1247 | day = mon = year = hour = min = sec = 0; | ||
1248 | |||
1249 | memset (tm, 0, sizeof (*tm)); | ||
1250 | |||
1251 | switch (sscanf (*p, | ||
1252 | "%2d-%3s-%4d%n %2d:%2d:%2d %5s%n", | ||
1253 | &day, month, &year, &scanned3, &hour, &min, &sec, zone, | ||
1254 | &scanned)) | ||
1255 | { | ||
1256 | case 3: | ||
1257 | scanned = scanned3; | ||
1258 | break; | ||
1259 | case 7: | ||
1260 | break; | ||
1261 | default: | ||
1262 | return -1; | ||
1263 | } | ||
1264 | |||
1265 | tm->tm_sec = sec; | ||
1266 | tm->tm_min = min; | ||
1267 | tm->tm_hour = hour; | ||
1268 | tm->tm_mday = day; | ||
1269 | |||
1270 | for (i = 0; i < 12; i++) | ||
1271 | { | ||
1272 | if (strncasecmp (month, MONTHS[i], 3) == 0) | ||
1273 | { | ||
1274 | mon = i; | ||
1275 | break; | ||
1276 | } | ||
1277 | } | ||
1278 | tm->tm_mon = mon; | ||
1279 | tm->tm_year = (year > 1900) ? year - 1900 : year; | ||
1280 | tm->tm_yday = 0; /* unknown. */ | ||
1281 | tm->tm_wday = 0; /* unknown. */ | ||
1282 | tm->tm_isdst = -1; /* unknown. */ | ||
1283 | |||
1284 | hh = (zone[1] - '0') * 10 + (zone[2] - '0'); | ||
1285 | mm = (zone[3] - '0') * 10 + (zone[4] - '0'); | ||
1286 | sign = (zone[0] == '-') ? -1 : +1; | ||
1287 | |||
1288 | if (tz) | ||
1289 | *tz = sign * (hh * 60 * 60 + mm * 60); | ||
1290 | |||
1291 | *p += scanned; | ||
1292 | |||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | static int | 1227 | static int |
1297 | imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, | 1228 | imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, |
1298 | size_t *plen) | 1229 | size_t *plen) |
... | @@ -1302,7 +1233,7 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, | ... | @@ -1302,7 +1233,7 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, |
1302 | m_imap_t m_imap = msg_imap->m_imap; | 1233 | m_imap_t m_imap = msg_imap->m_imap; |
1303 | f_imap_t f_imap = m_imap->f_imap; | 1234 | f_imap_t f_imap = m_imap->f_imap; |
1304 | struct tm tm; | 1235 | struct tm tm; |
1305 | int tz; | 1236 | mu_timezone tz; |
1306 | time_t now; | 1237 | time_t now; |
1307 | char datebuf[] = "mm-dd-yyyy hh:mm:ss +0000"; | 1238 | char datebuf[] = "mm-dd-yyyy hh:mm:ss +0000"; |
1308 | const char* date = datebuf; | 1239 | const char* date = datebuf; |
... | @@ -1326,10 +1257,10 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, | ... | @@ -1326,10 +1257,10 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, |
1326 | if (status != 0) | 1257 | if (status != 0) |
1327 | return status; | 1258 | return status; |
1328 | 1259 | ||
1329 | if (imap_parse_date_time(datep, &tm, &tz) != 0) | 1260 | if (mu_parse_imap_date_time(datep, &tm, &tz) != 0) |
1330 | now = (time_t)-1; | 1261 | now = (time_t)-1; |
1331 | else | 1262 | else |
1332 | now = mu_mktime (&tm, tz); | 1263 | now = mu_tm2time (&tm, &tz); |
1333 | 1264 | ||
1334 | /* if the time was unparseable, or mktime() didn't like what we | 1265 | /* if the time was unparseable, or mktime() didn't like what we |
1335 | parsed, use the calendar time. */ | 1266 | parsed, use the calendar time. */ | ... | ... |
mailbox/mutil.c
0 → 100644
1 | /* Copyright (C) 2001 Free Software Foundation, Inc. | ||
2 | A wrapper for mktime function allowing to specify the timezone. | ||
3 | |||
4 | The GNU C Library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public License as | ||
6 | published by the Free Software Foundation; either version 2 of the | ||
7 | License, or (at your option) any later version. | ||
8 | |||
9 | The GNU C Library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public | ||
15 | License along with the GNU C Library; see the file COPYING.LIB. If not, | ||
16 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
17 | Boston, MA 02111-1307, USA. */ | ||
18 | |||
19 | #if HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #ifdef HAVE_STRINGS_H | ||
25 | #include <strings.h> | ||
26 | #endif | ||
27 | #include <time.h> | ||
28 | |||
29 | #include <mailutils/mutil.h> | ||
30 | /* Convert struct tm into time_t, taking into account timezone offset. | ||
31 | |||
32 | mktime() always treats tm as if it was localtime, so convert it | ||
33 | to UTC, then adjust by the tm's real timezone, if it is known. | ||
34 | */ | ||
35 | time_t | ||
36 | mu_tm2time (struct tm *timeptr, mu_timezone* tz) | ||
37 | { | ||
38 | int offset = tz ? tz->utc_offset : 0; | ||
39 | |||
40 | return mktime(timeptr) - mu_utc_offset() + offset; | ||
41 | } | ||
42 | |||
43 | /* Convert time 0 at UTC to our localtime, that tells us the offset | ||
44 | of our current timezone from UTC. */ | ||
45 | time_t mu_utc_offset(void) | ||
46 | { | ||
47 | time_t t = 0; | ||
48 | struct tm* tm = gmtime(&t); | ||
49 | |||
50 | return mktime(tm); | ||
51 | } | ||
52 | |||
53 | static const char *months[] = | ||
54 | { | ||
55 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
56 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL | ||
57 | }; | ||
58 | |||
59 | static const char *wdays[] = | ||
60 | { | ||
61 | "Mon", "Teu", "Wed", "Thr", "Fri", "Sat", "Sun", NULL | ||
62 | }; | ||
63 | |||
64 | int | ||
65 | mu_parse_imap_date_time (const char **p, struct tm *tm, mu_timezone *tz) | ||
66 | { | ||
67 | int year, mon, day, hour, min, sec; | ||
68 | char zone[6] = "+0000"; /* ( "+" / "-" ) hhmm */ | ||
69 | char month[5] = ""; | ||
70 | int hh = 0; | ||
71 | int mm = 0; | ||
72 | int sign = 1; | ||
73 | int scanned = 0, scanned3; | ||
74 | int i; | ||
75 | int tzoffset; | ||
76 | |||
77 | day = mon = year = hour = min = sec = 0; | ||
78 | |||
79 | memset (tm, 0, sizeof (*tm)); | ||
80 | |||
81 | switch (sscanf (*p, | ||
82 | "%2d-%3s-%4d%n %2d:%2d:%2d %5s%n", | ||
83 | &day, month, &year, &scanned3, &hour, &min, &sec, zone, | ||
84 | &scanned)) | ||
85 | { | ||
86 | case 3: | ||
87 | scanned = scanned3; | ||
88 | break; | ||
89 | case 7: | ||
90 | break; | ||
91 | default: | ||
92 | return -1; | ||
93 | } | ||
94 | |||
95 | tm->tm_sec = sec; | ||
96 | tm->tm_min = min; | ||
97 | tm->tm_hour = hour; | ||
98 | tm->tm_mday = day; | ||
99 | |||
100 | for (i = 0; i < 12; i++) | ||
101 | { | ||
102 | if (strncasecmp (month, months[i], 3) == 0) | ||
103 | { | ||
104 | mon = i; | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | tm->tm_mon = mon; | ||
109 | tm->tm_year = (year > 1900) ? year - 1900 : year; | ||
110 | tm->tm_yday = 0; /* unknown. */ | ||
111 | tm->tm_wday = 0; /* unknown. */ | ||
112 | #if HAVE_TM_ISDST | ||
113 | tm->tm_isdst = -1; /* unknown. */ | ||
114 | #endif | ||
115 | |||
116 | hh = (zone[1] - '0') * 10 + (zone[2] - '0'); | ||
117 | mm = (zone[3] - '0') * 10 + (zone[4] - '0'); | ||
118 | sign = (zone[0] == '-') ? -1 : +1; | ||
119 | tzoffset = sign * (hh * 60 * 60 + mm * 60); | ||
120 | |||
121 | #if HAVE_TM_GMTOFFSET | ||
122 | tm->tm_gmtoffset = tzoffset; | ||
123 | #endif | ||
124 | |||
125 | if (tz) | ||
126 | { | ||
127 | tz->utc_offset = tzoffset; | ||
128 | tz->tz_name = NULL; | ||
129 | } | ||
130 | |||
131 | *p += scanned; | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /* "ctime" format is: Thu Jul 01 15:58:27 1999, with no trailing \n. */ | ||
137 | int | ||
138 | mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz) | ||
139 | { | ||
140 | int wday = 0; | ||
141 | int year = 0; | ||
142 | int mon = 0; | ||
143 | int day = 0; | ||
144 | int hour = 0; | ||
145 | int min = 0; | ||
146 | int sec = 0; | ||
147 | int n = 0; | ||
148 | int i; | ||
149 | char weekday[5] = ""; | ||
150 | char month[5] = ""; | ||
151 | |||
152 | if (sscanf (*p, "%3s %3s %2d %2d:%2d:%2d %d%n\n", | ||
153 | weekday, month, &day, &hour, &min, &sec, &year, &n) != 7) | ||
154 | return -1; | ||
155 | |||
156 | *p += n; | ||
157 | |||
158 | for (i = 0; i < 7; i++) | ||
159 | { | ||
160 | if (strncasecmp (weekday, wdays[i], 3) == 0) | ||
161 | { | ||
162 | wday = i; | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | for (i = 0; i < 12; i++) | ||
168 | { | ||
169 | if (strncasecmp (month, months[i], 3) == 0) | ||
170 | { | ||
171 | mon = i; | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if (tm) | ||
177 | { | ||
178 | memset (tm, 0, sizeof (struct tm)); | ||
179 | |||
180 | tm->tm_sec = sec; | ||
181 | tm->tm_min = min; | ||
182 | tm->tm_hour = hour; | ||
183 | tm->tm_mday = day; | ||
184 | tm->tm_wday = wday; | ||
185 | tm->tm_mon = mon; | ||
186 | tm->tm_year = (year > 1900) ? year - 1900 : year; | ||
187 | #ifdef HAVE_TM_ISDST | ||
188 | tm->tm_isdst = -1; /* unknown. */ | ||
189 | #endif | ||
190 | } | ||
191 | |||
192 | /* ctime has no timezone information, set tz to UTC if they ask. */ | ||
193 | if (tz) | ||
194 | memset (tz, 0, sizeof (struct mu_timezone)); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 |
... | @@ -1431,7 +1431,7 @@ struct tm | ... | @@ -1431,7 +1431,7 @@ struct tm |
1431 | }; | 1431 | }; |
1432 | #endif | 1432 | #endif |
1433 | 1433 | ||
1434 | int parse822_date_time(const char** p, const char* e, struct tm* tm) | 1434 | int parse822_date_time(const char** p, const char* e, struct tm* tm, struct mu_timezone* tz) |
1435 | { | 1435 | { |
1436 | /* date-time = [ day "," ] date time */ | 1436 | /* date-time = [ day "," ] date time */ |
1437 | 1437 | ||
... | @@ -1448,7 +1448,7 @@ int parse822_date_time(const char** p, const char* e, struct tm* tm) | ... | @@ -1448,7 +1448,7 @@ int parse822_date_time(const char** p, const char* e, struct tm* tm) |
1448 | int min = 0; | 1448 | int min = 0; |
1449 | int sec = 0; | 1449 | int sec = 0; |
1450 | 1450 | ||
1451 | int tz = 0; | 1451 | int tzoffset = 0; |
1452 | const char* tzname = 0; | 1452 | const char* tzname = 0; |
1453 | 1453 | ||
1454 | if((rc = parse822_day(p, e, &wday))) { | 1454 | if((rc = parse822_day(p, e, &wday))) { |
... | @@ -1468,7 +1468,7 @@ int parse822_date_time(const char** p, const char* e, struct tm* tm) | ... | @@ -1468,7 +1468,7 @@ int parse822_date_time(const char** p, const char* e, struct tm* tm) |
1468 | *p = save; | 1468 | *p = save; |
1469 | return rc; | 1469 | return rc; |
1470 | } | 1470 | } |
1471 | if((rc = parse822_time(p, e, &hour, &min, &sec, &tz, &tzname))) { | 1471 | if((rc = parse822_time(p, e, &hour, &min, &sec, &tzoffset, &tzname))) { |
1472 | *p = save; | 1472 | *p = save; |
1473 | return rc; | 1473 | return rc; |
1474 | } | 1474 | } |
... | @@ -1486,9 +1486,21 @@ int parse822_date_time(const char** p, const char* e, struct tm* tm) | ... | @@ -1486,9 +1486,21 @@ int parse822_date_time(const char** p, const char* e, struct tm* tm) |
1486 | tm->tm_min = min; | 1486 | tm->tm_min = min; |
1487 | tm->tm_sec = sec; | 1487 | tm->tm_sec = sec; |
1488 | 1488 | ||
1489 | #ifdef HAVE_TM_ISDST | ||
1489 | tm->tm_isdst = -1; /* unknown whether it's dst or not */ | 1490 | tm->tm_isdst = -1; /* unknown whether it's dst or not */ |
1490 | tm->tm_gmtoff = tz; | 1491 | #endif |
1492 | #ifdef HAVE_TM_GMTOFF | ||
1493 | tm->tm_gmtoff = tzoffset; | ||
1494 | #endif | ||
1495 | #ifdef HAVE_TM_ZONE | ||
1491 | tm->tm_zone = tzname; | 1496 | tm->tm_zone = tzname; |
1497 | #endif | ||
1498 | } | ||
1499 | |||
1500 | if(tz) | ||
1501 | { | ||
1502 | tz->utc_offset = tzoffset; | ||
1503 | tz->tz_name = tzname; | ||
1492 | } | 1504 | } |
1493 | 1505 | ||
1494 | return EOK; | 1506 | return EOK; | ... | ... |
-
Please register or sign in to post a comment