Implement INTERNALDATE in IMAP.
Showing
4 changed files
with
143 additions
and
7 deletions
1 | 2001-05-10 Alain Magloire | ||
2 | |||
3 | * imap4d/fetch.c: Implemented INTERNALDATE. | ||
4 | * mailbox/mbx_imap.c (imap_envelope_date): ctime() always | ||
5 | append a newline, nuke it. | ||
6 | * mailbox/stream.c (stream_read): If the amount requested is bigger | ||
7 | then the buffer cache size, bypass the buffering mechanism. | ||
8 | |||
1 | 2001-05-09 Alain Magloire | 9 | 2001-05-09 Alain Magloire |
2 | 10 | ||
3 | Take the missing pieces from the pop3d and make the | 11 | Take the missing pieces from the pop3d and make the | ... | ... |
... | @@ -371,6 +371,48 @@ fetch_flags (struct fetch_command *command, char *arg) | ... | @@ -371,6 +371,48 @@ fetch_flags (struct fetch_command *command, char *arg) |
371 | } | 371 | } |
372 | 372 | ||
373 | /* The internal date of the message. */ | 373 | /* The internal date of the message. */ |
374 | static const char *MONTHS[] = | ||
375 | { | ||
376 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
377 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | ||
378 | }; | ||
379 | #if 0 | ||
380 | /* The week day is recompute by mktime(). */ | ||
381 | static const char *WEEKDAYS[] = | ||
382 | { | ||
383 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" | ||
384 | }; | ||
385 | #endif | ||
386 | |||
387 | static const char * | ||
388 | get_timezone (const struct tm *tptr) | ||
389 | { | ||
390 | char tz[5]; | ||
391 | tz[0] = '\0'; | ||
392 | strftime (tz, sizeof (tz), "%Z", tptr); | ||
393 | if (strcasecmp (tz, "UT") == 0) | ||
394 | return "+0000"; | ||
395 | else if (strcasecmp (tz, "GMT") == 0) | ||
396 | return "+0000"; | ||
397 | else if (strcasecmp (tz, "EDT") == 0) | ||
398 | return "-0400"; | ||
399 | else if (strcasecmp (tz, "EST") == 0) | ||
400 | return "-0500"; | ||
401 | else if (strcasecmp (tz, "CDT") == 0) | ||
402 | return "-0500"; | ||
403 | else if (strcasecmp (tz, "CST") == 0) | ||
404 | return "-0600"; | ||
405 | else if (strcasecmp (tz, "MDT") == 0) | ||
406 | return "-0600"; | ||
407 | else if (strcasecmp (tz, "MST") == 0) | ||
408 | return "-0700"; | ||
409 | else if (strcasecmp (tz, "PDT") == 0) | ||
410 | return "-0700"; | ||
411 | else if (strcasecmp (tz, "PST") == 0) | ||
412 | return "-0800"; | ||
413 | return "-0000"; /* Oops. */ | ||
414 | } | ||
415 | |||
374 | /* FIXME: Wrong format? */ | 416 | /* FIXME: Wrong format? */ |
375 | static int | 417 | static int |
376 | fetch_internaldate (struct fetch_command *command, char *arg) | 418 | fetch_internaldate (struct fetch_command *command, char *arg) |
... | @@ -378,14 +420,71 @@ fetch_internaldate (struct fetch_command *command, char *arg) | ... | @@ -378,14 +420,71 @@ fetch_internaldate (struct fetch_command *command, char *arg) |
378 | char date[512]; | 420 | char date[512]; |
379 | envelope_t env = NULL; | 421 | envelope_t env = NULL; |
380 | message_t msg = NULL; | 422 | message_t msg = NULL; |
423 | struct tm tm; | ||
424 | struct tm *tptr; | ||
425 | (void)arg; | ||
381 | mailbox_get_message (mbox, command->msgno, &msg); | 426 | mailbox_get_message (mbox, command->msgno, &msg); |
382 | message_get_envelope (msg, &env); | 427 | message_get_envelope (msg, &env); |
383 | date[0] = '\0'; | 428 | date[0] = '\0'; |
384 | envelope_date (env, date, sizeof (date), NULL); | 429 | envelope_date (env, date, sizeof (date), NULL); |
430 | { | ||
431 | int year, mon, day, hour, min, sec; | ||
432 | int offt; | ||
433 | int i; | ||
434 | time_t now; | ||
435 | char month[5]; | ||
436 | char wday[5]; | ||
437 | |||
438 | month[0] = '\0'; | ||
439 | wday[0] = '\0'; | ||
440 | day = mon = year = hour = min = sec = offt = 0; | ||
441 | |||
442 | sscanf (date, "%3s %3s %2d %2d:%2d:%2d %d\n", wday, month, &day, | ||
443 | &hour, &min, &sec, &year); | ||
444 | tm.tm_sec = sec; | ||
445 | tm.tm_min = min; | ||
446 | tm.tm_hour = hour; | ||
447 | for (i = 0; i < 12; i++) | ||
448 | { | ||
449 | if (strncasecmp(month, MONTHS[i], 3) == 0) | ||
450 | { | ||
451 | mon = i; | ||
452 | break; | ||
453 | } | ||
454 | } | ||
455 | /* No need the week day is recompute by mktime. */ | ||
456 | #if 0 | ||
457 | for (i = 0; i < 7; i++) | ||
458 | { | ||
459 | if (strncasecmp(wday, WEEKDAYS[i], 3) == 0) | ||
460 | { | ||
461 | /* day = i; */ | ||
462 | break; | ||
463 | } | ||
464 | } | ||
465 | #endif | ||
466 | tm.tm_mday = day; | ||
467 | tm.tm_mon = mon; | ||
468 | tm.tm_year = (year > 1900) ? year - 1900 : year; | ||
469 | tm.tm_yday = 0; /* unknown. */ | ||
470 | tm.tm_wday = 0; /* unknown. */ | ||
471 | tm.tm_isdst = -1; /* unknown. */ | ||
472 | /* What to do the timezone? */ | ||
473 | now = mktime (&tm); | ||
474 | if (now == (time_t)-1) | ||
475 | { | ||
476 | /* Fall back to localtime. */ | ||
477 | now = time (NULL); | ||
478 | tptr = localtime (&now); | ||
479 | } | ||
480 | else | ||
481 | tptr = &tm; | ||
482 | } | ||
483 | strftime (date, sizeof (date), "%d-%b-%Y %X", &tm); | ||
385 | util_send ("%s", command->name); | 484 | util_send ("%s", command->name); |
386 | if (date[strlen (date) - 1] == '\n') | 485 | if (date[strlen (date) - 1] == '\n') |
387 | date[strlen (date) - 1] = '\0'; | 486 | date[strlen (date) - 1] = '\0'; |
388 | util_send (" \"%s\"", date); | 487 | util_send (" \"%s %s\"", date, get_timezone (&tm)); |
389 | return RESP_OK; | 488 | return RESP_OK; |
390 | } | 489 | } |
391 | 490 | ... | ... |
... | @@ -1275,9 +1275,13 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, | ... | @@ -1275,9 +1275,13 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, |
1275 | now = mktime (&tm); | 1275 | now = mktime (&tm); |
1276 | if (now == (time_t)-1) | 1276 | if (now == (time_t)-1) |
1277 | { | 1277 | { |
1278 | size_t len; | ||
1278 | /* Fall back to localtime. */ | 1279 | /* Fall back to localtime. */ |
1279 | now = time (NULL); | 1280 | now = time (NULL); |
1280 | snprintf (buffer, buflen, "%s", ctime(&now)); | 1281 | snprintf (buffer, buflen, "%s", ctime(&now)); |
1282 | len = strlen (buffer); | ||
1283 | if (len && buffer[len - 1] == '\n') | ||
1284 | buffer[len - 1] = '\0'; | ||
1281 | } | 1285 | } |
1282 | else | 1286 | else |
1283 | { | 1287 | { | ... | ... |
... | @@ -133,12 +133,16 @@ stream_setbufsiz (stream_t stream, size_t size) | ... | @@ -133,12 +133,16 @@ stream_setbufsiz (stream_t stream, size_t size) |
133 | } | 133 | } |
134 | 134 | ||
135 | /* We have to be clear about the buffering scheme, it is not designed to be | 135 | /* We have to be clear about the buffering scheme, it is not designed to be |
136 | use as a fully fledge buffer mechanism. It is rather turn for networking. | 136 | use as a fully fledge buffer mechanism. It is a simple mechanims for |
137 | Lots of code between POP and IMAP can be share this way. | 137 | networking. Lots of code between POP and IMAP can be share this way. |
138 | - First caveat; the offset as no meaning, it is up to the concrete | 138 | - First caveat; the offset as no meaning i.e. the code does move back or |
139 | _read() to return EISPIPE when error. | 139 | up the buffer, if the offset is different then the maintain interanl offset |
140 | the buffer is flush out and new read from the asking offset is done. It | ||
141 | is up to the concrete _read() to return EISPIPE when error. | ||
142 | |||
140 | - Again, this is targeting networking stream to make readline() | 143 | - Again, this is targeting networking stream to make readline() |
141 | a little bit more efficient, instead of reading a char at a time. */ | 144 | a little bit more efficient, instead of reading a char at a time. */ |
145 | |||
142 | int | 146 | int |
143 | stream_read (stream_t is, char *buf, size_t count, | 147 | stream_read (stream_t is, char *buf, size_t count, |
144 | off_t offset, size_t *pnread) | 148 | off_t offset, size_t *pnread) |
... | @@ -166,9 +170,30 @@ stream_read (stream_t is, char *buf, size_t count, | ... | @@ -166,9 +170,30 @@ stream_read (stream_t is, char *buf, size_t count, |
166 | size_t residue = count; | 170 | size_t residue = count; |
167 | int r; | 171 | int r; |
168 | 172 | ||
173 | /* If the amount requested is bigger then the buffer cache size | ||
174 | bypass it. Do no waste time and let it through. */ | ||
175 | if (count > is->rbuffer.bufsiz) | ||
176 | { | ||
177 | r = 0; | ||
178 | /* Drain the buffer first. */ | ||
179 | if (is->rbuffer.count > 0 && offset == is->rbuffer.offset) | ||
180 | { | ||
181 | (void)memcpy(buf, is->rbuffer.ptr, is->rbuffer.count); | ||
182 | is->rbuffer.offset += is->rbuffer.count; | ||
183 | residue -= is->rbuffer.count; | ||
184 | buf += is->rbuffer.count; | ||
185 | offset += is->rbuffer.count; | ||
186 | } | ||
187 | is->rbuffer.count = 0; | ||
188 | status = is->_read (is, buf, residue, offset, &r); | ||
189 | is->rbuffer.offset += r; | ||
190 | residue -= r; | ||
191 | if (pnread) | ||
192 | *pnread = count - residue; | ||
193 | return status; | ||
194 | } | ||
195 | |||
169 | /* Fill the buffer, do not want to start empty hand. */ | 196 | /* Fill the buffer, do not want to start empty hand. */ |
170 | /* if (is->rbuffer.count <= 0 || offset < is->rbuffer.offset */ | ||
171 | /* || offset > (is->rbuffer.offset + is->rbuffer.count)) */ | ||
172 | if (is->rbuffer.count <= 0 || offset != is->rbuffer.offset) | 197 | if (is->rbuffer.count <= 0 || offset != is->rbuffer.offset) |
173 | { | 198 | { |
174 | status = refill (is, offset); | 199 | status = refill (is, offset); | ... | ... |
-
Please register or sign in to post a comment