static QUERY *run_query (char *s, int quiet) { FILE *fp; QUERY *first = NULL; QUERY *cur = NULL; char cmd[_POSIX_PATH_MAX]; char *buf = NULL; size_t buflen; int dummy = 0; char msg[STRING]; char *p; pid_t thepid; mutt_expand_file_fmt (cmd, sizeof(cmd), QueryCmd, s); if ((thepid = mutt_create_filter (cmd, NULL, &fp, NULL)) < 0) { dprint (1, (debugfile, "unable to fork command: %s", cmd)); return 0; } if (!quiet) mutt_message _("Waiting for response..."); fgets (msg, sizeof (msg), fp); if ((p = strrchr (msg, '\n'))) *p = '\0'; while ((buf = mutt_read_line (buf, &buflen, fp, &dummy, 0)) != NULL) { if ((p = strtok(buf, "\t\n"))) { if (first == NULL) { first = (QUERY *) safe_calloc (1, sizeof (QUERY)); cur = first; } else { cur->next = (QUERY *) safe_calloc (1, sizeof (QUERY)); cur = cur->next; } cur->addr = rfc822_parse_adrlist (cur->addr, p); p = strtok(NULL, "\t\n"); if (p) { cur->name = safe_strdup (p); p = strtok(NULL, "\t\n"); if (p) cur->other = safe_strdup (p); } } } FREE (&buf); safe_fclose (&fp); if (mutt_wait_filter (thepid)) { dprint (1, (debugfile, "Error: %s\n", msg)); if (!quiet) mutt_error ("%s", msg); } else { if (!quiet) mutt_message ("%s", msg); } return first; }
static int tls_check_stored_hostname (const gnutls_datum *cert, const char *hostname) { char buf[80]; FILE *fp; char *linestr = NULL; size_t linestrsize; int linenum = 0; regex_t preg; regmatch_t pmatch[3]; /* try checking against names stored in stored certs file */ if ((fp = fopen (SslCertFile, "r"))) { if (REGCOMP(&preg, "^#H ([a-zA-Z0-9_\\.-]+) ([0-9A-F]{4}( [0-9A-F]{4}){7})[ \t]*$", REG_ICASE) != 0) { return 0; } buf[0] = '\0'; tls_fingerprint (GNUTLS_DIG_MD5, buf, sizeof (buf), cert); while ((linestr = mutt_read_line(linestr, &linestrsize, fp, &linenum, 0)) != NULL) { 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); safe_fclose (&fp); return 1; } } } } regfree(&preg); safe_fclose (&fp); } /* not found a matching name */ return 0; }
static void mh_read_sequences (struct mh_sequences *mhs, const char *path) { FILE *fp; int line = 1; char *buff = NULL; char *t; size_t sz = 0; short f; int first, last; char pathname[_POSIX_PATH_MAX]; snprintf (pathname, sizeof (pathname), "%s/.mh_sequences", path); if (!(fp = fopen (pathname, "r"))) return; while ((buff = mutt_read_line (buff, &sz, fp, &line))) { if (!(t = strtok (buff, " \t:"))) continue; if (!mutt_strcmp (t, MhUnseen)) f = MH_SEQ_UNSEEN; else if (!mutt_strcmp (t, MhFlagged)) f = MH_SEQ_FLAGGED; else if (!mutt_strcmp (t, MhReplied)) f = MH_SEQ_REPLIED; else /* unknown sequence */ continue; while ((t = strtok (NULL, " \t:"))) { mh_read_token (t, &first, &last); for (; first <= last; first++) mhs_set (mhs, first, f); } } safe_free ((void **) &buff); safe_fclose (&fp); }
static void mh_sequences_add_one (CONTEXT *ctx, int n, short unseen, short flagged, short replied) { short unseen_done = 0; short flagged_done = 0; short replied_done = 0; FILE *ofp = NULL, *nfp = NULL; char *tmpfname; char sequences[_POSIX_PATH_MAX]; char seq_unseen[STRING]; char seq_replied[STRING]; char seq_flagged[STRING]; char *buff = NULL; int line; size_t sz; if (mh_mkstemp (ctx, &nfp, &tmpfname) == -1) return; snprintf (seq_unseen, sizeof (seq_unseen), "%s:", NONULL (MhUnseen)); snprintf (seq_replied, sizeof (seq_replied), "%s:", NONULL (MhReplied)); snprintf (seq_flagged, sizeof (seq_flagged), "%s:", NONULL (MhFlagged)); snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path); if ((ofp = fopen (sequences, "r"))) { while ((buff = mutt_read_line (buff, &sz, ofp, &line))) { if (unseen && !strncmp (buff, seq_unseen, mutt_strlen (seq_unseen))) { fprintf (nfp, "%s %d\n", buff, n); unseen_done = 1; } else if (flagged && !strncmp (buff, seq_flagged, mutt_strlen (seq_flagged))) { fprintf (nfp, "%s %d\n", buff, n); flagged_done = 1; } else if (replied && !strncmp (buff, seq_replied, mutt_strlen (seq_replied))) { fprintf (nfp, "%s %d\n", buff, n); replied_done = 1; } else fprintf (nfp, "%s\n", buff); } } safe_fclose (&ofp); safe_free ((void **) &buff); if (!unseen_done && unseen) fprintf (nfp, "%s: %d\n", NONULL (MhUnseen), n); if (!flagged_done && flagged) fprintf (nfp, "%s: %d\n", NONULL (MhFlagged), n); if (!replied_done && replied) fprintf (nfp, "%s: %d\n", NONULL (MhReplied), n); safe_fclose (&nfp); unlink (sequences); if (safe_rename (tmpfname, sequences) != 0) unlink (tmpfname); safe_free ((void **) &tmpfname); }
void mh_update_sequences (CONTEXT *ctx) { FILE *ofp, *nfp; char sequences[_POSIX_PATH_MAX]; char *tmpfname; char *buff = NULL; char *p; size_t s; int l = 0; int i; int unseen = 0; int flagged = 0; int replied = 0; char seq_unseen[STRING]; char seq_replied[STRING]; char seq_flagged[STRING]; struct mh_sequences mhs; memset (&mhs, 0, sizeof (mhs)); snprintf (seq_unseen, sizeof (seq_unseen), "%s:", NONULL (MhUnseen)); snprintf (seq_replied, sizeof (seq_replied), "%s:", NONULL (MhReplied)); snprintf (seq_flagged, sizeof (seq_flagged), "%s:", NONULL (MhFlagged)); if (mh_mkstemp (ctx, &nfp, &tmpfname) != 0) { /* error message? */ return; } snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path); /* first, copy unknown sequences */ if ((ofp = fopen (sequences, "r"))) { while ((buff = mutt_read_line (buff, &s, ofp, &l))) { if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen))) continue; if (!mutt_strncmp (buff, seq_flagged, mutt_strlen (seq_flagged))) continue; if (!mutt_strncmp (buff, seq_replied, mutt_strlen (seq_replied))) continue; fprintf (nfp, "%s\n", buff); } } safe_fclose (&ofp); /* now, update our unseen, flagged, and replied sequences */ for (l = 0; l < ctx->msgcount; l++) { if (ctx->hdrs[l]->deleted) continue; if ((p = strrchr (ctx->hdrs[l]->path, '/'))) p++; else p = ctx->hdrs[l]->path; i = atoi (p); if (!ctx->hdrs[l]->read) { mhs_set (&mhs, i, MH_SEQ_UNSEEN); unseen++; } if (ctx->hdrs[l]->flagged) { mhs_set (&mhs, i, MH_SEQ_FLAGGED); flagged++; } if (ctx->hdrs[l]->replied) { mhs_set (&mhs, i, MH_SEQ_REPLIED); replied++; } } /* write out the new sequences */ if (unseen) mhs_write_one_sequence (nfp, &mhs, MH_SEQ_UNSEEN, NONULL (MhUnseen)); if (flagged) mhs_write_one_sequence (nfp, &mhs, MH_SEQ_FLAGGED, NONULL (MhFlagged)); if (replied) mhs_write_one_sequence (nfp, &mhs, MH_SEQ_REPLIED, NONULL (MhReplied)); mhs_free_sequences (&mhs); /* try to commit the changes - no guarantee here */ safe_fclose (&nfp); unlink (sequences); if (safe_rename (tmpfname, sequences) != 0) { /* report an error? */ unlink (tmpfname); } safe_free ((void **) &tmpfname); }
static int rfc1524_mailcap_parse (BODY *a, char *filename, char *type, rfc1524_entry *entry, int opt) { FILE *fp; char *buf = NULL; size_t buflen; char *ch; char *field; int found = FALSE; int copiousoutput; int composecommand; int editcommand; int printcommand; int btlen; int line = 0; /* rfc1524 mailcap file is of the format: * base/type; command; extradefs * type can be * for matching all * base with no /type is an implicit wild * command contains a %s for the filename to pass, default to pipe on stdin * extradefs are of the form: * def1="definition"; def2="define \;"; * line wraps with a \ at the end of the line * # for comments */ /* find length of basetype */ if ((ch = strchr (type, '/')) == NULL) return FALSE; btlen = ch - type; if ((fp = fopen (filename, "r")) != NULL) { while (!found && (buf = mutt_read_line (buf, &buflen, fp, &line, M_CONT)) != NULL) { /* ignore comments */ if (*buf == '#') continue; dprint (2, (debugfile, "mailcap entry: %s\n", buf)); /* check type */ ch = get_field (buf); if (ascii_strcasecmp (buf, type) && (ascii_strncasecmp (buf, type, btlen) || (buf[btlen] != 0 && /* implicit wild */ mutt_strcmp (buf + btlen, "/*")))) /* wildsubtype */ continue; /* next field is the viewcommand */ field = ch; ch = get_field (ch); if (entry) entry->command = safe_strdup (field); /* parse the optional fields */ found = TRUE; copiousoutput = FALSE; composecommand = FALSE; editcommand = FALSE; printcommand = FALSE; while (ch) { field = ch; ch = get_field (ch); dprint (2, (debugfile, "field: %s\n", field)); if (!ascii_strcasecmp (field, "needsterminal")) { if (entry) entry->needsterminal = TRUE; } else if (!ascii_strcasecmp (field, "copiousoutput")) { copiousoutput = TRUE; if (entry) entry->copiousoutput = TRUE; } else if (!ascii_strncasecmp (field, "composetyped", 12)) { /* this compare most occur before compose to match correctly */ if (get_field_text (field + 12, entry ? &entry->composetypecommand : NULL, type, filename, line)) composecommand = TRUE; } else if (!ascii_strncasecmp (field, "compose", 7)) { if (get_field_text (field + 7, entry ? &entry->composecommand : NULL, type, filename, line)) composecommand = TRUE; } else if (!ascii_strncasecmp (field, "print", 5)) { if (get_field_text (field + 5, entry ? &entry->printcommand : NULL, type, filename, line)) printcommand = TRUE; } else if (!ascii_strncasecmp (field, "edit", 4)) { if (get_field_text (field + 4, entry ? &entry->editcommand : NULL, type, filename, line)) editcommand = TRUE; } else if (!ascii_strncasecmp (field, "nametemplate", 12)) { get_field_text (field + 12, entry ? &entry->nametemplate : NULL, type, filename, line); } else if (!ascii_strncasecmp (field, "x-convert", 9)) { get_field_text (field + 9, entry ? &entry->convert : NULL, type, filename, line); } else if (!ascii_strncasecmp (field, "test", 4)) { /* * This routine executes the given test command to determine * if this is the right entry. */ char *test_command = NULL; size_t len; if (get_field_text (field + 4, &test_command, type, filename, line) && test_command) { len = mutt_strlen (test_command) + STRING; safe_realloc (&test_command, len); rfc1524_expand_command (a, a->filename, type, test_command, len); if (mutt_system (test_command)) { /* a non-zero exit code means test failed */ found = FALSE; } FREE (&test_command); } } } /* while (ch) */ if (opt == M_AUTOVIEW) { if (!copiousoutput) found = FALSE; } else if (opt == M_COMPOSE) { if (!composecommand) found = FALSE; } else if (opt == M_EDIT) { if (!editcommand) found = FALSE; } else if (opt == M_PRINT) { if (!printcommand) found = FALSE; } if (!found) { /* reset */ if (entry) { FREE (&entry->command); FREE (&entry->composecommand); FREE (&entry->composetypecommand); FREE (&entry->editcommand); FREE (&entry->printcommand); FREE (&entry->nametemplate); FREE (&entry->convert); entry->needsterminal = 0; entry->copiousoutput = 0; } } } /* while (!found && (buf = mutt_read_line ())) */ safe_fclose (&fp); } /* if ((fp = fopen ())) */ FREE (&buf); return found; }
int rfc3676_handler (BODY * a, STATE * s) { char *buf = NULL, *t = NULL; unsigned int quotelevel = 0, newql = 0, sigsep = 0; int buf_off = 0, delsp = 0, fixed = 0; size_t buf_len = 0, sz = 0; flowed_state_t fst; memset (&fst, 0, sizeof (fst)); /* respect DelSp of RfC3676 only with f=f parts */ if ((t = (char *) mutt_get_parameter ("delsp", a->parameter))) { delsp = mutt_strlen (t) == 3 && ascii_strncasecmp (t, "yes", 3) == 0; t = NULL; fst.delsp = 1; } dprint (4, (debugfile, "f=f: DelSp: %s\n", delsp ? "yes" : "no")); while ((buf = mutt_read_line (buf, &sz, s->fpin, NULL, 0))) { buf_len = mutt_strlen (buf); newql = get_quote_level (buf); /* end flowed paragraph (if we're within one) if quoting level * changes (should not but can happen, see RFC 3676, sec. 4.5.) */ if (newql != quotelevel) flush_par (s, &fst); quotelevel = newql; buf_off = newql; /* respect sender's space-stuffing by removing one leading space */ if (buf[buf_off] == ' ') buf_off++; /* test for signature separator */ sigsep = ascii_strcmp (buf + buf_off, "-- ") == 0; /* a fixed line either has no trailing space or is the * signature separator */ fixed = buf_len == buf_off || buf[buf_len - 1] != ' ' || sigsep; /* print fixed-and-standalone, fixed-and-empty and sigsep lines as * fixed lines */ if ((fixed && (!fst.width || !buf_len)) || sigsep) { /* if we're within a flowed paragraph, terminate it */ flush_par (s, &fst); print_fixed_line (buf + buf_off, s, quotelevel, &fst); continue; } /* for DelSp=yes, we need to strip one SP prior to CRLF on flowed lines */ if (delsp && !fixed) buf[--buf_len] = '\0'; print_flowed_line (buf + buf_off, s, quotelevel, &fst, fixed); } flush_par (s, &fst); FREE (&buf); return (0); }
int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) { char ch; char qc = 0; /* quote char */ char *pc; /* reset the destination pointer to the beginning of the buffer */ dest->dptr = dest->data; SKIPWS (tok->dptr); while ((ch = *tok->dptr)) { if (!qc) { if ((ISSPACE (ch) && !(flags & M_TOKEN_SPACE)) || (ch == '#' && !(flags & M_TOKEN_COMMENT)) || (ch == '=' && (flags & M_TOKEN_EQUAL)) || (ch == ';' && !(flags & M_TOKEN_SEMICOLON)) || ((flags & M_TOKEN_PATTERN) && strchr ("~!|", ch))) break; } tok->dptr++; if (ch == qc) qc = 0; /* end of quote */ else if (!qc && (ch == '\'' || ch == '"') && !(flags & M_TOKEN_QUOTE)) qc = ch; else if (ch == '\\' && qc != '\'') { if (!*tok->dptr) return -1; /* premature end of token */ switch (ch = *tok->dptr++) { case 'c': case 'C': if (!*tok->dptr) return -1; /* premature end of token */ mutt_buffer_addch (dest, (toupper (*tok->dptr) - '@') & 0x7f); tok->dptr++; break; case 'r': mutt_buffer_addch (dest, '\r'); break; case 'n': mutt_buffer_addch (dest, '\n'); break; case 't': mutt_buffer_addch (dest, '\t'); break; case 'f': mutt_buffer_addch (dest, '\f'); break; case 'e': mutt_buffer_addch (dest, '\033'); break; default: if (isdigit ((unsigned char) ch) && isdigit ((unsigned char) *tok->dptr) && isdigit ((unsigned char) *(tok->dptr + 1))) { mutt_buffer_addch (dest, (ch << 6) + (*tok->dptr << 3) + *(tok->dptr + 1) - 3504); tok->dptr += 2; } else mutt_buffer_addch (dest, ch); } } else if (ch == '^' && (flags & M_TOKEN_CONDENSE)) { if (!*tok->dptr) return -1; /* premature end of token */ ch = *tok->dptr++; if (ch == '^') mutt_buffer_addch (dest, ch); else if (ch == '[') mutt_buffer_addch (dest, '\033'); else if (isalpha ((unsigned char) ch)) mutt_buffer_addch (dest, toupper (ch) - '@'); else { mutt_buffer_addch (dest, '^'); mutt_buffer_addch (dest, ch); } } else if (ch == '`' && (!qc || qc == '"')) { #ifndef LIBMUTT FILE *fp; pid_t pid; char *cmd, *ptr; size_t expnlen; BUFFER expn; int line = 0; pc = tok->dptr; do { if ((pc = strpbrk (pc, "\\`"))) { /* skip any quoted chars */ if (*pc == '\\') pc += 2; } } while (pc && *pc != '`'); if (!pc) { dprint (1, (debugfile, "mutt_get_token: mismatched backtics\n")); return (-1); } cmd = mutt_substrdup (tok->dptr, pc); if ((pid = mutt_create_filter (cmd, NULL, &fp, NULL)) < 0) { dprint (1, (debugfile, "mutt_get_token: unable to fork command: %s", cmd)); return (-1); } FREE (&cmd); tok->dptr = pc + 1; /* read line */ memset (&expn, 0, sizeof (expn)); expn.data = mutt_read_line (NULL, &expn.dsize, fp, &line); fclose (fp); mutt_wait_filter (pid); /* if we got output, make a new string consiting of the shell ouptput plus whatever else was left on the original line */ /* BUT: If this is inside a quoted string, directly add output to * the token */ if (expn.data && qc) { mutt_buffer_addstr (dest, expn.data); FREE (&expn.data); } else if (expn.data) { expnlen = mutt_strlen (expn.data); tok->dsize = expnlen + mutt_strlen (tok->dptr) + 1; ptr = safe_malloc (tok->dsize); memcpy (ptr, expn.data, expnlen); strcpy (ptr + expnlen, tok->dptr); if (tok->destroy) FREE (&tok->data); tok->data = ptr; tok->dptr = ptr; tok->destroy = 1; /* mark that the caller should destroy this data */ ptr = NULL; FREE (&expn.data); } #else int backtick_not_supported__file_bug = 0; assert(backtick_not_supported__file_bug); #endif } else if (ch == '$' && (!qc || qc == '"') && (*tok->dptr == '{' || isalpha ((unsigned char) *tok->dptr))) { char *env = NULL, *var = NULL; if (*tok->dptr == '{') { tok->dptr++; if ((pc = strchr (tok->dptr, '}'))) { var = mutt_substrdup (tok->dptr, pc); tok->dptr = pc + 1; } } else { for (pc = tok->dptr; isalpha ((unsigned char) *pc) || *pc == '_'; pc++) ; var = mutt_substrdup (tok->dptr, pc); tok->dptr = pc; } if (var && (env = getenv (var))) mutt_buffer_addstr (dest, env); FREE (&var); } else mutt_buffer_addch (dest, ch); } mutt_buffer_addch (dest, 0); /* terminate the string */ SKIPWS (tok->dptr); return 0; }