static char rcsid[] = "@(#)$Id: message_pattern.c,v 1.9 2006/04/09 07:37:42 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.9 $ $State: Exp $ * * Author: Kari Hurtta ****************************************************************************** * Inludes code from pattern.c which have following copyright: * * The Elm Mail System * * Copyright (c) 1988-1992 USENET Community Trust * Copyright (c) 1986,1987 Dave Taylor ****************************************************************************/ #include "def_mcommon.h" #include "s_elm.h" DEBUG_VAR(Debug,__FILE__,"menu"); static unsigned char *s2us P_((char *str)); static unsigned char *s2us(str) char *str; { return (unsigned char *)str; } static CONST unsigned char *cs2us P_((const char *str)); static CONST unsigned char *cs2us(str) CONST char *str; { return (CONST unsigned char *)str; } #if ANSI_C #define S_(x) static x; #else #define S_(x) #endif #include #ifndef ANSI_C extern int errno; #endif int mc_matches_mbx(u,idx, meta_pattern) union mcommon_union *u; int idx; struct string * meta_pattern; { struct MailboxView *mbxview = u->mbx.mw; struct header_rec *a = give_header(mbxview,idx); int r = 0; if (a) { r = from_matches(a, meta_pattern) || subject_matches(a, meta_pattern); } return r; } int from_matches(mss, pattern) struct header_rec *mss; struct string *pattern; { /** Returns true iff the pattern occurs in it's entirety in the from line of the indicated message **/ struct addr_item *p; int match = 0; if (mss) for (p = mss->from; p && p->fullname && p->addr; p++) { struct string *s = new_string2(ASCII_SET,s2us(p->addr)); if (find_pattern_from_string(p->fullname,pattern,1)) match++; if (find_pattern_from_string(p->comment,pattern,1)) match++; if (find_pattern_from_string(s,pattern,1)) match++; free_string(&s); } return match; } int to_matches(mss, pattern) struct header_rec *mss; struct string * pattern; { /** Returns true iff the pattern occurs in it's entirety in the TO line of the indicated message **/ struct addr_item *p; int match = 0; if (mss) for (p = mss->to; p && p->fullname && p->addr; p++) { struct string *s = new_string2(ASCII_SET,s2us(p->addr)); if (find_pattern_from_string(p->fullname,pattern,1)) match++; if (find_pattern_from_string(p->comment,pattern,1)) match++; if (find_pattern_from_string(s,pattern,1)) match++; free_string(&s); } return match; } int cc_matches(mss, pattern) struct header_rec *mss; struct string * pattern; { /** Returns true iff the pattern occurs in it's entirety in the CC line of the indicated message **/ struct addr_item *p; int match = 0; if (mss) for (p = mss->cc; p && p->fullname && p->addr; p++) { struct string *s = new_string2(ASCII_SET,s2us(p->addr)); if (find_pattern_from_string(p->fullname,pattern,1)) match++; if (find_pattern_from_string(p->comment,pattern,1)) match++; if (find_pattern_from_string(s,pattern,1)) match++; free_string(&s); } return match; } int subject_matches(mss, pattern) struct header_rec *mss; struct string * pattern; { /** Returns true iff the pattern occurs in it's entirety in the subject line of the indicated message **/ int ret = 0; if (mss && mss->subject) ret = find_pattern_from_string(mss->subject, pattern,1); return ret; } struct search_mes { struct string * pat; int found; }; S_(mw_init_handler mw_init_search) static void mw_init_search(hdl) struct walk_handler *hdl; { hdl->u.search_mes = safe_malloc(sizeof (* (hdl->u.search_mes))); hdl->u.search_mes -> pat = NULL; hdl->u.search_mes -> found = 0; } S_(mw_free_handler mw_free_search) static void mw_free_search(hdl) struct walk_handler *hdl; { free(hdl->u.search_mes); hdl->u.search_mes = NULL; } S_(mw_action_handler mw_action_search) static void mw_action_search(hdl,ptr,state_in,fp,state_out) struct walk_handler *hdl; mime_t *ptr; in_state_t *state_in; FILE *fp; /* Same than state_in */ out_state_t *state_out; /* NULL */ { charset_t res = NULL; char buffer[1024]; int l; if (ptr->description && find_pattern_from_string(ptr->description, hdl->u.search_mes -> pat,1)) { hdl->u.search_mes -> found = 1; DPRINT(Debug,3,(&Debug, "%S found from description: %S\n", hdl->u.search_mes -> pat, ptr->description)); } mime_get_charset(&res, ptr->TYPE_opts,NULL, default_mimetext_charset /* FIXME: No correct */); while (0 < (l = state_getl(buffer,sizeof buffer,state_in))) { struct string *x = new_string(res); add_streambytes_to_string(x,l,s2us(buffer),NULL); if (find_pattern_from_string(x,hdl->u.search_mes -> pat,1)) { hdl->u.search_mes -> found = 1; DPRINT(Debug,3,(&Debug, "%S found from: %S\n", hdl->u.search_mes -> pat, x)); } free_string(&x); } } static struct handler_type search_mech_type = { WALKTYPE_magic, mw_init_search, mw_free_search, mw_action_search }; int mc_match_in_text_mbx(u,meta_pattern, page, LOC) union mcommon_union *u; struct string * meta_pattern; struct menu_context *page; struct screen_parts *LOC; { struct MailboxView *mbxview = u->mbx.mw; int LINES, COLUMNS; /* function match_in_message() from pattern.c */ /** Match a string INSIDE a message...starting at the current message read each line and try to find the pattern. As soon as we do, set current and leave! Returns 1 if found, 0 if not **/ char buffer[VERY_LONG_STRING]; int message_number, lines, line, line_len, err; int mc; int ret = 0; int selected = get_selected(mbxview); struct walk_handler * walk = malloc_walk_handler(&search_mech_type); menu_get_sizes(page, &LINES, &COLUMNS); message_number = get_current(mbxview)-1; walk->u.search_mes -> pat = meta_pattern; lib_transient(CATGETS(elm_msg_cat, ElmSet, ElmSearchingFolderPattern, "Searching folder for pattern...")); mc = get_message_count(mbxview); while (message_number < mc) { struct header_rec *hdr = give_header(mbxview,message_number); if (!selected || (selected && hdr->status & VISIBLE)) { FILE *ZZ; in_state_t state_in; int val = (message_number+1) / (float) mc * 100; if ((message_number+1) % readmsginc == 0 || val % readdatapercentinc == 0) { PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet, ElmSearchingInMessage, "Searching %d (%02d%%) "), (message_number+1), val); CleartoEOLN(); } /* Search first from subject and from */ if (from_matches(hdr, meta_pattern) || subject_matches(hdr, meta_pattern)) { int current = message_number+1; set_current(mbxview,current); clear_error(); ret = 1; PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet, ElmSearchingInMessageFound, "Searching %d (%02d%%) FOUND"), (message_number+1), val); CleartoEOLN(); goto out; } if (!give_message_data(mbxview,message_number, &hdr,&ZZ,NULL,mime_parse_routine)) { failXX: err = errno; DPRINT(Debug,1,(&Debug, "Error: seek %ld bytes into file failed. errno %d (%s)\n", hdr ? hdr->offset : -1, err, "match_in_message")); lib_error(CATGETS(elm_msg_cat, ElmSet, ElmMatchSeekFailed, "ELM [match] failed looking %ld bytes into file (%s)."), hdr ? hdr->offset : -1, error_description(err)); ret = 1; /* fake it out to avoid replacing error message */ goto out; } if (!hdr->mime_parsed) { DPRINT(Debug,1,(&Debug, "mime_parse_routine was not called\n")); mime_parse_routine(NULL,hdr,ZZ); } { struct menu_common MENU; int vis; set_mcommon_from_mbxview(&MENU,mbxview); vis = compute_visible(message_number+1, &MENU); menu_header_status_update(LOC->header_page,vis-1); } /* Copy some headers from part 1 */ if (skip_envelope(hdr, ZZ) != -1) { int found = 0; header_list_ptr all_headers = file_read_headers(ZZ, RHL_MARK_FOLDING); header_list_ptr next_hdr; for (next_hdr = all_headers; next_hdr; next_hdr = next_hdr -> next_header) { CONST char * hdr_name = give_header_name(next_hdr->header_name); struct string *s = new_string2(ASCII_SET,cs2us(hdr_name)); struct string *buffer = give_decoded_header(next_hdr, !(hdr->status & NOHDRENCODING), hdr -> header_charset); if (find_pattern_from_string(buffer,meta_pattern,1)) found++; if (find_pattern_from_string(s,meta_pattern,1)) found++; free_string(&buffer); free_string(&s); } if (all_headers) delete_headers(&all_headers); if (found) { int current = message_number+1; set_current(mbxview,current); clear_error(); ret = 1; PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet, ElmSearchingInMessageFound, "Searching %d (%02d%%) FOUND"), (message_number+1), val); CleartoEOLN(); goto out; } } else goto failXX; in_state_clear(&state_in, STATE_in_file); set_in_state_file(ZZ,&state_in); simple_mime_walk(&(hdr->mime_rec), walk, &state_in, NULL); in_state_destroy(&state_in); if (walk->u.search_mes ->found) { int current = message_number+1; set_current(mbxview,current); clear_error(); ret = 1; PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet, ElmSearchingInMessageFound, "Searching %d (%02d%%) FOUND"), (message_number+1), val); CleartoEOLN(); goto out; } } /** now we've passed the end of THIS message...increment and continue the search with the next message! **/ message_number++; } out: free_walk_handler(&walk); return(ret); } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */