/* PUBLIC HTAA_parseArgList() * PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD * ON ENTRY: * str is a comma-separated list: * * item, item, item * where * item ::= value * | name=value * | name="value" * * Leading and trailing whitespace is ignored * everywhere except inside quotes, so the following * examples are equal: * * name=value,foo=bar * name="value",foo="bar" * name = value , foo = bar * name = "value" , foo = "bar" * * ON EXIT: * returns a list of name-value pairs (actually HTAssocList*). * For items with no name, just value, the name is * the number of order number of that item. E.g. * "1" for the first, etc. */ HTAssocList *HTAA_parseArgList(char *str) { HTAssocList *assoc_list = HTAssocList_new(); char *cur = NULL; char *name = NULL; int n = 0; if (!str) return assoc_list; while (*str) { SKIPWS(str); /* Skip leading whitespace */ cur = str; n++; while (*cur && *cur != '=' && *cur != ',') cur++; /* Find end of name (or lonely value without a name) */ KILLWS(cur); /* Kill trailing whitespace */ if (*cur == '=') { /* Name followed by a value */ *(cur++) = '\0'; /* Terminate name */ StrAllocCopy(name, str); SKIPWS(cur); /* Skip WS leading the value */ str = cur; if (*str == '"') { /* Quoted value */ str++; cur = str; while (*cur && *cur != '"') cur++; if (*cur == '"') *(cur++) = '\0'; /* Terminate value */ /* else it is lacking terminating quote */ SKIPWS(cur); /* Skip WS leading comma */ if (*cur == ',') cur++; /* Skip separating colon */ } else { /* Unquoted value */ while (*cur && *cur != ',') cur++; KILLWS(cur); /* Kill trailing whitespace */ if (*cur == ',') *(cur++) = '\0'; /* else *cur already NULL */ } } else { /* No name, just a value */ if (*cur == ',') *(cur++) = '\0'; /* Terminate value */ /* else last value on line (already terminated by NULL) */ HTSprintf0(&name, "%d", n); /* Item order number for name */ } HTAssocList_add(assoc_list, name, str); str = cur; } /* while *str */ FREE(name); return assoc_list; }
static ZZJSON *parse_value(ZZJSON_CONFIG *config) { ZZJSON *retval = NULL; int c; SKIPWS(); c = GETC(); UNGETC(c); switch (c) { case '"': retval = parse_string2(config); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': retval = parse_number(config); break; case '{': retval = parse_object(config); break; case '[': retval = parse_array(config); break; case 't': retval = parse_true(config); break; case 'f': retval = parse_false(config); break; case 'n': retval = parse_null(config); break; } if (!retval) { ERROR("value: invalid value"); return retval; } return retval; }
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) { SKIPWS (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; }
/* 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 = line + 4; SKIPWS (c); 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 *next_word (const char *s) { while (*s && !ISSPACE (*s)) s++; SKIPWS (s); return s; }
void __find(char *in, struct __Token *min, struct __Token *max) { char *it = in; char *next = it; int id = 0; memset(min, 0, sizeof(struct __Token)); memset(max, 0, sizeof(struct __Token)); SKIPWS(it); while (*it != 0) { if (iswspace((int)(*it))) { int len = it - next; if (min->len == 0) { min->len = len; min->loc = id - len; max->len = len; max->loc = id - len; } else { if (len > max->len) { max->len = len; max->loc = id - len; } if (len < min->len) { min->len = len; min->loc = id - len; } } SKIPWS(it); next = it; } ++it; ++id; } }
ZZJSON *zzjson_parse(ZZJSON_CONFIG *config) { ZZJSON *retval; int c; SKIPWS(); c = GETC(); UNGETC(c); if (c == '[') retval = parse_array(config); else if (c == '{') retval = parse_object(config); else { ERROR("expected '[' or '{'"); return NULL; } if (!retval) return NULL; SKIPWS(); c = GETC(); if (c >= 0 && !ALLOW_GARBAGE_AT_END) { ERROR("parse: garbage at end of file"); zzjson_free(config, retval); return NULL; } return retval; }
struct userdefs * getusrdef(char *usertype) { char instr[512], *ptr; const parsent_t *pe; if (is_role(usertype)) { if ((defptr = fopen(DEFROLEFILE, "r")) == NULL) { defaults.defshell = DEFROLESHL; defaults.defprof = DEFROLEPROF; return (&defaults); } } else { if ((defptr = fopen(DEFFILE, "r")) == NULL) return (&defaults); } while (fgets(instr, sizeof (instr), defptr) != NULL) { ptr = instr; SKIPWS(ptr); if (*ptr == '#') continue; pe = scan(&ptr); if (pe != NULL) { switch (pe->type) { case INT: FIELD(&defaults, pe, int) = (int)strtol(ptr, NULL, 10); break; case PROJID: FIELD(&defaults, pe, projid_t) = (projid_t)strtol(ptr, NULL, 10); break; case STR: FIELD(&defaults, pe, char *) = dup_to_nl(ptr); break; } } } (void) fclose(defptr); return (&defaults); }
static const char * parse_route_addr (const char *s, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr) { char token[STRING]; size_t tokenlen = 0; SKIPWS (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 != '>' || !addr->mailbox) { RFC822Error = ERR_BAD_ROUTE_ADDR; return NULL; } 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 = msg + 5; SKIPWS (c2); 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); }
LPCSTR parse_route_addr( LPCSTR s, LPSTR comment, size_t *commentlen, size_t commentmax, PPerson addr ) { char token[128]; size_t tokenlen = 0; SKIPWS (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 != '>' || addr->Addr.IsEmpty() ) { // RFC822Error = ERR_BAD_ROUTE_ADDR; return NULL; } s ++; return s; }
/* imap_next_word: return index into string where next IMAP word begins */ char *imap_next_word (char *s) { int quoted = 0; while (*s) { if (*s == '\\') { s++; if (*s) s++; continue; } if (*s == '\"') quoted = quoted ? 0 : 1; if (!quoted && ISSPACE (*s)) break; s++; } SKIPWS (s); 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; SKIPWS (ch); break; } } str_skip_trailws (s); return ch; }
/** * mutt_parse_icommand - Parse an informational command * @param line Command to execute * @param err Buffer for error messages * @retval #MUTT_CMD_SUCCESS Success * @retval #MUTT_CMD_ERROR Error (no message): command not found * @retval #MUTT_CMD_ERROR Error with message: command failed * @retval #MUTT_CMD_WARNING Warning with message: command failed */ enum CommandResult mutt_parse_icommand(/* const */ char *line, struct Buffer *err) { if (!line || !*line || !err) return MUTT_CMD_ERROR; enum CommandResult rc = MUTT_CMD_ERROR; struct Buffer expn, token; mutt_buffer_init(&expn); mutt_buffer_init(&token); expn.data = expn.dptr = line; expn.dsize = mutt_str_strlen(line); mutt_buffer_reset(err); SKIPWS(expn.dptr); while (*expn.dptr) { mutt_extract_token(&token, &expn, 0); for (size_t i = 0; ICommandList[i].name; i++) { if (mutt_str_strcmp(token.data, ICommandList[i].name) != 0) continue; rc = ICommandList[i].func(&token, &expn, ICommandList[i].data, err); if (rc != 0) goto finish; break; /* Continue with next command */ } } finish: if (expn.destroy) FREE(&expn.data); return rc; }
/* 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; 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); mem_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); mem_free (&PostContext); return (-1); } if (mutt_prepare_template (NULL, PostContext, hdr, h, 0) < 0) { mx_fastclose_mailbox (PostContext); mem_free (&PostContext); return (-1); } /* finished with this message, so delete it. */ mutt_set_flag (PostContext, h, M_DELETE, 1); /* and consider it saved, so that it won't be moved to the trash folder */ mutt_set_flag (PostContext, h, M_APPENDED, 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); mem_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 = tmp->data + 18; SKIPWS (p); 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 = tmp->data + 11; SKIPWS (p); strfcpy (fcc, p, fcclen); mutt_pretty_mailbox (fcc); /* 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; } else if ((WithCrypto & APPLICATION_PGP) && (str_ncmp ("Pgp:", tmp->data, 4) == 0 /* this is generated * by old mutt versions */ || str_ncmp ("X-Mutt-PGP:", tmp->data, 11) == 0)) { hdr->security = mutt_parse_crypt_hdr (strchr (tmp->data, ':') + 1, 1); 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) && str_ncmp ("X-Mutt-SMIME:", tmp->data, 13) == 0) { hdr->security = mutt_parse_crypt_hdr (strchr (tmp->data, ':') + 1, 1); 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 (str_ncmp ("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; } } return (code); }
int imap_append_message (CONTEXT *ctx, MESSAGE *msg) { IMAP_DATA* idata; FILE *fp; char buf[LONG_STRING]; char mbox[LONG_STRING]; char mailbox[LONG_STRING]; char internaldate[IMAP_DATELEN]; char imap_flags[SHORT_STRING]; size_t len; progress_t progressbar; size_t sent; int c, last; IMAP_MBOX mx; int rc; idata = (IMAP_DATA*) ctx->data; if (imap_parse_path (ctx->path, &mx)) return -1; imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox)); if (!*mailbox) strfcpy (mailbox, "INBOX", sizeof (mailbox)); if ((fp = fopen (msg->path, "r")) == NULL) { mutt_perror (msg->path); goto fail; } /* currently we set the \Seen flag on all messages, but probably we * should scan the message Status header for flag info. Since we're * already rereading the whole file for length it isn't any more * expensive (it'd be nice if we had the file size passed in already * by the code that writes the file, but that's a lot of changes. * Ideally we'd have a HEADER structure with flag info here... */ for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c) { if(c == '\n' && last != '\r') len++; len++; } rewind (fp); mutt_progress_init (&progressbar, _("Uploading message..."), MUTT_PROGRESS_SIZE, NetInc, len); imap_munge_mbox_name (idata, mbox, sizeof (mbox), mailbox); imap_make_date (internaldate, msg->received); imap_flags[0] = imap_flags[1] = 0; if (msg->flags.read) safe_strcat (imap_flags, sizeof (imap_flags), " \\Seen"); if (msg->flags.replied) safe_strcat (imap_flags, sizeof (imap_flags), " \\Answered"); if (msg->flags.flagged) safe_strcat (imap_flags, sizeof (imap_flags), " \\Flagged"); if (msg->flags.draft) safe_strcat (imap_flags, sizeof (imap_flags), " \\Draft"); snprintf (buf, sizeof (buf), "APPEND %s (%s) \"%s\" {%lu}", mbox, imap_flags + 1, internaldate, (unsigned long) len); imap_cmd_start (idata, buf); do rc = imap_cmd_step (idata); while (rc == IMAP_CMD_CONTINUE); if (rc != IMAP_CMD_RESPOND) { char *pc; dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", idata->buf)); pc = idata->buf + SEQLEN; SKIPWS (pc); pc = imap_next_word (pc); mutt_error ("%s", pc); mutt_sleep (1); safe_fclose (&fp); goto fail; } for (last = EOF, sent = len = 0; (c = fgetc(fp)) != EOF; last = c) { if (c == '\n' && last != '\r') buf[len++] = '\r'; buf[len++] = c; if (len > sizeof(buf) - 3) { sent += len; flush_buffer(buf, &len, idata->conn); mutt_progress_update (&progressbar, sent, -1); } } if (len) flush_buffer(buf, &len, idata->conn); mutt_socket_write (idata->conn, "\r\n"); safe_fclose (&fp); do rc = imap_cmd_step (idata); while (rc == IMAP_CMD_CONTINUE); if (!imap_code (idata->buf)) { char *pc; dprint (1, (debugfile, "imap_append_message(): command failed: %s\n", idata->buf)); pc = idata->buf + SEQLEN; SKIPWS (pc); pc = imap_next_word (pc); mutt_error ("%s", pc); mutt_sleep (1); goto fail; } FREE (&mx.mbox); return 0; fail: FREE (&mx.mbox); return -1; }
int mutt_parse_crypt_hdr (char *p, int set_signas) { int pgp = 0; char pgp_sign_as[LONG_STRING] = "\0", *q; char smime_cryptalg[LONG_STRING] = "\0"; if (!WithCrypto) return 0; SKIPWS (p); for (; *p; p++) { switch (*p) { case 'e': case 'E': pgp |= ENCRYPT; break; case 's': case 'S': pgp |= SIGN; q = pgp_sign_as; if (*(p + 1) == '<') { for (p += 2; *p && *p != '>' && q < pgp_sign_as + sizeof (pgp_sign_as) - 1; *q++ = *p++); if (*p != '>') { mutt_error _("Illegal PGP 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 PGP 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': pgp |= INLINE; break; default: mutt_error _("Illegal PGP header"); return 0; } } /* the cryptalg field must not be empty */ if ((WithCrypto & APPLICATION_SMIME) && *smime_cryptalg) str_replace (&SmimeCryptAlg, smime_cryptalg); if ((WithCrypto & APPLICATION_PGP) && (set_signas || *pgp_sign_as)) str_replace (&PgpSignAs, pgp_sign_as); return pgp; }
char *mutt_skip_whitespace (char *p) { SKIPWS (p); return p; }
ADDRESS *rfc822_parse_adrlist (ADDRESS *top, const char *s) { const char *begin, *ps; char comment[STRING], phrase[STRING]; size_t phraselen = 0, commentlen = 0; ADDRESS *cur, *last = NULL; RFC822Error = 0; last = top; while (last && last->next) last = last->next; SKIPWS (s); begin = s; while (*s) { if (*s == ',') { if (phraselen) { phrase[phraselen] = 0; add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && last && !last->personal) { comment[commentlen] = 0; last->personal = safe_strdup (comment); } #ifdef EXACT_ADDRESS if (last && !last->val) last->val = mutt_substrdup (begin, s); #endif commentlen = 0; phraselen = 0; s++; begin = s; SKIPWS (begin); } 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 == ':') { cur = rfc822_new_address (); phrase[phraselen] = 0; 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++; begin = s; SKIPWS (begin); } else if (*s == ';') { if (phraselen) { phrase[phraselen] = 0; add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && !last->personal) { comment[commentlen] = 0; 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++; begin = s; SKIPWS (begin); } else if (*s == '<') { phrase[phraselen] = 0; cur = rfc822_new_address (); if (phraselen) { if (cur->personal) FREE (&cur->personal); /* if we get something like "Michael R. Elkins" remove the quotes */ rfc822_dequote_comment (phrase); 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) phrase[phraselen++] = ' '; if ((ps = next_token (s, phrase, &phraselen, sizeof (phrase) - 1)) == NULL) { rfc822_free_address (&top); return NULL; } s = ps; } SKIPWS (s); } if (phraselen) { phrase[phraselen] = 0; comment[commentlen] = 0; add_addrspec (&top, &last, phrase, comment, &commentlen, sizeof (comment) - 1); } else if (commentlen && last && !last->personal) { comment[commentlen] = 0; last->personal = safe_strdup (comment); } #ifdef EXACT_ADDRESS if (last) last->val = mutt_substrdup (begin, s); #endif return top; }
static NEOERR* _hdf_read_string (HDF *hdf, const char **str, STRING *line, const char *path, int *lineno, int include_handle) { NEOERR *err; HDF *lower; char *s; char *name, *value; HDF_ATTR *attr = NULL; while (**str != '\0') { /* Reset string length, but don't free the reserved buffer */ line->len = 0; err = _copy_line_advance(str, line); if (err) return nerr_pass(err); attr = NULL; (*lineno)++; s = line->buf; SKIPWS(s); if (!strncmp(s, "#include ", 9) && include_handle != INCLUDE_IGNORE) { if (include_handle == INCLUDE_ERROR) { return nerr_raise (NERR_PARSE, "[%d]: #include not supported in string parse", *lineno); } else if (include_handle < INCLUDE_MAX_DEPTH) { int l; s += 9; name = neos_strip(s); l = strlen(name); if (name[0] == '"' && name[l-1] == '"') { name[l-1] = '\0'; name++; } err = hdf_read_file_internal(hdf, name, include_handle + 1); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else { return nerr_raise (NERR_MAX_RECURSION, "[%d]: Too many recursion levels.", *lineno ); } } else if (s[0] == '#') { /* comment: pass */ } else if (s[0] == '}') /* up */ { s = neos_strip(s); if (strcmp(s, "}")) { err = nerr_raise(NERR_PARSE, "[%s:%d] Trailing garbage on line following }: %s", path, *lineno, line->buf); return err; } return STATUS_OK; } else if (s[0]) { /* Valid hdf name is [0-9a-zA-Z_.]+ */ name = s; while (*s && (isalnum(*s) || *s == '_' || *s == '.' || *(unsigned char*)s > 127)) s++; SKIPWS(s); if (s[0] == '[') /* attributes */ { *s = '\0'; name = neos_strip(name); s++; err = parse_attr(&s, &attr); if (err) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } SKIPWS(s); } if (s[0] == '=') /* assignment */ { *s = '\0'; name = neos_strip(name); s++; value = neos_strip(s); err = _set_value (hdf, name, value, 1, 1, 0, attr, NULL); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == ':' && s[1] == '=') /* copy */ { *s = '\0'; name = neos_strip(name); s+=2; value = neos_strip(s); value = hdf_get_value(hdf->top, value, ""); err = _set_value (hdf, name, value, 1, 1, 0, attr, NULL); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == ':') /* link */ { *s = '\0'; name = neos_strip(name); s++; value = neos_strip(s); err = _set_value (hdf, name, value, 1, 1, 1, attr, NULL); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == '{') /* deeper */ { *s = '\0'; name = neos_strip(name); lower = hdf_get_obj (hdf, name); if (lower == NULL) { err = _set_value (hdf, name, NULL, 1, 1, 0, attr, &lower); } else { err = _set_value (lower, NULL, lower->value, 1, 1, 0, attr, NULL); } if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } err = _hdf_read_string (lower, str, line, path, lineno, include_handle); if (err != STATUS_OK) { return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else if (s[0] == '<' && s[1] == '<') /* multi-line assignment */ { char *m; int msize = 0; int mmax = 128; int l; *s = '\0'; name = neos_strip(name); s+=2; value = neos_strip(s); l = strlen(value); if (l == 0) { err = nerr_raise(NERR_PARSE, "[%s:%d] No multi-assignment terminator given: %s", path, *lineno, line->buf); return err; } m = (char *) malloc (mmax * sizeof(char)); if (m == NULL) { return nerr_raise(NERR_NOMEM, "[%s:%d] Unable to allocate memory for multi-line assignment to %s", path, *lineno, name); } while (_copy_line (str, m+msize, mmax-msize) != 0) { (*lineno)++; if (!strncmp(value, m+msize, l) && isspace(m[msize+l])) { m[msize] = '\0'; break; } msize += strlen(m+msize); if (msize + l + 10 > mmax) { void *new_ptr; mmax += 128; new_ptr = realloc (m, mmax * sizeof(char)); if (new_ptr == NULL) { free(m); return nerr_raise(NERR_NOMEM, "[%s:%d] Unable to allocate memory for multi-line assignment to %s: size=%d", path, *lineno, name, mmax); } m = (char *) new_ptr; } } err = _set_value (hdf, name, m, 0, 1, 0, attr, NULL); if (err != STATUS_OK) { free (m); return nerr_pass_ctx(err, "In file %s:%d", path, *lineno); } } else { err = nerr_raise(NERR_PARSE, "[%s:%d] Unable to parse line %s", path, *lineno, line->buf); return err; } } } return STATUS_OK; }
PPerson rfc822_parse_adrlist( PPerson Top, LPCSTR s ) { LPCSTR begin; LPCSTR ps; char comment[128], phrase[128]; size_t phraselen = 0, commentlen = 0; PPerson Cur; PPerson Last = Top; while ( Last && Last->m_Next ) Last = Last->m_Next; SKIPWS( s ); begin = s; 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->Name.IsEmpty() ) { terminate_buffer( comment, commentlen ); Last->Name = comment; } #ifdef EXACT_ADDRESS if ( Last && Last->val == NULL ) Last->val = mutt_substrdup( begin, s ); #endif commentlen = 0; phraselen = 0; s ++; begin = s; SKIPWS( begin ); } else if ( *s == '(' ) { if ( commentlen && commentlen < sizeof( comment ) - 1 ) comment[ commentlen++ ] = ' '; if ( ( ps = next_token( s, comment, &commentlen, sizeof (comment) - 1)) == NULL ) { delete Top; Top = NULL; return NULL; } s = ps; } else if ( *s == ':' ) { terminate_buffer( phrase, phraselen ); Cur = create CPerson; Cur->Addr = phrase; //Cur->group = 1; if ( Last ) Last->m_Next = Cur; else Top = Cur; Last = Cur; #ifdef EXACT_ADDRESS last->val = mutt_substrdup (begin, s); #endif phraselen = 0; commentlen = 0; s ++; begin = s; SKIPWS( begin ); } else if ( *s == ';' ) { if ( phraselen ) { terminate_buffer (phrase, phraselen); add_addrspec( &Top, &Last, phrase, comment, &commentlen, sizeof( comment ) - 1 ); } else if (commentlen && Last && Last->Name.IsEmpty() ) { terminate_buffer (comment, commentlen); Last->Name = comment; } #ifdef EXACT_ADDRESS if (last && !last->val) last->val = mutt_substrdup (begin, s); #endif /* add group terminator */ Cur = create CPerson; if ( Last ) { Last->m_Next = Cur; Last = Cur; } phraselen = 0; commentlen = 0; s ++; begin = s; SKIPWS( begin ); } else if ( *s == '<' ) { terminate_buffer( phrase, phraselen ); Cur = create CPerson; if ( phraselen ) { FarSF::Unquote( phrase ); Cur->Name = phrase; } if ( ( ps = parse_route_addr( s + 1, comment, &commentlen, sizeof( comment ) - 1, Cur ) ) == NULL ) { delete Top; delete Cur; Top = NULL; Cur = NULL; return NULL; } if ( Last ) Last->m_Next = Cur; else Top = Cur; Last = Cur; phraselen = 0; commentlen = 0; s = ps; } else { if ( phraselen && phraselen < sizeof( phrase ) - 1 && *s != '.' ) phrase[phraselen++] = ' '; if ( ( ps = next_token( s, phrase, &phraselen, sizeof( phrase ) - 1 ) ) == NULL ) { delete Top; Top = NULL; return NULL; } s = ps; } SKIPWS (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->Name.IsEmpty() ) { terminate_buffer( comment, commentlen ); Last->Name = comment; } #ifdef EXACT_ADDRESS if ( Last ) Last->val = mutt_substrdup( begin, s ); #endif return Top; }
/* After calling, * - b->data points to the found token, or NULL is end of parsing * - b->ptr points to the begining of next token * * If the TOKEN_ALLOC option is used, the original string is not mangled * and memory is allocated for the token. */ static char * get_token(buffer *b, int options) { char quote = 0, c; char *end = NULL; assert(b); SKIPWS(b->ptr); if(*b->ptr && strchr("\"'", *b->ptr)) quote = *(b->ptr++); b->data = b->ptr; while(1) { if(!(c = *b->ptr)) { end = b->ptr; break; } if(!quote && ( ISSPACE(c) || ((options & TOKEN_EQUAL) && (c == '=')) || ((options & TOKEN_COMMA) && (c == ','))) ) { end = b->ptr; break; } else if(c == quote) { quote = 0; end = b->ptr++; break; } b->ptr++; } if(quote) return _("quote mismatch"); if(options & (TOKEN_EQUAL | TOKEN_COMMA)) SKIPWS(b->ptr); /* whitespaces can precede the sign */ if((options & TOKEN_EQUAL) && (*b->ptr != '=')) return _("no assignment character found"); if((options & TOKEN_COMMA) && *b->ptr && (*b->ptr != ',')) return _("error in comma separated list"); if(b->ptr == b->data) { b->data = NULL; return NULL; /* no error, just end of parsing */ } if(options & TOKEN_ALLOC) /* freeing is the caller's responsibility */ b->data = xstrndup(b->data, end - b->data); else *end = 0; b->ptr++; /* advance to next token */ SKIPWS(b->ptr); return NULL; }
/* attributes are of the form [key1, key2, key3=value, key4="repr"] */ static NEOERR* parse_attr(char **str, HDF_ATTR **attr) { NEOERR *err = STATUS_OK; char *s = *str; char *k, *v; int k_l, v_l; STRING buf; char c; HDF_ATTR *ha, *hal = NULL; *attr = NULL; string_init(&buf); while (*s && *s != ']') { k = s; k_l = 0; v = NULL; v_l = 0; while (*s && isalnum(*s)) s++; k_l = s-k; if (*s == '\0' || k_l == 0) { _dealloc_hdf_attr(attr); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } SKIPWS(s); if (*s == '=') { s++; SKIPWS(s); if (*s == '"') { s++; while (*s && *s != '"') { if (*s == '\\') { if (isdigit(*(s+1))) { s++; c = *s - '0'; if (isdigit(*(s+1))) { s++; c = (c * 8) + (*s - '0'); if (isdigit(*(s+1))) { s++; c = (c * 8) + (*s - '0'); } } } else { s++; if (*s == 'n') c = '\n'; else if (*s == 't') c = '\t'; else if (*s == 'r') c = '\r'; else c = *s; } err = string_append_char(&buf, c); } else { err = string_append_char(&buf, *s); } if (err) { string_clear(&buf); _dealloc_hdf_attr(attr); return nerr_pass(err); } s++; } if (*s == '\0') { _dealloc_hdf_attr(attr); string_clear(&buf); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } s++; v = buf.buf; v_l = buf.len; } else { v = s; while (*s && *s != ' ' && *s != ',' && *s != ']') s++; if (*s == '\0') { _dealloc_hdf_attr(attr); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } v_l = s-v; } } else { v = "1"; } ha = (HDF_ATTR*) calloc (1, sizeof(HDF_ATTR)); if (ha == NULL) { _dealloc_hdf_attr(attr); string_clear(&buf); return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s); } if (*attr == NULL) *attr = ha; ha->key = neos_strndup(k, k_l); if (v) ha->value = neos_strndup(v, v_l); else ha->value = strdup(""); if (ha->key == NULL || ha->value == NULL) { _dealloc_hdf_attr(attr); string_clear(&buf); return nerr_raise(NERR_NOMEM, "Unable to load attributes: %s", s); } if (hal != NULL) hal->next = ha; hal = ha; string_clear(&buf); SKIPWS(s); if (*s == ',') { s++; SKIPWS(s); } } if (*s == '\0') { _dealloc_hdf_attr(attr); return nerr_raise(NERR_PARSE, "Misformed attribute specification: %s", *str); } *str = s+1; return STATUS_OK; }
static ZZJSON *parse_array(ZZJSON_CONFIG *config) { ZZJSON *retval = NULL, **next = &retval; int c; SKIPWS(); c = GETC(); if (c != '[') { ERROR("array: expected '['"); return NULL; } SKIPWS(); c = GETC(); while (c > 0 && c != ']') { ZZJSON *zzjson = NULL, *val = NULL; UNGETC(c); SKIPWS(); val = parse_value(config); if (!val) { ERROR("array: value expected"); goto errout; } SKIPWS(); c = GETC(); if (c != ',' && c != ']') { ERROR("array: expected ',' or ']'"); errout_with_val: zzjson_free(config, val); goto errout; } if (c == ',') { SKIPWS(); c = GETC(); if (c == ']' && !ALLOW_EXTRA_COMMA) { ERROR("array: expected value after ','"); goto errout_with_val; } } UNGETC(c); zzjson = config->calloc(1, sizeof(ZZJSON)); if (!zzjson) { MEMERROR(); zzjson_free(config, val); goto errout_with_val; } zzjson->type = ZZJSON_ARRAY; zzjson->value.array.val = val; *next = zzjson; next = &zzjson->next; c = GETC(); } if (c != ']') { ERROR("array: expected ']'"); goto errout; } if (!retval) { /* empty array, [ ] */ retval = config->calloc(1, sizeof(ZZJSON)); if (!retval) { MEMERROR(); return NULL; } retval->type = ZZJSON_ARRAY; } return retval; errout: zzjson_free(config, retval); return NULL; }
int is_from (const char *s, char *path, size_t pathlen, time_t *tp) { struct tm tm; int yr; if (path) *path = 0; if (mutt_strncmp ("From ", s, 5) != 0) return 0; s = next_word (s); /* skip over the From part. */ if (!*s) return 0; dprint (3, (debugfile, "\nis_from(): parsing: %s", s)); if (!is_day_name (s)) { const char *p; size_t len; short q = 0; for (p = s; *p && (q || !ISSPACE (*p)); p++) { if (*p == '\\') { if (*++p == '\0') return 0; } else if (*p == '"') { q = !q; } } if (q || !*p) return 0; /* pipermail archives have the return_path obscured such as "me at mutt.org" */ if (ascii_strncasecmp(p, " at ", 4) == 0) { p = strchr(p + 4, ' '); if (!p) { dprint (1, (debugfile, "is_from(): error parsing what appears to be a pipermail-style obscured return_path: %s\n", s)); return 0; } } if (path) { len = (size_t) (p - s); if (len + 1 > pathlen) len = pathlen - 1; memcpy (path, s, len); path[len] = 0; dprint (3, (debugfile, "is_from(): got return path: %s\n", path)); } s = p + 1; SKIPWS (s); if (!*s) return 0; if (!is_day_name (s)) { dprint(1, (debugfile, "is_from(): expected weekday, got: %s\n", s)); return 0; } } s = next_word (s); if (!*s) return 0; /* do a quick check to make sure that this isn't really the day of the week. * this could happen when receiving mail from a local user whose login name * is the same as a three-letter abbreviation of the day of the week. */ if (is_day_name (s)) { s = next_word (s); if (!*s) return 0; } /* now we should be on the month. */ if ((tm.tm_mon = mutt_check_month (s)) < 0) return 0; /* day */ s = next_word (s); if (!*s) return 0; if (sscanf (s, "%d", &tm.tm_mday) != 1) return 0; /* time */ s = next_word (s); if (!*s) return 0; /* Accept either HH:MM or HH:MM:SS */ if (sscanf (s, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 3); else if (sscanf (s, "%d:%d", &tm.tm_hour, &tm.tm_min) == 2) tm.tm_sec = 0; else return 0; s = next_word (s); if (!*s) return 0; /* timezone? */ if (isalpha ((unsigned char) *s) || *s == '+' || *s == '-') { s = next_word (s); if (!*s) return 0; /* * some places have two timezone fields after the time, e.g. * From [email protected] Wed Aug 2 00:39:12 MET DST 1995 */ if (isalpha ((unsigned char) *s)) { s = next_word (s); if (!*s) return 0; } } /* year */ if (sscanf (s, "%d", &yr) != 1) return 0; tm.tm_year = yr > 1900 ? yr - 1900 : (yr < 70 ? yr + 100 : yr); dprint (3,(debugfile, "is_from(): month=%d, day=%d, hr=%d, min=%d, sec=%d, yr=%d.\n", tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year)); tm.tm_isdst = -1; if (tp) *tp = mutt_mktime (&tm, 0); return 1; }
static ZZJSON *parse_object(ZZJSON_CONFIG *config) { ZZJSON *retval = NULL; int c; ZZJSON **next = &retval; SKIPWS(); c = GETC(); if (c != '{') { ERROR("object: expected '{'"); return NULL; } SKIPWS(); c = GETC(); while (c > 0 && c != '}') { ZZJSON *zzjson = NULL, *val = NULL; char *str; UNGETC(c); str = parse_string(config); if (!str) { ERROR("object: expected string"); errout_with_str: config->free(str); goto errout; } SKIPWS(); c = GETC(); if (c != ':') { ERROR("object: expected ':'"); goto errout_with_str; } SKIPWS(); val = parse_value(config); if (!val) { ERROR("object: value expected"); goto errout_with_str; } SKIPWS(); c = GETC(); if (c != ',' && c != '}') { ERROR("object: expected ',' or '}'"); errout_with_str_and_val: zzjson_free(config, val); goto errout_with_str; } if (c == ',') { SKIPWS(); c = GETC(); if (c == '}' && !ALLOW_EXTRA_COMMA) { ERROR("object: expected pair after ','"); goto errout_with_str_and_val; } } UNGETC(c); zzjson = config->calloc(1, sizeof(ZZJSON)); if (!zzjson) { MEMERROR(); goto errout_with_str_and_val; } zzjson->type = ZZJSON_OBJECT; zzjson->value.object.label = str; zzjson->value.object.val = val; *next = zzjson; next = &zzjson->next; c = GETC(); } if (c != '}') { ERROR("object: expected '}'"); goto errout; } if (!retval) { /* empty object, { } */ retval = config->calloc(1, sizeof(ZZJSON)); if (!retval) { MEMERROR(); return NULL; } retval->type = ZZJSON_OBJECT; } return retval; errout: zzjson_free(config, retval); return NULL; }
void mutt_edit_headers (const char *editor, const char *body, HEADER *msg, char *fcc, size_t fcclen) { char path[_POSIX_PATH_MAX]; /* tempfile used to edit headers + body */ char buffer[LONG_STRING]; char *p; FILE *ifp, *ofp; int i, keep; int in_reply_to = 0; /* did we see the in-reply-to field ? */ ENVELOPE *n; time_t mtime; struct stat st; LIST *cur, *last = NULL, *tmp; mutt_mktemp (path); if ((ofp = safe_fopen (path, "w")) == NULL) { mutt_perror (path); return; } mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0); fputc ('\n', ofp); /* tie off the header. */ /* now copy the body of the message. */ if ((ifp = fopen (body, "r")) == NULL) { mutt_perror (body); return; } mutt_copy_stream (ifp, ofp); fclose (ifp); fclose (ofp); if (stat (path, &st) == -1) { mutt_perror (path); return; } mtime = st.st_mtime; mutt_edit_file (editor, path); stat (path, &st); if (mtime == st.st_mtime) { dprint (1, (debugfile, "ci_edit_headers(): temp file was not modified.\n")); /* the file has not changed! */ mutt_unlink (path); return; } mutt_unlink (body); mutt_free_list (&msg->env->userhdrs); /* Read the temp file back in */ if ((ifp = fopen (path, "r")) == NULL) { mutt_perror (path); return; } if ((ofp = safe_fopen (body, "w")) == NULL) { /* intentionally leak a possible temporary file here */ fclose (ifp); mutt_perror (body); return; } n = mutt_read_rfc822_header (ifp, NULL, 1, 0); while ((i = fread (buffer, 1, sizeof (buffer), ifp)) > 0) fwrite (buffer, 1, i, ofp); fclose (ofp); fclose (ifp); mutt_unlink (path); /* restore old info. */ n->references = msg->env->references; msg->env->references = NULL; mutt_free_envelope (&msg->env); msg->env = n; mutt_expand_aliases_env (msg->env); /* search through the user defined headers added to see if either a * fcc: or attach-file: field was specified. */ cur = msg->env->userhdrs; while (cur) { keep = 1; /* keep track of whether or not we see the in-reply-to field. if we did * not, remove the references: field later so that we can generate a new * message based upon this one. */ if (mutt_strncasecmp ("in-reply-to. good thing you replied:", cur->data, 12) == 0) in_reply_to = 1; else if (fcc && mutt_strncasecmp ("fcc:", cur->data, 4) == 0) { p = cur->data + 4; SKIPWS (p); if (*p) { strfcpy (fcc, p, fcclen); mutt_pretty_mailbox (fcc); } keep = 0; } else if (mutt_strncasecmp ("attach file:", cur->data, 7) == 0) { BODY *body; BODY *parts; char *q; p = cur->data + 7; SKIPWS (p); if (*p) { if ((q = strpbrk (p, " \t"))) { mutt_substrcpy (path, p, q, sizeof (path)); SKIPWS (q); } else strfcpy (path, p, sizeof (path)); mutt_expand_path (path, sizeof (path)); if ((body = mutt_make_file_attach (path))) { body->description = safe_strdup (q); for (parts = msg->content; parts->next; parts = parts->next) ; parts->next = body; } else { mutt_pretty_mailbox (path); mutt_error (_("%s: unable to attach file. try again"), path); } } keep = 0; } #ifdef HAVE_PGP else if (mutt_strncasecmp ("pgp:", cur->data, 4) == 0) { msg->pgp = mutt_parse_pgp_hdr (cur->data + 4, 0); keep = 0; } #endif if (keep) { last = cur; cur = cur->next; } else { if (last) last->next = cur->next; else msg->env->userhdrs = cur->next; tmp = cur; cur = cur->next; tmp->next = NULL; mutt_free_list (&tmp); } } if (!in_reply_to) mutt_free_list (&msg->env->references); }
static ZZJSON *parse_number(ZZJSON_CONFIG *config) { ZZJSON *zzjson; unsigned long long ival = 0, expo = 0; double dval = 0.0, frac = 0.0, fracshft = 10.0; int c, dbl = 0, sign = 1, signexpo = 1; SKIPWS(); c = GETC(); if (c == '-') { sign = -1; c = GETC(); } if (c == '0') { c = GETC(); goto skip; } if (!isdigit(c)) { ERROR("number: digit expected"); return NULL; } while (isdigit(c)) { ival *= 10; ival += c - '0'; c = GETC(); } skip: if (c != '.') goto skipfrac; dbl = 1; c = GETC(); if (!isdigit(c)) { ERROR("number: digit expected"); return NULL; } while (isdigit(c)) { frac += (double)(c - '0') / fracshft; fracshft *= 10.0; c = GETC(); } skipfrac: if (c != 'e' && c != 'E') goto skipexpo; dbl = 1; c = GETC(); if (c == '+') c = GETC(); else if (c == '-') { signexpo = -1; c = GETC(); } if (!isdigit(c)) { ERROR("number: digit expected"); return NULL; } while (isdigit(c)) { expo *= 10; expo += c - '0'; c = GETC(); } skipexpo: UNGETC(c); if (dbl) { dval = sign * (long long) ival; dval += sign * frac; dval *= pow(10.0, (double) signexpo * expo); } zzjson = config->calloc(1, sizeof(ZZJSON)); if (!zzjson) { MEMERROR(); return NULL; } if (dbl) { zzjson->type = ZZJSON_NUMBER_DOUBLE; zzjson->value.number.val.dval = dval; } else { zzjson->type = sign < 0 ? ZZJSON_NUMBER_NEGINT : ZZJSON_NUMBER_POSINT; zzjson->value.number.val.ival = ival; } return zzjson; }
int mutt_parse_hook (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { HOOK *ptr; BUFFER command, pattern; int rc, not = 0; regex_t *rx = NULL; pattern_t *pat = NULL; char path[_POSIX_PATH_MAX]; mutt_buffer_init (&pattern); mutt_buffer_init (&command); if (*s->dptr == '!') { s->dptr++; SKIPWS (s->dptr); not = 1; } mutt_extract_token (&pattern, s, 0); if (!MoreArgs (s)) { strfcpy (err->data, _("too few arguments"), err->dsize); goto error; } mutt_extract_token (&command, s, (data & (M_FOLDERHOOK | M_SENDHOOK | M_SEND2HOOK | M_ACCOUNTHOOK | M_REPLYHOOK)) ? M_TOKEN_SPACE : 0); if (!command.data) { strfcpy (err->data, _("too few arguments"), err->dsize); goto error; } if (MoreArgs (s)) { strfcpy (err->data, _("too many arguments"), err->dsize); goto error; } if (data & (M_FOLDERHOOK | M_MBOXHOOK)) { strfcpy (path, pattern.data, sizeof (path)); _mutt_expand_path (path, sizeof (path), 1); FREE (&pattern.data); memset (&pattern, 0, sizeof (pattern)); pattern.data = safe_strdup (path); } else if (DefaultHook && !(data & (M_CHARSETHOOK | M_ICONVHOOK | M_ACCOUNTHOOK)) && (!WithCrypto || !(data & M_CRYPTHOOK)) ) { char tmp[HUGE_STRING]; /* At this stage remain only message-hooks, reply-hooks, send-hooks, * send2-hooks, save-hooks, and fcc-hooks: All those allowing full * patterns. If given a simple regexp, we expand $default_hook. */ strfcpy (tmp, pattern.data, sizeof (tmp)); mutt_check_simple (tmp, sizeof (tmp), DefaultHook); FREE (&pattern.data); memset (&pattern, 0, sizeof (pattern)); pattern.data = safe_strdup (tmp); } if (data & (M_MBOXHOOK | M_SAVEHOOK | M_FCCHOOK)) { strfcpy (path, command.data, sizeof (path)); mutt_expand_path (path, sizeof (path)); FREE (&command.data); memset (&command, 0, sizeof (command)); command.data = safe_strdup (path); } /* check to make sure that a matching hook doesn't already exist */ for (ptr = Hooks; ptr; ptr = ptr->next) { if (ptr->type == data && ptr->rx.not == not && !mutt_strcmp (pattern.data, ptr->rx.pattern)) { if (data & (M_FOLDERHOOK | M_SENDHOOK | M_SEND2HOOK | M_MESSAGEHOOK | M_ACCOUNTHOOK | M_REPLYHOOK)) { /* these hooks allow multiple commands with the same * pattern, so if we've already seen this pattern/command pair, just * ignore it instead of creating a duplicate */ if (!mutt_strcmp (ptr->command, command.data)) { FREE (&command.data); FREE (&pattern.data); return 0; } } else { /* other hooks only allow one command per pattern, so update the * entry with the new command. this currently does not change the * order of execution of the hooks, which i think is desirable since * a common action to perform is to change the default (.) entry * based upon some other information. */ FREE (&ptr->command); ptr->command = command.data; FREE (&pattern.data); return 0; } } if (!ptr->next) break; } if (data & (M_SENDHOOK | M_SEND2HOOK | M_SAVEHOOK | M_FCCHOOK | M_MESSAGEHOOK | M_REPLYHOOK)) { if ((pat = mutt_pattern_comp (pattern.data, (data & (M_SENDHOOK | M_SEND2HOOK | M_FCCHOOK)) ? 0 : M_FULL_MSG, err)) == NULL) goto error; } else { /* Hooks not allowing full patterns: Check syntax of regexp */ rx = safe_malloc (sizeof (regex_t)); #ifdef M_CRYPTHOOK if ((rc = REGCOMP (rx, NONULL(pattern.data), ((data & (M_CRYPTHOOK|M_CHARSETHOOK|M_ICONVHOOK)) ? REG_ICASE : 0))) != 0) #else if ((rc = REGCOMP (rx, NONULL(pattern.data), (data & (M_CHARSETHOOK|M_ICONVHOOK)) ? REG_ICASE : 0)) != 0) #endif /* M_CRYPTHOOK */ { regerror (rc, rx, err->data, err->dsize); FREE (&rx); goto error; } } if (ptr) { ptr->next = safe_calloc (1, sizeof (HOOK)); ptr = ptr->next; } else Hooks = ptr = safe_calloc (1, sizeof (HOOK)); ptr->type = data; ptr->command = command.data; ptr->pattern = pat; ptr->rx.pattern = pattern.data; ptr->rx.rx = rx; ptr->rx.not = not; return 0; error: FREE (&pattern.data); FREE (&command.data); return (-1); }
static char *parse_string(ZZJSON_CONFIG *config) { unsigned int len = 16, pos = 0; int c; char *str = NULL; SKIPWS(); c = GETC(); if (c != '"') { ERROR("string: expected \" at the start"); return NULL; } str = config->malloc(len); if (!str) { MEMERROR(); return NULL; } c = GETC(); while (c > 0 && c != '"') { if (!ALLOW_CONTROL_CHARS && c >= 0 && c <= 31) { ERROR("string: control characters not allowed"); goto errout; } if (c == '\\') { c = GETC(); switch (c) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'u': { UNGETC(c); /* ignore \uHHHH, copy verbatim */ c = '\\'; break; } case '\\': case '/': case '"': break; default: if (!ALLOW_ILLEGAL_ESCAPE) { ERROR("string: illegal escape character"); goto errout; } } } str[pos++] = c; if (pos == len-1) { void *tmp = str; len *= 2; str = config->realloc(str, len); if (!str) { MEMERROR(); str = tmp; goto errout; } } c = GETC(); } if (c != '"') { ERROR("string: expected \" at the end"); goto errout; } str[pos] = 0; return str; errout: config->free(str); return NULL; }