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 <hurtta+elm@posti.FMI.FI>
******************************************************************************
* 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 <errno.h>
#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:
*/
syntax highlighted by Code2HTML, v. 0.9.1