Commit 4a151fd8 4a151fd82add56d993437bcceb969a7cf8dd3bdf by Sergey Poznyakoff

Bugfixes.

* imap4d/util.c (util_parse_internal_date): Use MU_DATETIME_INTERNALDATE
format.
* include/mailutils/util.h (MU_DATETIME_IMAP_SEARCH): Rename to
MU_DATETIME_INTERNALDATE (previous incorrect definition removed).
(MU_DATETIME_RFC822): New format.
* libmailutils/address/address.c: Accessors for local_part and
domain invalidate email field.
(validate_email): New static function.
(mu_address_sget_email): Reconstruct email, if necessary.
(mu_address_format_string): Likewise.
* libmailutils/base/date.c (mu_c_streamftime): Allow for %$ specifier
for compatibility with mu_scan_datetime.
(mu_scan_datetime): Use %$ to idicate optional end of string.
* libmailutils/tests/scantime.at: Update.
* libproto/imap/fetch.c (_fill_response): Use MU_DATETIME_RFC822 format.
* mu/imap.c (fetch_response_printer): Print subject.
1 parent 93717359
...@@ -374,7 +374,7 @@ util_parse_internal_date (char *date, time_t *timep, ...@@ -374,7 +374,7 @@ util_parse_internal_date (char *date, time_t *timep,
374 mu_timezone tz; 374 mu_timezone tz;
375 time_t time; 375 time_t time;
376 376
377 if (mu_scan_datetime (date, MU_DATETIME_IMAP_SEARCH, &tm, &tz, NULL)) 377 if (mu_scan_datetime (date, MU_DATETIME_INTERNALDATE, &tm, &tz, NULL))
378 return 1; 378 return 1;
379 379
380 adjust_tm (&tm, &tz, flag); 380 adjust_tm (&tm, &tz, flag);
......
...@@ -74,8 +74,9 @@ int mu_scan_datetime (const char *input, const char *fmt, struct tm *tm, ...@@ -74,8 +74,9 @@ int mu_scan_datetime (const char *input, const char *fmt, struct tm *tm,
74 /* Common datetime formats: */ 74 /* Common datetime formats: */
75 #define MU_DATETIME_FROM "%a %b %e %H:%M:%S %Y" 75 #define MU_DATETIME_FROM "%a %b %e %H:%M:%S %Y"
76 #define MU_DATETIME_IMAP "%d-%b-%Y %H:%M:%S %z" 76 #define MU_DATETIME_IMAP "%d-%b-%Y %H:%M:%S %z"
77 #define MU_DATETIME_IMAP_SEARCH "%d-%b-%Y%? %H:%M:%S %z" 77 #define MU_DATETIME_INTERNALDATE "%d-%b-%Y%$ %H:%M:%S %z"
78 #define MU_DATETIME_INTERNALDATE "%a, %e %b %Y %H:%M:%S %z" 78 /* FIXME: [%a, ] part is actually optional */
79 #define MU_DATETIME_RFC822 "%a, %e %b %Y %H:%M:%S %z"
79 80
80 81
81 /* ----------------------- */ 82 /* ----------------------- */
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 Lesser General Public License for more details. 13 Lesser General Public License for more details.
14 14
15 You should have received a copy of the GNU Lesser General 15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see 16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */ 17 <http://www.gnu.org/licenses/>. */
18 18
19 #ifdef HAVE_CONFIG_H 19 #ifdef HAVE_CONFIG_H
...@@ -213,11 +213,11 @@ mu_address_concatenate (mu_address_t to, mu_address_t *from) ...@@ -213,11 +213,11 @@ mu_address_concatenate (mu_address_t to, mu_address_t *from)
213 return 0; 213 return 0;
214 } 214 }
215 215
216 mu_address_t 216 mu_address_t
217 _address_get_nth (mu_address_t addr, size_t no) 217 _address_get_nth (mu_address_t addr, size_t no)
218 { 218 {
219 int i; 219 int i;
220 220
221 for (i = 1; addr; addr = addr->next, i++) 221 for (i = 1; addr; addr = addr->next, i++)
222 if (i == no) 222 if (i == no)
223 break; 223 break;
...@@ -239,13 +239,13 @@ mu_address_get_nth (mu_address_t addr, size_t no, mu_address_t *pret) ...@@ -239,13 +239,13 @@ mu_address_get_nth (mu_address_t addr, size_t no, mu_address_t *pret)
239 #define AC4(a,b,c,d) a ## b ## c ## d 239 #define AC4(a,b,c,d) a ## b ## c ## d
240 #define ACCESSOR(action,field) AC4(mu_address_,action,_,field) 240 #define ACCESSOR(action,field) AC4(mu_address_,action,_,field)
241 241
242 #define DECL_SET(field) \ 242 #define DECL_SET(field) \
243 int \ 243 int \
244 ACCESSOR(set, field) (mu_address_t addr, size_t no, const char *buf) \ 244 ACCESSOR(set, field) (mu_address_t addr, size_t no, const char *buf) \
245 { \ 245 { \
246 char *s; \ 246 char *s; \
247 mu_address_t subaddr; \ 247 mu_address_t subaddr; \
248 \ 248 \
249 if (addr == NULL) \ 249 if (addr == NULL) \
250 return EINVAL; \ 250 return EINVAL; \
251 \ 251 \
...@@ -253,22 +253,59 @@ ACCESSOR(set, field) (mu_address_t addr, size_t no, const char *buf) \ ...@@ -253,22 +253,59 @@ ACCESSOR(set, field) (mu_address_t addr, size_t no, const char *buf) \
253 if (!subaddr) \ 253 if (!subaddr) \
254 return MU_ERR_NOENT; \ 254 return MU_ERR_NOENT; \
255 \ 255 \
256 s = strdup (buf); \ 256 if (buf) \
257 if (!s) \ 257 { \
258 return errno; \ 258 s = strdup (buf); \
259 \ 259 if (!s) \
260 return errno; \
261 } \
262 else \
263 s = (char *) buf; \
264 \
260 free (subaddr->field); \ 265 free (subaddr->field); \
261 subaddr->field = s; \ 266 subaddr->field = s; \
262 \ 267 \
263 return 0; \ 268 return 0; \
264 } 269 }
265 270
271 #define DECL_SET_EI(field) \
272 int \
273 ACCESSOR(set, field) (mu_address_t addr, size_t no, const char *buf) \
274 { \
275 char *s; \
276 mu_address_t subaddr; \
277 \
278 if (addr == NULL) \
279 return EINVAL; \
280 \
281 subaddr = _address_get_nth (addr, no); \
282 if (!subaddr) \
283 return MU_ERR_NOENT; \
284 \
285 if (buf) \
286 { \
287 s = strdup (buf); \
288 if (!s) \
289 return errno; \
290 } \
291 else \
292 s = (char *) buf; \
293 \
294 free (subaddr->field); \
295 subaddr->field = s; \
296 \
297 free (subaddr->email); \
298 subaddr->email = NULL; \
299 \
300 return 0; \
301 }
302
266 #define DECL_SGET(field) \ 303 #define DECL_SGET(field) \
267 int \ 304 int \
268 ACCESSOR(sget,field) (mu_address_t addr, size_t no, char const **sptr) \ 305 ACCESSOR(sget,field) (mu_address_t addr, size_t no, char const **sptr) \
269 { \ 306 { \
270 mu_address_t subaddr; \ 307 mu_address_t subaddr; \
271 \ 308 \
272 if (addr == NULL) \ 309 if (addr == NULL) \
273 return EINVAL; \ 310 return EINVAL; \
274 \ 311 \
...@@ -287,7 +324,7 @@ ACCESSOR(get,field) (mu_address_t addr, size_t no, char *buf, size_t len, \ ...@@ -287,7 +324,7 @@ ACCESSOR(get,field) (mu_address_t addr, size_t no, char *buf, size_t len, \
287 size_t i; \ 324 size_t i; \
288 const char *str; \ 325 const char *str; \
289 int status = ACCESSOR(sget, field) (addr, no, &str); \ 326 int status = ACCESSOR(sget, field) (addr, no, &str); \
290 \ 327 \
291 if (status) \ 328 if (status) \
292 return status; \ 329 return status; \
293 \ 330 \
...@@ -322,7 +359,13 @@ ACCESSOR(aget, field) (mu_address_t addr, size_t no, char **buf) \ ...@@ -322,7 +359,13 @@ ACCESSOR(aget, field) (mu_address_t addr, size_t no, char **buf) \
322 DECL_SET(field) \ 359 DECL_SET(field) \
323 DECL_SGET(field) \ 360 DECL_SGET(field) \
324 DECL_GET(field) \ 361 DECL_GET(field) \
325 DECL_AGET(field) 362 DECL_AGET(field)
363
364 #define DECL_ACCESSORS_EI(field) \
365 DECL_SET_EI(field) \
366 DECL_SGET(field) \
367 DECL_GET(field) \
368 DECL_AGET(field)
326 369
327 370
328 371
...@@ -330,15 +373,115 @@ DECL_AGET(field) ...@@ -330,15 +373,115 @@ DECL_AGET(field)
330 DECL_ACCESSORS(personal) 373 DECL_ACCESSORS(personal)
331 /* Comments */ 374 /* Comments */
332 DECL_ACCESSORS(comments) 375 DECL_ACCESSORS(comments)
333 /* Email */
334 DECL_ACCESSORS(email)
335 /* Local part */ 376 /* Local part */
336 DECL_ACCESSORS(local_part) 377 DECL_ACCESSORS_EI(local_part)
337 /* Domain */ 378 /* Domain */
338 DECL_ACCESSORS(domain) 379 DECL_ACCESSORS_EI(domain)
339 /* Route */ 380 /* Route */
340 DECL_ACCESSORS(route) 381 DECL_ACCESSORS(route)
341 382
383 /* Email */
384 int
385 mu_address_set_email (mu_address_t addr, size_t no, const char *buf)
386 {
387 char *s;
388 mu_address_t subaddr;
389
390 if (addr == NULL)
391 return EINVAL;
392
393 subaddr = _address_get_nth (addr, no);
394 if (!subaddr)
395 return MU_ERR_NOENT;
396
397 if (buf)
398 {
399 s = strdup (buf);
400 if (!s)
401 return errno;
402 }
403 else
404 s = (char *) buf;
405
406 free (subaddr->email);
407 subaddr->email = s;
408
409 free (subaddr->local_part);
410 free (subaddr->domain);
411 if (s)
412 {
413 char *p = strchr (subaddr->email, '@');
414 if (p)
415 {
416 size_t len = p - subaddr->email;
417 subaddr->local_part = malloc (len + 1);
418 if (subaddr->local_part)
419 {
420 memcpy (subaddr->local_part, p, len);
421 subaddr->local_part[len] = 0;
422 }
423 subaddr->domain = strdup (p + 1);
424 }
425 }
426 else
427 {
428 subaddr->local_part = NULL;
429 subaddr->domain = NULL;
430 }
431
432 return 0;
433 }
434
435 static int
436 validate_email (mu_address_t subaddr)
437 {
438 if (!subaddr->email)
439 {
440 if (subaddr->local_part)
441 {
442 const char *domain;
443
444 if (subaddr->domain)
445 domain = subaddr->domain;
446 else
447 mu_get_user_email_domain (&domain);
448 if (domain)
449 {
450 char *p;
451 subaddr->email = malloc (strlen (subaddr->local_part) +
452 strlen (domain) + 2);
453 if (!subaddr->email)
454 return ENOMEM;
455 p = mu_stpcpy (subaddr->email, subaddr->local_part);
456 *p++ = '@';
457 mu_stpcpy (p, (char*) domain);
458 }
459 }
460 }
461 return 0;
462 }
463
464 int
465 mu_address_sget_email (mu_address_t addr, size_t no, char const **sptr)
466 {
467 mu_address_t subaddr;
468
469 if (addr == NULL)
470 return EINVAL;
471
472 subaddr = _address_get_nth (addr, no);
473 if (!subaddr)
474 return MU_ERR_NOENT;
475
476 validate_email (subaddr);
477 *sptr = subaddr->email;
478 return 0;
479 }
480
481 DECL_GET(email)
482 DECL_AGET(email)
483
484
342 485
343 486
344 #define format_char(c) do {\ 487 #define format_char(c) do {\
...@@ -349,7 +492,7 @@ DECL_ACCESSORS(route) ...@@ -349,7 +492,7 @@ DECL_ACCESSORS(route)
349 }\ 492 }\
350 else\ 493 else\
351 rc++;\ 494 rc++;\
352 } while(0) 495 } while(0)
353 496
354 #define format_string(str) do {\ 497 #define format_string(str) do {\
355 if (buflen) \ 498 if (buflen) \
...@@ -361,22 +504,23 @@ DECL_ACCESSORS(route) ...@@ -361,22 +504,23 @@ DECL_ACCESSORS(route)
361 else\ 504 else\
362 rc += strlen (str);\ 505 rc += strlen (str);\
363 } while (0) 506 } while (0)
364 507
365 size_t 508 size_t
366 mu_address_format_string (mu_address_t addr, char *buf, size_t buflen) 509 mu_address_format_string (mu_address_t addr, char *buf, size_t buflen)
367 { 510 {
368 int rc = 0; 511 int rc = 0;
369 int comma = 0; 512 int comma = 0;
370 513
371 for (;addr; addr = addr->next) 514 for (;addr; addr = addr->next)
372 { 515 {
516 validate_email (addr);
373 if (addr->email) 517 if (addr->email)
374 { 518 {
375 int space = 0; 519 int space = 0;
376 520
377 if (comma) 521 if (comma)
378 format_char (','); 522 format_char (',');
379 523
380 if (addr->personal) 524 if (addr->personal)
381 { 525 {
382 format_char ('"'); 526 format_char ('"');
...@@ -384,7 +528,7 @@ mu_address_format_string (mu_address_t addr, char *buf, size_t buflen) ...@@ -384,7 +528,7 @@ mu_address_format_string (mu_address_t addr, char *buf, size_t buflen)
384 format_char ('"'); 528 format_char ('"');
385 space++; 529 space++;
386 } 530 }
387 531
388 if (addr->comments) 532 if (addr->comments)
389 { 533 {
390 if (space) 534 if (space)
...@@ -394,7 +538,7 @@ mu_address_format_string (mu_address_t addr, char *buf, size_t buflen) ...@@ -394,7 +538,7 @@ mu_address_format_string (mu_address_t addr, char *buf, size_t buflen)
394 format_char (')'); 538 format_char (')');
395 space++; 539 space++;
396 } 540 }
397 541
398 if (space) 542 if (space)
399 format_char (' '); 543 format_char (' ');
400 format_char ('<'); 544 format_char ('<');
...@@ -435,14 +579,14 @@ int ...@@ -435,14 +579,14 @@ int
435 mu_address_is_group (mu_address_t addr, size_t no, int *yes) 579 mu_address_is_group (mu_address_t addr, size_t no, int *yes)
436 { 580 {
437 mu_address_t subaddr; 581 mu_address_t subaddr;
438 582
439 if (addr == NULL) 583 if (addr == NULL)
440 return EINVAL; 584 return EINVAL;
441 585
442 subaddr = _address_get_nth (addr, no); 586 subaddr = _address_get_nth (addr, no);
443 if (!subaddr) 587 if (!subaddr)
444 return MU_ERR_NOENT; 588 return MU_ERR_NOENT;
445 589
446 if (yes) 590 if (yes)
447 *yes = _address_is_group (subaddr); 591 *yes = _address_is_group (subaddr);
448 return 0; 592 return 0;
...@@ -465,7 +609,7 @@ mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t *n) ...@@ -465,7 +609,7 @@ mu_address_to_string (mu_address_t addr, char *buf, size_t len, size_t *n)
465 return ENOMEM; 609 return ENOMEM;
466 mu_address_format_string (addr, addr->addr, i+1); 610 mu_address_format_string (addr, addr->addr, i+1);
467 } 611 }
468 612
469 i = mu_cpystr (buf, addr->addr, len); 613 i = mu_cpystr (buf, addr->addr, len);
470 if (n) 614 if (n)
471 *n = i; 615 *n = i;
...@@ -562,12 +706,12 @@ mu_address_dup (mu_address_t src) ...@@ -562,12 +706,12 @@ mu_address_dup (mu_address_t src)
562 706
563 return dst; 707 return dst;
564 } 708 }
565 709
566 int 710 int
567 mu_address_union (mu_address_t *a, mu_address_t b) 711 mu_address_union (mu_address_t *a, mu_address_t b)
568 { 712 {
569 mu_address_t last = NULL; 713 mu_address_t last = NULL;
570 714
571 if (!a || !b) 715 if (!a || !b)
572 return EINVAL; 716 return EINVAL;
573 717
...@@ -601,4 +745,3 @@ mu_address_union (mu_address_t *a, mu_address_t b) ...@@ -601,4 +745,3 @@ mu_address_union (mu_address_t *a, mu_address_t b)
601 } 745 }
602 return 0; 746 return 0;
603 } 747 }
604
......
...@@ -515,6 +515,10 @@ mu_c_streamftime (mu_stream_t str, const char *fmt, struct tm *input_tm, ...@@ -515,6 +515,10 @@ mu_c_streamftime (mu_stream_t str, const char *fmt, struct tm *input_tm,
515 /* A literal '%' character. */ 515 /* A literal '%' character. */
516 rc = mu_stream_write (str, "%", 1, NULL); 516 rc = mu_stream_write (str, "%", 1, NULL);
517 break; 517 break;
518
519 case '$':
520 /* Ignored for compatibilty with mu_scan_datetime */
521 break;
518 522
519 case '+': 523 case '+':
520 /* Not supported (date and time in date(1) format. */ 524 /* Not supported (date and time in date(1) format. */
...@@ -849,7 +853,7 @@ mu_scan_datetime (const char *input, const char *fmt, ...@@ -849,7 +853,7 @@ mu_scan_datetime (const char *input, const char *fmt,
849 rc = MU_ERR_PARSE; 853 rc = MU_ERR_PARSE;
850 break; 854 break;
851 855
852 case '?': 856 case '$':
853 eof_ok = 1; 857 eof_ok = 1;
854 break; 858 break;
855 } 859 }
......
...@@ -47,7 +47,7 @@ sec=1,min=55,hour=11,mday=11,mon=10,year=111,wday=5,tz=3600 ...@@ -47,7 +47,7 @@ sec=1,min=55,hour=11,mday=11,mon=10,year=111,wday=5,tz=3600
47 ]) 47 ])
48 48
49 SCANTIME([IMAP search time format],[imap-search], 49 SCANTIME([IMAP search time format],[imap-search],
50 [%d-%b-%Y%? %H:%M:%S %z], 50 [%d-%b-%Y%$ %H:%M:%S %z],
51 [03-May-2011 13:25:26 +0100 51 [03-May-2011 13:25:26 +0100
52 03-May-2011], 52 03-May-2011],
53 [sec=26,min=25,hour=13,mday=3,mon=4,year=111,wday=2,tz=3600 53 [sec=26,min=25,hour=13,mday=3,mon=4,year=111,wday=2,tz=3600
......
...@@ -472,7 +472,7 @@ _fill_response (void *item, void *data) ...@@ -472,7 +472,7 @@ _fill_response (void *item, void *data)
472 else 472 else
473 { 473 {
474 if (mu_scan_datetime (elt->v.string, 474 if (mu_scan_datetime (elt->v.string,
475 MU_DATETIME_IMAP, 475 MU_DATETIME_RFC822,
476 &env->envelope->date, 476 &env->envelope->date,
477 &env->envelope->tz, NULL)) 477 &env->envelope->tz, NULL))
478 rc = MU_ERR_FAILURE; 478 rc = MU_ERR_FAILURE;
......
...@@ -266,6 +266,9 @@ fetch_response_printer (void *item, void *data) ...@@ -266,6 +266,9 @@ fetch_response_printer (void *item, void *data)
266 mu_stream_printf (str, "ENVELOPE:\n"); 266 mu_stream_printf (str, "ENVELOPE:\n");
267 267
268 format_date (str, "date", &resp->envelope.date, &resp->envelope.tz); 268 format_date (str, "date", &resp->envelope.date, &resp->envelope.tz);
269 mu_stream_printf (str, " subject = %s\n",
270 resp->envelope.subject ?
271 resp->envelope.subject : "NIL");
269 272
270 format_email (str, "from", resp->envelope.from); 273 format_email (str, "from", resp->envelope.from);
271 format_email (str, "sender", resp->envelope.sender); 274 format_email (str, "sender", resp->envelope.sender);
......