📄 mh.c
字号:
mutt_str_replace (&h->maildir_flags, p); q = h->maildir_flags; while (*p) { switch (*p) { case 'F': h->flagged = 1; break; case 'S': /* seen */ h->read = 1; break; case 'R': /* replied */ h->replied = 1; break; case 'T': /* trashed */ h->trash = 1; h->deleted = 1; break; default: *q++ = *p; break; } p++; } } if (q == h->maildir_flags) FREE (&h->maildir_flags); else if (q) *q = '\0';}static void maildir_update_mtime (CONTEXT * ctx){ char buf[_POSIX_PATH_MAX]; struct stat st; if (ctx->magic == M_MAILDIR) { snprintf (buf, sizeof (buf), "%s/%s", ctx->path, "cur"); if (stat (buf, &st) == 0) ctx->mtime_cur = st.st_mtime; snprintf (buf, sizeof (buf), "%s/%s", ctx->path, "new"); } else { snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path); if (stat (buf, &st) == 0) ctx->mtime_cur = st.st_mtime; strfcpy (buf, ctx->path, sizeof (buf)); } if (stat (buf, &st) == 0) ctx->mtime = st.st_mtime;}/* * Actually parse a maildir message. This may also be used to fill * out a fake header structure generated by lazy maildir parsing. */static HEADER *maildir_parse_message (int magic, const char *fname, int is_old, HEADER * _h){ FILE *f; HEADER *h = _h; struct stat st; if ((f = fopen (fname, "r")) != NULL) { if (!h) h = mutt_new_header (); h->env = mutt_read_rfc822_header (f, h, 0, 0); fstat (fileno (f), &st); fclose (f); if (!h->received) h->received = h->date_sent; if (h->content->length <= 0) h->content->length = st.st_size - h->content->offset; h->index = -1; if (magic == M_MAILDIR) { /* * maildir stores its flags in the filename, so ignore the * flags in the header of the message */ h->old = is_old; maildir_parse_flags (h, fname); } return h; } return NULL;}/* * Note that this routine will _not_ modify the context given by * ctx. * * It's used in the first parsing pass on maildir and MH folders. * In the MH case, this means full parsing of the folder. In the * maildir case, it means that we only look at flags, and create a * fake HEADER structure, which may later be filled in by * maildir_parse_message(), when called from * maildir_delayed_parsing(). * */static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last, const char *subdir, const char *fname, int *count, int is_old, ino_t inode#if USE_HCACHE , header_cache_t *hc#endif ){ struct maildir *entry; HEADER *h = NULL; char buf[_POSIX_PATH_MAX];#if USE_HCACHE void *data;#endif if (subdir) snprintf (buf, sizeof (buf), "%s/%s/%s", ctx->path, subdir, fname); else snprintf (buf, sizeof (buf), "%s/%s", ctx->path, fname); if (ctx->magic == M_MH) {#ifdef USE_HCACHE if (hc && (data = mutt_hcache_fetch (hc, fname, strlen))) h = mutt_hcache_restore ((unsigned char *) data, NULL); else#endif h = maildir_parse_message (ctx->magic, buf, is_old, NULL); } else { h = mutt_new_header (); h->old = is_old; maildir_parse_flags (h, buf); } if (h != NULL) { if (count) { (*count)++; if (!ctx->quiet && ReadInc && ((*count % ReadInc) == 0 || *count == 1)) mutt_message (_("Reading %s... %d"), ctx->path, *count); } if (subdir) { snprintf (buf, sizeof (buf), "%s/%s", subdir, fname); h->path = safe_strdup (buf); } else h->path = safe_strdup (fname); entry = safe_calloc (sizeof (struct maildir), 1); entry->h = h; entry->header_parsed = (ctx->magic == M_MH);#ifdef USE_INODESORT entry->inode = inode;#endif /* USE_INODESORT */ **last = entry; *last = &entry->next; return 0; } return -1;}/* Ignore the garbage files. A valid MH message consists of only * digits. Deleted message get moved to a filename with a comma before * it. */int mh_valid_message (const char *s){ for (; *s; s++) { if (!isdigit ((unsigned char) *s)) return 0; } return 1;}static int maildir_parse_dir (CONTEXT * ctx, struct maildir ***last, const char *subdir, int *count){ DIR *dirp; struct dirent *de; char buf[_POSIX_PATH_MAX]; int is_old = 0;#ifdef USE_HCACHE header_cache_t *hc = NULL;#endif if (subdir) { snprintf (buf, sizeof (buf), "%s/%s", ctx->path, subdir); is_old = (mutt_strcmp ("cur", subdir) == 0); } else strfcpy (buf, ctx->path, sizeof (buf)); if ((dirp = opendir (buf)) == NULL) return -1;#ifdef USE_HCACHE if (ctx && ctx->magic == M_MH) hc = mutt_hcache_open (HeaderCache, ctx->path);#endif while ((de = readdir (dirp)) != NULL) { if ((ctx->magic == M_MH && !mh_valid_message (de->d_name)) || (ctx->magic == M_MAILDIR && *de->d_name == '.')) continue; /* FOO - really ignore the return value? */ dprint (2, (debugfile, "%s:%d: parsing %s\n", __FILE__, __LINE__, de->d_name)); maildir_parse_entry (ctx, last, subdir, de->d_name, count, is_old, #if HAVE_DIRENT_D_INO de->d_ino#else 0#endif#if USE_HCACHE , hc#endif ); } closedir (dirp);#if USE_HCACHE mutt_hcache_close (hc);#endif return 0;}static int maildir_add_to_context (CONTEXT * ctx, struct maildir *md){ int oldmsgcount = ctx->msgcount; while (md) { dprint (2, (debugfile, "%s:%d maildir_add_to_context(): Considering %s\n", __FILE__, __LINE__, NONULL (md->canon_fname))); if (md->h) { dprint (2, (debugfile, "%s:%d Adding header structure. Flags: %s%s%s%s%s\n", __FILE__, __LINE__, md->h->flagged ? "f" : "", md->h->deleted ? "D" : "", md->h->replied ? "r" : "", md->h->old ? "O" : "", md->h->read ? "R" : "")); if (ctx->msgcount == ctx->hdrmax) mx_alloc_memory (ctx); ctx->hdrs[ctx->msgcount] = md->h; ctx->hdrs[ctx->msgcount]->index = ctx->msgcount; ctx->size += md->h->content->length + md->h->content->offset - md->h->content->hdr_offset; md->h = NULL; ctx->msgcount++; } md = md->next; } if (ctx->msgcount > oldmsgcount) { mx_update_context (ctx, ctx->msgcount - oldmsgcount); return 1; } return 0;}static int maildir_move_to_context (CONTEXT * ctx, struct maildir **md){ int r; r = maildir_add_to_context (ctx, *md); maildir_free_maildir (md); return r;}#if USE_HCACHEstatic size_t maildir_hcache_keylen (const char *fn){ const char * p = strrchr (fn, ':'); return p ? (size_t) (p - fn) : mutt_strlen(fn);}#endif#ifdef USE_INODESORT/* * Merge two maildir lists according to the inode numbers. */static struct maildir* maildir_merge_inode (struct maildir *left, struct maildir *right){ struct maildir* head; struct maildir* tail; if (left && right) { if (left->inode < right->inode) { head = left; left = left->next; } else { head = right; right = right->next; } } else { if (left) return left; else return right; } tail = head; while (left && right) { if (left->inode < right->inode) { tail->next = left; left = left->next; } else { tail->next = right; right = right->next; } tail = tail->next; } if (left) { tail->next = left; } else { tail->next = right; } return head;}/* * Sort maildir list according to inode. */static struct maildir* maildir_sort_inode(struct maildir* list){ struct maildir* left = list; struct maildir* right = list; if (!list || !list->next) { return list; } list = list->next; while (list && list->next) { right = right->next; list = list->next->next; } list = right; right = right->next; list->next = 0; left = maildir_sort_inode(left); right = maildir_sort_inode(right); return maildir_merge_inode(left, right);}#endif /* USE_INODESORT *//* * This function does the second parsing pass for a maildir-style * folder. */void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md){ struct maildir *p; char fn[_POSIX_PATH_MAX]; int count;#if USE_HCACHE header_cache_t *hc = NULL; void *data; struct timeval *when = NULL; struct stat lastchanged; int ret; hc = mutt_hcache_open (HeaderCache, ctx->path);#endif for (p = md, count = 0; p; p = p->next, count++) { if (! (p && p->h && !p->header_parsed)) continue; if (!ctx->quiet && ReadInc && ((count % ReadInc) == 0 || count == 1)) mutt_message (_("Reading %s... %d"), ctx->path, count);#if USE_HCACHE data = mutt_hcache_fetch (hc, p->h->path + 3, &maildir_hcache_keylen); when = (struct timeval *) data;#endif snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path);#if USE_HCACHE if (option(OPTHCACHEVERIFY)) ret = stat(fn, &lastchanged); else { lastchanged.st_mtime = 0; ret = 0; } if (data != NULL && !ret && lastchanged.st_mtime <= when->tv_sec) { p->h = mutt_hcache_restore ((unsigned char *)data, &p->h); maildir_parse_flags (p->h, fn); } else#endif if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) { p->header_parsed = 1;#if USE_HCACHE mutt_hcache_store (hc, p->h->path + 3, p->h, 0, &maildir_hcache_keylen);#endif } else mutt_free_header (&p->h);#if USE_HCACHE FREE(&data);#endif }#if USE_HCACHE mutt_hcache_close (hc);#endif}/* Read a MH/maildir style mailbox. * * args: * ctx [IN/OUT] context for this mailbox * subdir [IN] NULL for MH mailboxes, otherwise the subdir of the * maildir mailbox to read from */int mh_read_dir (CONTEXT * ctx, const char *subdir){ struct maildir *md; struct mh_sequences mhs; struct maildir **last; int count; memset (&mhs, 0, sizeof (mhs)); maildir_update_mtime (ctx); md = NULL; last = &md; count = 0; if (maildir_parse_dir (ctx, &last, subdir, &count) == -1) return -1; if (ctx->magic == M_MH) { mh_read_sequences (&mhs, ctx->path); mh_update_maildir (md, &mhs); mhs_free_sequences (&mhs); }#ifdef USE_INODESORT md = maildir_sort_inode(md);#endif /* USE_INODESORT */ if (ctx->magic == M_MAILDIR) maildir_delayed_parsing (ctx, md);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -