/** * mutt_regex_new - Create an Regex from a string * @param str Regular expression * @param flags Type flags, e.g. #DT_REGEX_MATCH_CASE * @param err Buffer for error messages * @retval ptr New Regex object * @retval NULL Error */ struct Regex *mutt_regex_new(const char *str, int flags, struct Buffer *err) { if (!str) return NULL; int rflags = 0; struct Regex *reg = mutt_mem_calloc(1, sizeof(struct Regex)); reg->regex = mutt_mem_calloc(1, sizeof(regex_t)); reg->pattern = mutt_str_strdup(str); /* Should we use smart case matching? */ if (((flags & DT_REGEX_MATCH_CASE) == 0) && mutt_mb_is_lower(str)) rflags |= REG_ICASE; /* Is a prefix of '!' allowed? */ if (((flags & DT_REGEX_ALLOW_NOT) != 0) && (str[0] == '!')) { reg->not = true; str++; } int rc = REGCOMP(reg->regex, str, rflags); if ((rc != 0) && err) { regerror(rc, reg->regex, err->data, err->dsize); mutt_regex_free(®); return NULL; } return reg; }
void beregex::compile() // compile the regex { if(pat.size()==0) return; nreg_ = calloc(sizeof(regex_t),1); if(REGCOMP(nreg,pat.c_str(),flags | REG_EXTENDED)!=0){ std::cerr << "regular expression compile error '" << pat << "' flags=" << flags << "\n"; exit(1); } }
/** * mutt_regex_compile - Create an Regex from a string * @param str Regular expression * @param flags Type flags, e.g. REG_ICASE * @retval ptr New Regex object * @retval NULL Error */ struct Regex *mutt_regex_compile(const char *str, int flags) { struct Regex *rx = mutt_mem_calloc(1, sizeof(struct Regex)); rx->pattern = mutt_str_strdup(str); rx->regex = mutt_mem_calloc(1, sizeof(regex_t)); if (REGCOMP(rx->regex, NONULL(str), flags) != 0) mutt_regex_free(&rx); return rx; }
int main(int argc, char **argv) { CONTEXT *ctx; HEADER *header=0; FILE *f; char folder[_POSIX_PATH_MAX]; long i; int index_hint,check; if( argc < 2 ) { perror("usage: test <Maildir>\n"); exit(1); } strcpy(folder,argv[1]); FileMask.rx = (regex_t *) safe_malloc (sizeof (regex_t)); REGCOMP(FileMask.rx,"!^\\.[^.]",0); ReplyRegexp.rx = (regex_t *) safe_malloc (sizeof (regex_t)); REGCOMP(ReplyRegexp.rx,"^(re([\\[0-9\\]+])*|aw):[ \t]*",0); ctx=mx_open_mailbox(folder,0,NULL); // index_hint=ctx->vcount; // check = mx_check_mailbox(ctx, &index_hint,0); // printf("index_hint: %d, check: %d\n",index_hint,check); printf("\nmsgs: %d\nnew: %d\nunread: %d\ntagged: %d\n", ctx->msgcount, ctx->new, ctx->unread, ctx->tagged ); for( i=ctx->msgcount-1; i>=0;i-- ) { header=ctx->hdrs[i]; printf("%d,%d: '%s'\n", header->msgno, header->lines, ( header->env->to && header->env->to->mailbox ? header->env->to->mailbox : "" ) ); } mx_close_mailbox(ctx,NULL); exit(0); }
static int menu_search (MUTTMENU * menu, int op) { int r; int searchDir; regex_t re; char buf[SHORT_STRING]; if (op != OP_SEARCH_NEXT && op != OP_SEARCH_OPPOSITE) { strfcpy (buf, menu->searchBuf ? menu->searchBuf : "", sizeof (buf)); if (mutt_get_field ((op == OP_SEARCH) ? _("Search for: ") : _("Reverse search for: "), buf, sizeof (buf), M_CLEAR) != 0 || !buf[0]) return (-1); str_replace (&menu->searchBuf, buf); menu->searchDir = (op == OP_SEARCH) ? M_SEARCH_DOWN : M_SEARCH_UP; } else { if (!menu->searchBuf) { mutt_error _("No search pattern."); return (-1); } } searchDir = (menu->searchDir == M_SEARCH_UP) ? -1 : 1; if (op == OP_SEARCH_OPPOSITE) searchDir = -searchDir; if ((r = REGCOMP (&re, menu->searchBuf, REG_NOSUB | mutt_which_case (menu->searchBuf))) != 0) { regerror (r, &re, buf, sizeof (buf)); regfree (&re); mutt_error ("%s", buf); return (-1); } r = menu->current + searchDir; while (r >= 0 && r < menu->max) { if (menu->search (menu, &re, r) == 0) { regfree (&re); return r; } r += searchDir; } regfree (&re); mutt_error _("Not found."); return (-1); }
/* **! method: create(string uri) **! Append data to the decode buffer. **! arg: string uri **! A URI pointing to the mailstore. **! Examples: **! imap://user:pass@host/INBOX **! /path/to/mbox **! /path/to/Maildir **! /path/to/mh **! returns: **! nothing (for now) **! name: Mailstore() - class constructor for Maistore */ void f_create(INT32 args) { char *path; get_all_args("create",args,"%s",&path); THIS->debug=0; THIS->folder=strdup(path); if( !FileMask.rx ) { FileMask.rx = (regex_t *) malloc (sizeof (regex_t)); REGCOMP(FileMask.rx,"!^\\.[^.]",0); } if( !ReplyRegexp.rx ) { ReplyRegexp.rx = (regex_t *) malloc (sizeof (regex_t)); REGCOMP(ReplyRegexp.rx,"^(re([\\[0-9\\]+])*|aw):[ \t]*",0); } THIS->ctx=mx_open_mailbox(THIS->folder, M_QUIET ,NULL); if( THIS->ctx == NULL ) { Pike_error("Context not open for folder '%s'\n",THIS->folder); } pop_n_elems(args); }
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; }
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; }
/** * mutt_yesorno - Ask the user a Yes/No question * @param msg Prompt * @param def Default answer, see #QuadOption * @retval num Selection made, see #QuadOption */ enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def) { struct Event ch; char *yes = _("yes"); char *no = _("no"); char *answer_string = NULL; int answer_string_wid, msg_wid; size_t trunc_msg_len; bool redraw = true; int prompt_lines = 1; char *expr = NULL; regex_t reyes; regex_t reno; char answer[2]; answer[1] = '\0'; bool reyes_ok = (expr = nl_langinfo(YESEXPR)) && (expr[0] == '^') && (REGCOMP(&reyes, expr, REG_NOSUB) == 0); bool reno_ok = (expr = nl_langinfo(NOEXPR)) && (expr[0] == '^') && (REGCOMP(&reno, expr, REG_NOSUB) == 0); /* In order to prevent the default answer to the question to wrapped * around the screen in the even the question is wider than the screen, * ensure there is enough room for the answer and truncate the question * to fit. */ safe_asprintf(&answer_string, " ([%s]/%s): ", (def == MUTT_YES) ? yes : no, (def == MUTT_YES) ? no : yes); answer_string_wid = mutt_strwidth(answer_string); msg_wid = mutt_strwidth(msg); while (true) { if (redraw || SigWinch) { redraw = false; if (SigWinch) { SigWinch = 0; mutt_resize_screen(); clearok(stdscr, TRUE); mutt_menu_current_redraw(); } if (MuttMessageWindow->cols) { prompt_lines = (msg_wid + answer_string_wid + MuttMessageWindow->cols - 1) / MuttMessageWindow->cols; prompt_lines = MAX(1, MIN(3, prompt_lines)); } if (prompt_lines != MuttMessageWindow->rows) { mutt_window_reflow_message_rows(prompt_lines); mutt_menu_current_redraw(); } /* maxlen here is sort of arbitrary, so pick a reasonable upper bound */ trunc_msg_len = mutt_wstr_trunc( msg, 4 * prompt_lines * MuttMessageWindow->cols, prompt_lines * MuttMessageWindow->cols - answer_string_wid, NULL); mutt_window_move(MuttMessageWindow, 0, 0); SETCOLOR(MT_COLOR_PROMPT); addnstr(msg, trunc_msg_len); addstr(answer_string); NORMAL_COLOR; mutt_window_clrtoeol(MuttMessageWindow); } mutt_refresh(); /* SigWinch is not processed unless timeout is set */ mutt_getch_timeout(30 * 1000); ch = mutt_getch(); mutt_getch_timeout(-1); if (ch.ch == -2) continue; if (CI_is_return(ch.ch)) break; if (ch.ch < 0) { def = MUTT_ABORT; break; } answer[0] = ch.ch; if (reyes_ok ? (regexec(&reyes, answer, 0, 0, 0) == 0) : (tolower(ch.ch) == 'y')) { def = MUTT_YES; break; } else if (reno_ok ? (regexec(&reno, answer, 0, 0, 0) == 0) : (tolower(ch.ch) == 'n')) { def = MUTT_NO; break; } else { BEEP(); } } FREE(&answer_string); if (reyes_ok) regfree(&reyes); if (reno_ok) regfree(&reno); if (MuttMessageWindow->rows != 1) { mutt_window_reflow_message_rows(1); mutt_menu_current_redraw(); } else mutt_window_clearline(MuttMessageWindow, 0); if (def != MUTT_ABORT) { addstr((char *) ((def == MUTT_YES) ? yes : no)); mutt_refresh(); } else { /* when the users cancels with ^G, clear the message stored with * mutt_message() so it isn't displayed when the screen is refreshed. */ mutt_clear_error(); } return def; }