Commit 8ea94114 8ea94114b3242ab560db0aa6092354b2d327e527 by Sergey Poznyakoff

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.
1 parent 671cdfcc
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
......