/* logical.c */
#include "ml.h"
#define SECONDS_PER_DAY (60*60*24)
static char lan[4];
static char lheure[64];
char *mois[12]= {
"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
};
static int dpm[]= {/*dec - dec */
31, 30, 28, 31, 30, 31, 30, 31, 31, 31, 31, 30, 31
};
static int leap_dpm[]= {/*dec - dec */
31, 30, 29, 31, 30, 31, 30, 31, 31, 31, 31, 30, 31
};
/*
* Macro definitions. These are filter criteria which are expanded
* at search time and contain more than one filter rule. for instance,
* "conversant john" is the same as "from john or to john or cc john".
*/
static LEAF recipient_macro[]= {
{ "CC", NO_OP, FALSE, pred_field, NULL },
{ "TO", OR_OP, FALSE, pred_field, NULL },
{ NULL, NO_OP, FALSE, pred_simple, NULL }
};
static LEAF correspondent_macro[]= {
{ "FROM", NO_OP, FALSE, pred_field, NULL },
{ "TO", OR_OP, FALSE, pred_field, NULL },
{ NULL, NO_OP, FALSE, pred_simple, NULL }
};
static LEAF conversant_macro[]= {
{ "FROM", NO_OP, FALSE, pred_field, NULL },
{ "TO", OR_OP, FALSE, pred_field, NULL },
{ "CC", OR_OP, FALSE, pred_field, NULL },
{ NULL, NO_OP, FALSE, pred_simple, NULL }
};
static LEAFMACRO macro_petals[]= {
{ RECIPIENT_MACRO, recipient_macro, 2 },
{ CORRESPONDENT_MACRO, correspondent_macro, 2 },
{ CONVERSANT_MACRO, conversant_macro, 3 },
{ NULL, NULL, 0 }
};
#ifdef __STDC__
Message_List *apply_op_to_operands(Mailbox *mailbox, BOOLEAN_OPERATOR op,
Message_List **list1,
Message_List **list2)
#else
Message_List *apply_op_to_operands(mailbox,op,list1,list2)
Mailbox *mailbox;
BOOLEAN_OPERATOR op;
Message_List **list1;
Message_List **list2;
#endif
{
Message_List *result = NULL;
switch(op) {
case AND_OP:
conjunct_and(mailbox,*list1,*list2);
result = mailbox->found;
mailbox->found = NULL;
break;
/*
* A no_op is treated as an or_op because we don't know which of the
* two lists to preserve -- one of them will be empty. The other needs
* to be returned. Or'ing the two gives us the right result, regardless.
*/
case OR_OP:
case NO_OP:
conjunct_or(mailbox,*list1,*list2);
result = mailbox->found;
mailbox->found = NULL;
break;
default:
/* this shouldn't ever happen. */
break;
}
free_message_list(*list1,TRUE,FALSE);
*list1 = NULL;
free_message_list(*list2,TRUE,FALSE);
*list2 = NULL;
return(result);
}
#ifdef __STDC__
LEAFMACRO *macro_expansion_required(LEAF *leaf)
#else
LEAFMACRO *macro_expansion_required(leaf)
LEAF *leaf;
#endif
{
int i;
LEAFMACRO *lm = macro_petals;
char tmp[FILEBUFFLEN];
strcpy(tmp, leaf->predicate);
/*
* We have either
* predicate "FIELD"
* or
* predicate
* In the former case we NUL terminate the predicate
* for comparison to our macro predicates
*/
if (leaf->predicate_type == pred_field ||
leaf->predicate_type == pred_dynamic_field) {
/* select the predicate only - it is terminated by a space */
strtok(tmp, " "); /* NULL out the SPACE */
}
for (i = 0; lm->macro_name; ++i, ++lm)
if (strcasecmp(lm->macro_name, tmp) == 0)
return lm;
return NIL;
}
#ifdef __STDC__
void do_imap_macro_mail_search(Mailbox *mailbox, Lview *parent,
LEAFMACRO *lm, LEAF *petal)
#else
void do_imap_macro_mail_search(mailbox, parent, lm, petal)
Mailbox *mailbox;
Lview *parent;
LEAFMACRO *lm; /* The expansion rules */
LEAF *petal; /* The macro which we expand */
#endif
{
LEAF *macro= lm->leaves;
int n_leaves= lm->n_leaves;
int i;
char field[FILEBUFFLEN], *fptr= field;
Boolean local_ok= TRUE;
Message_List *result = NULL;
Message_List *current = NULL;
/* see if our MACRO predicate requires a field */
if (petal->predicate_type == pred_field ||
petal->predicate_type == pred_dynamic_field) {
/* extract the field */
strcpy(field, petal->predicate); /* "pred field" */
fptr = strchr(field,(int) SPACECHAR) + 1; /* skip the space */
} else
fptr = NULL;
/* EXPAND our macro here one leaf at a time ... */
for (i = 0; i < n_leaves; ++i, ++macro) {
char pred[FILEBUFFLEN]; /* for expanded predicate */
/*
* Contruct a search predicate with a field if necessary.
* Our macros NEVER include them since they are dynamic
*/
strcpy(pred, macro->predicate); /* get the MACRO predicate */
if ((petal->predicate_type == pred_field ||
petal->predicate_type == pred_dynamic_field) &&
macro->predicate_type == pred_field) { /* double check OK */
strcat(pred, SPACESTR); /* adjunct the FIELD */
strcat(pred, fptr);
}
/*
* Dispatch the search
*/
free_message_list(mailbox->found,TRUE,FALSE);
mailbox->found = NULL;
local_ok = local_search(mailbox, parent, pred);
if (local_ok == FALSE)
remote_search(mailbox, parent, pred);
/*
* Save the current results.
*/
current = mailbox->found;
mailbox->found = NULL;
/*
* Now accumulate the results with any operands
*/
if(macro->operator == NO_OP) {
result = current;
current = NULL;
}
else
result = apply_op_to_operands(mailbox, macro->operator,
&result, ¤t);
}
/*
* Our accumulated results are in "result". We'll make it appear
* as though this was a simple mailbox search, (results accumulated
* into "mailbox->found") since that's what the dispatcher is expecting.
* We're done with the intermediate list. Free its memory.
*/
free_message_list(current, TRUE, FALSE);
mailbox->found = result;
return;
}
#ifdef __STDC__
void remote_search(Mailbox *mailbox, Lview *parent, char *predicate)
#else
void remote_search(mailbox, parent, predicate)
Mailbox *mailbox;
Lview *parent;
char *predicate;
#endif
{
Message_List *result;
free_message_list(mailbox->found,TRUE,FALSE);
mailbox->found = NULL;
mail_search(mailbox->mailstream,predicate);
result = mailbox->found;
mailbox->found = NULL;
conjunct_and(mailbox,result,parent->message_list);
free_message_list(result,TRUE,FALSE);
}
/*
* Do the search on the given mail box
*/
#ifdef __STDC__
void do_imap_mail_search(Mailbox *mailbox, Lview *parent, LEAF *leaf)
#else
void do_imap_mail_search(mailbox, parent, leaf)
Mailbox *mailbox;
Lview *parent;
LEAF *leaf;
#endif
{
Boolean local_ok = TRUE;
/*
* Some searches are dispatched to the server,
* and others we do locally from our cache */
free_message_list(mailbox->found,TRUE,FALSE);
mailbox->found = NULL;
local_ok = local_search(mailbox, parent, leaf->predicate);
if (local_ok == FALSE)
remote_search(mailbox, parent, leaf->predicate);
return;
}
/*
* Does a search on all search petals, and accumulates the results
* into result
*/
#ifdef __STDC__
Message_List *do_imap_search(Mailbox *mailbox, Lview *parent, LEAF *petal)
#else
Message_List *do_imap_search(mailbox, parent, petal)
Mailbox *mailbox;
Lview *parent;
LEAF *petal;
#endif
{
LEAF *leaf = petal;
char *old_pred;
char *new_pred;
Message_List *current = NULL;
Message_List *result = NULL;
/* run down the petals accumulating the results of
* each search */
while (leaf) {
LEAFMACRO *lm;
new_pred = update_dynamic_predicates(leaf);
if(new_pred) {
/* Temporarily switch the predicates for the search */
old_pred = leaf->predicate;
leaf->predicate = new_pred;
}
else
old_pred = NULL;
if ((lm = macro_expansion_required(leaf)) != NIL)
do_imap_macro_mail_search(mailbox, parent, lm, leaf);
else
do_imap_mail_search(mailbox, parent, leaf);
if (old_pred) {
fs_give((void **) &new_pred);
leaf->predicate = old_pred;
}
/* If we have found something, hold on to it */
current = mailbox->found;
/* reset the search results */
mailbox->found = NULL;
/* Look for negation */
if(leaf->atomic_not == TRUE) {
negate_search(mailbox,current,parent->message_list);
current = mailbox->found;
mailbox->found = NULL;
}
/* apply operation to the result, EG: a OR b */
if(leaf->operator == NO_OP) {
result = current;
current = NULL;
}
else
result = apply_op_to_operands(mailbox, leaf->operator,
&result, ¤t);
leaf = leaf->next;
}
if(current)
free_message_list(current,TRUE,FALSE);
return(result);
}
#ifdef __STDC__
void set_leading_lan(void)
#else
void set_leading_lan()
#endif
{
struct timeval tp;
struct timezone tzp;
char *date;
gettimeofday(&tp, &tzp);
date = ctime((time_t *) &tp.tv_sec);
lan[0] = date[20];
lan[1] = date[21];
lan[2] = '\0';
}
#ifdef __STDC__
char *set_today(void)
#else
char *set_today()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_hier(void)
#else
char *set_hier()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
horloge -= SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_mois_dernier(void)
#else
char *set_mois_dernier()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int days_last_month;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
/* Take us to the debut of last month */
/* THe debut of this month */
horloge = horloge - ((temps->tm_mday - 1)* SECONDS_PER_DAY);
/* Our month tables begin with dec, and tm_mon is 0 - 11, ie, tm_mon + 1
* indexes THIS MONTH in our tables, alors tm_mon indexes LAST MONTH: */
days_last_month = ((temps->tm_year % 4) == 0) ?
leap_dpm[temps->tm_mon] : dpm[temps->tm_mon];
horloge -= days_last_month * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_mois_courant(void)
#else
char *set_mois_courant()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
sprintf(lheure, "\" 1-%s-%s%2d\"", mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_january(void)
#else
char *set_january()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
sprintf(lheure, "\" 1-JAN-%s%2d\"", lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_february(void)
#else
char *set_february()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-FEB-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_march(void)
#else
char *set_march()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-MAR-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_april(void)
#else
char *set_april()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-APR-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_may(void)
#else
char *set_may()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-MAY-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_june(void)
#else
char *set_june()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-JUN-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_july(void)
#else
char *set_july()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-JUL-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_august(void)
#else
char *set_august()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-AUG-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_september(void)
#else
char *set_september()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-SEP-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_october(void)
#else
char *set_october()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-OCT-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_november(void)
#else
char *set_november()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-NOV-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_december(void)
#else
char *set_december()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
int year;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
year = temps->tm_year;
sprintf(lheure, "\" 1-DEC-%s%2d\"", lan, year);
return lheure;
}
#ifdef __STDC__
char *set_sunday(void)
#else
char *set_sunday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= temps->tm_wday * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_monday(void)
#else
char *set_monday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= (temps->tm_wday - 1) * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_tuesday(void)
#else
char *set_tuesday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= (temps->tm_wday - 2) * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_wednesday(void)
#else
char *set_wednesday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= (temps->tm_wday - 3) * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_thursday(void)
#else
char *set_thursday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= (temps->tm_wday - 4) * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_friday(void)
#else
char *set_friday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= (temps->tm_wday - 5) * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_saturday(void)
#else
char *set_saturday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge -= (temps->tm_wday - 6) * SECONDS_PER_DAY;
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday, mois[temps->tm_mon],
lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lastsunday(void)
#else
char *set_lastsunday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (7 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lastmonday(void)
#else
char *set_lastmonday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (6 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lasttuesday(void)
#else
char *set_lasttuesday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (5 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lastwednesday(void)
#else
char *set_lastwednesday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (4 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lastthursday(void)
#else
char *set_lastthursday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (3 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lastfriday(void)
#else
char *set_lastfriday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (2 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
char *set_lastsaturday(void)
#else
char *set_lastsaturday()
#endif
{
time_t horloge;
struct tm *temps;
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
horloge = (time_t)tp.tv_sec;
temps = localtime(&horloge);
horloge = horloge - (temps->tm_wday * SECONDS_PER_DAY)
- (1 * SECONDS_PER_DAY);
temps = localtime(&horloge);
sprintf(lheure, "\"%2d-%s-%s%2d\"", temps->tm_mday,
mois[temps->tm_mon], lan, temps->tm_year);
return lheure;
}
#ifdef __STDC__
void conjunct_and(Mailbox *mailbox, Message_List *list1, Message_List *list2)
#else
void conjunct_and(mailbox,list1, list2)
Mailbox *mailbox;
Message_List *list1;
Message_List *list2;
#endif
{
Message_List *ptr1;
Message_List *ptr2;
Boolean found_it = FALSE;
free_message_list(mailbox->found, TRUE, FALSE);
mailbox->found = NULL;
for(ptr1 = list1; ptr1; ptr1 = ptr1->next) {
found_it = FALSE;
for(ptr2 = list2; ptr2; ptr2 = ptr2->next) {
if(ptr1->message == ptr2->message) {
found_it = TRUE;
break;
}
}
if(found_it == TRUE)
mm_searched(mailbox->mailstream,ptr1->message->msgno);
}
return;
}
#ifdef __STDC__
void conjunct_or(Mailbox *mailbox, Message_List *list1, Message_List *list2)
#else
void conjunct_or(mailbox,list1, list2)
Mailbox *mailbox;
Message_List *list1;
Message_List *list2;
#endif
{
Message_List *ptr;
Message_List *ptr2;
/*
* Not easy. First we have to combine the two lists into an intermediate
* list, and then weed out duplicates. To do this, efficiently,
* we sort the intermediate list, since there may be no logical ordering.
*/
free_message_list(mailbox->found, TRUE, FALSE);
mailbox->found = NULL;
for(ptr = list1; ptr; ptr = ptr->next)
mm_searched(mailbox->mailstream,ptr->message->msgno);
for(ptr = list2; ptr; ptr = ptr->next)
mm_searched(mailbox->mailstream,ptr->message->msgno);
ptr = sort_message_list(mailbox->found,REP_ASCENDING);
mailbox->found = NULL;
for(ptr2 = ptr; ptr2; ptr2 = ptr2->next) {
if((ptr2->next != NULL)
&& (ptr2->message != NULL)
&& (ptr2->next->message != NULL)
&& (ptr2->next->message->msgno == ptr2->message->msgno))
ptr2 = ptr2->next;
if(ptr2->message)
mm_searched(mailbox->mailstream,ptr2->message->msgno);
}
free_message_list(ptr,TRUE,FALSE);
return;
}
#ifdef __STDC__
void negate_search(Mailbox *mailbox, Message_List *list1, Message_List *list2)
#else
void negate_search(mailbox,list1,list2)
Mailbox *mailbox;
Message_List *list1;
Message_List *list2;
#endif
{
Message_List *ptr;
Message_List *message_list;
Boolean found_it = FALSE;
for(message_list = list2;
message_list; message_list = message_list->next) {
found_it = FALSE;
for(ptr = list1; ptr; ptr = ptr->next) {
if(ptr->message == message_list->message) {
found_it = TRUE;
break;
}
}
if(found_it == FALSE)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
free_message_list(list1,TRUE,FALSE);
return;
}
/*
* Each of the functions below return TRUE unless the search should
* be defaulted to the server.
*/
#ifdef __STDC__
Boolean local_new_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_new_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if((! elt->seen) && elt->recent)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return(TRUE);
}
/*
* Do a search on the mailbox cache for deleted messages
*/
#ifdef __STDC__
Boolean local_deleted_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_deleted_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(elt->deleted)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_undeleted_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_undeleted_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(! elt->deleted)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_flagged_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_flagged_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(elt->flagged)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_unflagged_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_unflagged_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(! elt->flagged)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_seen_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_seen_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(elt->seen)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_unseen_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_unseen_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(! elt->seen)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_answered_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_answered_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(elt->answered)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_unanswered_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_unanswered_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(! elt->answered)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_recent_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_recent_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(elt->recent)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_old_search(Mailbox *mailbox, Message_List *parent)
#else
Boolean local_old_search(mailbox,parent)
Mailbox *mailbox;
Message_List *parent;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if(! elt->recent)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
/*
* Here we have the text searches:
* SUBJECT
* FROM
* TEXT
* BODY
* HEADER
* TO
* CC
* REPLY-TO
* SENDER
* MESSAGE-ID
* IN-REPLY-TO
* REPLY-TO
* return-path
* remail
* > n if rfc822_size > n, then true ...
*/
#ifdef __STDC__
Boolean local_subject_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_subject_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char *subject;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message) {
subject = message_list->message->subject;
if(subject) {
len = strlen(subject);
if((len) && (search(subject, len, pattern, strlen(pattern))))
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_body_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_body_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
return(FALSE);
}
#ifdef __STDC__
Boolean local_header_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_header_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
return(FALSE);
}
#ifdef __STDC__
Boolean local_text_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_text_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
return(FALSE);
}
#ifdef __STDC__
Boolean local_msgid_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_msgid_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char *msgid;
for(message_list = parent; message_list; message_list = message_list->next) {
if((message_list->message) && (message_list->message->envelope)) {
msgid = message_list->message->envelope->message_id;
if((msgid) && (strlen(msgid))
&& search(msgid,strlen(msgid),pattern,strlen(pattern)))
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_size_plus_grand_que(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_size_plus_grand_que(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
MESSAGECACHE *elt;
unsigned long size = (unsigned long) atol(pattern);
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
if((elt) && (elt->rfc822_size > size))
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_inreplyto_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_inreplyto_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char *in_reply_to;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
in_reply_to = message_list->message->envelope->in_reply_to;
if((in_reply_to) && (strlen(in_reply_to))
&& search(in_reply_to,strlen(in_reply_to), pattern,strlen(pattern)))
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_on_search(Mailbox *mailbox, Message_List *parent, char *pattern)
#else
Boolean local_on_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
unsigned long date, msg_date;
MESSAGECACHE *elt;
MESSAGECACHE tmp_elt;
if (!mail_parse_date (&tmp_elt, pattern))
return(FALSE);
date = (tmp_elt.year << 9) + (tmp_elt.month << 5) + tmp_elt.day;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
msg_date = (elt->year << 9) + (elt->month << 5) + elt->day;
if (msg_date == date) /* message on the date */
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_since_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_since_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
unsigned long date, msg_date;
MESSAGECACHE *elt;
MESSAGECACHE tmp_elt;
if (!mail_parse_date (&tmp_elt, pattern))
return(TRUE);
date = (tmp_elt.year << 9) + (tmp_elt.month << 5) + tmp_elt.day;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
msg_date = (elt->year << 9) + (elt->month << 5) + elt->day;
if (msg_date >= date)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_before_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_before_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
unsigned long date, msg_date;
MESSAGECACHE *elt;
MESSAGECACHE tmp_elt;
if (!mail_parse_date (&tmp_elt, pattern))
return(TRUE);
date = (tmp_elt.year << 9) + (tmp_elt.month << 5) + tmp_elt.day;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->longcache) {
elt = &(message_list->message->longcache->elt);
msg_date = (elt->year << 9) + (elt->month << 5) + elt->day;
if (msg_date < date)
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return TRUE;
}
#ifdef __STDC__
Boolean local_from_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_from_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char addr[FILEBUFFLEN];
ADDRESS *base;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
base = message_list->message->envelope->from;
local_make_addr_str(base,addr);
len = strlen(addr);
if((len) && (search(addr,len,pattern,strlen(pattern))))
mm_searched(mailbox->mailstream, message_list->message->msgno);
}
}
return(TRUE);
}
#ifdef __STDC__
Boolean local_to_search(Mailbox *mailbox, Message_List *parent, char *pattern)
#else
Boolean local_to_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char addr[FILEBUFFLEN];
ADDRESS *base;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
base = message_list->message->envelope->to;
while(base) {
local_make_addr_str(base,addr);
len = strlen(addr);
if((len) && (search(addr,len,pattern,strlen(pattern)))) {
mm_searched(mailbox->mailstream, message_list->message->msgno);
break;
}
else
base = base->next;
}
}
}
return(TRUE);
}
#ifdef __STDC__
Boolean local_cc_search(Mailbox *mailbox, Message_List *parent, char *pattern)
#else
Boolean local_cc_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char addr[FILEBUFFLEN];
ADDRESS *base;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
base = message_list->message->envelope->cc;
while(base) {
local_make_addr_str(base,addr);
len = strlen(addr);
if((len) && (search(addr,len,pattern,strlen(pattern)))) {
mm_searched(mailbox->mailstream, message_list->message->msgno);
break;
}
else
base = base->next;
}
}
}
return(TRUE);
}
#ifdef __STDC__
Boolean local_reply_to_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_reply_to_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char addr[FILEBUFFLEN];
ADDRESS *base;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
base = message_list->message->envelope->reply_to;
while(base) {
local_make_addr_str(base,addr);
len = strlen(addr);
if((len) && (search(addr,len,pattern,strlen(pattern)))) {
mm_searched(mailbox->mailstream, message_list->message->msgno);
break;
}
else
base = base->next;
}
}
}
return(TRUE);
}
#ifdef __STDC__
Boolean local_sender_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_sender_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char addr[FILEBUFFLEN];
ADDRESS *base;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
base = message_list->message->envelope->sender;
while(base) {
local_make_addr_str(base,addr);
len = strlen(addr);
if((len) && (search(addr,len,pattern,strlen(pattern)))) {
mm_searched(mailbox->mailstream, message_list->message->msgno);
break;
}
else
base = base->next;
}
}
}
return(TRUE);
}
#ifdef __STDC__
Boolean local_replyto_search(Mailbox *mailbox, Message_List *parent,
char *pattern)
#else
Boolean local_replyto_search(mailbox,parent,pattern)
Mailbox *mailbox;
Message_List *parent;
char *pattern;
#endif
{
Message_List *message_list;
char addr[FILEBUFFLEN];
ADDRESS *base;
int len;
for(message_list = parent; message_list; message_list = message_list->next) {
if(message_list->message && message_list->message->envelope) {
base = message_list->message->envelope->reply_to;
while(base) {
local_make_addr_str(base,addr);
len = strlen(addr);
if((len) && (search(addr,len,pattern,strlen(pattern)))) {
mm_searched(mailbox->mailstream, message_list->message->msgno);
break;
}
else
base = base->next;
}
}
}
return(TRUE);
}
/*
* IF the predicate type requires a dynamic field, ie, one whose
* value is set at search time, then set its value. We remake the
* predicate/field pair, and return it to be used in search
*/
DYNAMIC dynamic_table[]= {
{
NULL,
XtNfilterToday,
"TODAY",
set_today },
{
NULL,
XtNfilterYesterday,
"YESTERDAY",
set_hier },
{
NULL,
XtNfilterLastMonth,
"LASTMONTH",
set_mois_dernier },
{
NULL,
XtNfilterThisMonth,
"THISMONTH",
set_mois_courant },
{
NULL,
XtNfilterJanuary,
"JANUARY",
set_january },
{
NULL,
XtNfilterFebruary,
"FEBRUARY",
set_february },
{
NULL,
XtNfilterMarch,
"MARCH",
set_march },
{
NULL,
XtNfilterApril,
"APRIL",
set_april },
{
NULL,
XtNfilterMay,
"MAY",
set_may },
{
NULL,
XtNfilterJune,
"JUNE",
set_june },
{
NULL,
XtNfilterJuly,
"JULY",
set_july },
{
NULL,
XtNfilterAugust,
"AUGUST",
set_august },
{
NULL,
XtNfilterSeptember,
"SEPTEMBER",
set_september },
{
NULL,
XtNfilterOctober,
"OCTOBER",
set_october },
{
NULL,
XtNfilterNovember,
"NOVEMBER",
set_november },
{
NULL,
XtNfilterDecember,
"DECEMBER",
set_december },
{
NULL,
XtNfilterSunday,
"SUNDAY",
set_sunday },
{
NULL,
XtNfilterMonday,
"MONDAY",
set_monday },
{
NULL,
XtNfilterTuesday,
"TUESDAY",
set_tuesday },
{
NULL,
XtNfilterWednesday,
"WEDNESDAY",
set_wednesday },
{
NULL,
XtNfilterThursday,
"THURSDAY",
set_thursday },
{
NULL,
XtNfilterFriday,
"FRIDAY",
set_friday },
{
NULL,
XtNfilterSaturday,
"SATURDAY",
set_saturday },
{
NULL,
XtNfilterLastSunday,
"LASTSUNDAY",
set_lastsunday },
{
NULL,
XtNfilterLastMonday,
"LASTMONDAY",
set_lastmonday },
{
NULL,
XtNfilterLastTuesday,
"LASTTUESDAY",
set_lasttuesday },
{
NULL,
XtNfilterLastWednesday,
"LASTWEDNESDAY",
set_lastwednesday },
{
NULL,
XtNfilterLastThursday,
"LASTTHURSDAY",
set_lastthursday },
{
NULL,
XtNfilterLastFriday,
"LASTFRIDAY",
set_lastfriday },
{
NULL,
XtNfilterLastSaturday,
"LASTSATURDAY",
set_lastsaturday },
{ NULL, NULL, NULL, NULL }
};
/* Simple search dispatchers (no args). */
SEARCHERS local_chercheurs_simple[]= {
{ "NEW", local_new_search },
{ "OLD", local_old_search },
{ "DELETED", local_deleted_search },
{ "UNDELETED", local_undeleted_search },
{ "SEEN", local_seen_search },
{ "UNSEEN", local_unseen_search },
{ "RECENT", local_recent_search },
{ "ANSWERED", local_answered_search },
{ "UNANSWERED", local_unanswered_search },
{ "FLAGGED", local_flagged_search },
{ "UNFLAGGED", local_unflagged_search },
{ NULL, NULL }
};
/* These require a search pattern */
SEARCHERS local_chercheurs_grands[] = {
{ "SUBJECT", local_subject_search },
{ "FROM", local_from_search },
{ "TO", local_to_search },
{ "CC", local_cc_search },
{ "ON", local_on_search },
{ "SINCE", local_since_search },
{ "BEFORE", local_before_search },
{ "MESSAGE-ID", local_msgid_search },
{ "SENDER", local_sender_search },
{ "IN-REPLY-TO", local_inreplyto_search },
{ "LARGER", local_size_plus_grand_que },
{ "HEADER", local_header_search },
{ "TEXT", local_text_search },
{ "BODY", local_body_search },
{ NULL, NULL }
};
#ifdef __STDC__
char *update_dynamic_predicates(LEAF *leaf)
#else
char *update_dynamic_predicates(leaf)
LEAF *leaf;
#endif
{
char tmp[FILEBUFFLEN];
char unquoted[FILEBUFFLEN];
char *field;
char *dynamic_value;
DYNAMIC *dyn;
int len;
char *nouveau;
if (leaf->predicate_type != pred_dynamic_field)
return NULL;
/* Isolate the field */
field = strchr(leaf->predicate,(int) SPACECHAR) + 1;
if(*field == DQUOTECHAR)
field ++;
strcpy(unquoted,field);
if(unquoted[strlen(unquoted) - 1] == DQUOTECHAR)
unquoted[strlen(unquoted) - 1] = NUL_TERM;
/* dispatch on field value */
for (dynamic_value = NULL, dyn = dynamic_table; dyn->value; ++dyn) {
if (strcasecmp(unquoted, dyn->localized) == STRMATCH) {
dynamic_value = (*dyn->set_dynamic)();
break;
}
}
if (!dynamic_value) {
/* Dynamic values NOT required in dynamic fields */
return NULL;
}
/*
* Remake predicate with dynamic value and protocol verb (not localized).
*/
strcpy(tmp, leaf->predicate);
strtok(tmp, " "); /* NULL terminate predicate */
len = strlen(tmp) + strlen(dynamic_value) + 2; /* SPACE and NULL too */
nouveau = (char *)fs_get(len);
sprintf(nouveau, "%s %s", tmp, dynamic_value);
return nouveau;
}
/*
* The dispatcher
*/
#ifdef __STDC__
void local_select_field(char *str, char *obuf)
#else
void local_select_field(str, obuf)
char *str;
char *obuf;
#endif
{
/* clear any leading SPACES */
while (*str == SPACECHAR)
++str;
/* Now a possibly leading \" */
if (*str && *str == DQUOTECHAR)
++str;
/* copy the rest into out output buffer */
strcpy(obuf, str);
/* now step on the last " */
if(obuf[strlen(obuf) - 1] == DQUOTECHAR)
obuf[strlen(obuf) - 1] = NUL_TERM;
return;
}
#ifdef __STDC__
Boolean local_search(Mailbox *mailbox, Lview *lview, char *predicate)
#else
Boolean local_search(mailbox, lview, predicate)
Mailbox *mailbox;
Lview *lview;
char *predicate;
#endif
{
char token[PARSEBUFLEN];
char field[PARSEBUFLEN];
char *chemise= token;
SEARCHERS *chs;
SEARCHERS *gchs;
/* strip off the chemise */
while (*predicate && *predicate != SPACECHAR)
*chemise++ = *predicate++;
*chemise = NUL_TERM;
/* OK, find the local chercheur */
for (chs = local_chercheurs_simple; chs->token; ++chs) {
if (strcasecmp(chs->token, token) == STRMATCH) {
return (*chs->chercheur)(mailbox, lview->message_list);
}
}
for (gchs = local_chercheurs_grands; gchs->token; ++gchs) {
if (strcasecmp(gchs->token, token) == STRMATCH) {
local_select_field(predicate, field);
return (*gchs->chercheur)(mailbox, lview->message_list, field);
}
}
return FALSE;
}
/* Action parsing routines and tables. */
ACTIONREC actlist[] = {
{ "delete", NULL, XtNactionDelete, DELETE_ACT, FALSE, FALSE, TRUE },
{ "expunge", NULL, XtNactionExpunge, EXPUNGE_ACT, FALSE, FALSE, TRUE },
{ "copy", NULL, XtNactionCopy, COPY_ACT, FALSE, TRUE, TRUE },
{ "move", NULL, XtNactionMove, MOVE_ACT, FALSE, TRUE, TRUE },
{ "save", NULL, XtNactionSave, SAVE_ACT, TRUE, TRUE, TRUE },
{ "shell", NULL, XtNactionShell, SHELL_ACT, TRUE, TRUE, TRUE },
{ "flag", NULL, XtNactionFlag, FLAG_ACT, FALSE, FALSE, TRUE },
{ "set", NULL, XtNactionSet, SET_ACT, FALSE, TRUE, TRUE },
{ "unset", NULL, XtNactionUnset, UNSET_ACT, FALSE, TRUE, TRUE },
{ "reply", NULL, XtNactionReply, REPLY_ACT, FALSE, TRUE, FALSE },
{ "print", NULL, XtNactionPrint, PRINT_ACT, TRUE, FALSE, TRUE },
{ "select", NULL, XtNactionSelect, SELECT_ACT, FALSE, FALSE, TRUE },
{ "new", NULL, XtNactionNew, NEW_ACT, FALSE, FALSE, TRUE },
{ "unseen", NULL, XtNactionUnseen, UNSEEN_ACT, FALSE, FALSE, TRUE },
{ "unselect", NULL, XtNactionUnselect, UNSELECT_ACT, FALSE, FALSE, TRUE },
{ "read", NULL, XtNactionRead, READ_ACT, FALSE, FALSE, TRUE },
{ NULL, NULL, NULL, NO_ACT, FALSE, FALSE, FALSE }
};
HEADERREC hdrlist[] = {
{ "noheader", NULL, XtNactionNoHeader, HEADER_NONE },
{ "partheader", NULL, XtNactionPartHeader, HEADER_PART },
{ "fullheader", NULL, XtNactionFullHeader, HEADER_FULL },
{ NULL, NULL, NULL, HEADER_UNKNOWN }
};
#ifdef __STDC__
void init_action_and_header_list(void)
#else
void init_action_and_header_list()
#endif
{
int i;
for(i = 0; actlist[i].name != NULL; i ++ )
actlist[i].localized = MLGetLocalized(actlist[i].resource,actlist[i].name);
for(i = 0; hdrlist[i].name != NULL; i ++)
hdrlist[i].localized = MLGetLocalized(hdrlist[i].resource,hdrlist[i].name);
return;
}
#ifdef __STDC__
ACTIONREC *find_action(char *s)
#else
ACTIONREC *find_action(s)
char *s;
#endif
{
ACTIONREC *a;
for(a = actlist; (a->name != NULL); a ++ ) {
if(strncasecmp(s,a->localized,strlen(a->localized)) == 0)
return(a);
}
return(NULL);
}
#ifdef __STDC__
HEADERREC *get_hdrlist(char *s)
#else
HEADERREC *get_hdrlist(s)
char *s;
#endif
{
HEADERREC *h;
for(h = hdrlist; (h->name != NULL); h ++ ) {
if(strncasecmp(s,h->localized,strlen(h->localized)) == 0)
return(h);
}
return(NULL);
}
#ifdef __STDC__
void free_actions(char **ss)
#else
void free_actions(ss)
char ** ss;
#endif
{
int n;
for(n = 0; ss[n] != NULL; n ++)
fs_give((void **) &(ss[n]));
fs_give((void **) ss);
return;
}
#ifdef __STDC__
char **get_actions(char *s)
#else
char **get_actions(s)
char *s;
#endif
{
int len, n;
char *ptr = s;
char *endptr;
char *zeroptr;
char **ret = NULL;
char buf[FILEBUFFLEN];
len = count_separators(s);
if(!len)
return(NULL);
ret = (char **) fs_get((len + 1) * sizeof(char *));
n = 0;
while(*ptr != NUL_TERM) {
while(isspace(*((unsigned char *)ptr)))
ptr ++;
endptr = strchr(ptr,ACTION_SEPARATOR);
if(endptr == NULL)
break;
strncpy(buf,ptr,(int) (endptr - ptr));
buf[endptr-ptr] = NUL_TERM;
for(zeroptr = &buf[strlen(buf)-1];
(isspace(*((unsigned char *)zeroptr))); zeroptr --)
*zeroptr = NUL_TERM;
if(! strlen(buf))
break;
ret[n] = cpystr(buf);
n ++;
ptr = (++endptr);
}
ret[n] = NULL;
return(ret);
}
#ifdef __STDC__
int count_separators(char *s)
#else
int count_separators(s)
char *s;
#endif
{
int n = 0;
char *p;
for(p = s; (*p) ; p ++ )
if(*p == ACTION_SEPARATOR)
n ++;
return(n);
}
/* Warning: we dispose of the calling string in this call */
#ifdef __STDC__
char *clean_and_parse_action(char *s)
#else
char *clean_and_parse_action(s)
char *s;
#endif
{
char buffer[FILEBUFFLEN];
char warn[FILEBUFFLEN];
char *ptr = s;
char *ret = NULL;
char *end_of_arg = NULL;
int errors = 0;
char *qptr = NULL;
ACTIONREC *a = NULL;
HEADERREC *h = NULL;
*buffer = NUL_TERM;
while(*ptr) {
while(isspace(*((unsigned char *) ptr)))
ptr ++;
a = find_action(ptr);
if(a == NULL || a->implemented == FALSE) {
if(strlen(ptr)) {
end_of_arg = strpbrk(ptr," \t\n;");
if(end_of_arg)
*end_of_arg = NUL_TERM;
sprintf(warn,MLGetLocalized(XtNmsgUnknownAction,MsgUnknownAction),ptr);
mm_log(warn,WARN);
errors ++;
}
buffer[strlen(buffer)] = NUL_TERM;
break;
}
else {
ptr += strlen(a->localized);
strcat(buffer,a->localized);
strcat(buffer,SPACESTR);
if( a->arg == FALSE && a->option == FALSE ) {
ptr = strchr(ptr,(int) ACTION_SEPARATOR);
if(ptr) {
strcat(buffer,"; ");
ptr ++;
continue;
}
else {
strcat(buffer, "; ");
break;
}
}
if(a->option == TRUE ) {
while(isspace(*((unsigned char *)ptr)))
ptr ++;
h = get_hdrlist(ptr);
if(h) {
ptr += strlen(h->localized);
strcat(buffer,h->localized);
strcat(buffer,SPACESTR);
}
else {
strcat(buffer,hdrlist[HEADER_PART].localized);
strcat(buffer,SPACESTR);
}
}
if(a->arg == FALSE) {
ptr = strchr(ptr,(int) ACTION_SEPARATOR);
if(ptr) {
strcat(buffer,"; ");
ptr ++;
continue;
}
else {
strcat(buffer, "; ");
break;
}
}
while(isspace(*((unsigned char *)ptr)))
ptr ++;
if((! *ptr) || (*ptr == ACTION_SEPARATOR)) {
sprintf(warn,MLGetLocalized(XtNmsgActionRequiresArg,
MsgActionRequiresArg),a->localized);
mm_log(warn,WARN);
errors ++;
break;
}
if(*ptr == DQUOTECHAR) {
qptr = strchr(ptr+1, DQUOTECHAR);
if(! qptr) {
mm_log(MLGetLocalized(XtNmsgMissingQuote,MsgMissingQuote),WARN);
errors ++;
break;
}
end_of_arg = strpbrk(qptr," \t\n;");
}
else
end_of_arg = strpbrk(ptr," \t\n;");
if(! end_of_arg) {
strcat(buffer,(char *)ptr);
strcat(buffer," ; ");
break;
}
else {
strncat(buffer,ptr,(int) (end_of_arg - ptr));
strcat(buffer," ; ");
ptr = end_of_arg;
while((isspace(*((unsigned char *)ptr)))
|| (*ptr == ACTION_SEPARATOR))
ptr ++;
continue;
}
}
}
fs_give((void **) &s);
if(errors) {
ret = cpystr(EMPTYSTR);
return(ret);
}
if(strlen(buffer))
ret = cpystr(buffer);
else
ret = cpystr(EMPTYSTR);
return(ret);
}
/* Filter parsing routines and tables. */
static STOKEN search_tokens[]= {
{
NULL,
XtNfilterTo,
"TO", /* Token string */
TRUE, /* True if field required */
STRSEARCH,
}, /* search type: local / server */
{
NULL,
XtNfilterFrom,
"FROM",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterCc,
"CC",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterCorrespondent,
CORRESPONDENT_MACRO,
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterRecipient,
RECIPIENT_MACRO,
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterConversant,
CONVERSANT_MACRO,
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterSubject,
"SUBJECT",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterText,
"TEXT",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterHeader,
"HEADER",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterBody,
"BODY",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterMessageId,
"MESSAGE-ID",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterSender,
"SENDER",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterReplyTo,
"REPLY-TO",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterInReplyTo,
"IN-REPLY-TO",
TRUE,
STRSEARCH,
},
{
NULL,
XtNfilterSince,
"SINCE",
TRUE,
TIMESEARCH, /* TIME attribute */
},
{
NULL,
XtNfilterBefore,
"BEFORE",
TRUE,
TIMESEARCH,
},
{
NULL,
XtNfilterOn,
"ON",
TRUE,
TIMESEARCH,
},
{
NULL,
XtNfilterLarger,
"LARGER",
TRUE,
ATOMIC+NUMERIC,
},
{
NULL,
XtNfilterNew,
"NEW",
FALSE,
NONE,
},
{
NULL,
XtNfilterOld,
"OLD",
FALSE,
NONE,
},
{
NULL,
XtNfilterDeleted,
"DELETED",
FALSE,
NONE,
},
{
NULL,
XtNfilterUndeleted,
"UNDELETED",
FALSE,
NONE,
},
{
NULL,
XtNfilterSeen,
"SEEN",
FALSE,
NONE,
},
{
NULL,
XtNfilterUnseen,
"UNSEEN",
FALSE,
NONE,
},
{
NULL,
XtNfilterRecent,
"RECENT",
FALSE,
NONE,
},
{
NULL,
XtNfilterAnswered,
"ANSWERED",
FALSE,
NONE,
},
{
NULL,
XtNfilterUnanswered,
"UNANSWERED",
FALSE,
NONE,
},
{
NULL,
XtNfilterFlagged,
"FLAGGED",
FALSE,
NONE,
},
{
NULL,
XtNfilterUnflagged,
"UNFLAGGED",
FALSE,
NONE,
},
{
NULL,
NULL,
NULL,
FALSE,
NONE,
}
};
BOOLEAN_LIST boolean_tokens[]= {
{ NULL, XtNfilterAnd, "AND", AND_OP },
{ NULL, XtNfilterOr, "OR", OR_OP },
{ NULL, XtNfilterNot, "NOT", NOT_OP },
{ NULL, NULL, NULL, NO_OP }
};
#ifdef __STDC__
void init_logical_view_structures(void)
#else
void init_logical_view_structures()
#endif
{
int i;
for(i = 0; search_tokens[i].token != NULL; i ++)
search_tokens[i].localized = MLGetLocalized(search_tokens[i].resource,
search_tokens[i].token);
for(i = 0; dynamic_table[i].value != NULL; i ++)
dynamic_table[i].localized = MLGetLocalized(dynamic_table[i].resource,
dynamic_table[i].value);
for(i = 0; boolean_tokens[i].operator != NULL; i ++)
boolean_tokens[i].localized = MLGetLocalized(boolean_tokens[i].resource,
boolean_tokens[i].operator);
}
/* return pointer to last char in a string */
#ifdef __STDC__
char *last(char *str)
#else
char *last(str)
char *str;
#endif
{
int len = strlen(str);
return &str[len - 1];
}
/* Match str to a token in tlist.
* Return a STOKEN pointer, or NULL */
#ifdef __STDC__
STOKEN * found_token(STOKEN *tlist, char *token, parse_errors *err)
#else
STOKEN * found_token(tlist, token, err)
STOKEN *tlist;
char *token;
parse_errors *err;
#endif
{
int i;
for (i = 0; tlist[i].token; ++i)
if (strcasecmp(token, tlist[i].localized) == STRMATCH)
return &tlist[i];
*err = illegal_token;
return NULL;
}
#ifdef __STDC__
BOOLEAN_OPERATOR found_boolean(BOOLEAN_LIST *blist, char *str)
#else
BOOLEAN_OPERATOR found_boolean(blist, str)
BOOLEAN_LIST *blist;
char *str;
#endif
{
int i;
for (i = 0; boolean_tokens[i].operator; ++i)
if (strcasecmp(str, boolean_tokens[i].localized) == STRMATCH) {
return boolean_tokens[i].boole;
}
return NO_OP;
}
#ifdef __STDC__
char *make_predicate(char *token, char *field, Boolean needs_field,
unsigned long attributes)
#else
char *make_predicate(token, field, needs_field, attributes)
char *token, *field;
Boolean needs_field;
unsigned long attributes;
#endif
{
int len;
char *string = NULL;
Boolean quoted;
if (needs_field == FALSE)
return(cpystr(token));
len = strlen(token) + strlen(field) + 8;
string = (char *) fs_get(len);
quoted = (*field == DQUOTECHAR);
if ((quoted == TRUE) || (attributes & ATOMIC))
sprintf(string,"%s %s", token, field);
else
sprintf(string,"%s \"%s\"", token, field);
return string;
}
/* place null at end of field, and return pointer to beginnig
of the field.
n_excess will count surrounding parenthesis and any whitespace
we step on to terminate the field .*/
#ifdef __STDC__
char *set_form_end(char *field, int *n_excess, parse_errors *err)
#else
char *set_form_end(field, n_excess, err)
char *field;
int *n_excess;
parse_errors *err;
#endif
{
char c, *cp= field, *cp0= field;
*n_excess = 0;
if (*cp == DQUOTECHAR) { /* search for '"' */
++cp; /* skip initial '"' */
while ((c = *cp++) != NUL_TERM) {
if (c == DQUOTECHAR) {
*cp = NUL_TERM; /* tie it off */
return cp0; /* found our matching " */
}
}
/*
* We should never reach this error because "" parsing is done
* before we parse for structure detail */
*err = missing_dquote;
return NULL; /* This should never happen */
}
/* OK, search for whitespace or a terminating ')' */
while ((c = *cp) != NUL_TERM) {
if ((c == SPACECHAR) || (c == TABCHAR)) {
*cp = NUL_TERM; /* tie it off */
++n_excess; /* stepped on white-space */
}
++cp;
}
return cp0;
}
#ifdef __STDC__
Boolean numeric_field(char *field, parse_errors *err)
#else
Boolean numeric_field(field, err)
char *field;
parse_errors *err;
#endif
{
int i;
if (*field == '\"') ++field;
i = atoi(field);
if (i <= 0) {
*err = illegal_numeric_field;
return FALSE;
}
return TRUE;
}
#ifdef __STDC__
Boolean select_field(char **fptr, STOKEN *tptr, char *field,
int *len_trouve, parse_errors *err)
#else
Boolean select_field(fptr, tptr, field, len_trouve, err)
char **fptr;
STOKEN *tptr;
char *field;
int *len_trouve;
parse_errors *err;
#endif
{
char c;
int loc_len= 0;
char *loc_str, *str= field;
/* Anything left? */
if (!*field) {
*err = missing_field;
return FALSE;
}
loc_str = set_form_end(str, &loc_len, err);
if (!loc_str)
return FALSE;
/* Is it a \". Note that any surrounding parenthesis have
already been counted in set_form_end(). */
if (*loc_str == DQUOTECHAR) { /* quoted field */
++loc_str;
loc_len += 1;
while (((c = *loc_str++)) != NUL_TERM) { /* cherche '"' termination */
loc_len += 1;
if (c == DQUOTECHAR) {
*len_trouve = loc_len;
*fptr = str;
return TRUE;
}
}
*err = missing_dquote;
return FALSE;
}
/* Take next variable, ie, break on white-space or end-of-string */
while (((c = *loc_str++)) != NUL_TERM)
if ((c == SPACECHAR) || (c == TABCHAR))
break;
else
loc_len += 1;
*len_trouve = loc_len;
*fptr = str;
return TRUE;
}
#ifdef __STDC__
int fix_whitespace(char *str)
#else
int fix_whitespace(str)
char *str;
#endif
{
char *src, *dst;
char c;
int ws= 1; /* to clear leading whitespace */
src = dst = str;
/* Compact all whitespace */
while (((c = *src++)) != NUL_TERM) {
if (c == LFCHAR)
continue; /* skip RETURN */
if ((c == SPACECHAR) || (c == TABCHAR)) {
ws += 1; /* count whitespace */
if (ws > 1) continue; /* skip it */
c = SPACECHAR; /* use SPACE */
} else
ws = 0;
*dst++ = c;
}
*dst = NUL_TERM;
}
/* refuse blank names */
#ifdef __STDC__
Boolean whitespace_name(char *str)
#else
Boolean whitespace_name(str)
char *str;
#endif
{
char c;
while (((c = *str++)) != NUL_TERM)
if ((c != SPACECHAR) && (c != TABCHAR))
return FALSE;
return TRUE;
}
/*
* add a new leaf to our tree. */
#ifdef __STDC__
void add_leaf_to_tree(LEAF **root, char *ctoken, char *cfield,
BOOLEAN_OPERATOR operator, STOKEN *tptr,
Boolean found_not)
#else
void add_leaf_to_tree(root, ctoken, cfield, operator, tptr, found_not)
LEAF **root;
char *ctoken;
char *cfield;
BOOLEAN_OPERATOR operator;
STOKEN *tptr;
Boolean found_not;
#endif
{
LEAF *leaf = (LEAF *) fs_get(sizeof(LEAF));
LEAF *prev;
leaf->predicate = make_predicate(ctoken, cfield,
tptr->field_required,
tptr->field_attributes);
leaf->operator = operator;
leaf->atomic_not = found_not;
leaf->predicate_type = (tptr->field_required ? pred_field : pred_simple);
/* some predicate fields are dynamic at search time */
if ((leaf->predicate_type == pred_field)
&& (tptr->field_attributes & TIMESEARCH))
leaf->predicate_type = pred_dynamic_field;
/* Adjoin the leaf to the tree */
if (*root == NULL)
*root = leaf;
else {
for(prev = *root; prev->next; prev = prev->next)
;
prev->next = leaf;
}
leaf->next = NULL;
}
/*
* dispose of the tree */
#ifdef __STDC__
void cut_down_the_tree(LEAF *leafs)
#else
void cut_down_the_tree(leafs)
LEAF *leafs;
#endif
{
LEAF *feuille;
/* dispose of the tree */
while (leafs) {
feuille = leafs;
fs_give((void **) &feuille->predicate); /* the string */
leafs = feuille->next; /* next leaf */
fs_give((void **) &feuille); /* the structure */
}
}
/*
* create IMAP search filter from the tree's leaf's */
#ifdef __STDC__
void move_leafs_to_filter(LEAF **search_tree, char **search_text,
LEAF *leafs, char *text)
#else
void move_leafs_to_filter(search_tree, search_text, leafs, text)
LEAF **search_tree;
char **search_text;
LEAF *leafs;
char *text;
#endif
{
/* the search_filter.name is set up by the caller to lv_parse_filter */
*search_tree = leafs;
*search_text = text;
}
/* augment the filter by len */
#ifdef __STDC__
char *advance_filter(char *filter, int *filter_len, int len)
#else
char *advance_filter(filter, filter_len, len)
char *filter;
int *filter_len;
int len;
#endif
{
*filter_len -= len; /* decrement by string length */
if (*filter_len > 1) {
filter += len + 1; /* next list item */
*filter_len -= 1; /* advance one char more */
} else
filter += len; /* points to NULL termination */
return filter;
}
/*
* Here we parse the filter text provided by the user
* Returns: parse_success if parse does not fail. Otherwise an ERROR
*/
#define TOKEN_STOPS " \t"
#define ERRMSGLEN 32
#ifdef __STDC__
parse_errors lv_parse_filter(char *name_text, char *filter_text,
LEAF **search_tree, char **search_text,
char *errmsg)
#else
parse_errors lv_parse_filter(name_text, filter_text, search_tree,
search_text, errmsg)
char *name_text;
char *filter_text;
LEAF **search_tree;
char **search_text;
char *errmsg;
#endif
{
char *search_string; /* destination */
STOKEN *tokens= search_tokens; /* our tokens */
char *filter= filter_text; /* source to parse */
char *ctoken; /* current token */
STOKEN *tptr; /* token block */
char *field; /* for a field */
int filter_len; /* chars in filter */
int field_len;
int other_len;
parse_errors err, rval; /* in places, used for error return */
BOOLEAN_OPERATOR operator = NO_OP; /* AND_OP / OR_OP / NO_OP */
BOOLEAN_OPERATOR not_op = NO_OP;
LEAF *arbe= NULL; /* the tree which grows on C street */
int next_term= TOKEN; /* initially a TOKEN */
int parsing; /* counts terms */
Boolean looping= TRUE; /* keeps it going */
Boolean found_not = FALSE;
char *ptr0;
char *ptr9;
/* Make sure the name is not white-space */
if (whitespace_name(name_text)) {
return invalid_name;
}
fix_whitespace(filter); /* clear unnecessary whitespace */
filter_len = strlen(filter); /* what's is there */
operator = NO_OP;
search_string = cpystr(filter); /* save a copy */
*errmsg = NUL_TERM; /* no message yet */
strcpy(errmsg, MLGetLocalized(XtNmsgFilterParseError,
MsgFilterParseError));
/* Main parse loop... */
for (parsing = 0; looping; ++parsing) {
/*
* Here we expect to find a predicate like "FROM" or "DELETED"
*/
ptr0 = filter;
if(*ptr0 == DQUOTECHAR) {
ptr0 ++;
while (*ptr0 && *ptr0 != DQUOTECHAR)
ptr0 ++;
}
ptr9 = strpbrk(ptr0, TOKEN_STOPS);
if(ptr9)
*ptr9 = NUL_TERM;
ctoken = filter;
if(*ctoken == NUL_TERM)
ctoken = NULL;
/* !@#$%^&*()#%@&^% strtok! */
/*ctoken = strtok(filter, TOKEN_STOPS); first token */
if (!ctoken) {
if (parsing == 0) { /* First time through */
err = empty_filter; /* no filter provided */
}
else
if (next_term == GEORGES_BOOLE) { /* Final term a predicate */
err = no_error;
}
else
err = missing_predicate; /* No predicate after AND/OR */
break;
}
/* check for token or Boolean operator */
switch (next_term) {
case TOKEN:
/* First check for NOT. It's a boolean, but will be located here. */
not_op = found_boolean(boolean_tokens, ctoken);
if (not_op == NOT_OP) {
found_not = TRUE;
other_len = strlen(ctoken);
filter = advance_filter(filter, &filter_len, other_len);
ptr0 = filter;
if(*ptr0 == DQUOTECHAR) {
ptr0 ++;
while (*ptr0 && *ptr0 != DQUOTECHAR)
ptr0 ++;
}
ptr9 = strpbrk(ptr0, TOKEN_STOPS);
if(ptr9)
*ptr9 = NUL_TERM;
ctoken = filter;
if(*ctoken == NUL_TERM)
ctoken = NULL;
/* !@#$%^&*()#%@&^% strtok! */
/* ctoken = strtok(filter, TOKEN_STOPS); first token */
}
else
found_not = FALSE;
/* select a token from our tokens[] */
if ((tptr = found_token(tokens, ctoken, &err)) == NULL) {
looping = FALSE;
strcat(errmsg, ctoken);
continue;
}
else {
other_len = strlen(ctoken); /* includes parenthesis, not */
next_term = GEORGES_BOOLE; /* Boolean next en haut.*/
}
filter = advance_filter(filter, &filter_len, other_len);
break;
case GEORGES_BOOLE:
/*
* We find the operator which binds the NEXT predicate with
* it predecessors
*/
operator = found_boolean(boolean_tokens, ctoken);
if ((operator == NO_OP) || (operator == NOT_OP)) {
err = expected_boolean;
looping = FALSE;
strcat(errmsg, ctoken);
continue;
}
else {
other_len = strlen(ctoken);
next_term = TOKEN; /* token on next pass */
}
filter = advance_filter(filter, &filter_len, other_len);
continue;
}
/* check for <field> */
if (tptr->field_required) {
if (!select_field(&field, tptr, filter, &field_len, &err)) {
looping = FALSE; /* err set in select_field */
strcat(errmsg, ctoken);
continue;
}
if (tptr->field_attributes & NUMERIC &&
!numeric_field(field, &err)) {
looping = FALSE;
strcat(errmsg, field);
continue;
}
filter_len -= field_len; /* decrement chars remaining */
filter += field_len; /* skip field in string */
*filter = '\0'; /* terminate predicate */
if (filter_len > 0) { /* then not at end */
++filter; /* to next term */
--filter_len; /* one less character */
}
}
else {
field = ""; /* No field - filter is OK. */
}
/* place in our parsing tree */
add_leaf_to_tree(&arbe, ctoken, field, operator, tptr, found_not);
}
/*
* chase down the tree and build the various search filters
*/
if (err == no_error) {
move_leafs_to_filter(search_tree, search_text, arbe, search_string);
rval = parse_success;
}
else {
cut_down_the_tree(arbe); /* dispose of the tree */
fs_give((void **) &search_string); /* And the string */
rval = err;
}
return rval;
}
syntax highlighted by Code2HTML, v. 0.9.1