2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
4 * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
6 * This file is part of mutt-ng, see http://www.muttng.org/.
7 * It's licensed under the GNU General Public License,
8 * please see the file GPL in the top level source directory.
11 #include <lib-lib/lib-lib.h>
15 #include <lib-lua/lib-lua.h>
16 #include <lib-sys/unix.h>
17 #include <lib-mime/mime.h>
18 #include <lib-ui/lib-ui.h>
33 #include <imap/imap.h>
36 #define MAXLOCKATTEMPT 5
38 static mx_t const *mxfmts[] = {
46 /* hack so that it's linked together */
50 #define MX_IDX(idx) (idx >= 0 && idx < countof(mxfmts))
51 #define mutt_is_spool(s) (m_strcmp(Spoolfile, s) == 0)
53 static int dotlock_file(const char *path, int retry)
55 char lockfile[_POSIX_PATH_MAX];
56 snprintf(lockfile, sizeof(lockfile), "%s.lock", path);
58 if (lockfile_create(lockfile, retry ? 1 : 0, 0)) {
60 mutt_error (_("Can't dotlock %s.\n"), lockfile);
65 static int undotlock_file (const char *path)
67 char lockfile[_POSIX_PATH_MAX];
68 snprintf(lockfile, sizeof(lockfile), "%s.lock", path);
69 return lockfile_remove(lockfile);
72 /* looks up index of type for path in mxfmts */
73 static int mx_get_idx (const char* path) {
77 /* first, test all non-local folders to avoid stat() call */
78 for (i = 0; i < countof(mxfmts); i++) {
79 if (!mxfmts[i]->local)
80 t = mxfmts[i]->mx_is_magic(path, NULL);
84 if (stat (path, &st) == 0) {
85 /* if stat() succeeded, keep testing until success and
86 * pass stat() info so that we only need to do it once */
87 for (i = 0; i < countof(mxfmts); i++) {
89 t = mxfmts[i]->mx_is_magic(path, &st);
98 * excl if excl != 0, request an exclusive lock
99 * time_out should retry locking?
101 int mx_lock_file(const char *path, int fd, int excl, int time_out)
103 int count = 0, attempt = 0;
105 .l_type = excl ? F_WRLCK : F_RDLCK,
106 .l_whence = SEEK_SET,
109 if (dotlock_file(path, time_out) < 0)
112 while (fcntl(fd, F_SETLK, &lck) == -1) {
113 if (errno != EAGAIN && errno != EACCES) {
114 mutt_perror("fcntl");
118 if (++count >= (time_out ? MAXLOCKATTEMPT : 0)) {
120 mutt_error _("Timeout exceeded while attempting fcntl lock!");
123 mutt_message(_("Waiting for fcntl lock... %d"), ++attempt);
129 undotlock_file(path);
133 int mx_unlock_file(const char *path, int fd)
135 struct flock unlockit;
137 p_clear(&unlockit, 1);
138 unlockit.l_type = F_UNLCK;
139 unlockit.l_whence = SEEK_SET;
140 fcntl(fd, F_SETLK, &unlockit);
141 undotlock_file(path);
145 /* try to figure out what type of mailbox ``path'' is */
146 int mx_get_magic (const char *path) {
149 if (m_strlen(path) == 0)
151 if ((i = mx_get_idx (path)) >= 0)
152 return mxfmts[i]->type;
156 int mx_is_local (int m) {
159 return mxfmts[m]->local;
162 /* mx_access: Wrapper for access, checks permissions on a given mailbox.
163 * We may be interested in using ACL-style flags at some point, currently
164 * we use the normal access() flags. */
165 int mx_access (const char *path, int flags)
169 if ((i = mx_get_idx (path)) >= 0 && mxfmts[i]->mx_access)
170 return mxfmts[i]->mx_access(path,flags);
174 static int mx_open_mailbox_append (CONTEXT * ctx, int flags)
178 /* special case for appending to compressed folders -
179 * even if we can not open them for reading */
180 if (mutt_can_append_compressed (ctx->path))
181 mutt_open_append_compressed (ctx);
185 if (mx_get_magic (ctx->path) == M_IMAP)
186 return imap_open_mailbox_append (ctx);
188 if (stat (ctx->path, &sb) == 0) {
189 ctx->magic = mx_get_magic (ctx->path);
191 switch (ctx->magic) {
193 mutt_error (_("%s is not a mailbox."), ctx->path);
198 } else if (errno == ENOENT) {
199 int len = m_strlen(ctx->path);
200 if (len > 0 && ctx->path[len - 1] == '/') {
201 char tmp[_POSIX_PATH_MAX];
203 if (mkdir (ctx->path, S_IRWXU)) {
204 mutt_perror (ctx->path);
208 snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
209 if (mkdir (tmp, S_IRWXU)) {
215 snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);
216 if (mkdir (tmp, S_IRWXU)) {
218 snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
223 snprintf (tmp, sizeof (tmp), "%s/tmp", ctx->path);
224 if (mkdir (tmp, S_IRWXU)) {
226 snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
228 snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);
233 ctx->magic = M_MAILDIR;
238 mutt_perror (ctx->path);
242 if (ctx->magic == M_MBOX) {
243 if (!(ctx->fp = safe_fopen(ctx->path, flags & M_NEWFOLDER ? "w" : "a"))) {
244 mutt_perror(ctx->path);
247 if (mbox_lock_mailbox(ctx, 1, 1) != 0) {
248 mutt_error(_("Couldn't lock %s\n"), ctx->path);
252 fseeko(ctx->fp, 0, 2);
258 * open a mailbox and parse it
261 * flags M_NOSORT do not sort mailbox
262 * M_APPEND open mailbox for appending
263 * M_READONLY open mailbox in read-only mode
264 * M_QUIET only print error messages
265 * ctx if non-null, context struct to use
267 CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx)
273 ctx = p_new(CONTEXT, 1);
275 ctx->path = m_strdup(path);
277 ctx->msgnotreadyet = -1;
282 if (flags & M_READONLY)
287 if (flags & (M_APPEND | M_NEWFOLDER)) {
288 if (mx_open_mailbox_append (ctx, flags) != 0) {
289 mx_fastclose_mailbox (ctx);
297 if (!MX_IDX(ctx->magic-1))
298 ctx->magic = mx_get_magic (path);
300 if (ctx->magic == M_COMPRESSED)
301 mutt_open_read_compressed (ctx);
304 mutt_error (_("%s is not a mailbox."), path);
306 if (ctx->magic == -1)
309 if (ctx->magic <= 0) {
310 mx_fastclose_mailbox (ctx);
316 /* if the user has a `push' command in their .muttrc, or in a folder-hook,
317 * it will cause the progress messages not to be displayed because
318 * mutt_refresh() will think we are in the middle of a macro. so set a
319 * flag to indicate that we should really refresh the screen.
321 set_option (OPTFORCEREFRESH);
324 mutt_message (_("Reading %s..."), ctx->path);
326 rc = mxfmts[ctx->magic-1]->mx_open_mailbox(ctx);
329 if ((flags & M_NOSORT) == 0) {
330 /* avoid unnecessary work since the mailbox is completely unthreaded
332 unset_option (OPTSORTSUBTHREADS);
333 unset_option (OPTNEEDRESCORE);
334 mutt_sort_headers (ctx, 1);
340 mx_fastclose_mailbox (ctx);
345 unset_option (OPTFORCEREFRESH);
349 /* free up memory associated with the mailbox context */
350 void mx_fastclose_mailbox (CONTEXT * ctx)
357 if (MX_IDX(ctx->magic-1) && mxfmts[ctx->magic-1]->mx_fastclose_mailbox)
358 mxfmts[ctx->magic-1]->mx_fastclose_mailbox(ctx);
360 hash_delete (&ctx->subj_hash, NULL);
362 hash_delete (&ctx->id_hash, NULL);
363 mutt_clear_threads (ctx);
364 for (i = 0; i < ctx->msgcount; i++)
365 header_delete(&ctx->hdrs[i]);
366 p_delete(&ctx->hdrs);
370 mutt_fast_close_compressed (ctx);
372 p_delete(&ctx->path);
373 p_delete(&ctx->pattern);
374 pattern_list_wipe(&ctx->limit_pattern);
379 /* save changes to disk */
380 static int sync_mailbox (CONTEXT * ctx, int *index_hint)
385 mutt_message (_("Writing %s..."), ctx->path);
387 if (MX_IDX(ctx->magic-1))
388 /* the 1 is only of interest for IMAP and means EXPUNGE */
389 rc = mxfmts[ctx->magic-1]->mx_sync_mailbox(ctx,1,index_hint);
391 if (rc == 0 && ctx->cinfo)
392 return mutt_sync_compressed (ctx);
397 /* move deleted mails to the trash folder */
398 static int trash_append (CONTEXT * ctx)
404 if (!TrashPath || !ctx->deleted ||
405 (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
408 for (; i < ctx->msgcount && (!ctx->hdrs[i]->deleted ||
409 ctx->hdrs[i]->appended); i++);
410 if (i == ctx->msgcount)
411 return 0; /* nothing to be done */
413 if (mutt_save_confirm (TrashPath, &st) != 0) {
414 mutt_error _("message(s) not deleted");
419 if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino
420 && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
421 return 0; /* we are in the trash folder: simple sync */
423 if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL) {
424 for (i = 0; i < ctx->msgcount; i++)
425 if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended
426 && !ctx->hdrs[i]->purged
427 && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1) {
428 mx_close_mailbox (ctx_trash, NULL);
432 mx_close_mailbox (ctx_trash, NULL);
435 mutt_error _("Can't open trash folder");
443 /* save changes and close mailbox */
444 static int _mx_close_mailbox (CONTEXT * ctx, int *index_hint)
446 int i, move_messages = 0, purge = 1, read_msgs = 0;
450 char mbox[_POSIX_PATH_MAX];
458 if (ctx->readonly || ctx->dontwrite) {
459 /* mailbox is readonly or we don't want to write */
460 mx_fastclose_mailbox (ctx);
465 /* mailbox was opened in write-mode */
466 if (ctx->magic == M_MBOX)
467 mbox_close_mailbox (ctx);
469 mx_fastclose_mailbox (ctx);
473 for (i = 0; i < ctx->msgcount; i++) {
474 if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read
475 && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
479 if (read_msgs && quadoption (OPT_MOVE) != M_NO) {
480 m_strcpy(mbox, sizeof(mbox), NONULL(Inbox));
481 isSpool = mutt_is_spool (ctx->path) && !mutt_is_spool (mbox);
482 mutt_expand_path (mbox, sizeof (mbox));
485 snprintf (buf, sizeof (buf), _("Move read messages to %s?"), mbox);
486 if ((move_messages = query_quadoption (OPT_MOVE, buf)) == -1) {
494 * There is no point in asking whether or not to purge if we are
495 * just marking messages as "trash".
497 if (ctx->deleted && !(ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) {
498 snprintf (buf, sizeof (buf), ctx->deleted == 1
499 ? _("Purge %d deleted message?") :
500 _("Purge %d deleted messages?"), ctx->deleted);
501 if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) {
507 /* IMAP servers manage the OLD flag themselves */
508 if (ctx->magic != M_IMAP)
509 if (option (OPTMARKOLD)) {
510 for (i = 0; i < ctx->msgcount; i++) {
511 if (!ctx->hdrs[i]->deleted && !ctx->hdrs[i]->old)
512 mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, 1);
517 mutt_message (_("Moving read messages to %s..."), mbox);
519 /* try to use server-side copy first */
522 if (ctx->magic == M_IMAP && imap_mx.mx_is_magic (mbox, NULL) == M_IMAP) {
523 /* tag messages for moving, and clear old tags, if any */
524 for (i = 0; i < ctx->msgcount; i++)
525 if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted
526 && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
527 ctx->hdrs[i]->tagged = 1;
529 ctx->hdrs[i]->tagged = 0;
531 i = imap_copy_messages (ctx, NULL, mbox, 1);
534 if (i == 0) /* success */
536 else if (i == -1) { /* horrible error, bail */
540 else /* use regular append-copy mode */
542 if (mx_open_mailbox (mbox, M_APPEND, &f) == NULL) {
547 for (i = 0; i < ctx->msgcount; i++) {
548 if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted
549 && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) {
550 if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) ==
552 mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1);
553 mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1);
556 mx_close_mailbox (&f, NULL);
563 mx_close_mailbox (&f, NULL);
567 else if (!ctx->changed && ctx->deleted == 0) {
568 mutt_message _("Mailbox is unchanged.");
570 mx_fastclose_mailbox (ctx);
574 /* copy mails to the trash before expunging */
575 if (purge && ctx->deleted)
576 if (trash_append (ctx) != 0) {
581 /* allow IMAP to preserve the deleted flag across sessions */
582 if (ctx->magic == M_IMAP) {
583 if ((check = imap_sync_mailbox (ctx, purge, index_hint)) != 0) {
591 for (i = 0; i < ctx->msgcount; i++)
592 ctx->hdrs[i]->deleted = 0;
596 if (ctx->changed || ctx->deleted) {
597 if ((check = sync_mailbox (ctx, index_hint)) != 0) {
605 mutt_message (_("%d kept, %d moved, %d deleted."),
606 ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted);
608 mutt_message (_("%d kept, %d deleted."),
609 ctx->msgcount - ctx->deleted, ctx->deleted);
611 if (ctx->cinfo && mutt_slow_close_compressed (ctx))
614 mx_fastclose_mailbox (ctx);
619 int mx_close_mailbox (CONTEXT * ctx, int *index_hint) {
623 ret = _mx_close_mailbox (ctx, index_hint);
624 sidebar_set_buffystats (ctx);
628 /* update a Context structure's internal tables. */
630 void mx_update_tables (CONTEXT * ctx, int committing)
634 /* update memory to reflect the new state of the mailbox */
643 #define this_body ctx->hdrs[j]->content
644 for (i = 0, j = 0; i < ctx->msgcount; i++) {
645 if ((committing && (!ctx->hdrs[i]->deleted ||
646 (ctx->magic == M_MAILDIR
647 && option (OPTMAILDIRTRASH)))) || (!committing
651 ctx->hdrs[j] = ctx->hdrs[i];
654 ctx->hdrs[j]->msgno = j;
655 if (ctx->hdrs[j]->virtual != -1) {
656 ctx->v2r[ctx->vcount] = j;
657 ctx->hdrs[j]->virtual = ctx->vcount++;
658 ctx->vsize += this_body->length + this_body->offset -
659 this_body->hdr_offset;
663 ctx->hdrs[j]->changed = 0;
664 else if (ctx->hdrs[j]->changed)
668 || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) {
669 if (ctx->hdrs[j]->deleted)
673 if (ctx->hdrs[j]->tagged)
675 if (ctx->hdrs[j]->flagged)
677 if (!ctx->hdrs[j]->read) {
679 if (!ctx->hdrs[j]->old)
686 if (ctx->magic == M_MH || ctx->magic == M_MAILDIR)
687 ctx->size -= (ctx->hdrs[i]->content->length +
688 ctx->hdrs[i]->content->offset -
689 ctx->hdrs[i]->content->hdr_offset);
690 /* remove message from the hash tables */
691 if (ctx->subj_hash && ctx->hdrs[i]->env->real_subj)
692 hash_remove (ctx->subj_hash, ctx->hdrs[i]->env->real_subj,
694 if (ctx->id_hash && ctx->hdrs[i]->env->message_id)
695 hash_remove (ctx->id_hash, ctx->hdrs[i]->env->message_id,
697 header_delete(&ctx->hdrs[i]);
703 /* update sidebar count */
704 sidebar_set_buffystats (ctx);
708 /* save changes to mailbox
714 static int _mx_sync_mailbox (CONTEXT * ctx, int *index_hint)
718 int msgcount, deleted;
720 if (ctx->dontwrite) {
721 char buf[STRING], tmp[STRING];
723 if (km_expand_key (buf, sizeof (buf),
724 km_find_func (MENU_MAIN, OP_TOGGLE_WRITE)))
725 snprintf (tmp, sizeof (tmp), _(" Press '%s' to toggle write"), buf);
727 m_strcpy(tmp, sizeof(tmp), _("Use 'toggle-write' to re-enable write!"));
729 mutt_error (_("Mailbox is marked unwritable. %s"), tmp);
732 else if (ctx->readonly) {
733 mutt_error _("Mailbox is read-only.");
738 if (!ctx->changed && !ctx->deleted) {
739 mutt_message _("Mailbox is unchanged.");
747 snprintf (buf, sizeof (buf), ctx->deleted == 1
748 ? _("Purge %d deleted message?") :
749 _("Purge %d deleted messages?"), ctx->deleted);
750 if ((purge = query_quadoption (OPT_DELETE, buf)) < 0)
752 else if (purge == M_NO) {
754 return 0; /* nothing to do! */
755 /* let IMAP servers hold on to D flags */
756 if (ctx->magic != M_IMAP)
758 for (i = 0; i < ctx->msgcount; i++)
759 ctx->hdrs[i]->deleted = 0;
763 else if (ctx->last_tag && ctx->last_tag->deleted)
764 ctx->last_tag = NULL; /* reset last tagged msg now useless */
767 /* really only for IMAP - imap_sync_mailbox results in a call to
768 * mx_update_tables, so ctx->deleted is 0 when it comes back */
769 msgcount = ctx->msgcount;
770 deleted = ctx->deleted;
772 if (purge && ctx->deleted) {
773 if (trash_append (ctx) == -1)
777 if (ctx->magic == M_IMAP)
778 rc = imap_sync_mailbox (ctx, purge, index_hint);
780 rc = sync_mailbox (ctx, index_hint);
782 if (ctx->magic == M_IMAP && !purge)
783 mutt_message (_("Mailbox checkpointed."));
785 mutt_message (_("%d kept, %d deleted."), msgcount - deleted, deleted);
789 /* if we haven't deleted any messages, we don't need to resort */
790 /* ... except for certain folder formats which need "unsorted"
791 * sort order in order to synchronize folders.
793 * MH and maildir are safe. mbox-style seems to need re-sorting,
794 * at least with the new threading code.
796 if (purge || (ctx->magic != M_MAILDIR && ctx->magic != M_MH)) {
797 /* IMAP does this automatically after handling EXPUNGE */
798 if (ctx->magic != M_IMAP)
800 mx_update_tables (ctx, 1);
801 mutt_sort_headers (ctx, 1); /* rethread from scratch */
809 int mx_sync_mailbox (CONTEXT* ctx, int* index_hint) {
810 int ret = _mx_sync_mailbox (ctx, index_hint);
811 sidebar_set_buffystats (ctx);
816 * dest destintation mailbox
817 * hdr message being copied (required for maildir support, because
818 * the filename depends on the message flags)
820 MESSAGE *mx_open_new_message (CONTEXT * dest, HEADER * hdr, int flags)
826 if (!MX_IDX(dest->magic-1)) {
830 msg = p_new(MESSAGE, 1);
831 msg->magic = dest->magic;
835 msg->flags.flagged = hdr->flagged;
836 msg->flags.replied = hdr->replied;
837 msg->flags.read = hdr->read;
838 msg->received = hdr->received;
841 if (msg->received == 0)
842 time (&msg->received);
844 if (mxfmts[dest->magic-1]->mx_open_new_message(msg, dest, hdr) == 0) {
845 if (msg->magic == M_MBOX && flags & M_ADD_FROM) {
847 if (hdr->env->return_path)
848 p = hdr->env->return_path;
849 else if (hdr->env->sender)
850 p = hdr->env->sender;
855 fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL(mod_core.username),
856 ctime (&msg->received));
865 /* check for new mail */
866 int mx_check_mailbox (CONTEXT * ctx, int *index_hint, int lock) {
868 return mutt_check_mailbox_compressed (ctx);
873 if (MX_IDX(ctx->magic-1) && mxfmts[ctx->magic-1]->mx_check_mailbox)
874 return mxfmts[ctx->magic-1]->mx_check_mailbox(ctx, index_hint, lock);
880 /* return a stream pointer for a message */
881 MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
885 if (!MX_IDX(ctx->magic) || !mxfmts[ctx->magic - 1]->mx_open_message)
888 msg = p_new(MESSAGE, 1);
889 msg->magic = ctx->magic;
890 if (mxfmts[ctx->magic - 1]->mx_open_message(msg, ctx, msgno))
895 /* commit a message to a folder */
897 int mx_commit_message (MESSAGE * msg, CONTEXT * ctx) {
898 if (!(msg->write && ctx->append)) {
901 if (!ctx || !MX_IDX(ctx->magic-1) || !mxfmts[ctx->magic-1]->mx_commit_message)
903 return mxfmts[ctx->magic-1]->mx_commit_message (msg, ctx);
906 /* close a pointer to a message */
907 int mx_close_message (MESSAGE ** msg)
911 if ((*msg)->magic == M_MH || (*msg)->magic == M_MAILDIR
912 || (*msg)->magic == M_IMAP || (*msg)->magic == M_POP)
914 r = m_fclose(&(*msg)->fp);
920 unlink ((*msg)->path);
921 p_delete(&(*msg)->path);
928 void mx_alloc_memory (CONTEXT * ctx)
932 p_realloc(&ctx->hdrs, ctx->hdrmax);
933 p_realloc(&ctx->v2r, ctx->hdrmax);
934 p_clear(ctx->hdrs + ctx->msgcount, ctx->hdrmax - ctx->msgcount);
935 p_clear(ctx->v2r + ctx->msgcount, ctx->hdrmax - ctx->msgcount);
938 /* this routine is called to update the counts in the context structure for
939 * the last message header parsed.
941 void mx_update_context (CONTEXT * ctx, int new_messages)
946 for (msgno = ctx->msgcount - new_messages; msgno < ctx->msgcount; msgno++) {
947 h = ctx->hdrs[msgno];
949 /* NOTE: this _must_ be done before the check for mailcap! */
950 h->security = crypt_query (h->content);
953 ctx->v2r[ctx->vcount] = msgno;
954 h->virtual = ctx->vcount++;
960 if (h->env->supersedes) {
964 ctx->id_hash = mutt_make_id_hash (ctx);
966 h2 = hash_find (ctx->id_hash, h->env->supersedes);
968 /* p_delete(&h->env->supersedes); should I ? */
971 if (!ctx->counting && mod_score.enable)
972 mutt_score_message (ctx, h2, 1);
976 /* add this message to the hash tables */
977 if (ctx->id_hash && h->env->message_id)
978 hash_insert (ctx->id_hash, h->env->message_id, h);
979 if (!ctx->counting) {
980 if (ctx->subj_hash && h->env->real_subj)
981 hash_insert (ctx->subj_hash, h->env->real_subj, h);
983 if (mod_score.enable)
984 mutt_score_message (ctx, h, 0);
999 /* update sidebar count */
1000 sidebar_set_buffystats (ctx);
1005 * 1 if the specified mailbox contains 0 messages.
1006 * 0 if the mailbox contains messages
1009 int mx_check_empty (const char *path)
1012 if ((i = mx_get_idx (path)) >= 0 && mxfmts[i]->mx_check_empty)
1013 return mxfmts[i]->mx_check_empty(path);
1018 int mx_acl_check(CONTEXT *ctx, int flag)
1020 if (!mxfmts[ctx->magic-1]->mx_acl_check)
1022 return mxfmts[ctx->magic-1]->mx_acl_check(ctx,flag);
1025 void mutt_parse_mime_message (CONTEXT * ctx, HEADER * cur)
1031 if (cur->content->type != TYPEMESSAGE
1032 && cur->content->type != TYPEMULTIPART)
1033 break; /* nothing to do */
1035 if (cur->content->parts)
1036 break; /* The message was parsed earlier. */
1038 if ((msg = mx_open_message (ctx, cur->msgno))) {
1039 mutt_parse_part (msg->fp, cur->content);
1041 cur->security = crypt_query (cur->content);
1043 mx_close_message (&msg);
1046 mutt_count_body_parts (cur, flags | M_PARTS_RECOUNT);