Implement the mu_mailbox_get_uidls function and --uidl option in movemail.
* include/mailutils/mailbox.h (MU_UIDL_LENGH) (MU_UIDL_BUFFER_SIZE): New defines. (struct mu_uidl): New struct. (mu_mailbox_get_uidls): New prototype. * libproto/include/mailbox0.h (struct _mu_mailbox): New member _get_uidls. * libproto/pop/mbox.c: Implement _get_uidls. * libproto/pop/folder.c: Include mailutils/cctype.h. * mailbox/mailbox.c (mu_mailbox_get_uidls): New function. * movemail/movemail.c: Implement --uidl option: use UIDLs to avoid downloading same messages twice. Based on the idea of Alfred M. Szmidt. Implement --verbose option. * libproto/imap/mbox.c: Fix comment. * NEWS: Update. * doc/texinfo/programs.texi: Update.
Showing
9 changed files
with
305 additions
and
27 deletions
1 | GNU mailutils NEWS -- history of user-visible changes. 2009-05-25 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2009-07-08 |
2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, | 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, |
3 | 2008, 2009 Free Software Foundation, Inc. | 3 | 2008, 2009 Free Software Foundation, Inc. |
4 | See the end of file for copying conditions. | 4 | See the end of file for copying conditions. |
... | @@ -18,6 +18,15 @@ All MU client utilities make use of the user ticket file, | ... | @@ -18,6 +18,15 @@ All MU client utilities make use of the user ticket file, |
18 | New configuration file entities allow to modify user's personal | 18 | New configuration file entities allow to modify user's personal |
19 | namespace and visible home directory. | 19 | namespace and visible home directory. |
20 | 20 | ||
21 | * Movemail | ||
22 | |||
23 | When called with the `--uidl' command line option, the utility tries | ||
24 | to avoid copying the message if a message with the same UIDL already | ||
25 | exists in the destination mailbox. | ||
26 | |||
27 | The `--verbose' command line option enables outputting additional | ||
28 | information. | ||
29 | |||
21 | * API | 30 | * API |
22 | 31 | ||
23 | * Wicket/Ticket functions | 32 | * Wicket/Ticket functions |
... | @@ -50,6 +59,10 @@ The `remote+sendmail', `remote+prog' and `remote+smtp' mailbox formats | ... | @@ -50,6 +59,10 @@ The `remote+sendmail', `remote+prog' and `remote+smtp' mailbox formats |
50 | are deprecated in favor of `sendmail', `prog' and `smtp', | 59 | are deprecated in favor of `sendmail', `prog' and `smtp', |
51 | correspondingly. | 60 | correspondingly. |
52 | 61 | ||
62 | ** New functions | ||
63 | |||
64 | - mu_mailbox_get_uidls | ||
65 | |||
53 | ** Removed functions | 66 | ** Removed functions |
54 | 67 | ||
55 | - mu_sieve_get_ticket | 68 | - mu_sieve_get_ticket | ... | ... |
1 | @c This is part of the GNU Mailutils manual. | 1 | @c This is part of the GNU Mailutils manual. |
2 | @c Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 | 2 | @c Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 |
3 | @c Free Software Foundation, Inc. | 3 | @c Free Software Foundation, Inc. |
4 | @c See file mailutils.texi for copying conditions. | 4 | @c See file mailutils.texi for copying conditions. |
5 | @comment ******************************************************************* | 5 | @comment ******************************************************************* |
... | @@ -4034,6 +4034,15 @@ If @var{bool} is @samp{true}, reverse message sorting order. | ... | @@ -4034,6 +4034,15 @@ If @var{bool} is @samp{true}, reverse message sorting order. |
4034 | If @var{bool} is @samp{true}, output information used by Emacs rmail interface. | 4034 | If @var{bool} is @samp{true}, output information used by Emacs rmail interface. |
4035 | @end deffn | 4035 | @end deffn |
4036 | 4036 | ||
4037 | @deffn {Movemail Config} uidl @var{bool} | ||
4038 | Avoid copying the message if a message with the same UIDL already | ||
4039 | exists in the destination mailbox. | ||
4040 | @end deffn | ||
4041 | |||
4042 | @deffn {Movemail Config} verbose @var{level} | ||
4043 | Set verbosity level. | ||
4044 | @end deffn | ||
4045 | |||
4037 | @multitable @columnfractions 0.3 0.6 | 4046 | @multitable @columnfractions 0.3 0.6 |
4038 | @headitem Statement @tab Reference | 4047 | @headitem Statement @tab Reference |
4039 | @item debug @tab @xref{Debug Statement}. | 4048 | @item debug @tab @xref{Debug Statement}. |
... | @@ -4147,9 +4156,6 @@ Preserve the source mailbox | ... | @@ -4147,9 +4156,6 @@ Preserve the source mailbox |
4147 | @itemx --reverse | 4156 | @itemx --reverse |
4148 | Reverse the sorting order | 4157 | Reverse the sorting order |
4149 | 4158 | ||
4150 | @item --license | ||
4151 | Print GPL license and exit | ||
4152 | |||
4153 | @item --external-locker=@var{program} | 4159 | @item --external-locker=@var{program} |
4154 | Use given @var{program} as the external locker program. | 4160 | Use given @var{program} as the external locker program. |
4155 | 4161 | ||
... | @@ -4177,6 +4183,13 @@ Use specified URL as a mailspool directory | ... | @@ -4177,6 +4183,13 @@ Use specified URL as a mailspool directory |
4177 | @item --tls[=@var{bool}] | 4183 | @item --tls[=@var{bool}] |
4178 | Enable (default) or disable TLS support | 4184 | Enable (default) or disable TLS support |
4179 | 4185 | ||
4186 | @item -u | ||
4187 | @item --uidl | ||
4188 | Use UIDLs to avoid downloading the same message twice. | ||
4189 | |||
4190 | @item -v | ||
4191 | @item --verbose | ||
4192 | Increase verbosity level. | ||
4180 | @end table | 4193 | @end table |
4181 | 4194 | ||
4182 | @page | 4195 | @page | ... | ... |
... | @@ -66,6 +66,16 @@ extern int mu_mailbox_sync (mu_mailbox_t); | ... | @@ -66,6 +66,16 @@ extern int mu_mailbox_sync (mu_mailbox_t); |
66 | extern int mu_mailbox_save_attributes (mu_mailbox_t) | 66 | extern int mu_mailbox_save_attributes (mu_mailbox_t) |
67 | __attribute__ ((deprecated)); | 67 | __attribute__ ((deprecated)); |
68 | 68 | ||
69 | #define MU_UIDL_LENGTH 70 | ||
70 | #define MU_UIDL_BUFFER_SIZE (MU_UIDL_LENGTH+1) | ||
71 | |||
72 | struct mu_uidl | ||
73 | { | ||
74 | size_t msgno; | ||
75 | char uidl[MU_UIDL_BUFFER_SIZE]; | ||
76 | }; | ||
77 | extern int mu_mailbox_get_uidls (mu_mailbox_t, mu_list_t *); | ||
78 | |||
69 | /* Update and scanning. */ | 79 | /* Update and scanning. */ |
70 | extern int mu_mailbox_get_size (mu_mailbox_t, mu_off_t *size); | 80 | extern int mu_mailbox_get_size (mu_mailbox_t, mu_off_t *size); |
71 | extern int mu_mailbox_is_updated (mu_mailbox_t); | 81 | extern int mu_mailbox_is_updated (mu_mailbox_t); | ... | ... |
... | @@ -719,14 +719,14 @@ imap_scan (mu_mailbox_t mailbox, size_t msgno, size_t *pcount) | ... | @@ -719,14 +719,14 @@ imap_scan (mu_mailbox_t mailbox, size_t msgno, size_t *pcount) |
719 | return imap_scan0 (mailbox, msgno, pcount , 1); | 719 | return imap_scan0 (mailbox, msgno, pcount , 1); |
720 | } | 720 | } |
721 | 721 | ||
722 | /* Usually when this function is call it is because there is an oberver | 722 | /* Normally this function is called when an observer is trying to build |
723 | attach an the client is try to build some sort of list/tree header | 723 | some sort of list/tree header as the scanning progresses. But doing |
724 | as the scanning progress. But doing this for each message can be | 724 | this for each message can be time consuming and inefficient. So we |
725 | time consuming and inefficient. So we bundle all the request | 725 | bundle all requests into one and ask the server for everything: |
726 | into one and ask the server for everything "FETCH 1:*". The good | 726 | "FETCH 1:*". The good side is that everything will be faster and we |
727 | side is that everything will be faster and we do not do lot of small | 727 | do not do lots of small transcations, but rather a big one. The bad |
728 | transcation but rather a big one. The bad thing is that every thing | 728 | side is that everything will be cached in the structure using a lot of |
729 | will be cache in the structure using a lot of memory. */ | 729 | memory. */ |
730 | static int | 730 | static int |
731 | imap_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int notif) | 731 | imap_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int notif) |
732 | { | 732 | { | ... | ... |
... | @@ -74,6 +74,7 @@ struct _mu_mailbox | ... | @@ -74,6 +74,7 @@ struct _mu_mailbox |
74 | int (*_get_size) (mu_mailbox_t, mu_off_t *); | 74 | int (*_get_size) (mu_mailbox_t, mu_off_t *); |
75 | 75 | ||
76 | int (*_quick_get_message) (mu_mailbox_t, mu_message_qid_t, mu_message_t *); | 76 | int (*_quick_get_message) (mu_mailbox_t, mu_message_qid_t, mu_message_t *); |
77 | int (*_get_uidls) (mu_mailbox_t, mu_list_t); | ||
77 | }; | 78 | }; |
78 | 79 | ||
79 | #ifdef __cplusplus | 80 | #ifdef __cplusplus | ... | ... |
... | @@ -34,7 +34,8 @@ | ... | @@ -34,7 +34,8 @@ |
34 | #include <mailutils/auth.h> | 34 | #include <mailutils/auth.h> |
35 | #include <mailutils/errno.h> | 35 | #include <mailutils/errno.h> |
36 | #include <mailutils/mailbox.h> | 36 | #include <mailutils/mailbox.h> |
37 | #include <mailutils/mutil.h> | 37 | #include <mailutils/cstr.h> |
38 | #include <mailutils/cctype.h> | ||
38 | 39 | ||
39 | #include <folder0.h> | 40 | #include <folder0.h> |
40 | #include <registrar0.h> | 41 | #include <registrar0.h> | ... | ... |
... | @@ -55,6 +55,7 @@ | ... | @@ -55,6 +55,7 @@ |
55 | #include <mailutils/md5.h> | 55 | #include <mailutils/md5.h> |
56 | #include <mailutils/io.h> | 56 | #include <mailutils/io.h> |
57 | #include <mailutils/mutil.h> | 57 | #include <mailutils/mutil.h> |
58 | #include <mailutils/cstr.h> | ||
58 | #include <mailutils/cctype.h> | 59 | #include <mailutils/cctype.h> |
59 | 60 | ||
60 | #include <folder0.h> | 61 | #include <folder0.h> |
... | @@ -417,6 +418,57 @@ pop_destroy (mu_mailbox_t mbox) | ... | @@ -417,6 +418,57 @@ pop_destroy (mu_mailbox_t mbox) |
417 | } | 418 | } |
418 | } | 419 | } |
419 | 420 | ||
421 | static int | ||
422 | pop_mbox_uidls (mu_mailbox_t mbox, mu_list_t list) | ||
423 | { | ||
424 | pop_data_t mpd = mbox->data; | ||
425 | int status; | ||
426 | |||
427 | status = pop_writeline (mpd, "UIDL\r\n"); | ||
428 | CHECK_ERROR (mpd, status); | ||
429 | MU_DEBUG (mbox->debug, MU_DEBUG_PROT, mpd->buffer); | ||
430 | |||
431 | status = pop_write (mpd); | ||
432 | CHECK_EAGAIN (mpd, status); | ||
433 | |||
434 | status = pop_read_ack (mpd); | ||
435 | CHECK_EAGAIN (mpd, status); | ||
436 | MU_DEBUG (mpd->mbox->debug, MU_DEBUG_PROT, mpd->buffer); | ||
437 | |||
438 | if (!mu_c_strncasecmp (mpd->buffer, "+OK", 3)) | ||
439 | { | ||
440 | do | ||
441 | { | ||
442 | char *p; | ||
443 | size_t num; | ||
444 | struct mu_uidl *uidl; | ||
445 | |||
446 | status = pop_read_ack (mpd); | ||
447 | MU_DEBUG (mpd->mbox->debug, MU_DEBUG_PROT, mpd->buffer); | ||
448 | |||
449 | num = strtoul (mpd->buffer, &p, 10); | ||
450 | if (*p == 0 || !mu_isblank (*p)) | ||
451 | continue; /* FIXME: or error? */ | ||
452 | p = mu_str_skip_class (p, MU_CTYPE_SPACE); | ||
453 | mu_rtrim_cset (p, "\r\n"); | ||
454 | |||
455 | uidl = malloc (sizeof (uidl[0])); | ||
456 | if (!uidl) | ||
457 | { | ||
458 | status = ENOMEM; | ||
459 | break; | ||
460 | } | ||
461 | uidl->msgno = num; | ||
462 | strncpy (uidl->uidl, p, MU_UIDL_BUFFER_SIZE); | ||
463 | status = mu_list_append (list, uidl); | ||
464 | } | ||
465 | while (mpd->nl); | ||
466 | } | ||
467 | else | ||
468 | status = ENOSYS; | ||
469 | return status; | ||
470 | } | ||
471 | |||
420 | /* | 472 | /* |
421 | POP3 CAPA support. | 473 | POP3 CAPA support. |
422 | */ | 474 | */ |
... | @@ -454,12 +506,16 @@ pop_parse_capa (pop_data_t mpd) | ... | @@ -454,12 +506,16 @@ pop_parse_capa (pop_data_t mpd) |
454 | mpd->capa |= CAPA_STLS; | 506 | mpd->capa |= CAPA_STLS; |
455 | } | 507 | } |
456 | while (mpd->nl); | 508 | while (mpd->nl); |
509 | |||
510 | if (mpd->capa & CAPA_UIDL) | ||
511 | mpd->mbox->_get_uidls = pop_mbox_uidls; | ||
512 | |||
457 | return status; | 513 | return status; |
458 | } | 514 | } |
459 | else | 515 | else |
460 | { | 516 | { |
461 | /* mu_error ("CAPA not implemented"); */ /* FIXME */ | 517 | /* mu_error ("CAPA not implemented"); */ /* FIXME */ |
462 | return -1; | 518 | return ENOSYS; |
463 | } | 519 | } |
464 | } | 520 | } |
465 | 521 | ||
... | @@ -485,7 +541,6 @@ pop_capa (mu_mailbox_t mbox) | ... | @@ -485,7 +541,6 @@ pop_capa (mu_mailbox_t mbox) |
485 | return pop_parse_capa (mpd); | 541 | return pop_parse_capa (mpd); |
486 | } | 542 | } |
487 | 543 | ||
488 | |||
489 | /* Simple User/pass authentication for pop. We ask for the info | 544 | /* Simple User/pass authentication for pop. We ask for the info |
490 | from the standard input. */ | 545 | from the standard input. */ |
491 | int | 546 | int |
... | @@ -1427,7 +1482,7 @@ pop_message_size (mu_message_t msg, size_t *psize) | ... | @@ -1427,7 +1482,7 @@ pop_message_size (mu_message_t msg, size_t *psize) |
1427 | CLEAR_STATE (mpd); | 1482 | CLEAR_STATE (mpd); |
1428 | 1483 | ||
1429 | if (status != 0) | 1484 | if (status != 0) |
1430 | status = MU_ERR_PARSE; | 1485 | return MU_ERR_PARSE; |
1431 | 1486 | ||
1432 | /* The size of the message is with the extra '\r' octet for everyline. | 1487 | /* The size of the message is with the extra '\r' octet for everyline. |
1433 | Substract to get, hopefully, a good count. */ | 1488 | Substract to get, hopefully, a good count. */ |
... | @@ -1570,7 +1625,7 @@ pop_uid (mu_message_t msg, size_t *puid) | ... | @@ -1570,7 +1625,7 @@ pop_uid (mu_message_t msg, size_t *puid) |
1570 | return 0; | 1625 | return 0; |
1571 | } | 1626 | } |
1572 | 1627 | ||
1573 | /* Get the UIDL. Client should be prepare since it may fail. UIDL is | 1628 | /* Get the UIDL. The client should be prepared, since it may fail. UIDL is |
1574 | optional on many POP servers. | 1629 | optional on many POP servers. |
1575 | FIXME: We should check the "mpd->capa & CAPA_UIDL" and fall back to | 1630 | FIXME: We should check the "mpd->capa & CAPA_UIDL" and fall back to |
1576 | a md5 scheme ? Or maybe check for "X-UIDL" a la Qpopper ? */ | 1631 | a md5 scheme ? Or maybe check for "X-UIDL" a la Qpopper ? */ |
... | @@ -1582,14 +1637,12 @@ pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ... | @@ -1582,14 +1637,12 @@ pop_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1582 | int status = 0; | 1637 | int status = 0; |
1583 | void *func = (void *)pop_uidl; | 1638 | void *func = (void *)pop_uidl; |
1584 | size_t num; | 1639 | size_t num; |
1585 | /* According to the RFC uidl's are no longer then 70 chars. Still playit | 1640 | char uniq[MU_UIDL_BUFFER_SIZE]; |
1586 | safe */ | ||
1587 | char uniq[128]; | ||
1588 | 1641 | ||
1589 | if (mpm == NULL) | 1642 | if (mpm == NULL) |
1590 | return EINVAL; | 1643 | return EINVAL; |
1591 | 1644 | ||
1592 | /* Is it cache ? */ | 1645 | /* Is it cached ? */ |
1593 | if (mpm->uidl) | 1646 | if (mpm->uidl) |
1594 | { | 1647 | { |
1595 | size_t len = strlen (mpm->uidl); | 1648 | size_t len = strlen (mpm->uidl); | ... | ... |
... | @@ -681,3 +681,66 @@ mu_mailbox_unlock (mu_mailbox_t mbox) | ... | @@ -681,3 +681,66 @@ mu_mailbox_unlock (mu_mailbox_t mbox) |
681 | return mu_locker_unlock (lock); | 681 | return mu_locker_unlock (lock); |
682 | } | 682 | } |
683 | 683 | ||
684 | static void | ||
685 | free_uidl (void *item) | ||
686 | { | ||
687 | free (item); | ||
688 | } | ||
689 | |||
690 | int | ||
691 | mu_mailbox_get_uidls (mu_mailbox_t mbox, mu_list_t *plist) | ||
692 | { | ||
693 | mu_list_t list; | ||
694 | int status; | ||
695 | |||
696 | if (mbox == NULL) | ||
697 | return MU_ERR_MBX_NULL; | ||
698 | if (plist == NULL) | ||
699 | return EINVAL; | ||
700 | status = mu_list_create (&list); | ||
701 | if (status) | ||
702 | return status; | ||
703 | mu_list_set_destroy_item (list, free_uidl); | ||
704 | if (mbox->_get_uidls) | ||
705 | status = mbox->_get_uidls (mbox, list); | ||
706 | else | ||
707 | { | ||
708 | size_t i, total; | ||
709 | |||
710 | status = mu_mailbox_messages_count (mbox, &total); | ||
711 | if (status) | ||
712 | return status; | ||
713 | for (i = 1; i <= total; i++) | ||
714 | { | ||
715 | mu_message_t msg = NULL; | ||
716 | char buf[MU_UIDL_BUFFER_SIZE]; | ||
717 | size_t n; | ||
718 | struct mu_uidl *uidl; | ||
719 | |||
720 | status = mu_mailbox_get_message (mbox, i, &msg); | ||
721 | if (status) | ||
722 | break; | ||
723 | status = mu_message_get_uidl (msg, buf, sizeof (buf), &n); | ||
724 | if (status) | ||
725 | break; | ||
726 | uidl = malloc (sizeof (uidl[0])); | ||
727 | if (!uidl) | ||
728 | { | ||
729 | status = ENOMEM; | ||
730 | break; | ||
731 | } | ||
732 | uidl->msgno = i; | ||
733 | strncpy (uidl->uidl, strdup (buf), MU_UIDL_BUFFER_SIZE); | ||
734 | status = mu_list_append (list, uidl); | ||
735 | if (status) | ||
736 | { | ||
737 | free_uidl (uidl); | ||
738 | break; | ||
739 | } | ||
740 | } | ||
741 | } | ||
742 | *plist = list; | ||
743 | return status; | ||
744 | } | ||
745 | |||
746 | ... | ... |
... | @@ -47,6 +47,12 @@ static struct argp_option options[] = { | ... | @@ -47,6 +47,12 @@ static struct argp_option options[] = { |
47 | { "copy-permissions", 'P', NULL, 0, | 47 | { "copy-permissions", 'P', NULL, 0, |
48 | N_("Copy original mailbox permissions and ownership when applicable"), | 48 | N_("Copy original mailbox permissions and ownership when applicable"), |
49 | 0 }, | 49 | 0 }, |
50 | { "uidl", 'u', NULL, 0, | ||
51 | N_("Use UIDLs to avoid downloading the same message twice"), | ||
52 | 0 }, | ||
53 | { "verbose", 'v', NULL, 0, | ||
54 | N_("Increase verbosity level"), | ||
55 | 0 }, | ||
50 | { NULL, 0, NULL, 0, NULL, 0 } | 56 | { NULL, 0, NULL, 0, NULL, 0 } |
51 | }; | 57 | }; |
52 | 58 | ||
... | @@ -54,6 +60,8 @@ static int reverse_order; | ... | @@ -54,6 +60,8 @@ static int reverse_order; |
54 | static int preserve_mail; | 60 | static int preserve_mail; |
55 | static int emacs_mode; | 61 | static int emacs_mode; |
56 | static int copy_meta; | 62 | static int copy_meta; |
63 | static int uidl_option; | ||
64 | static int verbose_option; | ||
57 | 65 | ||
58 | static error_t | 66 | static error_t |
59 | parse_opt (int key, char *arg, struct argp_state *state) | 67 | parse_opt (int key, char *arg, struct argp_state *state) |
... | @@ -74,6 +82,14 @@ parse_opt (int key, char *arg, struct argp_state *state) | ... | @@ -74,6 +82,14 @@ parse_opt (int key, char *arg, struct argp_state *state) |
74 | copy_meta = 1; | 82 | copy_meta = 1; |
75 | break; | 83 | break; |
76 | 84 | ||
85 | case 'u': | ||
86 | mu_argp_node_list_new (&lst, "uidl", "yes"); | ||
87 | break; | ||
88 | |||
89 | case 'v': | ||
90 | verbose_option++; | ||
91 | break; | ||
92 | |||
77 | case OPT_EMACS: | 93 | case OPT_EMACS: |
78 | mu_argp_node_list_new (&lst, "emacs", "yes"); | 94 | mu_argp_node_list_new (&lst, "emacs", "yes"); |
79 | break; | 95 | break; |
... | @@ -109,6 +125,10 @@ struct mu_cfg_param movemail_cfg_param[] = { | ... | @@ -109,6 +125,10 @@ struct mu_cfg_param movemail_cfg_param[] = { |
109 | N_("Reverse message sorting order.") }, | 125 | N_("Reverse message sorting order.") }, |
110 | { "emacs", mu_cfg_bool, &emacs_mode, 0, NULL, | 126 | { "emacs", mu_cfg_bool, &emacs_mode, 0, NULL, |
111 | N_("Output information used by Emacs rmail interface.") }, | 127 | N_("Output information used by Emacs rmail interface.") }, |
128 | { "uidl", mu_cfg_bool, &uidl_option, 0, NULL, | ||
129 | N_("Use UIDLs to avoid downloading the same message twice.") }, | ||
130 | { "verbose", mu_cfg_int, &verbose_option, 0, NULL, | ||
131 | N_("Increase verbosity level.") }, | ||
112 | { NULL } | 132 | { NULL } |
113 | }; | 133 | }; |
114 | 134 | ||
... | @@ -227,13 +247,13 @@ move_message (mu_mailbox_t src, mu_mailbox_t dst, size_t msgno) | ... | @@ -227,13 +247,13 @@ move_message (mu_mailbox_t src, mu_mailbox_t dst, size_t msgno) |
227 | 247 | ||
228 | if ((rc = mu_mailbox_get_message (src, msgno, &msg)) != 0) | 248 | if ((rc = mu_mailbox_get_message (src, msgno, &msg)) != 0) |
229 | { | 249 | { |
230 | fprintf (stderr, _("Cannot read message %lu: %s\n"), | 250 | mu_error (_("Cannot read message %lu: %s"), |
231 | (unsigned long) msgno, mu_strerror (rc)); | 251 | (unsigned long) msgno, mu_strerror (rc)); |
232 | return rc; | 252 | return rc; |
233 | } | 253 | } |
234 | if ((rc = mu_mailbox_append_message (dst, msg)) != 0) | 254 | if ((rc = mu_mailbox_append_message (dst, msg)) != 0) |
235 | { | 255 | { |
236 | fprintf (stderr, _("Cannot append message %lu: %s\n"), | 256 | mu_error (_("Cannot append message %lu: %s\n"), |
237 | (unsigned long) msgno, mu_strerror (rc)); | 257 | (unsigned long) msgno, mu_strerror (rc)); |
238 | return rc; | 258 | return rc; |
239 | } | 259 | } |
... | @@ -344,6 +364,36 @@ set_permissions (mu_mailbox_t mbox) | ... | @@ -344,6 +364,36 @@ set_permissions (mu_mailbox_t mbox) |
344 | exit (1); | 364 | exit (1); |
345 | } | 365 | } |
346 | 366 | ||
367 | static int | ||
368 | _compare_uidls (const void *item, const void *value) | ||
369 | { | ||
370 | const struct mu_uidl *a = item; | ||
371 | const struct mu_uidl *b = value; | ||
372 | |||
373 | return strcmp (a->uidl, b->uidl); | ||
374 | } | ||
375 | |||
376 | static int | ||
377 | _compare_msgno (const void *item, const void *value) | ||
378 | { | ||
379 | const struct mu_uidl *a = item; | ||
380 | const struct mu_uidl *b = value; | ||
381 | |||
382 | if (a->msgno < b->msgno) | ||
383 | return -1; | ||
384 | if (a->msgno > b->msgno) | ||
385 | return 1; | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int | ||
390 | msgno_in_list (mu_list_t list, size_t num) | ||
391 | { | ||
392 | struct mu_uidl t; | ||
393 | t.msgno = num; | ||
394 | return mu_list_locate (list, &t, NULL) == 0; | ||
395 | } | ||
396 | |||
347 | int | 397 | int |
348 | main (int argc, char **argv) | 398 | main (int argc, char **argv) |
349 | { | 399 | { |
... | @@ -352,6 +402,8 @@ main (int argc, char **argv) | ... | @@ -352,6 +402,8 @@ main (int argc, char **argv) |
352 | int rc = 0; | 402 | int rc = 0; |
353 | char *source_name, *dest_name; | 403 | char *source_name, *dest_name; |
354 | int flags; | 404 | int flags; |
405 | mu_list_t src_uidl_list = NULL; | ||
406 | size_t msg_count = 0; | ||
355 | 407 | ||
356 | /* Native Language Support */ | 408 | /* Native Language Support */ |
357 | MU_APP_INIT_NLS (); | 409 | MU_APP_INIT_NLS (); |
... | @@ -396,18 +448,90 @@ main (int argc, char **argv) | ... | @@ -396,18 +448,90 @@ main (int argc, char **argv) |
396 | 448 | ||
397 | open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL); | 449 | open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL); |
398 | 450 | ||
399 | mu_mailbox_messages_count (source, &total); | 451 | rc = mu_mailbox_messages_count (source, &total); |
452 | if (rc) | ||
453 | { | ||
454 | mu_error(_("Cannot count messages: %s"), mu_strerror (rc)); | ||
455 | exit (1); | ||
456 | } | ||
457 | |||
458 | if (verbose_option) | ||
459 | mu_diag_output (MU_DIAG_INFO, | ||
460 | _("Number of messages in source mailbox: %lu"), | ||
461 | (unsigned long) total); | ||
462 | |||
463 | if (uidl_option) | ||
464 | { | ||
465 | mu_iterator_t itr; | ||
466 | mu_list_t dst_uidl_list = NULL; | ||
467 | |||
468 | rc = mu_mailbox_get_uidls (source, &src_uidl_list); | ||
469 | if (rc) | ||
470 | die (source, _("Cannot get UIDLs"), rc); | ||
471 | rc = mu_mailbox_get_uidls (dest, &dst_uidl_list); | ||
472 | if (rc) | ||
473 | die (dest, _("Cannot get UIDLs"), rc); | ||
474 | |||
475 | mu_list_set_comparator (src_uidl_list, NULL); | ||
476 | mu_list_set_comparator (dst_uidl_list, _compare_uidls); | ||
477 | |||
478 | mu_list_get_iterator (src_uidl_list, &itr); | ||
479 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
480 | mu_iterator_next (itr)) | ||
481 | { | ||
482 | struct mu_uidl *uidl; | ||
483 | |||
484 | mu_iterator_current (itr, (void **)&uidl); | ||
485 | if (mu_list_locate (dst_uidl_list, uidl, NULL) == 0) | ||
486 | mu_list_remove (src_uidl_list, uidl); | ||
487 | } | ||
488 | mu_iterator_destroy (&itr); | ||
489 | mu_list_destroy (&dst_uidl_list); | ||
490 | mu_list_set_comparator (src_uidl_list, _compare_msgno); | ||
491 | } | ||
492 | |||
400 | if (reverse_order) | 493 | if (reverse_order) |
401 | { | 494 | { |
402 | for (i = total; rc == 0 && i > 0; i--) | 495 | for (i = total; i > 0; i--) |
496 | { | ||
497 | if (src_uidl_list && !msgno_in_list (src_uidl_list, i)) | ||
498 | { | ||
499 | if (verbose_option > 1) | ||
500 | mu_diag_output (MU_DIAG_INFO, _("Ignoring message %lu"), | ||
501 | (unsigned long) i); | ||
502 | continue; | ||
503 | } | ||
403 | rc = move_message (source, dest, i); | 504 | rc = move_message (source, dest, i); |
505 | if (rc == 0) | ||
506 | msg_count++; | ||
507 | else | ||
508 | break; | ||
509 | } | ||
404 | } | 510 | } |
405 | else | 511 | else |
406 | { | 512 | { |
407 | for (i = 1; rc == 0 && i <= total; i++) | 513 | for (i = 1; i <= total; i++) |
514 | { | ||
515 | if (src_uidl_list && !msgno_in_list (src_uidl_list, i)) | ||
516 | { | ||
517 | if (verbose_option > 1) | ||
518 | mu_diag_output (MU_DIAG_INFO, _("Ignoring message %lu"), | ||
519 | (unsigned long) i); | ||
520 | continue; | ||
521 | } | ||
408 | rc = move_message (source, dest, i); | 522 | rc = move_message (source, dest, i); |
523 | if (rc == 0) | ||
524 | msg_count++; | ||
525 | else | ||
526 | break; | ||
527 | } | ||
409 | } | 528 | } |
410 | 529 | ||
530 | if (verbose_option) | ||
531 | mu_diag_output (MU_DIAG_INFO, | ||
532 | _("Number of processed messages: %lu"), | ||
533 | (unsigned long) msg_count); | ||
534 | |||
411 | if (rc) | 535 | if (rc) |
412 | return rc; | 536 | return rc; |
413 | 537 | ... | ... |
-
Please register or sign in to post a comment