static const char * parse_mailboxdomain (const char *s, const char *nonspecial, char *mailbox, size_t *mailboxlen, size_t mailboxmax, char *comment, size_t *commentlen, size_t commentmax) { const char *ps; while (*s) { s = skip_email_wsp(s); if (strchr (nonspecial, *s) == NULL && is_special (*s)) return s; if (*s == '(') { if (*commentlen && *commentlen < commentmax) comment[(*commentlen)++] = ' '; ps = next_token (s, comment, commentlen, commentmax); } else ps = next_token (s, mailbox, mailboxlen, mailboxmax); if (!ps) return NULL; s = ps; } return s; }
/* NUL terminates a rfc 1524 field, * returns start of next field or NULL */ static char *get_field (char *s) { char *ch; if (!s) return NULL; while ((ch = strpbrk (s, ";\\")) != NULL) { if (*ch == '\\') { s = ch + 1; if (*s) s++; } else { *ch = 0; ch = skip_email_wsp(ch + 1); break; } } mutt_remove_trailing_ws (s); return ch; }
/* Parse CAPA output */ static int fetch_capa (char *line, void *data) { POP_DATA *pop_data = (POP_DATA *)data; char *c; if (!ascii_strncasecmp (line, "SASL", 4)) { FREE (&pop_data->auth_list); c = skip_email_wsp(line + 4); pop_data->auth_list = safe_strdup (c); } else if (!ascii_strncasecmp (line, "STLS", 4)) pop_data->cmd_stls = 1; else if (!ascii_strncasecmp (line, "USER", 4)) pop_data->cmd_user = 1; else if (!ascii_strncasecmp (line, "UIDL", 4)) pop_data->cmd_uidl = 1; else if (!ascii_strncasecmp (line, "TOP", 3)) pop_data->cmd_top = 1; return 0; }
static const char * parse_route_addr (const char *s, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr) { char token[LONG_STRING]; size_t tokenlen = 0; s = skip_email_wsp(s); /* find the end of the route */ if (*s == '@') { while (s && *s == '@') { if (tokenlen < sizeof (token) - 1) token[tokenlen++] = '@'; s = parse_mailboxdomain (s + 1, ",.\\[](", token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax); } if (!s || *s != ':') { RFC822Error = ERR_BAD_ROUTE; return NULL; /* invalid route */ } if (tokenlen < sizeof (token) - 1) token[tokenlen++] = ':'; s++; } if ((s = parse_address (s, token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax, addr)) == NULL) return NULL; if (*s != '>') { RFC822Error = ERR_BAD_ROUTE_ADDR; return NULL; } if (!addr->mailbox) addr->mailbox = safe_strdup ("@"); s++; return s; }
/* Copy error message to err_msg buffer */ void pop_error (POP_DATA *pop_data, char *msg) { char *t, *c, *c2; t = strchr (pop_data->err_msg, '\0'); c = msg; if (!mutt_strncmp (msg, "-ERR ", 5)) { c2 = skip_email_wsp(msg + 5); if (*c2) c = c2; } strfcpy (t, c, sizeof (pop_data->err_msg) - strlen (pop_data->err_msg)); mutt_remove_trailing_ws (pop_data->err_msg); }
static int edit_envelope (ENVELOPE *en) { char buf[HUGE_STRING]; LIST *uh = UserHeader; if (edit_address (&en->to, "To: ") == -1 || en->to == NULL) return (-1); if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1) return (-1); if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1) return (-1); if (en->subject) { if (option (OPTFASTREPLY)) return (0); else strfcpy (buf, en->subject, sizeof (buf)); } else { const char *p; buf[0] = 0; for (; uh; uh = uh->next) { if (ascii_strncasecmp ("subject:", uh->data, 8) == 0) { p = skip_email_wsp(uh->data + 8); strncpy (buf, p, sizeof (buf)); } } } if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) != 0 || (!buf[0] && query_quadoption (OPT_SUBJECT, _("No subject, abort?")) != M_NO)) { mutt_message _("No subject, aborting."); return (-1); } mutt_str_replace (&en->subject, buf); return 0; }
int mutt_parse_crypt_hdr (const char *p, int set_empty_signas, int crypt_app) { char smime_cryptalg[LONG_STRING] = "\0"; char sign_as[LONG_STRING] = "\0", *q; int flags = 0; if (!WithCrypto) return 0; p = skip_email_wsp(p); for (; *p; p++) { switch (*p) { case 'e': case 'E': flags |= ENCRYPT; break; case 'o': case 'O': flags |= OPPENCRYPT; break; case 's': case 'S': flags |= SIGN; q = sign_as; if (*(p+1) == '<') { for (p += 2; *p && *p != '>' && q < sign_as + sizeof (sign_as) - 1; *q++ = *p++) ; if (*p!='>') { mutt_error _("Illegal crypto header"); return 0; } } *q = '\0'; break; /* This used to be the micalg parameter. * * It's no longer needed, so we just skip the parameter in order * to be able to recall old messages. */ case 'm': case 'M': if(*(p+1) == '<') { for (p += 2; *p && *p != '>'; p++) ; if(*p != '>') { mutt_error _("Illegal crypto header"); return 0; } } break; case 'c': case 'C': q = smime_cryptalg; if(*(p+1) == '<') { for(p += 2; *p && *p != '>' && q < smime_cryptalg + sizeof(smime_cryptalg) - 1; *q++ = *p++) ; if(*p != '>') { mutt_error _("Illegal S/MIME header"); return 0; } } *q = '\0'; break; case 'i': case 'I': flags |= INLINE; break; default: mutt_error _("Illegal crypto header"); return 0; } } /* the cryptalg field must not be empty */ if ((WithCrypto & APPLICATION_SMIME) && *smime_cryptalg) mutt_str_replace (&SmimeCryptAlg, smime_cryptalg); /* Set {Smime,Pgp}SignAs, if desired. */ if ((WithCrypto & APPLICATION_PGP) && (crypt_app == APPLICATION_PGP) && (flags & SIGN) && (set_empty_signas || *sign_as)) mutt_str_replace (&PgpSignAs, sign_as); if ((WithCrypto & APPLICATION_SMIME) && (crypt_app == APPLICATION_SMIME) && (flags & SIGN) && (set_empty_signas || *sign_as)) mutt_str_replace (&SmimeDefaultKey, sign_as); return flags; }
/* args: * ctx Context info, used when recalling a message to which * we reply. * hdr envelope/attachment info for recalled message * cur if message was a reply, `cur' is set to the message which * `hdr' is in reply to * fcc fcc for the recalled message * fcclen max length of fcc * * return vals: * -1 error/no messages * 0 normal exit * SENDREPLY recalled message is a reply */ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size_t fcclen) { HEADER *h; int code = SENDPOSTPONED; LIST *tmp; LIST *last = NULL; LIST *next; const char *p; int opt_delete; if (!Postponed) return (-1); if ((PostContext = mx_open_mailbox (Postponed, M_NOSORT, NULL)) == NULL) { PostCount = 0; mutt_error _("No postponed messages."); return (-1); } if (! PostContext->msgcount) { PostCount = 0; mx_close_mailbox (PostContext, NULL); FREE (&PostContext); mutt_error _("No postponed messages."); return (-1); } if (PostContext->msgcount == 1) { /* only one message, so just use that one. */ h = PostContext->hdrs[0]; } else if ((h = select_msg ()) == NULL) { mx_close_mailbox (PostContext, NULL); FREE (&PostContext); return (-1); } if (mutt_prepare_template (NULL, PostContext, hdr, h, 0) < 0) { mx_fastclose_mailbox (PostContext); FREE (&PostContext); return (-1); } /* finished with this message, so delete it. */ mutt_set_flag (PostContext, h, M_DELETE, 1); /* update the count for the status display */ PostCount = PostContext->msgcount - PostContext->deleted; /* avoid the "purge deleted messages" prompt */ opt_delete = quadoption (OPT_DELETE); set_quadoption (OPT_DELETE, M_YES); mx_close_mailbox (PostContext, NULL); set_quadoption (OPT_DELETE, opt_delete); FREE (&PostContext); for (tmp = hdr->env->userhdrs; tmp; ) { if (ascii_strncasecmp ("X-Mutt-References:", tmp->data, 18) == 0) { if (ctx) { /* if a mailbox is currently open, look to see if the orignal message the user attempted to reply to is in this mailbox */ p = skip_email_wsp(tmp->data + 18); if (!ctx->id_hash) ctx->id_hash = mutt_make_id_hash (ctx); *cur = hash_find (ctx->id_hash, p); } /* Remove the X-Mutt-References: header field. */ next = tmp->next; if (last) last->next = tmp->next; else hdr->env->userhdrs = tmp->next; tmp->next = NULL; mutt_free_list (&tmp); tmp = next; if (*cur) code |= SENDREPLY; } else if (ascii_strncasecmp ("X-Mutt-Fcc:", tmp->data, 11) == 0) { p = skip_email_wsp(tmp->data + 11); strfcpy (fcc, p, fcclen); mutt_pretty_mailbox (fcc, fcclen); /* remove the X-Mutt-Fcc: header field */ next = tmp->next; if (last) last->next = tmp->next; else hdr->env->userhdrs = tmp->next; tmp->next = NULL; mutt_free_list (&tmp); tmp = next; /* note that x-mutt-fcc was present. we do this because we want to add a * default fcc if the header was missing, but preserve the request of the * user to not make a copy if the header field is present, but empty. * see http://dev.mutt.org/trac/ticket/3653 */ code |= SENDPOSTPONEDFCC; } else if ((WithCrypto & APPLICATION_PGP) && (mutt_strncmp ("Pgp:", tmp->data, 4) == 0 /* this is generated * by old mutt versions */ || mutt_strncmp ("X-Mutt-PGP:", tmp->data, 11) == 0)) { hdr->security = mutt_parse_crypt_hdr (strchr (tmp->data, ':') + 1, 1, APPLICATION_PGP); hdr->security |= APPLICATION_PGP; /* remove the pgp field */ next = tmp->next; if (last) last->next = tmp->next; else hdr->env->userhdrs = tmp->next; tmp->next = NULL; mutt_free_list (&tmp); tmp = next; } else if ((WithCrypto & APPLICATION_SMIME) && mutt_strncmp ("X-Mutt-SMIME:", tmp->data, 13) == 0) { hdr->security = mutt_parse_crypt_hdr (strchr (tmp->data, ':') + 1, 1, APPLICATION_SMIME); hdr->security |= APPLICATION_SMIME; /* remove the smime field */ next = tmp->next; if (last) last->next = tmp->next; else hdr->env->userhdrs = tmp->next; tmp->next = NULL; mutt_free_list (&tmp); tmp = next; } #ifdef MIXMASTER else if (mutt_strncmp ("X-Mutt-Mix:", tmp->data, 11) == 0) { char *t; mutt_free_list (&hdr->chain); t = strtok (tmp->data + 11, " \t\n"); while (t) { hdr->chain = mutt_add_list (hdr->chain, t); t = strtok (NULL, " \t\n"); } next = tmp->next; if (last) last->next = tmp->next; else hdr->env->userhdrs = tmp->next; tmp->next = NULL; mutt_free_list (&tmp); tmp = next; } #endif else { last = tmp; tmp = tmp->next; } } if (option (OPTCRYPTOPPORTUNISTICENCRYPT)) crypt_opportunistic_encrypt (hdr); return (code); }
ADDRESS *rfc822_parse_adrlist (ADDRESS *top, const char *s) { int ws_pending, nl; #ifdef EXACT_ADDRESS const char *begin; #endif const char *ps; char comment[LONG_STRING], phrase[LONG_STRING]; size_t phraselen = 0, commentlen = 0; ADDRESS *cur, *last = NULL; RFC822Error = 0; last = top; while (last && last->next) last = last->next; ws_pending = is_email_wsp (*s); if ((nl = mutt_strlen (s))) nl = s[nl - 1] == '\n'; s = skip_email_wsp(s); #ifdef EXACT_ADDRESS begin = s; #endif while (*s) { if (*s == ',') { if (phraselen) { terminate_buffer (phrase, phraselen); add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && last && !last->personal) { terminate_buffer (comment, commentlen); last->personal = safe_strdup (comment); } #ifdef EXACT_ADDRESS if (last && !last->val) last->val = mutt_substrdup (begin, s); #endif commentlen = 0; phraselen = 0; s++; #ifdef EXACT_ADDRESS begin = skip_email_wsp(s); #endif } else if (*s == '(') { if (commentlen && commentlen < sizeof (comment) - 1) comment[commentlen++] = ' '; if ((ps = next_token (s, comment, &commentlen, sizeof (comment) - 1)) == NULL) { rfc822_free_address (&top); return NULL; } s = ps; } else if (*s == '"') { if (phraselen && phraselen < sizeof (phrase) - 1) phrase[phraselen++] = ' '; if ((ps = parse_quote (s + 1, phrase, &phraselen, sizeof (phrase) - 1)) == NULL) { rfc822_free_address (&top); return NULL; } s = ps; } else if (*s == ':') { cur = rfc822_new_address (); terminate_buffer (phrase, phraselen); cur->mailbox = safe_strdup (phrase); cur->group = 1; if (last) last->next = cur; else top = cur; last = cur; #ifdef EXACT_ADDRESS last->val = mutt_substrdup (begin, s); #endif phraselen = 0; commentlen = 0; s++; #ifdef EXACT_ADDRESS begin = skip_email_wsp(s); #endif } else if (*s == ';') { if (phraselen) { terminate_buffer (phrase, phraselen); add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && last && !last->personal) { terminate_buffer (comment, commentlen); last->personal = safe_strdup (comment); } #ifdef EXACT_ADDRESS if (last && !last->val) last->val = mutt_substrdup (begin, s); #endif /* add group terminator */ cur = rfc822_new_address (); if (last) { last->next = cur; last = cur; } phraselen = 0; commentlen = 0; s++; #ifdef EXACT_ADDRESS begin = skip_email_wsp(s); #endif } else if (*s == '<') { terminate_buffer (phrase, phraselen); cur = rfc822_new_address (); if (phraselen) cur->personal = safe_strdup (phrase); if ((ps = parse_route_addr (s + 1, comment, &commentlen, sizeof (comment) - 1, cur)) == NULL) { rfc822_free_address (&top); rfc822_free_address (&cur); return NULL; } if (last) last->next = cur; else top = cur; last = cur; phraselen = 0; commentlen = 0; s = ps; } else { if (phraselen && phraselen < sizeof (phrase) - 1 && ws_pending) phrase[phraselen++] = ' '; if ((ps = next_token (s, phrase, &phraselen, sizeof (phrase) - 1)) == NULL) { rfc822_free_address (&top); return NULL; } s = ps; } ws_pending = is_email_wsp(*s); s = skip_email_wsp(s); } if (phraselen) { terminate_buffer (phrase, phraselen); terminate_buffer (comment, commentlen); add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && last && !last->personal) { terminate_buffer (comment, commentlen); last->personal = safe_strdup (comment); } #ifdef EXACT_ADDRESS if (last) last->val = mutt_substrdup (begin, s - nl < begin ? begin : s - nl); #endif return top; }