Commit bc49501d bc49501df35333b6f45b526e6dbc1850e434d9a2 by Alain Magloire

Implement INTERNALDATE in IMAP.

1 parent 70a288c9
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);
......