static char rcsid[] = "@(#)$Id: addr_util.c,v 1.50 2007/03/07 19:23:49 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.50 $ $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
*****************************************************************************/
/** This file contains addressing utilities
**/
#include "def_elm.h"
#include "s_elm.h"
#include "s_me.h"
DEBUG_VAR(Debug,__FILE__,"addr");
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
static char *us2s P_((unsigned char *str));
static char *us2s(str)
unsigned char *str;
{
return (char *)str;
}
int aliases_to_expanded(x,aview)
struct expanded_address *x;
struct AliasView *aview;
{
int i;
int tagged = 0;
int ac = get_alias_count(aview);
CONST int NEWPOS = x->addrs_len;
for (i=0; i < ac; i++) {
struct alias_rec *a = give_alias(aview,i);
if (a &&
ison(a->status, TAGGED)) {
struct string *s = new_string2(display_charset,
s2us(a->alias));
add_textual_addr_(x,s,NEWPOS,0);
tagged++;
free_string(&s);
}
}
if (tagged == 0) {
int alias_current = get_alias_current(aview);
struct alias_rec *a = give_alias(aview,alias_current-1);
if (a) {
struct string *s = new_string2(display_charset,
s2us(a->alias));
add_textual_addr_(x,s,NEWPOS,0);
free_string(&s);
}
}
return tagged;
}
int argv_to_expanded(result,argv,mailer_info,aview)
struct expanded_address *result;
char *argv[];
struct mailer_info *mailer_info;
struct AliasView *aview;
{
int i,res;
free_expanded_address(result);
DPRINT(Debug,6,
(&Debug, "argv_to_expanded:"));
for (i = 0; argv[i]; i++) {
DPRINT(Debug,6,
(&Debug, " [%d]=%s",i,argv[i]));
}
DPRINT(Debug,6,
(&Debug,"\n"));
for (i = 0; argv[i]; i++) {
/* Because this comes from argument vector,
we use system charset instead of display_charset
*/
struct string * s = new_string2(system_charset,
s2us(argv[i]));
add_textual_addr_(result,s,0,0);
free_string(&s);
}
dump_expanded_address(6,"argv_to_expanded: before build_address_l()",
*result);
/* And make address structures */
res = build_address_l(result,mailer_info,aview);
dump_expanded_address(6,"argv_to_expanded: (result)",*result);
DPRINT(Debug,6,
(&Debug, "argv_to_expanded=%d\n",res));
return res;
}
void addr_to_expanded(result,addrs,mailer_info,aview)
struct expanded_address *result;
struct addr_item *addrs;
struct mailer_info *mailer_info;
struct AliasView *aview;
{
int i;
free_expanded_address(result);
DPRINT(Debug,6,
(&Debug ,"addr_to_expanded:"));
if (!addrs) {
DPRINT(Debug,6,
(&Debug ," -- NULL"));
} else {
for (i = 0;
addrs[i].addr && addrs[i].fullname && addrs[i].comment; i++) {
CONST char *A, *B;
DPRINT(Debug,6,
(&Debug,
" [%d]: {addr=%s, fullname=%S, comment=%S}",
i,
addrs[i].addr, addrs[i].fullname,
addrs[i].comment));
A = get_string_MIME_name(addrs[i].fullname);
B = get_string_lang(addrs[i].fullname);
DPRINT(Debug,11,
(&Debug, " (fullname cs=%s lang=%s)",
A ? A : "<none>",
B ? B : "<none>"));
A = get_string_MIME_name(addrs[i].comment);
B = get_string_lang(addrs[i].comment);
DPRINT(Debug,11,
(&Debug, " (comment cs=%s lang=%s)",
A ? A : "<none>",
B ? B : "<none>"));
}
}
DPRINT(Debug,6,
(&Debug, "\n"));
for (i = 0;
addrs && addrs[i].addr && addrs[i].fullname && addrs[i].comment;
i++) {
int pos = add_expanded_addr_(result,addrs[i].addr,
addrs[i].fullname, addrs[i].comment);
add_textual_addr_(result,NULL,pos,1);
}
dump_expanded_address(7,"addr_to_expanded: before build_address_l()",
*result);
/* And make address structures */
build_address_l(result,mailer_info,aview);
dump_expanded_address(6,"addr_to_expanded: (result)",*result);
}
void expanded_to_edit_buffer(buffer,expanded)
struct string ** buffer;
struct expanded_address expanded;
{
struct textual *ptr;
buffer[0] = '\0';
if (*buffer)
free_string(buffer);
dump_expanded_address(6,"expanded_to_edit_buffer",expanded);
for (ptr = expanded.surface;
ptr < expanded.surface + expanded.surface_len;
ptr++) {
if (*buffer) {
struct string * temp;
add_ascii_to_string(*buffer,s2us(", "));
temp = cat_strings(*buffer,ptr->Textual,0);
free_string(buffer);
*buffer = temp;
} else
*buffer = dup_string(ptr->Textual);
}
if (!*buffer)
*buffer = new_string(display_charset);
DPRINT(Debug,6,
(&Debug, "expanded_to_edit_buffer: (result) buffer=%S\n",
*buffer));
}
void update_expanded_from_edit_buffer(expanded,buffer,mailer_info,aview)
struct expanded_address *expanded;
CONST struct string *buffer;
struct mailer_info *mailer_info;
struct AliasView *aview; /* NULL if aliases should be ignored */
{
int i,next;
struct expanded_address result;
struct textual *ptr = expanded->surface;
struct string_token * tokenized = string_tokenize(buffer, TOK_mail);
zero_expanded_address(&result);
DPRINT(Debug,6,
(&Debug, "update_expanded_from_edit_buffer: buffer=%S\n",
buffer));
dump_expanded_address(6,"update_expanded_from_edit_buffer: (initial)",
*expanded);
for (i = 0; tokenized[i].token; i = next) {
CONST int NEWPOS = result.addrs_len;
struct string * surface = NULL;
int q= 0, spacecount = 0, q_seen = 0;
int Tlen = string_len(tokenized[i].token);
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer: [%d]=\"%S\" %04x\n",
i,
tokenized[i].token,
tokenized[i].special));
if (0x0020 /* SPACE */ == tokenized[i].special ||
0x002C /* ',' */ == tokenized[i].special) {
next = i+1;
continue;
}
for (next = i; tokenized[next].token; next++) {
if (0x003C /* '<' */ == tokenized[next].special) {
q++;
q_seen = 1;
} else if (0x003E /* '>' */ == tokenized[next].special)
q--;
else if (!q && 0x002C /* ',' */ == tokenized[next].special)
break;
else if (!q && q_seen &&
0x0020 /* SPACE */ != tokenized[next].special &&
0x0028 /* '(' */ != tokenized[next].special)
break;
else if (!q && 0x0020 /* SPACE */ == tokenized[next].special &&
tokenized[next+1].token &&
0x0028 /* '(' */ == tokenized[next+1].special)
/* Don't count whitespaces before comments */ ;
else if (!q && q_seen &&
0x0020 /* SPACE */ == tokenized[i].special)
break;
else if (!q && 0x0020 /* SPACE */ == tokenized[next].special)
spacecount ++;
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer+ [%d]=\"%S\" %04x q=%d\n",
next,
tokenized[next].token,
tokenized[next].special,
q));
if (surface) {
struct string * tmp1 = cat_strings(surface,
tokenized[next].token,0);
free_string(&surface);
surface = tmp1;
} else {
surface = dup_string(tokenized[next].token);
}
}
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer- spacecount=%d, q=seen=%d\n",
spacecount,q_seen));
if (surface &&
ptr < expanded->surface + expanded->surface_len &&
0 == string_cmp(ptr->Textual,
surface,
-999 /* Unknow values are not equal */
)) {
int r;
int pos = NEWPOS;
int count = 0;
int j;
/* no change -- copy original */
for (j = 0; j < ptr->len; j++) {
CONST struct addr_item *ptr1 = & (expanded->addrs[ptr->pos+j]);
int p = ADD_EXPANDED(result,ptr1->addr,ptr1->fullname,
ptr1->comment);
if (0 == count)
pos = p;
count++;
}
r=ADD_TEXTUAL(result,ptr->Textual,pos,count);
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer-> [%d] = %S (keep %d addresses)\n",
r,surface,count));
}
/* Starting with - is alias expansion removing syntax */
else if (aview &&
Tlen > 0 &&
give_unicode_from_string(tokenized[i].token,
0) == 0x002D /* '-' */
) {
int r;
struct string * surface1 = NULL;
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer= resscan from %d\n",i));
for (next = i; tokenized[next].token; next++) {
if (0x003C /* '<' */ == tokenized[next].special ||
0x003E /* '>' */ == tokenized[next].special ||
0x002C /* ',' */ == tokenized[next].special ||
0x0020 /* SPACE */ == tokenized[next].special)
break;
DPRINT(Debug,9,
(&Debug,
"expanded_to_edit_buffer+ [%d]=\"%S\" %04x\n",
next,tokenized[next].token,tokenized[next].special));
if (surface1) {
struct string * tmp1 = cat_strings(surface1,
tokenized[next].token,
0);
free_string(&surface1);
surface1 = tmp1;
} else {
surface1 = dup_string(tokenized[next].token);
}
}
r=ADD_TEXTUAL(result,surface1,NEWPOS,0);
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer-> [%d] = %S\n",
r,surface1));
if (surface1)
free_string(&surface1);
/* word <address> */
} else if (spacecount <= 1 && q_seen) {
int r = ADD_TEXTUAL(result,surface,NEWPOS,0);
DPRINT(Debug,9,
(&Debug, "update_expanded_from_edit_buffer-> [%d] = %S\n",
r,surface));
} else {
struct string * surface1 = NULL;
int r;
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer= resscan from %d\n",i));
for (next = i; tokenized[next].token; next++) {
if (!q &&
0x0020 /* SPACE */ == tokenized[next].special &&
tokenized[next+1].token &&
0x0028 /* '(' */ == tokenized[next+1].special)
/* Don't break on whitespaces before comments */ ;
else if (0x003C /* '<' */ == tokenized[next].special ||
0x003E /* '>' */ == tokenized[next].special ||
0x002C /* ',' */ == tokenized[next].special ||
0x0020 /* SPACE */ == tokenized[next].special)
break;
DPRINT(Debug,9,
(&Debug,
"update_expanded_from_edit_buffer+ [%d]=\"%S\" %04x\n",
next,
tokenized[next].token,
tokenized[next].special));
if (surface1) {
struct string * tmp1 = cat_strings(surface1,
tokenized[next].token,
0);
free_string(&surface1);
surface1 = tmp1;
} else {
surface1 = dup_string(tokenized[next].token);
}
}
if (!surface1) {
DPRINT(Debug,9,
(&Debug, "update_expanded_from_edit_buffer-> parse failure\n"));
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmUnparseable,
"Unparseable (%S): %S"),
tokenized[next].token,buffer);
break;
}
r=ADD_TEXTUAL(result,surface1,NEWPOS,0);
DPRINT(Debug,9,
(&Debug, "update_expanded_from_edit_buffer-> [%d] = %S\n",
r,surface1));
if (surface1)
free_string(&surface1);
}
if (ptr < expanded->surface + expanded->surface_len)
ptr++;
if (i == next) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmUnparseable,
"Unparseable (%S): %S"),
tokenized[next].token,buffer);
next++;
}
if (surface)
free_string(&surface);
}
dump_expanded_address(6,"update_expanded_from_edit_buffer: before build_address_l",
result);
build_address_l(&result,mailer_info,aview);
free_expanded_address(expanded);
*expanded = result; /* put new (same?) result to place */
if (tokenized)
free_string_tokenized(&tokenized);
dump_expanded_address(6,"update_expanded_from_edit_buffer: (result)",
*expanded);
}
#ifdef I_NETDB
static int verify_mail_domain P_((char *domain));
static int verify_mail_domain(domain)
char *domain;
{
static char * last_verify_domain = NULL;
static int last_verify_result = -1;
time_t last_verify_time = 0;
int result = -1;
time_t now;
time(&now);
if (last_verify_time + 1000 > now &&
last_verify_domain &&
0 == istrcmp(last_verify_domain,domain))
result = last_verify_result;
if (-1 == result) {
struct hostent *he = NULL;
lib_transient(CATGETS(elm_msg_cat, MeSet,
MeLookingUp,
"Looking up %s ..."),
domain);
he = gethostbyname(domain);
if (!he) {
DPRINT(Debug,9,(&Debug,
"verify_mail_domain: %s: h_errno=%d\n",
domain,h_errno));
switch(h_errno) {
case HOST_NOT_FOUND:
result = 0;
break;
case NO_ADDRESS:
result = 1;
}
} else
result = 1;
if (result >= 0) {
last_verify_domain = strmcpy(last_verify_domain,domain);
last_verify_result = result;
last_verify_time = now;
if (result)
lib_transient(CATGETS(elm_msg_cat, MeSet,MeLookingUpOK,
"Looking up %s ... OK"),
domain);
else
lib_transient(CATGETS(elm_msg_cat, MeSet,MeLookingUpNotExists,
"Looking up %s ... Not exists"),
domain);
} else
lib_transient(CATGETS(elm_msg_cat, MeSet,
MeLookingUpFailed,
"Looking up %s ... Failed"),
domain);
}
return result;
}
#endif
int build_address_l(expanded,mailer_info,aview)
struct expanded_address *expanded;
struct mailer_info *mailer_info;
struct AliasView *aview; /* NULL id aliases should NOT be expanded */
{
struct textual *ptr;
int expands = 0;
struct expanded_address result;
int too_long = FALSE;
dump_expanded_address(9,"build_address_l",*expanded);
zero_expanded_address(&result);
for (ptr = expanded->surface;
ptr < expanded->surface + expanded->surface_len;
ptr++) {
CONST int NEWPOS = result.addrs_len;
struct addr_item * aliases;
struct addr_item verify_result;
enum mailer_errcode errcode = MAILER_NOT_AVAIL;
if (!ptr->Textual) {
if (ptr->len == 1) {
/* If we have no textual presentation we are converting
* from struct addrs
*/
struct string * temp =
make_surface_addr(expanded->addrs[ptr->pos]);
int pos = ADD_EXPANDED(result,
expanded->addrs[ptr->pos].addr,
expanded->addrs[ptr->pos].fullname,
expanded->addrs[ptr->pos].comment);
ADD_TEXTUAL(result,temp,pos,1);
free_string(&temp);
} else {
DPRINT(Debug,1,
(&Debug,
"build_address_l: SOFWARE ERROR: [%d]: textual=NULL, len=%d\n",
ptr - expanded->surface, ptr->len));
}
}
else {
charset_t utf8 = MIME_name_to_charset("UTF-8",0);
struct string * utf8_temp;
unsigned char * utf8_textual;
DPRINT(Debug,10,(&Debug,"build_address_l: processing %S\n",
ptr->Textual));
/* HACK: We use UTF-8 version of Textual .... */
if (!utf8)
panic("CHARSET PANIC",__FILE__,__LINE__,"build_address_l",
"UTF-8 not found",0);
utf8_temp = convert_string(utf8,ptr->Textual,0);
utf8_textual = stream_from_string(utf8_temp,0,NULL);
if (utf8_textual[0] == '-') {
/* Is also on result's remove list */
ADD_TEXTUAL(result,ptr->Textual,NEWPOS,0);
}
else if (qstrpbrk(us2s(utf8_textual),"!@: <>,()") != NULL) {
struct string * temp = NULL;
if (ptr->len == 1)
temp = make_surface_addr(expanded->addrs[ptr->pos]);
if (temp && 0 == string_cmp(temp,ptr->Textual,999)) {
/* no change -- preserve original address */
int pos;
DPRINT(Debug,10,(&Debug,"build_address_l: ... no change\n"));
pos = ADD_EXPANDED(result,
expanded->addrs[ptr->pos].addr,
expanded->addrs[ptr->pos].fullname,
expanded->addrs[ptr->pos].comment);
ADD_TEXTUAL(result,temp,pos,1);
} else {
/* generate addresses from textual 'surface'
presentation */
int pos = NEWPOS;
int count = 0;
struct addr_item * address =
break_down_address(us2s(utf8_textual),
/* If user pastes encoded words
from somewhere decode them also.
*/
is_rfc1522(us2s(utf8_textual)),
utf8);
struct addr_item *ptr1;
for (ptr1 = address;
ptr1 && ptr1 -> addr &&
ptr1->fullname && ptr1->comment;
ptr1++) {
charset_t utf7;
int p;
char * sep;
DPRINT(Debug,10,(&Debug,"build_address_l: ... got %s\n",
ptr1->addr));
sep = qstrpbrk(ptr1->addr,"!:@");
if (sep) {
DPRINT(Debug,9,
(&Debug,
"build_address_l: addr %s separator %c\n",
ptr1->addr,
*sep));
}
if (sep && '@' == *sep &&
sep > ptr1->addr) {
if (0 == istrcmp(sep+1,hostfullname) ||
0 == istrcmp(sep+1,hostname)) {
local_address_verify:
if (verify_local_address) {
DPRINT(Debug,9,(&Debug,
"build_address_l: verifying local address %s\n",
ptr1->addr));
if (mailer_info &&
verify_mailer_domaddr(mailer_info,
ptr1->addr,
&verify_result,
&errcode)) {
DPRINT(Debug,5,
(&Debug,
"Address %s verified -- really %s\n",
ptr1->addr,
verify_result.addr));
ptr1->addr = strmcpy(ptr1->addr,
verify_result.addr);
if (!ptr1->fullname) {
ptr1->fullname = verify_result.fullname;
verify_result.fullname = NULL;
} else if (verify_result.fullname)
free_string(&verify_result.fullname);
if (!ptr1->comment) {
ptr1->comment = verify_result.comment;
verify_result.comment = NULL;
} else if (verify_result.comment)
free_string(&verify_result.comment);
free(verify_result.addr);
verify_result.addr = NULL;
} else {
switch (errcode) {
case MAILER_NOT_AVAIL:
lib_error(CATGETS(elm_msg_cat,
ElmSet,
ElmVerifyNot1,
"Unable to verify mail address %s"),
ptr1->addr);
break;
case MAILER_NOT_EXIST:
lib_error(CATGETS(elm_msg_cat,
ElmSet, ElmVerifyBad1,
"Address %s is not e-mail address"),
ptr1->addr);
break;
}
}
}
} else {
#ifdef I_NETDB
if (verify_domain) {
int r;
DPRINT(Debug,9,
(&Debug,
"build_address_l: verifying domain %s\n",
sep+1));
r = verify_mail_domain(sep+1);
if (0 == r) {
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmDomainUnknown,
"Domain %s of address %S is unknown"),
sep+1,
ptr->Textual);
}
}
#endif
}
} else { /* Local address */
if (sep == NULL &&
mailer_info &&
query_mailer_info(mailer_info,MI_USE_DOMAIN)) {
DPRINT(Debug,10,(&Debug,
"build_address_l: Adding domain %s to address %s\n",
hostfullname, ptr1->addr));
ptr1->addr = strmcat(ptr1->addr,"@");
ptr1->addr = strmcat(ptr1->addr, hostfullname);
}
goto local_address_verify; /* HACK */
}
if (text_charset != utf8 &&
0 != (CS_mapping
& charset_properties(text_charset))) {
struct string * A, *B;
/* Convert strings to text_charset
so that utf-8 is not show on
MIME encoded words
*/
A = convert_string(text_charset,ptr1->fullname,1);
B = convert_string(text_charset,ptr1->comment,1);
p = ADD_EXPANDED(result,ptr1->addr,A, B);
free_string(&A);
free_string(&B);
} else if (convert_utf_header &&
(utf7 = MIME_name_to_charset("UTF-7",0)) &&
0 != (CS_mapping & charset_properties(utf7))) {
struct string * A, *B;
/* If we are using utf-8 as text charset convert it to utf-7 */
A = convert_string(utf7,ptr1->fullname,1);
B = convert_string(utf7,ptr1->comment,1);
p = ADD_EXPANDED(result,ptr1->addr,A, B);
free_string(&A);
free_string(&B);
} else
p = ADD_EXPANDED(result,ptr1->addr,
ptr1->fullname, ptr1->comment);
if (0 == count)
pos = p;
count++;
}
ADD_TEXTUAL(result,ptr->Textual,pos,count);
if (address)
free_addr_items(address);
}
if (temp)
free_string(&temp);
}
else if (aview &&
NULL != (aliases =
get_alias_address_l(us2s(utf8_textual), TRUE,
&too_long,mailer_info,
aview))) {
struct addr_item *ptr1;
int pos = NEWPOS;
int count = 0;
expands = 1;
for (ptr1 = aliases;
ptr1 && ptr1 -> addr && ptr1->fullname && ptr1->comment;
ptr1++) {
struct textual *ptr2;
int p;
/* scan words to be eleminated */
for (ptr2 = expanded->surface;
ptr2 < expanded->surface + expanded->surface_len;
ptr2++) {
if (ptr2 -> Textual) {
/* FIXME: This is very ineffective */
struct string * utf8_temp2 =
convert_string(utf8,ptr2->Textual,0);
unsigned char * utf8_textual2 =
stream_from_string(utf8_temp2,0,NULL);
if (utf8_textual2[0] == '-') {
if (0 == strcmp(ptr1->addr,
&(us2s(utf8_textual2)[1])))
break;
}
free_string(&utf8_temp2);
free(utf8_textual2);
}
}
if (ptr2 &&
ptr2 < expanded->surface + expanded->surface_len)
/* Is on eliminating list -- don't add */
continue;
p = ADD_EXPANDED(result,ptr1->addr,ptr1->fullname,
ptr1->comment);
if (0 == count)
pos = p;
count++;
}
ADD_TEXTUAL(result,ptr->Textual,pos,count);
if (aliases)
free_addr_items(aliases);
}
else if (too_long) {
DPRINT(Debug,2,
(&Debug, "Overflowed alias expansion for %S\n",
ptr->Textual));
continue; /* Don't process */
}
else if (mailer_info &&
verify_mailer_addr(mailer_info,us2s(utf8_textual),
&verify_result,
&errcode)) {
int pos;
DPRINT(Debug,5,
(&Debug,
"Address %S verified -- really %s\n",
ptr->Textual,verify_result.addr));
/* Preserve possible comment and fullname
*
* Use dup_string() to avoid shared pointer so
* there no need to make spacial case for free_string()
*/
if (ptr->len == 1 && ! verify_result.fullname)
verify_result.fullname =
dup_string(expanded->addrs[ptr->pos].fullname);
if (ptr->len == 1 && ! verify_result.comment)
verify_result.comment =
dup_string(expanded->addrs[ptr->pos].comment);
if (!verify_result.fullname)
verify_result.fullname = new_string(display_charset);
if (!verify_result.comment)
verify_result.comment = new_string(display_charset);
pos = ADD_EXPANDED(result,verify_result.addr,
verify_result.fullname,
verify_result.comment);
ADD_TEXTUAL(result,ptr->Textual,pos,1);
/* ADD_EXPANDED makes copy, so original need to be free'ed
* on above there is make duplicate from
* expanded->addrs[ptr->pos].{fullname,comment) so
* this can be free'ed safely
*/
free_string(&verify_result.fullname);
free_string(&verify_result.comment);
free(verify_result.addr); verify_result.addr = NULL;
}
else {
struct string * gecos = NULL;
struct string * comment = NULL;
int pos;
DPRINT(Debug,10,(&Debug,
"build_address_l: local address %S verify failed\n",
ptr->Textual));
if (verify_local_address) {
switch (errcode) {
case MAILER_NOT_AVAIL:
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmVerifyNot,
"Unable to verify mail address %S"),
ptr->Textual);
break;
case MAILER_NOT_EXIST:
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmVerifyBad,
"Address %S is not e-mail address or Elm's alias"),
ptr->Textual);
break;
}
}
/* Preserve possible comment
*
* Use dup_string() to avoid shared pointer so
* there no need to make spacial case for free_string()
*/
if (ptr->len == 1)
gecos = dup_string(expanded->addrs[ptr->pos].fullname);
if (ptr->len == 1)
comment = dup_string(expanded->addrs[ptr->pos].comment);
if (!gecos)
gecos = new_string(display_charset);
if (!comment)
comment = new_string(display_charset);
pos = ADD_EXPANDED(result,us2s(utf8_textual),gecos,comment);
if (mailer_info &&
query_mailer_info(mailer_info,MI_USE_DOMAIN)) {
result.addrs[pos].addr =
strmcat(result.addrs[pos].addr,"@");
result.addrs[pos].addr = strmcat(result.addrs[pos].addr,
hostfullname);
}
ADD_TEXTUAL(result,ptr->Textual,pos,1);
if (check_only)
lib_error(CATGETS(elm_msg_cat, ElmSet, ElmAliasUnknown,
"(alias \"%S\" is unknown)"),
ptr->Textual);
/* ADD_EXPANDED makes copy, so original need to be free'ed
* on above there is make duplicate from
* expanded->addrs[ptr->pos].{fullname,comment) so
* this can be free'ed safely
*/
free_string(&gecos);
free_string(&comment);
}
free_string(&utf8_temp);
free(utf8_textual);
}
}
free_expanded_address(expanded);
*expanded = result; /* put new (same?) result to place */
dump_expanded_address(9,"build_address_l: (result)",*expanded);
DPRINT(Debug,9,
(&Debug,"build_address_l=%d\n",expands));
return expands;
}
int check_8bit_addr(addr)
struct addr_item * addr;
{
struct addr_item *p;
for (p = addr; p && p->fullname && p->addr && p->comment; p++) {
if (!can_ascii_string(p->fullname))
return TRUE;
if (!can_ascii_string(p->comment))
return TRUE;
}
return FALSE;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1