/* format date in IMAP style: DD-MMM-YYYY HH:MM:SS +ZZzz. * Caller should provide a buffer of IMAP_DATELEN bytes */ void imap_make_date (char *buf, time_t timestamp) { struct tm* tm = localtime (×tamp); time_t tz = mutt_local_tz (timestamp); tz /= 60; snprintf (buf, IMAP_DATELEN, "%02d-%s-%d %02d:%02d:%02d %+03d%02d", tm->tm_mday, Months[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, (int) tz / 60, (int) abs (tz) % 60); }
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; }