int mutt_parse_score (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { SCORE *ptr, *last; char *pattern, *pc; struct pattern_t *pat; mutt_extract_token (buf, s, 0); if (!MoreArgs (s)) { strfcpy (err->data, _("score: too few arguments"), err->dsize); return (-1); } pattern = buf->data; memset (buf, 0, sizeof (BUFFER)); mutt_extract_token (buf, s, 0); if (MoreArgs (s)) { FREE (&pattern); strfcpy (err->data, _("score: too many arguments"), err->dsize); return (-1); } /* look for an existing entry and update the value, else add it to the end of the list */ for (ptr = Score, last = NULL; ptr; last = ptr, ptr = ptr->next) if (mutt_strcmp (pattern, ptr->str) == 0) break; if (!ptr) { if ((pat = mutt_pattern_comp (pattern, 0, err)) == NULL) { FREE (&pattern); return (-1); } ptr = safe_calloc (1, sizeof (SCORE)); if (last) last->next = ptr; else Score = ptr; ptr->pat = pat; ptr->str = pattern; } else /* 'buf' arg was cleared and 'pattern' holds the only reference; * as here 'ptr' != NULL -> update the value only in which case * ptr->str already has the string, so pattern should be freed. */ FREE (&pattern); pc = buf->data; if (*pc == '=') { ptr->exact = 1; pc++; } ptr->val = atoi (pc); set_option (OPTNEEDRESCORE); return 0; }
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 int add_pattern (COLOR_LINE **top, const char *s, int sensitive, int fg, int bg, int attr, BUFFER *err, int is_index) { /* is_index used to store compiled pattern * only for `index' color object * when called from mutt_parse_color() */ COLOR_LINE *tmp = *top; while (tmp) { if (sensitive) { if (mutt_strcmp (s, tmp->pattern) == 0) break; } else { if (mutt_strcasecmp (s, tmp->pattern) == 0) break; } tmp = tmp->next; } if (tmp) { #ifdef HAVE_COLOR if (fg != -1 && bg != -1) { if (tmp->fg != fg || tmp->bg != bg) { mutt_free_color (tmp->fg, tmp->bg); tmp->fg = fg; tmp->bg = bg; attr |= mutt_alloc_color (fg, bg); } else attr |= (tmp->pair & ~A_BOLD); } #endif /* HAVE_COLOR */ tmp->pair = attr; } else { int r; char buf[LONG_STRING]; tmp = mutt_new_color_line (); if (is_index) { int i; strfcpy(buf, NONULL(s), sizeof(buf)); mutt_check_simple (buf, sizeof (buf), NONULL(SimpleSearch)); if((tmp->color_pattern = mutt_pattern_comp (buf, M_FULL_MSG, err)) == NULL) { mutt_free_color_line(&tmp, 1); return -1; } /* force re-caching of index colors */ for (i = 0; Context && i < Context->msgcount; i++) Context->hdrs[i]->pair = 0; } else if ((r = REGCOMP (&tmp->rx, s, (sensitive ? mutt_which_case (s) : REG_ICASE))) != 0) { regerror (r, &tmp->rx, err->data, err->dsize); mutt_free_color_line(&tmp, 1); return (-1); } tmp->next = *top; tmp->pattern = safe_strdup (s); #ifdef HAVE_COLOR if(fg != -1 && bg != -1) { tmp->fg = fg; tmp->bg = bg; attr |= mutt_alloc_color (fg, bg); } #endif tmp->pair = attr; *top = tmp; } return 0; }