/** * mh_read_sequences - Read a set of MH sequences * @param mhs Existing sequences * @param path File to read from * @retval 0 Success * @retval -1 Error */ int mh_read_sequences(struct MhSequences *mhs, const char *path) { int line = 1; char *buf = NULL; size_t sz = 0; MhSeqFlags flags; int first, last, rc = 0; char pathname[PATH_MAX]; snprintf(pathname, sizeof(pathname), "%s/.mh_sequences", path); FILE *fp = fopen(pathname, "r"); if (!fp) return 0; /* yes, ask callers to silently ignore the error */ while ((buf = mutt_file_read_line(buf, &sz, fp, &line, 0))) { char *t = strtok(buf, " \t:"); if (!t) continue; if (mutt_str_strcmp(t, C_MhSeqUnseen) == 0) flags = MH_SEQ_UNSEEN; else if (mutt_str_strcmp(t, C_MhSeqFlagged) == 0) flags = MH_SEQ_FLAGGED; else if (mutt_str_strcmp(t, C_MhSeqReplied) == 0) flags = MH_SEQ_REPLIED; else /* unknown sequence */ continue; while ((t = strtok(NULL, " \t:"))) { if (mh_read_token(t, &first, &last) < 0) { mhs_free_sequences(mhs); rc = -1; goto out; } for (; first <= last; first++) mhs_set(mhs, first, flags); } } rc = 0; out: FREE(&buf); mutt_file_fclose(&fp); return rc; }
/** * tls_check_stored_hostname - Does the hostname match a stored certificate? * @param cert Certificate * @param hostname Hostname * @retval 1 Hostname match found * @retval 0 Error, or no match */ static int tls_check_stored_hostname(const gnutls_datum_t *cert, const char *hostname) { char *linestr = NULL; size_t linestrsize = 0; int linenum = 0; regex_t preg; regmatch_t pmatch[3]; /* try checking against names stored in stored certs file */ FILE *fp = fopen(C_CertificateFile, "r"); if (fp) { if (REGCOMP(&preg, "^#H ([a-zA-Z0-9_\\.-]+) ([0-9A-F]{4}( [0-9A-F]{4}){7})[ \t]*$", REG_ICASE) != 0) { mutt_file_fclose(&fp); return 0; } char buf[80]; buf[0] = '\0'; tls_fingerprint(GNUTLS_DIG_MD5, buf, sizeof(buf), cert); while ((linestr = mutt_file_read_line(linestr, &linestrsize, fp, &linenum, 0))) { if ((linestr[0] == '#') && (linestr[1] == 'H')) { if (regexec(&preg, linestr, 3, pmatch, 0) == 0) { linestr[pmatch[1].rm_eo] = '\0'; linestr[pmatch[2].rm_eo] = '\0'; if ((strcmp(linestr + pmatch[1].rm_so, hostname) == 0) && (strcmp(linestr + pmatch[2].rm_so, buf) == 0)) { regfree(&preg); FREE(&linestr); mutt_file_fclose(&fp); return 1; } } } } regfree(&preg); mutt_file_fclose(&fp); } /* not found a matching name */ return 0; }
/** * mh_update_sequences - Update sequence numbers * @param m Mailbox * * XXX we don't currently remove deleted messages from sequences we don't know. * Should we? */ void mh_update_sequences(struct Mailbox *m) { char sequences[PATH_MAX]; char *tmpfname = NULL; char *buf = NULL; char *p = NULL; size_t s; int l = 0; int i; int unseen = 0; int flagged = 0; int replied = 0; char seq_unseen[256]; char seq_replied[256]; char seq_flagged[256]; struct MhSequences mhs = { 0 }; snprintf(seq_unseen, sizeof(seq_unseen), "%s:", NONULL(C_MhSeqUnseen)); snprintf(seq_replied, sizeof(seq_replied), "%s:", NONULL(C_MhSeqReplied)); snprintf(seq_flagged, sizeof(seq_flagged), "%s:", NONULL(C_MhSeqFlagged)); FILE *fp_new = NULL; if (mh_mkstemp(m, &fp_new, &tmpfname) != 0) { /* error message? */ return; } snprintf(sequences, sizeof(sequences), "%s/.mh_sequences", m->path); /* first, copy unknown sequences */ FILE *fp_old = fopen(sequences, "r"); if (fp_old) { while ((buf = mutt_file_read_line(buf, &s, fp_old, &l, 0))) { if (mutt_str_startswith(buf, seq_unseen, CASE_MATCH) || mutt_str_startswith(buf, seq_flagged, CASE_MATCH) || mutt_str_startswith(buf, seq_replied, CASE_MATCH)) continue; fprintf(fp_new, "%s\n", buf); } } mutt_file_fclose(&fp_old); /* now, update our unseen, flagged, and replied sequences */ for (l = 0; l < m->msg_count; l++) { if (m->emails[l]->deleted) continue; p = strrchr(m->emails[l]->path, '/'); if (p) p++; else p = m->emails[l]->path; if (mutt_str_atoi(p, &i) < 0) continue; if (!m->emails[l]->read) { mhs_set(&mhs, i, MH_SEQ_UNSEEN); unseen++; } if (m->emails[l]->flagged) { mhs_set(&mhs, i, MH_SEQ_FLAGGED); flagged++; } if (m->emails[l]->replied) { mhs_set(&mhs, i, MH_SEQ_REPLIED); replied++; } } /* write out the new sequences */ if (unseen) mhs_write_one_sequence(fp_new, &mhs, MH_SEQ_UNSEEN, NONULL(C_MhSeqUnseen)); if (flagged) mhs_write_one_sequence(fp_new, &mhs, MH_SEQ_FLAGGED, NONULL(C_MhSeqFlagged)); if (replied) mhs_write_one_sequence(fp_new, &mhs, MH_SEQ_REPLIED, NONULL(C_MhSeqReplied)); mhs_free_sequences(&mhs); /* try to commit the changes - no guarantee here */ mutt_file_fclose(&fp_new); unlink(sequences); if (mutt_file_safe_rename(tmpfname, sequences) != 0) { /* report an error? */ unlink(tmpfname); } FREE(&tmpfname); }