int handle_request(int socket_id, struct user client) { int e; struct signal sig; e = fetch_a_message(socket_id, client.name, &sig); if (e < 0) return -1; switch (sig.type) { case DISCONNECT: running = 0; break; case MESSAGE: if (is_to(sig.body.message, client)) { e = write(socket_id, &sig, sizeof(sig)); if (e < 0) return -1; } else if (is_from(sig.body.message, client)) { int to_pipe = open(sig.body.message.to.name, O_WRONLY | O_NONBLOCK); if (to_pipe < 0) return 0; e = write(to_pipe, &sig, sizeof(sig)); if (e < 0) return -1; close(to_pipe); printf("<%s> said %s to <%s>\n", sig.body.message.from.name, sig.body.message.text, sig.body.message.to.name); } break; } return e; }
int _mutt_append_message (CONTEXT *dest, FILE *fpin, CONTEXT *src, HEADER *hdr, BODY *body, int flags, int chflags) { char buf[STRING]; MESSAGE *msg; int r; fseeko (fpin, hdr->offset, 0); if (fgets (buf, sizeof (buf), fpin) == NULL) return -1; if ((msg = mx_open_new_message (dest, hdr, is_from (buf, NULL, 0, NULL) ? 0 : M_ADD_FROM)) == NULL) return -1; if (dest->magic == M_MBOX || dest->magic == M_MMDF) chflags |= CH_FROM | CH_FORCE_FROM; chflags |= (dest->magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE); r = _mutt_copy_message (msg->fp, fpin, hdr, body, flags, chflags); if (mx_commit_message (msg, dest) != 0) r = -1; #ifdef USE_NOTMUCH if (hdr && msg->commited_path && dest->magic == M_MAILDIR && src->magic == M_NOTMUCH) nm_update_filename(src, NULL, msg->commited_path, hdr); #endif mx_close_message (&msg); return r; }
/* returns 0 on success, -1 on error */ int mutt_save_attachment (FILE *fp, BODY *m, char *path, int flags, HEADER *hdr) { if (fp) { /* recv mode */ if(hdr && m->hdr && m->encoding != ENCBASE64 && m->encoding != ENCQUOTEDPRINTABLE && mutt_is_message_type(m->type, m->subtype)) { /* message type attachments are written to mail folders. */ char buf[HUGE_STRING]; HEADER *hn; CONTEXT ctx; MESSAGE *msg; int chflags = 0; int r = -1; hn = m->hdr; hn->msgno = hdr->msgno; /* required for MH/maildir */ hn->read = 1; fseeko (fp, m->offset, 0); if (fgets (buf, sizeof (buf), fp) == NULL) return -1; if (mx_open_mailbox(path, M_APPEND | M_QUIET, &ctx) == NULL) return -1; if ((msg = mx_open_new_message (&ctx, hn, is_from (buf, NULL, 0, NULL) ? 0 : M_ADD_FROM)) == NULL) { mx_close_mailbox(&ctx, NULL); return -1; } if (ctx.magic == M_MBOX || ctx.magic == M_MMDF) chflags = CH_FROM | CH_UPDATE_LEN; chflags |= (ctx.magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE); if (_mutt_copy_message (msg->fp, fp, hn, hn->content, 0, chflags) == 0 && mx_commit_message (msg, &ctx) == 0) r = 0; else r = -1; mx_close_message (&msg); mx_close_mailbox (&ctx, NULL); return r; } else { /* In recv mode, extract from folder and decode */ STATE s; memset (&s, 0, sizeof (s)); s.flags |= M_CHARCONV; if ((s.fpout = mutt_save_attachment_open (path, flags)) == NULL) { mutt_perror ("fopen"); mutt_sleep (2); return (-1); } fseeko ((s.fpin = fp), m->offset, 0); mutt_decode_attachment (m, &s); if (fclose (s.fpout) != 0) { mutt_perror ("fclose"); mutt_sleep (2); return (-1); } } } else { /* In send mode, just copy file */ FILE *ofp, *nfp; if ((ofp = fopen (m->filename, "r")) == NULL) { mutt_perror ("fopen"); return (-1); } if ((nfp = mutt_save_attachment_open (path, flags)) == NULL) { mutt_perror ("fopen"); safe_fclose (&ofp); return (-1); } if (mutt_copy_stream (ofp, nfp) == -1) { mutt_error _("Write fault!"); safe_fclose (&ofp); safe_fclose (&nfp); return (-1); } safe_fclose (&ofp); safe_fclose (&nfp); } return 0; }
/** * mbox_parse_mailbox - Read a mailbox from disk * @param m Mailbox * @retval 0 Success * @retval -1 Error * @retval -2 Aborted * * Note that this function is also called when new mail is appended to the * currently open folder, and NOT just when the mailbox is initially read. * * NOTE: it is assumed that the mailbox being read has been locked before this * routine gets called. Strange things could happen if it's not! */ static int mbox_parse_mailbox(struct Mailbox *m) { if (!m) return -1; struct MboxAccountData *adata = mbox_adata_get(m); if (!adata) return -1; struct stat sb; char buf[8192], return_path[256]; struct Email *e_cur = NULL; time_t t; int count = 0, lines = 0; LOFF_T loc; struct Progress progress; /* Save information about the folder at the time we opened it. */ if (stat(m->path, &sb) == -1) { mutt_perror(m->path); return -1; } m->size = sb.st_size; mutt_file_get_stat_timespec(&m->mtime, &sb, MUTT_STAT_MTIME); mutt_file_get_stat_timespec(&adata->atime, &sb, MUTT_STAT_ATIME); if (!m->readonly) m->readonly = access(m->path, W_OK) ? true : false; if (!m->quiet) { char msgbuf[256]; snprintf(msgbuf, sizeof(msgbuf), _("Reading %s..."), m->path); mutt_progress_init(&progress, msgbuf, MUTT_PROGRESS_MSG, C_ReadInc, 0); } if (!m->emails) { /* Allocate some memory to get started */ m->email_max = m->msg_count; m->msg_count = 0; m->msg_unread = 0; m->vcount = 0; mx_alloc_memory(m); } loc = ftello(adata->fp); while ((fgets(buf, sizeof(buf), adata->fp)) && (SigInt != 1)) { if (is_from(buf, return_path, sizeof(return_path), &t)) { /* Save the Content-Length of the previous message */ if (count > 0) { struct Email *e = m->emails[m->msg_count - 1]; if (e->content->length < 0) { e->content->length = loc - e->content->offset - 1; if (e->content->length < 0) e->content->length = 0; } if (!e->lines) e->lines = lines ? lines - 1 : 0; } count++; if (!m->quiet) { mutt_progress_update(&progress, count, (int) (ftello(adata->fp) / (m->size / 100 + 1))); } if (m->msg_count == m->email_max) mx_alloc_memory(m); m->emails[m->msg_count] = mutt_email_new(); e_cur = m->emails[m->msg_count]; e_cur->received = t - mutt_date_local_tz(t); e_cur->offset = loc; e_cur->index = m->msg_count; e_cur->env = mutt_rfc822_read_header(adata->fp, e_cur, false, false); /* if we know how long this message is, either just skip over the body, * or if we don't know how many lines there are, count them now (this will * save time by not having to search for the next message marker). */ if (e_cur->content->length > 0) { LOFF_T tmploc; loc = ftello(adata->fp); /* The test below avoids a potential integer overflow if the * content-length is huge (thus necessarily invalid). */ tmploc = (e_cur->content->length < m->size) ? (loc + e_cur->content->length + 1) : -1; if ((tmploc > 0) && (tmploc < m->size)) { /* check to see if the content-length looks valid. we expect to * to see a valid message separator at this point in the stream */ if ((fseeko(adata->fp, tmploc, SEEK_SET) != 0) || !fgets(buf, sizeof(buf), adata->fp) || !mutt_str_startswith(buf, "From ", CASE_MATCH)) { mutt_debug(LL_DEBUG1, "bad content-length in message %d (cl=" OFF_T_FMT ")\n", e_cur->index, e_cur->content->length); mutt_debug(LL_DEBUG1, "\tLINE: %s", buf); /* nope, return the previous position */ if ((loc < 0) || (fseeko(adata->fp, loc, SEEK_SET) != 0)) { mutt_debug(LL_DEBUG1, "#1 fseek() failed\n"); } e_cur->content->length = -1; } } else if (tmploc != m->size) { /* content-length would put us past the end of the file, so it * must be wrong */ e_cur->content->length = -1; } if (e_cur->content->length != -1) { /* good content-length. check to see if we know how many lines * are in this message. */ if (e_cur->lines == 0) { int cl = e_cur->content->length; /* count the number of lines in this message */ if ((loc < 0) || (fseeko(adata->fp, loc, SEEK_SET) != 0)) mutt_debug(LL_DEBUG1, "#2 fseek() failed\n"); while (cl-- > 0) { if (fgetc(adata->fp) == '\n') e_cur->lines++; } } /* return to the offset of the next message separator */ if (fseeko(adata->fp, tmploc, SEEK_SET) != 0) mutt_debug(LL_DEBUG1, "#3 fseek() failed\n"); } } m->msg_count++; if (!e_cur->env->return_path && return_path[0]) { e_cur->env->return_path = mutt_addr_parse_list(e_cur->env->return_path, return_path); } if (!e_cur->env->from) e_cur->env->from = mutt_addr_copy_list(e_cur->env->return_path, false); lines = 0; } else lines++; loc = ftello(adata->fp); } /* Only set the content-length of the previous message if we have read more * than one message during _this_ invocation. If this routine is called * when new mail is received, we need to make sure not to clobber what * previously was the last message since the headers may be sorted. */ if (count > 0) { struct Email *e = m->emails[m->msg_count - 1]; if (e->content->length < 0) { e->content->length = ftello(adata->fp) - e->content->offset - 1; if (e->content->length < 0) e->content->length = 0; } if (!e->lines) e->lines = lines ? lines - 1 : 0; } if (SigInt == 1) { SigInt = 0; return -2; /* action aborted */ } return 0; }
/** * mmdf_parse_mailbox - Read a mailbox in MMDF format * @param m Mailbox * @retval 0 Success * @retval -1 Failure * @retval -2 Aborted */ static int mmdf_parse_mailbox(struct Mailbox *m) { if (!m) return -1; struct MboxAccountData *adata = mbox_adata_get(m); if (!adata) return -1; char buf[8192]; char return_path[1024]; int count = 0; int lines; time_t t; LOFF_T loc, tmploc; struct Email *e = NULL; struct stat sb; struct Progress progress; if (stat(m->path, &sb) == -1) { mutt_perror(m->path); return -1; } mutt_file_get_stat_timespec(&adata->atime, &sb, MUTT_STAT_ATIME); mutt_file_get_stat_timespec(&m->mtime, &sb, MUTT_STAT_MTIME); m->size = sb.st_size; buf[sizeof(buf) - 1] = '\0'; if (!m->quiet) { char msgbuf[256]; snprintf(msgbuf, sizeof(msgbuf), _("Reading %s..."), m->path); mutt_progress_init(&progress, msgbuf, MUTT_PROGRESS_MSG, C_ReadInc, 0); } while (true) { if (!fgets(buf, sizeof(buf) - 1, adata->fp)) break; if (SigInt == 1) break; if (mutt_str_strcmp(buf, MMDF_SEP) == 0) { loc = ftello(adata->fp); if (loc < 0) return -1; count++; if (!m->quiet) mutt_progress_update(&progress, count, (int) (loc / (m->size / 100 + 1))); if (m->msg_count == m->email_max) mx_alloc_memory(m); e = mutt_email_new(); m->emails[m->msg_count] = e; e->offset = loc; e->index = m->msg_count; if (!fgets(buf, sizeof(buf) - 1, adata->fp)) { /* TODO: memory leak??? */ mutt_debug(LL_DEBUG1, "unexpected EOF\n"); break; } return_path[0] = '\0'; if (!is_from(buf, return_path, sizeof(return_path), &t)) { if (fseeko(adata->fp, loc, SEEK_SET) != 0) { mutt_debug(LL_DEBUG1, "#1 fseek() failed\n"); mutt_error(_("Mailbox is corrupt")); return -1; } } else e->received = t - mutt_date_local_tz(t); e->env = mutt_rfc822_read_header(adata->fp, e, false, false); loc = ftello(adata->fp); if (loc < 0) return -1; if ((e->content->length > 0) && (e->lines > 0)) { tmploc = loc + e->content->length; if ((tmploc > 0) && (tmploc < m->size)) { if ((fseeko(adata->fp, tmploc, SEEK_SET) != 0) || !fgets(buf, sizeof(buf) - 1, adata->fp) || (mutt_str_strcmp(MMDF_SEP, buf) != 0)) { if (fseeko(adata->fp, loc, SEEK_SET) != 0) mutt_debug(LL_DEBUG1, "#2 fseek() failed\n"); e->content->length = -1; } } else e->content->length = -1; } else e->content->length = -1; if (e->content->length < 0) { lines = -1; do { loc = ftello(adata->fp); if (loc < 0) return -1; if (!fgets(buf, sizeof(buf) - 1, adata->fp)) break; lines++; } while (mutt_str_strcmp(buf, MMDF_SEP) != 0); e->lines = lines; e->content->length = loc - e->content->offset; } if (!e->env->return_path && return_path[0]) e->env->return_path = mutt_addr_parse_list(e->env->return_path, return_path); if (!e->env->from) e->env->from = mutt_addr_copy_list(e->env->return_path, false); m->msg_count++; } else { mutt_debug(LL_DEBUG1, "corrupt mailbox\n"); mutt_error(_("Mailbox is corrupt")); return -1; } } if (SigInt == 1) { SigInt = 0; return -2; /* action aborted */ } return 0; }
int mmdf_parse_mailbox(CONTEXT *ctx) { char buf[HUGE_STRING]; char return_path[LONG_STRING]; int count = 0, oldmsgcount = ctx->msgcount; int lines; time_t t; LOFF_T loc, tmploc; HEADER *hdr; struct stat sb; #ifdef NFS_ATTRIBUTE_HACK struct utimbuf newtime; #endif /* ifdef NFS_ATTRIBUTE_HACK */ progress_t progress; char msgbuf[STRING]; if (stat(ctx->path, &sb) == -1) { mutt_perror(ctx->path); return -1; } ctx->atime = sb.st_atime; ctx->mtime = sb.st_mtime; ctx->size = sb.st_size; #ifdef NFS_ATTRIBUTE_HACK if (sb.st_mtime > sb.st_atime) { newtime.modtime = sb.st_mtime; newtime.actime = time(NULL); utime(ctx->path, &newtime); } #endif /* ifdef NFS_ATTRIBUTE_HACK */ buf[sizeof(buf) - 1] = 0; if (!ctx->quiet) { snprintf(msgbuf, sizeof(msgbuf), _("Reading %s..."), ctx->path); mutt_progress_init(&progress, msgbuf, M_PROGRESS_MSG, ReadInc, 0); } FOREVER { if (fgets(buf, sizeof(buf) - 1, ctx->fp) == NULL) break; if (mutt_strcmp(buf, MMDF_SEP) == 0) { loc = ftello(ctx->fp); count++; if (!ctx->quiet) mutt_progress_update(&progress, count, (int)(loc / (ctx->size / 100 + 1))); if (ctx->msgcount == ctx->hdrmax) mx_alloc_memory(ctx); ctx->hdrs[ctx->msgcount] = hdr = mutt_new_header(); hdr->offset = loc; hdr->index = ctx->msgcount; if (fgets(buf, sizeof(buf) - 1, ctx->fp) == NULL) { /* TODO: memory leak??? */ dprint(1, "mmdf_parse_mailbox: unexpected EOF\n"); break; } return_path[0] = 0; if (!is_from(buf, return_path, sizeof(return_path), &t)) { if (fseeko(ctx->fp, loc, SEEK_SET) != 0) { dprint(1, "mmdf_parse_mailbox: fseek() failed\n"); mutt_error _("Mailbox is corrupt!"); return -1; } } else hdr->received = t - mutt_local_tz(t); hdr->env = mutt_read_rfc822_header(ctx->fp, hdr, 0, 0); loc = ftello(ctx->fp); if ((hdr->content->length > 0) && (hdr->lines > 0)) { tmploc = loc + hdr->content->length; if ((0 < tmploc) && (tmploc < ctx->size)) { if ((fseeko(ctx->fp, tmploc, SEEK_SET) != 0) || (fgets(buf, sizeof(buf) - 1, ctx->fp) == NULL) || (mutt_strcmp(MMDF_SEP, buf) != 0)) { if (fseeko(ctx->fp, loc, SEEK_SET) != 0) dprint(1, "mmdf_parse_mailbox: fseek() failed\n"); hdr->content->length = -1; } } else hdr->content->length = -1; } else hdr->content->length = -1; if (hdr->content->length < 0) { lines = -1; do { loc = ftello(ctx->fp); if (fgets(buf, sizeof(buf) - 1, ctx->fp) == NULL) break; lines++; } while (mutt_strcmp(buf, MMDF_SEP) != 0); hdr->lines = lines; hdr->content->length = loc - hdr->content->offset; } if (!hdr->env->return_path && return_path[0]) hdr->env->return_path = rfc822_parse_adrlist( hdr->env->return_path, return_path); if (!hdr->env->from) hdr->env->from = rfc822_cpy_adr(hdr->env->return_path, 0); ctx->msgcount++; } else { dprint(1, "mmdf_parse_mailbox: corrupt mailbox!\n"); mutt_error _("Mailbox is corrupt!"); return -1; } } if (ctx->msgcount > oldmsgcount) mx_update_context(ctx, ctx->msgcount - oldmsgcount); return 0; }
/* Note that this function is also called when new mail is appended to the * currently open folder, and NOT just when the mailbox is initially read. * * NOTE: it is assumed that the mailbox being read has been locked before * this routine gets called. Strange things could happen if it's not! */ int mbox_parse_mailbox(CONTEXT *ctx) { struct stat sb; char buf[HUGE_STRING], return_path[STRING]; HEADER *curhdr; time_t t; int count = 0, lines = 0; LOFF_T loc; #ifdef NFS_ATTRIBUTE_HACK struct utimbuf newtime; #endif /* ifdef NFS_ATTRIBUTE_HACK */ progress_t progress; char msgbuf[STRING]; /* Save information about the folder at the time we opened it. */ if (stat(ctx->path, &sb) == -1) { mutt_perror(ctx->path); return -1; } ctx->size = sb.st_size; ctx->mtime = sb.st_mtime; ctx->atime = sb.st_atime; #ifdef NFS_ATTRIBUTE_HACK if (sb.st_mtime > sb.st_atime) { newtime.modtime = sb.st_mtime; newtime.actime = time(NULL); utime(ctx->path, &newtime); } #endif /* ifdef NFS_ATTRIBUTE_HACK */ if (!ctx->readonly) ctx->readonly = access(ctx->path, W_OK) ? 1 : 0; if (!ctx->quiet) { snprintf(msgbuf, sizeof(msgbuf), _("Reading %s..."), ctx->path); mutt_progress_init(&progress, msgbuf, M_PROGRESS_MSG, ReadInc, 0); } loc = ftello(ctx->fp); while (fgets(buf, sizeof(buf), ctx->fp) != NULL) { if (is_from(buf, return_path, sizeof(return_path), &t)) { /* Save the Content-Length of the previous message */ if (count > 0) { #define PREV ctx->hdrs[ctx->msgcount - 1] if (PREV->content->length < 0) { PREV->content->length = loc - PREV->content->offset - 1; if (PREV->content->length < 0) PREV->content->length = 0; } if (!PREV->lines) PREV->lines = lines ? lines - 1 : 0; } count++; if (!ctx->quiet) mutt_progress_update(&progress, count, (int)(ftello(ctx->fp) / (ctx->size / 100 + 1))); if (ctx->msgcount == ctx->hdrmax) mx_alloc_memory(ctx); curhdr = ctx->hdrs[ctx->msgcount] = mutt_new_header(); curhdr->received = t - mutt_local_tz(t); curhdr->offset = loc; curhdr->index = ctx->msgcount; curhdr->env = mutt_read_rfc822_header(ctx->fp, curhdr, 0, 0); /* if we know how long this message is, either just skip over the body, * or if we don't know how many lines there are, count them now *(this will * save time by not having to search for the next message marker). */ if (curhdr->content->length > 0) { LOFF_T tmploc; loc = ftello(ctx->fp); tmploc = loc + curhdr->content->length + 1; if ((0 < tmploc) && (tmploc < ctx->size)) { /* * check to see if the content-length looks valid. we *expect to * to see a valid message separator at this point in the *stream */ if ((fseeko(ctx->fp, tmploc, SEEK_SET) != 0) || (fgets(buf, sizeof(buf), ctx->fp) == NULL) || (mutt_strncmp("From ", buf, 5) != 0)) { dprint(1, "mbox_parse_mailbox: bad content-length in message %d (cl=" OFF_T_FMT ")\n", curhdr->index, curhdr->content->length); dprint(1, "\tLINE: %s", buf); if (fseeko(ctx->fp, loc, SEEK_SET) != 0) { /* nope, return the previous position */ dprint(1, "mbox_parse_mailbox: fseek() failed\n"); } curhdr->content->length = -1; } } else if (tmploc != ctx->size) { /* content-length would put us past the end of the file, so it * must be wrong */ curhdr->content->length = -1; } if (curhdr->content->length != -1) { /* good content-length. check to see if we know how many lines * are in this message. */ if (curhdr->lines == 0) { int cl = curhdr->content->length; /* count the number of lines in this message */ if (fseeko(ctx->fp, loc, SEEK_SET) != 0) dprint(1, "mbox_parse_mailbox: fseek() failed\n"); while (cl-- > 0) { if (fgetc(ctx->fp) == '\n') curhdr->lines++; } } /* return to the offset of the next message separator */ if (fseeko(ctx->fp, tmploc, SEEK_SET) != 0) dprint(1, "mbox_parse_mailbox: fseek() failed\n"); } } ctx->msgcount++; if (!curhdr->env->return_path && return_path[0]) curhdr->env->return_path = rfc822_parse_adrlist( curhdr->env->return_path, return_path); if (!curhdr->env->from) curhdr->env->from = rfc822_cpy_adr(curhdr->env->return_path, 0); lines = 0; } else lines++; loc = ftello(ctx->fp); } /* * Only set the content-length of the previous message if we have read more * than one message during _this_ invocation. If this routine is called * when new mail is received, we need to make sure not to clobber what * previously was the last message since the headers may be sorted. */ if (count > 0) { if (PREV->content->length < 0) { PREV->content->length = ftello(ctx->fp) - PREV->content->offset - 1; if (PREV->content->length < 0) PREV->content->length = 0; } if (!PREV->lines) PREV->lines = lines ? lines - 1 : 0; mx_update_context(ctx, count); } return 0; }
static int edit_one_message (CONTEXT *ctx, HEADER *cur) { char tmp[_POSIX_PATH_MAX]; char buff[STRING]; int omagic; int oerrno; int rc; unsigned short o_read; unsigned short o_old; int of, cf; CONTEXT tmpctx; MESSAGE *msg; FILE *fp = NULL; struct stat sb; time_t mtime = 0; mutt_mktemp (tmp, sizeof (tmp)); omagic = DefaultMagic; DefaultMagic = MUTT_MBOX; rc = (mx_open_mailbox (tmp, MUTT_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0; DefaultMagic = omagic; if (rc == -1) { mutt_error (_("could not create temporary folder: %s"), strerror (errno)); return -1; } rc = mutt_append_message (&tmpctx, ctx, cur, 0, CH_NOLEN | ((ctx->magic == MUTT_MBOX || ctx->magic == MUTT_MMDF) ? 0 : CH_NOSTATUS)); oerrno = errno; mx_close_mailbox (&tmpctx, NULL); if (rc == -1) { mutt_error (_("could not write temporary mail folder: %s"), strerror (oerrno)); goto bail; } if ((rc = stat (tmp, &sb)) == -1) { mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno)); goto bail; } /* * 2002-09-05 [email protected] * The file the user is going to edit is not a real mbox, so we need to * truncate the last newline in the temp file, which is logically part of * the message separator, and not the body of the message. If we fail to * remove it, the message will grow by one line each time the user edits * the message. */ if (sb.st_size != 0 && truncate (tmp, sb.st_size - 1) == -1) { mutt_error (_("could not truncate temporary mail folder: %s"), strerror (errno)); goto bail; } mtime = mutt_decrease_mtime (tmp, &sb); mutt_edit_file (NONULL(Editor), tmp); if ((rc = stat (tmp, &sb)) == -1) { mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno)); goto bail; } if (sb.st_size == 0) { mutt_message (_("Message file is empty!")); rc = 1; goto bail; } if (sb.st_mtime == mtime) { mutt_message (_("Message not modified!")); rc = 1; goto bail; } if ((fp = fopen (tmp, "r")) == NULL) { rc = -1; mutt_error (_("Can't open message file: %s"), strerror (errno)); goto bail; } if (mx_open_mailbox (ctx->path, MUTT_APPEND, &tmpctx) == NULL) { rc = -1; /* L10N: %s is from strerror(errno) */ mutt_error (_("Can't append to folder: %s"), strerror (errno)); goto bail; } of = 0; cf = ((tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF) ? 0 : CH_NOSTATUS); if (fgets (buff, sizeof (buff), fp) && is_from (buff, NULL, 0, NULL)) { if (tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF) cf = CH_FROM | CH_FORCE_FROM; } else of = MUTT_ADD_FROM; /* * XXX - we have to play games with the message flags to avoid * problematic behavior with maildir folders. * */ o_read = cur->read; o_old = cur->old; cur->read = cur->old = 0; msg = mx_open_new_message (&tmpctx, cur, of); cur->read = o_read; cur->old = o_old; if (msg == NULL) { mutt_error (_("Can't append to folder: %s"), strerror (errno)); mx_close_mailbox (&tmpctx, NULL); goto bail; } if ((rc = mutt_copy_hdr (fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf, NULL)) == 0) { fputc ('\n', msg->fp); rc = mutt_copy_stream (fp, msg->fp); } rc = mx_commit_message (msg, &tmpctx); mx_close_message (&tmpctx, &msg); mx_close_mailbox (&tmpctx, NULL); bail: if (fp) safe_fclose (&fp); if (rc >= 0) unlink (tmp); if (rc == 0) { mutt_set_flag (Context, cur, MUTT_DELETE, 1); mutt_set_flag (Context, cur, MUTT_PURGE, 1); mutt_set_flag (Context, cur, MUTT_READ, 1); if (option (OPTDELETEUNTAG)) mutt_set_flag (Context, cur, MUTT_TAG, 0); } else if (rc == -1) mutt_message (_("Error. Preserving temporary file: %s"), tmp); return rc; }