static char rcsid[] = "@(#)$Id: aliaslib.c,v 1.31 2006/04/09 07:37:17 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.31 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
/** Library of functions dealing with the alias system...
**/
#include "def_elm.h"
#include "s_elm.h"
DEBUG_VAR(Debug,__FILE__,"alias");
extern int current_mail_message;
struct expand {
struct addr_item *addrs;
int addrs_len;
};
static int add_ P_((struct expand *x, CONST char *ADR,
CONST struct string *FN,
CONST struct string *COMMENT));
static int add_(x,ADR,FN,COMMENT)
struct expand *x;
CONST char *ADR;
CONST struct string *FN;
CONST struct string *COMMENT;
{
x->addrs = safe_realloc(x->addrs,(x->addrs_len + 2) *
sizeof (struct addr_item));
x->addrs[x->addrs_len].addr = safe_strdup(ADR);
x->addrs[x->addrs_len].fullname = dup_string(FN);
x->addrs[x->addrs_len].comment = dup_string(COMMENT);
x->addrs[x->addrs_len+1].addr = NULL;
x->addrs[x->addrs_len+1].fullname = NULL;
x->addrs[x->addrs_len+1].comment = NULL;
return x->addrs_len++;
}
#define ADD(x,ADR,FN,COMMENT) add_(&x,ADR,FN,COMMENT)
static int do_get_alias_l P_((
char *name,
struct expand *buffer,
int mailing,
int sysalias,
int depth,
int *too_longp,
struct mailer_info *mailer_info,
struct AliasView *aview
));
/*
* Expand the comma-delimited group of names in "group", storing the result
* in "buffer". Returns TRUE if expansion occurs OK, else FALSE in the
* event of errors.
*/
static int do_expand_group_l P_((
char *group,
struct expand *buffer,
int sysalias,
int depth,
int *too_longp,
struct mailer_info *mailer_info,
struct AliasView *aview
));
static int do_expand_group_l(group, buffer, sysalias, depth, too_longp,
mailer_info, aview)
char *group; /* group list to expand */
struct expand *buffer; /* place to store result of expansion */
int sysalias; /* TRUE to suppress checks of the user's aliases*/
int depth; /* nesting depth */
int *too_longp; /* error code if expansion overflows buffer */
struct mailer_info *mailer_info;
struct AliasView *aview;
{
char ** tokenized = rfc822_tokenize(group);
char **ptr, **next = NULL;
int result = 0;
remove_space_tokenized(tokenized); /* removes spaces and comments */
for (ptr = tokenized; *ptr; ptr = next) {
char * name = *ptr;
int q_seen = 0;
int q = 0;
for (next = ptr; *next; next++) {
if (',' == (*next)[0] && !q)
break;
else if ('<' == (*next)[0]) {
q++;
q_seen++;
} else if ('>' == (*next)[0])
q--;
}
if (ptr+1 == next) {
struct addr_item verify_result;
enum mailer_errcode errcode = MAILER_NOT_AVAIL;
/* see if this name is really an alias */
if (do_get_alias_l(name,buffer,TRUE,sysalias,depth,too_longp,
mailer_info, aview))
continue;
if ( *too_longp ) {
result = 0;
goto fail;
}
/* verify it is a valid address */
if (mailer_info &&
verify_mailer_addr(mailer_info,name,
&verify_result,&errcode)) {
DPRINT(Debug,7,
(&Debug,
"Alias %s verified as address -- really %s\n",
name,verify_result.addr));
if (!verify_result.fullname)
verify_result.fullname = new_string(display_charset);
if (!verify_result.comment)
verify_result.comment = new_string(display_charset);
/* Max alias expansion limit? */
add_(buffer,
verify_result.addr,
verify_result.fullname,
verify_result.comment );
free_string(& verify_result.fullname);
free_string(& verify_result.comment);
free(verify_result.addr); verify_result.addr = NULL;
} else {
struct string * fn = NULL;
struct string * cm = NULL;
cm = new_string(display_charset);
fn = new_string(display_charset);
/* Max alias expansion limit? */
add_(buffer,name,fn,cm);
free_string(&fn);
free_string(&cm);
}
} else { /* must have address .... */
char * buffer1 = NULL;
char ** scanner = NULL;
for (scanner = ptr; scanner < next; scanner++) {
if (buffer1 && q_seen && !q)
buffer1 = strmcat(buffer1," "); /* Regenerate spaces for phrase */
if ('<' == (*scanner)[0])
q++;
else if ('>' == (*scanner)[0])
q--;
buffer1 = strmcat(buffer1,*scanner);
}
if (buffer1) {
struct addr_item * address =
break_down_address(buffer1,
/* If user pastes encoded words from
* somewhere decode them also.
*/
is_rfc1522(buffer1),
display_charset);
struct addr_item *ptr1;
for (ptr1 = address;
ptr1 && ptr1 -> addr && ptr1->fullname && ptr1->comment;
ptr1++) {
/* Max alias expansion limit? */
add_(buffer,ptr1->addr,ptr1->fullname, ptr1->comment);
}
if (address)
free_addr_items(address);
free(buffer1);
}
}
if (*next &&
',' == (*next)[0])
next++;
}
result = 1;
fail:
if (tokenized)
free_rfc822tokenized(tokenized);
return result;
}
static int do_get_alias_l(name, buffer, mailing, sysalias, depth, too_longp,
mailer_info, aview)
char *name; /* name to expand as an alias */
struct expand *buffer; /* place to store result of expansion */
int mailing; /* TRUE to fully expand group names & recursive aliases */
int sysalias; /* TRUE to suppress checks of the user's aliases */
int depth; /* recursion depth - initially call at depth=0 */
int *too_longp; /* error code if expansion overflows buffer */
struct mailer_info *mailer_info;
struct AliasView *aview;
{
struct alias_rec *match = NULL;
char * alias_address = NULL;
struct string * alias_fullname = NULL;
struct string * alias_comment = NULL;
struct addr_item * address;
int loc;
/* update the recursion depth counter */
++depth;
DPRINT(Debug,5,
(&Debug, "%*s->attempting alias expansion on \"%s\"\n",
(depth*2), "", name));
/* The next two blocks could be merged somewhat */
/* check for a user alias, unless in the midst of sys alias expansion */
if ( !sysalias &&
(loc = find_alias(name, USER, aview)) >= 0)
match = give_alias(aview,loc);
/* check for a system alias */
else if ( (loc = find_alias(name, SYSTEM, aview)) >= 0 ) {
match = give_alias(aview,loc);
sysalias = TRUE;
}
/* nope...this name wasn't an alias */
else
return FALSE;
if (!match)
return FALSE;
alias_address = match->address;
if ( 0 != (match->type & PERSON )) {
/* If user pastes encoded words from
* somewhere decode them also.
*/
alias_fullname = hdr_to_string(HDR_TEXT,match->name,
display_charset,
is_rfc1522(match->name));
}
DPRINT(Debug,5,
(&Debug, "%*s ->expanded alias to \"%s\"\n",
(depth*2), "", alias_address));
if (!alias_fullname)
alias_fullname = new_string(display_charset);
if (!alias_comment)
alias_comment = new_string(display_charset);
/* check for an exact match */
if (0 == strcmp(name,alias_address)) {
add_(buffer,alias_address,alias_fullname,alias_comment);
free_string(&alias_fullname);
free_string(&alias_comment);
/* Max alias expansion limit? */
return TRUE;
}
/* see if we are stuck in a loop */
if ( depth > 12 ) {
DPRINT(Debug,2,
(&Debug,
"alias expansion loop detected at \"%s\" - bailing out\n",
name));
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorExpanding,
"Error expanding \"%s\" - probable alias definition loop."),
name);
free_string(&alias_fullname);
free_string(&alias_comment);
return FALSE;
}
/* see if the alias equivalence is a group name */
if ( mailing && match->type & GROUP ) {
free_string(&alias_fullname);
free_string(&alias_comment);
return do_expand_group_l(alias_address,buffer,
sysalias,depth,too_longp,
mailer_info, aview
);
}
/* see if the alias equivalence is an email address,
* but not list of addresses. If address starts with @
* then it is source-route address and not list of addresses
*/
if (!(match->type & GROUP) &&
('@' == alias_address[0] || qstrpbrk(alias_address,",") == NULL) &&
qstrpbrk(alias_address,"!@:") != NULL ) {
add_(buffer,alias_address,alias_fullname,alias_comment);
free_string(&alias_fullname);
free_string(&alias_comment);
/* Max alias expansion limit? */
return TRUE;
}
/* see if the alias equivalence is itself an alias */
if ( mailing && qstrpbrk(alias_address,",!@:") == NULL &&
do_get_alias_l(alias_address,buffer,TRUE,sysalias,depth,
too_longp,mailer_info, aview))
return TRUE;
/* the alias equivalence must just be a local address or
list of addresses */
address = break_down_address(alias_address,
/* If user pastes encoded words from
* somewhere decode them also.
*/
is_rfc1522(alias_address),
display_charset);
/* only one address -- take fullname from alias */
if (address[0].addr && address[0].fullname &&
!string_len(address[0].fullname) && !address[1].addr)
add_(buffer,address[0].addr,alias_fullname,alias_comment);
else {
struct addr_item *ptr1;
/* List of addresses */
for (ptr1 = address;
ptr1 && ptr1 -> addr && ptr1->fullname && ptr1->comment;
ptr1++) {
/* Max alias expansion limit? */
add_(buffer,ptr1->addr,ptr1->fullname,ptr1->comment);
}
if (address)
free_addr_items(address);
}
free_string(&alias_fullname);
free_string(&alias_comment);
return TRUE;
}
struct addr_item *get_alias_address_l (name, mailing, too_longp,mailer_info,
aview)
char *name; /* name to expand as an alias */
int mailing; /* TRUE to fully expand group names & recursive aliases */
int *too_longp; /* error code if expansion overflows buffer */
struct mailer_info *mailer_info;
struct AliasView *aview;
{
struct expand result;
struct addr_item *bufptr = NULL;
int dummy = 0; /* header_page */
result.addrs_len = 0;
result.addrs = NULL;
/*
* Reopens files iff changed since last read
*/
open_alias_files(aview, NULL);
/*
* If name is an alias then return its expansion
*/
if (do_get_alias_l(name,&result,mailing,FALSE,0,too_longp,
mailer_info, aview)) {
bufptr = result.addrs;
DPRINT(Debug,2,
(&Debug,
"get_alias_address_l(%s) expands %d addresses.\n",
name,result.addrs_len));
}
else {
/*
* Nope...not an alias (or it was too long to expand)
*/
DPRINT(Debug,2,
(&Debug,
"Could not expand alias in get_alias_address_l(%s)%s\n",
name, *too_longp ? "\t...alias buffer overflowed." : ""));
if (result.addrs)
free_addr_items(result.addrs);
bufptr = NULL;
}
return(bufptr);
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1