Provide a function for quick retrieval of message lines.
* include/mailutils/message.h (mu_message_quick_lines): New proto. (mu_message_set_lines): Change signature of the 2nd argument. * include/mailutils/sys/message.h (_mu_message) <lines>: Change signature. * libmailutils/diag/errors (MU_ERR_INFO_UNAVAILABLE): New error code. * libmailutils/mailbox/message.c (mu_message_set_lines): Change signature of the 2nd argument. (mu_message_lines): Update call to the _lines method. (mu_message_quick_lines): New function. * libproto/pop/mbox.c (_POP3_MSG_LINES): New flag. (_pop3_message)<message_lines>: New member. (pop_create_pop3_message): New function. (pop_scan): Use LIST to obtain scan listing. (pop_message_lines): New function. (pop_create_message): Set _lines method. (pop_get_message): Use pop_create_pop3_message. * mail/from.c (hdr_quick_lines): New function. (compile_headline): New escape %L * pop3d/capa.c (pop3d_capa): Show XLINES capability if configured. * pop3d/list.c (pop3d_list): Optionally output the number of lines in the message. * pop3d/pop3d.c (pop3d_xlines): New global. (pop3d_cfg_param): New statement "scan-lines". * pop3d/pop3d.h (pop3d_xlines): New extern.
Showing
11 changed files
with
239 additions
and
48 deletions
... | @@ -97,8 +97,9 @@ extern int mu_message_set_size (mu_message_t, | ... | @@ -97,8 +97,9 @@ extern int mu_message_set_size (mu_message_t, |
97 | void *owner); | 97 | void *owner); |
98 | 98 | ||
99 | extern int mu_message_lines (mu_message_t, size_t *); | 99 | extern int mu_message_lines (mu_message_t, size_t *); |
100 | extern int mu_message_quick_lines (mu_message_t, size_t *); | ||
100 | extern int mu_message_set_lines (mu_message_t, | 101 | extern int mu_message_set_lines (mu_message_t, |
101 | int (*_lines) (mu_message_t, size_t *), | 102 | int (*_lines) (mu_message_t, size_t *, int), |
102 | void *owner); | 103 | void *owner); |
103 | 104 | ||
104 | extern int mu_message_get_num_parts (mu_message_t, size_t *nparts); | 105 | extern int mu_message_get_num_parts (mu_message_t, size_t *nparts); | ... | ... |
... | @@ -58,7 +58,7 @@ struct _mu_message | ... | @@ -58,7 +58,7 @@ struct _mu_message |
58 | int (*_get_num_parts) (mu_message_t, size_t *); | 58 | int (*_get_num_parts) (mu_message_t, size_t *); |
59 | int (*_get_part) (mu_message_t, size_t, mu_message_t *); | 59 | int (*_get_part) (mu_message_t, size_t, mu_message_t *); |
60 | int (*_is_multipart) (mu_message_t, int *); | 60 | int (*_is_multipart) (mu_message_t, int *); |
61 | int (*_lines) (mu_message_t, size_t *); | 61 | int (*_lines) (mu_message_t, size_t *, int); |
62 | int (*_size) (mu_message_t, size_t *); | 62 | int (*_size) (mu_message_t, size_t *); |
63 | }; | 63 | }; |
64 | 64 | ... | ... |
... | @@ -95,3 +95,5 @@ MU_ERR_AUTH_NO_CRED _("No credentials supplied") | ... | @@ -95,3 +95,5 @@ MU_ERR_AUTH_NO_CRED _("No credentials supplied") |
95 | 95 | ||
96 | MU_ERR_URL_MISS_PARTS _("URL missing required parts") | 96 | MU_ERR_URL_MISS_PARTS _("URL missing required parts") |
97 | MU_ERR_URL_EXTRA_PARTS _("URL has parts not allowed by its scheme") | 97 | MU_ERR_URL_EXTRA_PARTS _("URL has parts not allowed by its scheme") |
98 | |||
99 | MU_ERR_INFO_UNAVAILABLE _("Information is not yet available") | ... | ... |
... | @@ -882,7 +882,7 @@ mu_message_set_get_stream (mu_message_t msg, | ... | @@ -882,7 +882,7 @@ mu_message_set_get_stream (mu_message_t msg, |
882 | 882 | ||
883 | int | 883 | int |
884 | mu_message_set_lines (mu_message_t msg, int (*_lines) | 884 | mu_message_set_lines (mu_message_t msg, int (*_lines) |
885 | (mu_message_t, size_t *), void *owner) | 885 | (mu_message_t, size_t *, int), void *owner) |
886 | { | 886 | { |
887 | if (msg == NULL) | 887 | if (msg == NULL) |
888 | return EINVAL; | 888 | return EINVAL; |
... | @@ -902,7 +902,7 @@ mu_message_lines (mu_message_t msg, size_t *plines) | ... | @@ -902,7 +902,7 @@ mu_message_lines (mu_message_t msg, size_t *plines) |
902 | return EINVAL; | 902 | return EINVAL; |
903 | /* Overload. */ | 903 | /* Overload. */ |
904 | if (msg->_lines) | 904 | if (msg->_lines) |
905 | return msg->_lines (msg, plines); | 905 | return msg->_lines (msg, plines, 0); |
906 | if (plines) | 906 | if (plines) |
907 | { | 907 | { |
908 | hlines = blines = 0; | 908 | hlines = blines = 0; |
... | @@ -913,6 +913,36 @@ mu_message_lines (mu_message_t msg, size_t *plines) | ... | @@ -913,6 +913,36 @@ mu_message_lines (mu_message_t msg, size_t *plines) |
913 | return ret; | 913 | return ret; |
914 | } | 914 | } |
915 | 915 | ||
916 | /* Return the number of lines in the message, without going into | ||
917 | excess trouble for calculating it. If obtaining the result | ||
918 | means downloading the entire message (as is the case for POP3, | ||
919 | for example), return MU_ERR_INFO_UNAVAILABLE. */ | ||
920 | int | ||
921 | mu_message_quick_lines (mu_message_t msg, size_t *plines) | ||
922 | { | ||
923 | size_t hlines, blines; | ||
924 | int rc; | ||
925 | |||
926 | if (msg == NULL) | ||
927 | return EINVAL; | ||
928 | /* Overload. */ | ||
929 | if (msg->_lines) | ||
930 | { | ||
931 | int rc = msg->_lines (msg, plines, 1); | ||
932 | if (rc != ENOSYS) | ||
933 | return rc; | ||
934 | } | ||
935 | if (plines) | ||
936 | { | ||
937 | hlines = blines = 0; | ||
938 | if ((rc = mu_header_lines (msg->header, &hlines)) == 0) | ||
939 | rc = mu_body_lines (msg->body, &blines); | ||
940 | if (rc == 0) | ||
941 | *plines = hlines + blines; | ||
942 | } | ||
943 | return rc; | ||
944 | } | ||
945 | |||
916 | int | 946 | int |
917 | mu_message_set_size (mu_message_t msg, int (*_size) | 947 | mu_message_set_size (mu_message_t msg, int (*_size) |
918 | (mu_message_t, size_t *), void *owner) | 948 | (mu_message_t, size_t *), void *owner) | ... | ... |
... | @@ -60,6 +60,7 @@ | ... | @@ -60,6 +60,7 @@ |
60 | #define _POP3_MSG_SIZE 0x02 /* Message size obtained */ | 60 | #define _POP3_MSG_SIZE 0x02 /* Message size obtained */ |
61 | #define _POP3_MSG_SCANNED 0x04 /* Message has been scanned */ | 61 | #define _POP3_MSG_SCANNED 0x04 /* Message has been scanned */ |
62 | #define _POP3_MSG_ATTRSET 0x08 /* Attributes has been set */ | 62 | #define _POP3_MSG_ATTRSET 0x08 /* Attributes has been set */ |
63 | #define _POP3_MSG_LINES 0x10 /* Number of lines was obtained */ | ||
63 | 64 | ||
64 | struct _pop3_message | 65 | struct _pop3_message |
65 | { | 66 | { |
... | @@ -70,7 +71,8 @@ struct _pop3_message | ... | @@ -70,7 +71,8 @@ struct _pop3_message |
70 | size_t header_lines; /* Number of lines in the header */ | 71 | size_t header_lines; /* Number of lines in the header */ |
71 | size_t body_lines; /* Number of lines in the body */ | 72 | size_t body_lines; /* Number of lines in the body */ |
72 | int attr_flags; /* Message attributes */ | 73 | int attr_flags; /* Message attributes */ |
73 | size_t message_size; /* Message size */ | 74 | size_t message_size; /* Message size */ |
75 | size_t message_lines; /* Number of lines in the message */ | ||
74 | size_t num; /* Message number */ | 76 | size_t num; /* Message number */ |
75 | char *uidl; /* Cached uidl string. */ | 77 | char *uidl; /* Cached uidl string. */ |
76 | mu_message_t message; /* Pointer to the message structure */ | 78 | mu_message_t message; /* Pointer to the message structure */ |
... | @@ -95,6 +97,9 @@ struct _pop3_mailbox | ... | @@ -95,6 +97,9 @@ struct _pop3_mailbox |
95 | mu_secret_t secret; | 97 | mu_secret_t secret; |
96 | }; | 98 | }; |
97 | 99 | ||
100 | static int pop_create_pop3_message (struct _pop3_mailbox *mpd, size_t msgno, | ||
101 | struct _pop3_message **mptr); | ||
102 | |||
98 | 103 | ||
99 | /* ------------------------------------------------------------------------- */ | 104 | /* ------------------------------------------------------------------------- */ |
100 | /* Basic operations */ | 105 | /* Basic operations */ |
... | @@ -270,34 +275,89 @@ pop_messages_count (mu_mailbox_t mbox, size_t *pcount) | ... | @@ -270,34 +275,89 @@ pop_messages_count (mu_mailbox_t mbox, size_t *pcount) |
270 | } | 275 | } |
271 | return status; | 276 | return status; |
272 | } | 277 | } |
273 | 278 | ||
274 | static int | 279 | static int |
275 | pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) | 280 | pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) |
276 | { | 281 | { |
277 | int status; | 282 | int status; |
278 | size_t i; | 283 | size_t i; |
279 | size_t count = 0; | 284 | size_t count = 0; |
280 | 285 | struct _pop3_mailbox *mpd = mbox->data; | |
286 | int flags; | ||
287 | mu_iterator_t itr; | ||
288 | |||
281 | status = pop_messages_count (mbox, &count); | 289 | status = pop_messages_count (mbox, &count); |
282 | if (status != 0) | 290 | if (status != 0) |
283 | return status; | 291 | return status; |
284 | if (pcount) | 292 | if (pcount) |
285 | *pcount = count; | 293 | *pcount = count; |
286 | if (mbox->observable == NULL) | 294 | |
287 | return 0; | 295 | flags = _POP3_MSG_SIZE; |
288 | for (i = msgno; i <= count; i++) | 296 | if (!mu_pop3_capa_test (mpd->pop3, "XLINES", NULL)) |
297 | flags |= _POP3_MSG_LINES; | ||
298 | |||
299 | status = mu_pop3_list_all (mpd->pop3, &itr); | ||
300 | if (status) | ||
301 | return status; | ||
302 | |||
303 | for (i = 0, mu_iterator_first (itr); | ||
304 | i <= count && !mu_iterator_is_done (itr); | ||
305 | i++, mu_iterator_next (itr)) | ||
289 | { | 306 | { |
290 | size_t tmp = i; | 307 | const char *str; |
291 | if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD, | 308 | char *p; |
292 | &tmp) != 0) | 309 | size_t num; |
293 | break; | 310 | |
294 | if (((i + 1) % 10) == 0) | 311 | mu_iterator_current (itr, (void**) &str); |
312 | num = strtoul (str, &p, 10); | ||
313 | |||
314 | if (*p != ' ') | ||
295 | { | 315 | { |
296 | mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS, | 316 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, |
297 | NULL); | 317 | ("invalid reply to LIST command: %s", str)); |
318 | status = MU_ERR_BADREPLY; | ||
319 | break; | ||
320 | } | ||
321 | if (num >= msgno) | ||
322 | { | ||
323 | size_t size, lines; | ||
324 | struct _pop3_message *mpm; | ||
325 | |||
326 | size = strtoul (p + 1, &p, 10); | ||
327 | if (flags & _POP3_MSG_LINES) | ||
328 | { | ||
329 | if (*p != ' ') | ||
330 | { | ||
331 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
332 | ("invalid reply to LIST command: %s", str)); | ||
333 | status = MU_ERR_BADREPLY; | ||
334 | break; | ||
335 | } | ||
336 | lines = strtoul (p + 1, &p, 10); | ||
337 | } | ||
338 | |||
339 | status = pop_create_pop3_message (mpd, num, &mpm); | ||
340 | if (status) | ||
341 | break; | ||
342 | mpm->message_size = size; | ||
343 | if (flags & _POP3_MSG_LINES) | ||
344 | mpm->message_lines = lines; | ||
345 | mpm->flags |= flags; | ||
346 | |||
347 | if (mbox->observable) | ||
348 | { | ||
349 | if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD, | ||
350 | &num) != 0) | ||
351 | break; | ||
352 | if (((i + 1) % 10) == 0) | ||
353 | mu_observable_notify (mbox->observable, | ||
354 | MU_EVT_MAILBOX_PROGRESS, | ||
355 | NULL); | ||
356 | } | ||
298 | } | 357 | } |
299 | } | 358 | } |
300 | return 0; | 359 | mu_iterator_destroy (&itr); |
360 | return status; | ||
301 | } | 361 | } |
302 | 362 | ||
303 | /* There's no way to retrieve this info via POP3 */ | 363 | /* There's no way to retrieve this info via POP3 */ |
... | @@ -475,6 +535,29 @@ pop_message_size (mu_message_t msg, size_t *psize) | ... | @@ -475,6 +535,29 @@ pop_message_size (mu_message_t msg, size_t *psize) |
475 | } | 535 | } |
476 | 536 | ||
477 | static int | 537 | static int |
538 | pop_message_lines (mu_message_t msg, size_t *plines, int quick) | ||
539 | { | ||
540 | int rc; | ||
541 | struct _pop3_message *mpm = mu_message_get_owner (msg); | ||
542 | |||
543 | if (!(mpm->flags & _POP3_MSG_LINES)) | ||
544 | { | ||
545 | if (quick && !(mpm->flags & _POP3_MSG_CACHED)) | ||
546 | return MU_ERR_INFO_UNAVAILABLE; | ||
547 | if (!pop_is_updated (mpm->mpd->mbox)) | ||
548 | pop_scan (mpm->mpd->mbox, 1, NULL); | ||
549 | rc = pop_scan_message (mpm); | ||
550 | if (rc) | ||
551 | return rc; | ||
552 | mpm->message_lines = mpm->header_lines + mpm->body_lines + 1; | ||
553 | mpm->flags |= _POP3_MSG_LINES; | ||
554 | } | ||
555 | |||
556 | *plines = mpm->message_lines; | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static int | ||
478 | pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) | 561 | pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) |
479 | { | 562 | { |
480 | int status; | 563 | int status; |
... | @@ -486,10 +569,47 @@ pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) | ... | @@ -486,10 +569,47 @@ pop_create_message (struct _pop3_message *mpm, struct _pop3_mailbox *mpd) |
486 | 569 | ||
487 | mu_message_set_get_stream (msg, pop_message_get_stream, mpm); | 570 | mu_message_set_get_stream (msg, pop_message_get_stream, mpm); |
488 | mu_message_set_size (msg, pop_message_size, mpm); | 571 | mu_message_set_size (msg, pop_message_size, mpm); |
572 | mu_message_set_lines (msg, pop_message_lines, mpm); | ||
489 | mpm->message = msg; | 573 | mpm->message = msg; |
490 | return 0; | 574 | return 0; |
491 | } | 575 | } |
492 | 576 | ||
577 | static int | ||
578 | pop_create_pop3_message (struct _pop3_mailbox *mpd, size_t msgno, | ||
579 | struct _pop3_message **mptr) | ||
580 | { | ||
581 | int status; | ||
582 | struct _pop3_message *mpm; | ||
583 | |||
584 | if (msgno > mpd->msg_count) | ||
585 | return EINVAL; | ||
586 | |||
587 | if (!mpd->msg) | ||
588 | { | ||
589 | mpd->msg = calloc (mpd->msg_count, sizeof (mpd->msg[0])); | ||
590 | if (!mpd->msg) | ||
591 | return ENOMEM; | ||
592 | } | ||
593 | if (mpd->msg[msgno - 1]) | ||
594 | { | ||
595 | *mptr = mpd->msg[msgno - 1]; | ||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | mpm = calloc (1, sizeof (*mpm)); | ||
600 | if (mpm == NULL) | ||
601 | return ENOMEM; | ||
602 | |||
603 | /* Back pointer. */ | ||
604 | mpm->mpd = mpd; | ||
605 | mpm->num = msgno; | ||
606 | |||
607 | mpd->msg[msgno - 1] = mpm; | ||
608 | *mptr = mpm; | ||
609 | return status; | ||
610 | } | ||
611 | |||
612 | |||
493 | 613 | ||
494 | /* ------------------------------------------------------------------------- */ | 614 | /* ------------------------------------------------------------------------- */ |
495 | /* Header */ | 615 | /* Header */ |
... | @@ -798,36 +918,19 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) | ... | @@ -798,36 +918,19 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) |
798 | if (!pop_is_updated (mbox)) | 918 | if (!pop_is_updated (mbox)) |
799 | pop_scan (mbox, 1, NULL); | 919 | pop_scan (mbox, 1, NULL); |
800 | 920 | ||
801 | if (msgno > mpd->msg_count) | 921 | status = pop_create_pop3_message (mpd, msgno, &mpm); |
802 | return EINVAL; | 922 | if (status) |
803 | 923 | return status; | |
804 | if (!mpd->msg) | 924 | if (mpm->message) |
805 | { | ||
806 | mpd->msg = calloc (mpd->msg_count, sizeof (mpd->msg[0])); | ||
807 | if (!mpd->msg) | ||
808 | return ENOMEM; | ||
809 | } | ||
810 | if (mpd->msg[msgno - 1]) | ||
811 | { | 925 | { |
812 | *pmsg = mpd->msg[msgno - 1]->message; | 926 | *pmsg = mpm->message; |
813 | return 0; | 927 | return 0; |
814 | } | 928 | } |
815 | 929 | ||
816 | mpm = calloc (1, sizeof (*mpm)); | ||
817 | if (mpm == NULL) | ||
818 | return ENOMEM; | ||
819 | |||
820 | /* Back pointer. */ | ||
821 | mpm->mpd = mpd; | ||
822 | mpm->num = msgno; | ||
823 | |||
824 | status = pop_create_message (mpm, mpd); | 930 | status = pop_create_message (mpm, mpd); |
825 | if (status) | 931 | if (status) |
826 | { | 932 | return status; |
827 | free (mpm); | 933 | |
828 | return status; | ||
829 | } | ||
830 | |||
831 | do | 934 | do |
832 | { | 935 | { |
833 | status = pop_create_header (mpm); | 936 | status = pop_create_header (mpm); |
... | @@ -852,7 +955,6 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) | ... | @@ -852,7 +955,6 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) |
852 | 955 | ||
853 | mu_message_set_uid (mpm->message, pop_uid, mpm); | 956 | mu_message_set_uid (mpm->message, pop_uid, mpm); |
854 | 957 | ||
855 | mpd->msg[msgno - 1] = mpm; | ||
856 | mu_message_set_mailbox (mpm->message, mbox, mpm); | 958 | mu_message_set_mailbox (mpm->message, mbox, mpm); |
857 | *pmsg = mpm->message; | 959 | *pmsg = mpm->message; |
858 | return 0; | 960 | return 0; | ... | ... |
... | @@ -294,11 +294,29 @@ hdr_lines (struct header_call_args *args, void *data) | ... | @@ -294,11 +294,29 @@ hdr_lines (struct header_call_args *args, void *data) |
294 | { | 294 | { |
295 | size_t m_lines; | 295 | size_t m_lines; |
296 | char buf[UINTMAX_STRSIZE_BOUND]; | 296 | char buf[UINTMAX_STRSIZE_BOUND]; |
297 | |||
297 | mu_message_lines (args->msg, &m_lines); | 298 | mu_message_lines (args->msg, &m_lines); |
298 | 299 | ||
299 | return header_buf_string (args, umaxtostr (m_lines, buf)); | 300 | return header_buf_string (args, umaxtostr (m_lines, buf)); |
300 | } | 301 | } |
301 | 302 | ||
303 | /* %L */ | ||
304 | static char * | ||
305 | hdr_quick_lines (struct header_call_args *args, void *data) | ||
306 | { | ||
307 | size_t m_lines; | ||
308 | char buf[UINTMAX_STRSIZE_BOUND]; | ||
309 | int rc; | ||
310 | const char *p; | ||
311 | |||
312 | rc = mu_message_quick_lines (args->msg, &m_lines); | ||
313 | if (rc == 0) | ||
314 | p = umaxtostr (m_lines, buf); | ||
315 | else | ||
316 | p = "NA"; | ||
317 | return header_buf_string (args, p); | ||
318 | } | ||
319 | |||
302 | /* %m */ | 320 | /* %m */ |
303 | static char * | 321 | static char * |
304 | hdr_number (struct header_call_args *args, void *data) | 322 | hdr_number (struct header_call_args *args, void *data) |
... | @@ -466,6 +484,11 @@ compile_headline (const char *str) | ... | @@ -466,6 +484,11 @@ compile_headline (const char *str) |
466 | case 'l': /* The number of lines of the message */ | 484 | case 'l': /* The number of lines of the message */ |
467 | seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_lines); | 485 | seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_lines); |
468 | break; | 486 | break; |
487 | |||
488 | case 'L': /* Same, but in quick mode */ | ||
489 | seg = new_header_segment (ALIGN_NUMBER, width, NULL, | ||
490 | hdr_quick_lines); | ||
491 | break; | ||
469 | 492 | ||
470 | case 'm': /* Message number */ | 493 | case 'm': /* Message number */ |
471 | seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_number); | 494 | seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_number); | ... | ... |
... | @@ -38,7 +38,9 @@ pop3d_capa (char *arg) | ... | @@ -38,7 +38,9 @@ pop3d_capa (char *arg) |
38 | pop3d_outf ("UIDL\n"); | 38 | pop3d_outf ("UIDL\n"); |
39 | pop3d_outf ("RESP-CODES\n"); | 39 | pop3d_outf ("RESP-CODES\n"); |
40 | pop3d_outf ("PIPELINING\n"); | 40 | pop3d_outf ("PIPELINING\n"); |
41 | 41 | if (pop3d_xlines) | |
42 | pop3d_outf ("XLINES\n"); | ||
43 | |||
42 | #ifdef WITH_TLS | 44 | #ifdef WITH_TLS |
43 | if (tls_available && tls_done == 0) | 45 | if (tls_available && tls_done == 0) |
44 | pop3d_outf ("STLS\n"); | 46 | pop3d_outf ("STLS\n"); | ... | ... |
... | @@ -17,8 +17,27 @@ | ... | @@ -17,8 +17,27 @@ |
17 | 17 | ||
18 | #include "pop3d.h" | 18 | #include "pop3d.h" |
19 | 19 | ||
20 | /* Displays the size of message number arg or all messages (if no arg) */ | 20 | /* From RFC 1939: |
21 | 21 | ||
22 | In order to simplify parsing, all POP3 servers are | ||
23 | required to use a certain format for scan listings. A | ||
24 | scan listing consists of the message-number of the | ||
25 | message, followed by a single space and the exact size of | ||
26 | the message in octets. Methods for calculating the exact | ||
27 | size of the message are described in the "Message Format" | ||
28 | section below. This memo makes no requirement on what | ||
29 | follows the message size in the scan listing. Minimal | ||
30 | implementations should just end that line of the response | ||
31 | with a CRLF pair. More advanced implementations may | ||
32 | include other information, as parsed from the message. | ||
33 | <end of quote> | ||
34 | |||
35 | GNU pop3d uses this allowance and includes in the scan | ||
36 | listing the number of lines in message. This optional | ||
37 | feature is enabled by setting "scan-lines yes" in the | ||
38 | configuration file. When on, it is indicated by the | ||
39 | XLINES capability. | ||
40 | */ | ||
22 | int | 41 | int |
23 | pop3d_list (char *arg) | 42 | pop3d_list (char *arg) |
24 | { | 43 | { |
... | @@ -47,9 +66,12 @@ pop3d_list (char *arg) | ... | @@ -47,9 +66,12 @@ pop3d_list (char *arg) |
47 | { | 66 | { |
48 | mu_message_size (msg, &size); | 67 | mu_message_size (msg, &size); |
49 | mu_message_lines (msg, &lines); | 68 | mu_message_lines (msg, &lines); |
50 | pop3d_outf ("%s %s\n", | 69 | pop3d_outf ("%s %s", |
51 | mu_umaxtostr (0, mesgno), | 70 | mu_umaxtostr (0, mesgno), |
52 | mu_umaxtostr (1, size + lines)); | 71 | mu_umaxtostr (1, size + lines)); |
72 | if (pop3d_xlines) | ||
73 | pop3d_outf (" %s", mu_umaxtostr (2, lines)); | ||
74 | pop3d_outf ("\n"); | ||
53 | } | 75 | } |
54 | } | 76 | } |
55 | pop3d_outf (".\n"); | 77 | pop3d_outf (".\n"); |
... | @@ -64,10 +86,14 @@ pop3d_list (char *arg) | ... | @@ -64,10 +86,14 @@ pop3d_list (char *arg) |
64 | return ERR_MESG_DELE; | 86 | return ERR_MESG_DELE; |
65 | mu_message_size (msg, &size); | 87 | mu_message_size (msg, &size); |
66 | mu_message_lines (msg, &lines); | 88 | mu_message_lines (msg, &lines); |
67 | pop3d_outf ("+OK %s %s\n", | 89 | pop3d_outf ("+OK %s %s", |
68 | mu_umaxtostr (0, mesgno), | 90 | mu_umaxtostr (0, mesgno), |
69 | mu_umaxtostr (1, size + lines)); | 91 | mu_umaxtostr (1, size + lines)); |
92 | if (pop3d_xlines) | ||
93 | pop3d_outf (" %s", mu_umaxtostr (2, lines)); | ||
94 | pop3d_outf ("\n"); | ||
70 | } | 95 | } |
71 | 96 | ||
72 | return OK; | 97 | return OK; |
73 | } | 98 | } |
99 | ... | ... |
... | @@ -30,6 +30,7 @@ unsigned int idle_timeout; | ... | @@ -30,6 +30,7 @@ unsigned int idle_timeout; |
30 | int pop3d_transcript; | 30 | int pop3d_transcript; |
31 | int debug_mode; | 31 | int debug_mode; |
32 | int tls_required; | 32 | int tls_required; |
33 | int pop3d_xlines; | ||
33 | 34 | ||
34 | #ifdef WITH_TLS | 35 | #ifdef WITH_TLS |
35 | int tls_available; | 36 | int tls_available; |
... | @@ -95,6 +96,8 @@ static struct mu_cfg_param pop3d_cfg_param[] = { | ... | @@ -95,6 +96,8 @@ static struct mu_cfg_param pop3d_cfg_param[] = { |
95 | N_("days") }, | 96 | N_("days") }, |
96 | { "delete-expired", mu_cfg_bool, &expire_on_exit, 0, NULL, | 97 | { "delete-expired", mu_cfg_bool, &expire_on_exit, 0, NULL, |
97 | N_("Delete expired messages upon closing the mailbox.") }, | 98 | N_("Delete expired messages upon closing the mailbox.") }, |
99 | { "scan-lines", mu_cfg_bool, &pop3d_xlines, 0, NULL, | ||
100 | N_("Output the number of lines in the message in its scan listing.") }, | ||
98 | #ifdef WITH_TLS | 101 | #ifdef WITH_TLS |
99 | { "tls-required", mu_cfg_bool, &tls_required, 0, NULL, | 102 | { "tls-required", mu_cfg_bool, &tls_required, 0, NULL, |
100 | N_("Always require STLS before entering authentication phase.") }, | 103 | N_("Always require STLS before entering authentication phase.") }, | ... | ... |
... | @@ -196,6 +196,7 @@ extern struct mu_auth_data *auth_data; | ... | @@ -196,6 +196,7 @@ extern struct mu_auth_data *auth_data; |
196 | extern unsigned int idle_timeout; | 196 | extern unsigned int idle_timeout; |
197 | extern int pop3d_transcript; | 197 | extern int pop3d_transcript; |
198 | extern size_t pop3d_output_bufsize; | 198 | extern size_t pop3d_output_bufsize; |
199 | extern int pop3d_xlines; | ||
199 | 200 | ||
200 | extern pop3d_command_handler_t pop3d_find_command (const char *name); | 201 | extern pop3d_command_handler_t pop3d_find_command (const char *name); |
201 | 202 | ... | ... |
-
Please register or sign in to post a comment