|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 27869 (0x6cdd)
Types: TextFile
Names: »rfc822norm.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
└─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z«
└─⟦e5a54fb17⟧
└─⟦this⟧ »pp-5.0/Format/rfc822norm/rfc822norm.c«
/* rfc822norm: program to 822norm stdin to stdout */
# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Format/rfc822norm/RCS/rfc822norm.c,v 5.0 90/09/20 16:02:35 pp Exp Locker: pp $";
# endif
/*
* $Header: /cs/research/pp/hubris/pp-beta/Format/rfc822norm/RCS/rfc822norm.c,v 5.0 90/09/20 16:02:35 pp Exp Locker: pp $
*
* $Log: rfc822norm.c,v $
* Revision 5.0 90/09/20 16:02:35 pp
* rcsforce : 5.0 public release
*
*/
#include "util.h"
#include <isode/cmd_srch.h>
#include "ap.h"
#include "alias.h"
#include "chan.h"
#include "retcode.h"
#include "adr.h"
#define OPT_822 1
#define OPT_733 2
#define OPT_JNT 3
#define OPT_BIGEND 4
#define OPT_LITTLEEND 5
#define OPT_STRIPROUTES 6
#define OPT_STRIPDOMAIN 7
#define OPT_STRIPTRACE 8
#define OPT_JNTSENDER 9
#define OPT_FOLD 10
#define OPT_MSGID 11
#define OPT_PERCENT 12
#define OPT_HIDELOCAL 13
CMD_TABLE tbl_options [] = { /* rfc822norm commandline options */
"-822", OPT_822,
"-733", OPT_733,
"-jnt", OPT_JNT,
"-bigend", OPT_BIGEND,
"-littleend", OPT_LITTLEEND,
"-striproutes", OPT_STRIPROUTES,
"-stripdomain", OPT_STRIPDOMAIN,
"-striptrace", OPT_STRIPTRACE,
"-jntsender", OPT_JNTSENDER,
"-fold", OPT_FOLD,
"-msgid", OPT_MSGID,
"-percent", OPT_PERCENT,
"-hidelocal", OPT_HIDELOCAL,
0, -1
};
#define FLD_TO 1
#define FLD_CC 2
#define FLD_BCC 3
#define FLD_FROM 4
#define FLD_SENDER 5
#define FLD_REPLY_TO 6
#define FLD_RESENT_FROM 7
#define FLD_RESENT_SENDER 8
#define FLD_RESENT_TO 9
#define FLD_RESENT_CC 10
#define FLD_RESENT_BCC 11
#define FLD_RESENT_BY 12
#define FLD_REMAILED_FROM 13
#define FLD_REMAILED_TO 14
#define FLD_REMAILED_BY 15
#define FLD_REDISTRIBUTED_FROM 16
#define FLD_REDISTRIBUTED_TO 17
#define FLD_REDISTRIBUTED_BY 18
#define FLD_ORIG_SENDER 19
/* RFC 987 extensions */
#define FLD_RFC987 20
/* RFC 987 (88) extensions - proposed */
#define FLD_RFC987_88 21
CMD_TABLE tbl_fields [] = {/* address field names */
/* REAL RFC 822 */
"To", FLD_TO,
"CC", FLD_CC,
"bcc", FLD_BCC,
"From", FLD_FROM,
"Sender", FLD_SENDER,
"Reply-to", FLD_REPLY_TO,
"Resent-From", FLD_RESENT_FROM,
"Resent-Sender", FLD_RESENT_SENDER,
"Resent-To", FLD_RESENT_TO,
"Resent-Cc", FLD_RESENT_CC,
"Resent-Bcc", FLD_RESENT_BCC,
"Resent-By", FLD_RESENT_BY,
/* JNT stuff */
"Original-Sender", FLD_ORIG_SENDER,
/* RFC 733 & other misc stuff */
"Remailed-From", FLD_REMAILED_FROM,
"Remailed-To", FLD_REMAILED_TO,
"Remailed-By", FLD_REMAILED_BY,
"Redistributed-From", FLD_REDISTRIBUTED_FROM,
"Redistributed-To", FLD_REDISTRIBUTED_TO,
"Redistributed-By", FLD_REDISTRIBUTED_BY,
/* RFC 987 fields */
"P1-Recipient", FLD_RFC987,
/* RFC 987 (88) fields */
"X400-Originator", FLD_RFC987_88,
"X400-Recipients", FLD_RFC987_88,
"Notification-IPM-Originator", FLD_RFC987_88,
"Notification-Preferred-Recipients", FLD_RFC987_88,
"MTS-Originator", FLD_RFC987_88,
"MTS-Recipient", FLD_RFC987_88,
"Originally-Intended-Recipient", FLD_RFC987_88,
"Originator-Return-Address", FLD_RFC987_88,
"DL-Expansion-History", FLD_RFC987_88,
"Report-Reporting-DL-Name", FLD_RFC987_88,
"Report-Originator-and-DL-Expansion-History",
FLD_RFC987_88,
0, -1
};
#define FOLD_SPACE 0
#define FOLD_COMMA 1
#define FOLD_SEMICOLON 2
#define FOLD_RECIEVED 3
#define FOLD_NONE 4
CMD_TABLE tbl_nonfields [] = {/* feilds dont deal with */
"Received", FOLD_RECIEVED,
"X400-Received", FOLD_SEMICOLON,
"Via", FOLD_SEMICOLON,
"References", FOLD_COMMA,
"Keywords", FOLD_COMMA,
"X400-MTS-Identifier", FOLD_NONE,
"Message-ID", FOLD_NONE,
"In-Reply-To", FOLD_NONE,
"Obsoletes", FOLD_COMMA,
0, -1
};
CMD_TABLE tbl_tracefields [] = {/* fields viable for strip trace */
"Received", FOLD_RECIEVED,
"Via", FOLD_SEMICOLON,
"X400-Received", FOLD_SEMICOLON,
0, -1
};
typedef enum {maj_none, rfc822, rfc733, jnt} Major_options;
typedef enum {min_none, bigend, littleend} Minor_options;
extern void sys_init(), err_abrt();
static void norm_sender();
static int equalWithJntsender(), tidy_up();
static getitm(), out_adr();
static AP_ptr parse_and_norm();
char *myname;
int nadrs;
int pcol;
int nonempty;
int fold_width;
int order_pref;
int striptrace = FALSE,
striproutes = FALSE;
char **stripdomains = NULL;
char **hidedomains = NULL;
int num_domains = 0,
num_to_hide = 0,
message_id = 0,
msgid_req = FALSE;
char *jntsender = NULL,
*jntsendernorm = NULL;
AP_ptr jnttree, jntgroup, jntname, jntloc, jntdom, jntroute;
static int getach();
static int getbufchar();
static char *next_fold();
static char *fold_recieved();
static AP_ptr recur_stripdomain();
extern AP_ptr ap_pinit();
extern char *compress();
extern char *rcmd_srch();
extern int ap_outtype;
extern int ap_perlev;
extern char *loc_dom_site,
*loc_dom_mta;
extern char *calloc();
extern char *realloc();
char *rloc_dom_site,
*rloc_dom_mta;
static char *reverse();
#ifndef BSD42
#define random rand
#define srandom srand
#endif
#define DEFAULT_FOLD_WIDTH 79
/* ARGSUSED */
main(argc,argv)
int argc;
char **argv;
{
/* parse flags */
Major_options maj = maj_none;
Minor_options mino = min_none;
myname = *argv++;
sys_init(myname);
/* malloc_debug(2);*/
ap_outtype = AP_PARSE_SAME;
fold_width = DEFAULT_FOLD_WIDTH;
order_pref = CH_USA_PREF;
jntsendernorm = NULL;
jntsender = NULL;
message_id = 0;
msgid_req = FALSE;
srandom(getpid());
rloc_dom_site = reverse(loc_dom_site);
rloc_dom_mta = reverse(loc_dom_mta);
while (*argv != NULL) {
switch(cmd_srch(*argv,tbl_options)) {
case -1:
PP_LOG(LLOG_EXCEPTIONS,
("unknown option '%s'",*argv));
exit(1);
case OPT_MSGID:
msgid_req = TRUE;
break;
case OPT_PERCENT:
ap_use_percent();
ap_norm_all_domains();
break;
case OPT_FOLD:
if (*(argv+1) == NULL)
PP_LOG(LLOG_EXCEPTIONS,
("no fold width given with %s",*argv));
else {
++argv;
fold_width = atoi(*argv);
}
break;
case OPT_822:
if ((maj == maj_none) || (maj == rfc822)) {
ap_outtype |= AP_PARSE_822;
maj = rfc822;
}
break;
case OPT_733:
if ((maj == maj_none) || (maj == rfc733)) {
ap_outtype |= AP_PARSE_733;
maj = rfc733;
}
break;
case OPT_JNT:
if ((maj == maj_none || maj == jnt)
&& (mino == min_none || mino == bigend)) {
ap_outtype |= AP_PARSE_733;
maj = jnt;
ap_outtype |= AP_PARSE_BIG;
mino = bigend;
order_pref = CH_UK_PREF;
break;
}
PP_LOG(LLOG_EXCEPTIONS,
("multiple major parse options"));
exit(1);
case OPT_BIGEND:
if (mino == min_none || mino == bigend) {
ap_outtype |= AP_PARSE_BIG;
mino = bigend;
order_pref = CH_UK_PREF;
}
break;
case OPT_LITTLEEND:
if (mino == min_none || mino == littleend) {
mino = littleend;
break;
}
PP_LOG(LLOG_EXCEPTIONS,
("multiple minor parse options"));
exit(1);
case OPT_STRIPTRACE:
striptrace = TRUE;
break;
case OPT_STRIPROUTES:
striproutes = TRUE;
break;
case OPT_STRIPDOMAIN:
if (*(argv+1) == NULL)
PP_LOG(LLOG_EXCEPTIONS,
("no domain specified with %s", *argv));
else {
++argv;
if (num_domains == 0)
stripdomains = (char **) calloc(1,
(unsigned int) sizeof(char *));
else
stripdomains = (char **) realloc((char *) stripdomains,
(unsigned int) ((num_domains + 1) * sizeof(char *)));
stripdomains[num_domains++] = *argv;
}
break;
case OPT_JNTSENDER:
if (*(argv+1) == NULL)
PP_LOG(LLOG_EXCEPTIONS,
("no sender specified with %s", *argv));
else {
argv++;
jntsender = *argv;
}
break;
case OPT_HIDELOCAL:
if (*(argv+1) == NULL)
PP_LOG(LLOG_EXCEPTIONS,
("no domain specified with %s", *argv));
else {
++argv;
if (num_to_hide == 0)
hidedomains = (char **) calloc(1,
(unsigned int) sizeof(char *));
else
hidedomains = (char **) realloc((char *) hidedomains,
(unsigned int) ((num_to_hide + 1) * sizeof(char *)));
hidedomains[num_to_hide++] = *argv;
}
break;
default:
PP_LOG(LLOG_EXCEPTIONS,
("unknown option '%s'"));
exit(1);
}
argv++;
}
if (jntsender)
norm_sender();
/* ap_outtype set so now process */
if (proc() != OK)
err_abrt( RP_LIO, "couldn't reformat it");
free(rloc_dom_site);
free(rloc_dom_mta);
/* copy out rest of file */
exit(0);
}
/* \f
*/
static void norm_sender()
{
jnttree = ap_s2t(jntsender);
jnttree = parse_and_norm (jnttree, &jntgroup, &jntname,
&jntloc, &jntdom, &jntroute);
jntsendernorm = ap_p2s(jntgroup, jntname, jntloc, jntdom, jntroute);
}
static int equalWithJntsender(tree)
AP_ptr tree;
{
AP_ptr jix = tree, aix = jntloc;
while (jix != NULLAP &&
aix != NULLAP) {
if (jix -> ap_obtype == AP_COMMENT)
jix = jix -> ap_next;
else if (aix -> ap_obtype == AP_COMMENT)
aix = aix -> ap_next;
else if (strcmp(aix -> ap_obvalue, jix -> ap_obvalue) != 0)
return 0;
else {
aix = aix -> ap_next;
jix = jix -> ap_next;
}
}
while (jix != NULLAP && jix->ap_obvalue == NULLCP)
jix = jix -> ap_next;
while (aix != NULLAP && aix->ap_obvalue == NULLCP)
aix = aix -> ap_next;
if (aix == NULLAP && jix == NULLAP)
return 1;
return 0;
}
/* \f
*/
int noFrom, from;
/* 822norm stdin to stdout */
proc ()
{
int amp_fail;
int res;
int done;
register char *cp;
PP_TRACE(("outtype %o",ap_outtype));
noFrom = 1;
from = 0;
while ((getitm(&res) == OK) && (res == OK)) {
ap_clear();
nadrs = 0;
amp_fail = FALSE;
nonempty = FALSE;
done = FALSE;
if (ap_pinit(getbufchar) == BADAP) {
PP_LOG(LLOG_EXCEPTIONS,
("problem parsing message"));
return NOTOK;
}
while (done == FALSE) {
res = ap_1adr(); /* Parse one adr */
switch(res) {
case DONE: /* done */
done = TRUE;
break;
case NOTOK:
/* pass the garbage and generate warning */
amp_fail = TRUE;
break;
default: /* print it */
ap_ppush (getbufchar);
if ((res = out_adr(ap_pstrt)) != OK)
return res;
ap_ppop();
ap_pstrt = ap_pcur = ap_alloc ();
break;
}
}
putchar('\n');
if (ap_perlev) { /* if still nested */
PP_TRACE(("nested level %d",ap_perlev));
amp_fail++;
}
if (amp_fail == TRUE)
printf("PP_warning: Parse error in original version of preceding line\n");
}
if (message_id == 0 && msgid_req == TRUE) {
/* output message id */
MPDUid msgid;
char buf[BUFSIZ];
strcpy(buf, "Message-ID");
cp = &buf[0];
while (*cp != '\0')
putchar (*cp++);
putchar (':');
putchar (' ');
MPDUid_new(&msgid);
(void) sprintf(buf, "<\"%s\"@%s>",
msgid.mpduid_string, loc_dom_site);
cp = buf;
while (*cp != '\0')
putchar (*cp++);
putchar ('\n');
}
if (jntsendernorm != NULL && noFrom) {
/* output Sender */
cp = rcmd_srch(FLD_SENDER, tbl_fields);
while (*cp != '\0')
putchar(*cp++);
putchar(':');
putchar(' ');
cp = jntsendernorm;
while (*cp != '\0')
putchar(*cp++);
putchar('\n');
}
if (jntsendernorm != NULL) {
ap_sqdelete(jnttree, NULLAP);
free((char *)jnttree);
}
if (res == NOTOK)
return NOTOK;
tidy_up();
/* putchar('\n'); /* put blank line after header */
return (ferror(stdout) ? NOTOK : OK);
}
/* \f
*/
/* input routines */
static char *fieldbuf = NULL,
*contbuf = NULL;
static int fieldsize = 0,
contsize = 0;
static int fieldlen = 0,
contlen = 0;
static char *contix = NULL;
#define INC 2
/* returns current pointer = *orig + olength */
static char *resize_buf(orig, olength, size)
char **orig;
int olength,
*size;
{
*size += INC;
if (*orig == NULLCP)
*orig = calloc (1, (unsigned int) (*size));
else
*orig = realloc (*orig, (unsigned int) (*size));
return ((*orig)+olength);
}
/* returns OK while still got more input to read */
/* result == NOTOK if failed parsing */
static int getitm(result)
int *result;
{
register int c;
register char *cp,
*ix;
int gotitm = FALSE;
fieldlen = 0;
cp = fieldbuf;
*result = OK;
while (gotitm == FALSE) {
if ((c = getach()) == EOF)
/* end of file */
return NOTOK;
switch (c) {
case '\n':
if (fieldlen != 0)
break;
case '\0':
/* end of input */
return NOTOK;
}
/* putchar(c);*/
switch (c) {
case ':':
/* Field name collected */
if ((fieldlen+1) >= fieldsize)
cp = resize_buf(&fieldbuf,fieldlen,&fieldsize);
*cp = '\0';
PP_TRACE(("field '%s'",fieldbuf));
ix = fieldbuf;
if (isspace(*ix) && *ix != '\n') {
while (isspace(*ix) && *ix != '\n')
ix++;
/* rewind back one to first nonspace */
ix--;
}
/* got field now get contents */
cp = contbuf;
contlen = 0;
while (((c = getach()) != 0) && (c != EOF)) {
if (++contlen >= contsize)
cp = resize_buf(&contbuf,(contlen-1),&contsize);
*cp++ = c;
}
/* terminate with a null char */
if ((contlen + 1) >= contsize)
cp = resize_buf(&contbuf,contlen,&contsize);
*cp ='\0';
compress(fieldbuf, fieldbuf);
compress(contbuf, contbuf);
contix = contbuf;
/* check if need to skip */
if ((striptrace == TRUE)
&& (cmd_srch(fieldbuf, tbl_tracefields) != -1)) {
/* skip it */
cp = fieldbuf;
fieldlen = 0;
break;
}
if (cmd_srch(fieldbuf, tbl_fields) == FLD_FROM)
from = 1;
else
from = 0;
if (jntsender != NULL
&& (cmd_srch(fieldbuf, tbl_fields) == FLD_SENDER))
/* convert to Original-Sender */
cp = rcmd_srch(FLD_ORIG_SENDER, tbl_fields);
else
cp = fieldbuf;
pcol = strlen(cp)+2;
while (*cp != '\0')
putchar(*cp++);
putchar(':');
/* put in jpo's space */
putchar(' ');
if (cmd_srch(ix,tbl_fields) != -1) {
gotitm = TRUE;
} else {
int fold_num;
/* copy rest of line out */
nonempty = FALSE;
pcol = strlen(fieldbuf) + 1;
cp = contix;
if (lexequ(fieldbuf, "Message-ID") == 0)
message_id++;
if ((fold_num = cmd_srch(fieldbuf,tbl_nonfields)) == -1) {
PP_DBG(("unknown non field %s folding on spaces",fieldbuf));
fold_num = FOLD_SPACE;
}
while (*contix != '\0') {
/* go to next fold */
cp = next_fold(contix+1,fold_num);
if ((fold_width != -1)
&& (cp - contix + pcol > fold_width)
&& nonempty) {
/* new line */
pcol = strlen(fieldbuf) + 2;
printf("\n%*s", strlen(fieldbuf) + 2, "");
/* strip out white space */
while (isspace(*contix))
contix++;
} else
nonempty = TRUE;
pcol += cp - contix;
/* output line */
while (contix != cp)
putchar(*contix++);
}
putchar('\n');
if (c == EOF)
/* EOF */
return NOTOK;
}
cp = fieldbuf;
fieldlen = 0;
break;
default:
if (++fieldlen >= fieldsize)
cp = resize_buf(&fieldbuf,(fieldlen-1),&fieldsize);
*cp++ = c;
}
}
return OK;
}
static int isblank(ch)
char ch;
{
return (ch == ' ' || ch == '\t');
}
/* returns 0 when reach end of an item */
/* returns EOF when reach EOF */
static int getach()
{
static char buf[FILNSIZE];
static char *bufp = buf;
static int noInput = 0;
if (noInput == 0) { /* buffer is empty */
noInput = read(0, buf, FILNSIZE);
bufp = buf;
}
if (*bufp == '\n') {
if (noInput == 1) {
/* last char in buffer */
noInput = read(0, buf, FILNSIZE);
bufp = buf;
if (isblank(*bufp)) {
noInput--;
return *bufp++;
} else
return 0;
} else if (isblank(*(bufp+1))) {
/* skip newline */
bufp++;
noInput--;
}
}
if (*bufp == '\n') {
bufp++;
noInput--;
return 0;
}
return ((--noInput >= 0) ? *bufp++ : EOF);
}
static int getbufchar()
{
char ret = *contix;
if (ret != 0) contix++;
return (ret == 0) ? EOF : ret;
}
/* \f
*/
/* output routine */
static char *next_fold(ix,fold)
char *ix;
int fold;
{
char fold_ch;
switch (fold) {
case FOLD_NONE:
fold_ch = '\0';
break;
case FOLD_SPACE:
fold_ch = ' ';
break;
case FOLD_COMMA:
fold_ch = ',';
break;
case FOLD_SEMICOLON:
fold_ch = ';';
break;
case FOLD_RECIEVED:
return fold_recieved(ix);
break;
default:
PP_LOG(LLOG_EXCEPTIONS,
("unknown fold number %d",fold));
fold_ch = ' ';
}
while (*ix != '\0' && *ix != fold_ch)
ix++;
if (*ix == '\0')
return ix;
else
return ++ix;
}
static char *fold_recieved(chs)
char *chs;
{
char *ix;
while (*chs != '\0' && *chs != ';' && *chs != ' ')
chs++;
if (*chs == '\0')
return chs;
if (*chs == ';')
return ++chs;
/* skip leading spaces */
while (isspace(*chs))
chs++;
/* now check if have key words */
ix = chs;
while (*ix != '\0' &&
(ix - chs <= strlen("from")+1)) {
if (ix - chs == 3) {
if (strncmp(chs,"by ",3) == 0)
return chs;
else if (strncmp(chs,"id ",3) == 0)
return chs;
}
if (ix - chs == 4) {
if (strncmp(chs,"via ",4) == 0)
return chs;
else if (strncmp(chs,"for ",4) == 0)
return chs;
}
if (ix - chs == 5) {
if (strncmp(chs,"from ",5) == 0)
return chs;
else if (strncmp(chs, "with ", 5) == 0)
return chs;
}
ix++;
}
if (*ix == '\0')
return ix;
return fold_recieved(chs);
}
static int specifiedDomain(ptr)
AP_ptr ptr;
{
int specified = FALSE,
i = 0;
/* get to next domain */
while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN))
ptr = ptr->ap_next;
if (ptr == NULL)
return FALSE;
while (specified != TRUE && i < num_domains) {
if ((ptr->ap_obvalue != NULL)
&& (strcmp(stripdomains[i], ptr->ap_obvalue) == 0))
specified = TRUE;
i++;
}
return specified;
}
static int hiddenDomain(ptr)
AP_ptr ptr;
{
int hidden = FALSE,
i, nwild, nw;
char *bp, *cp;
/* get to next domain */
while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN))
ptr = ptr->ap_next;
if (ptr == NULL)
return 0;
if (ptr->ap_obvalue != NULL)
for (i = 0; hidden != TRUE && i < num_to_hide; i++) {
for (nwild = 0; hidedomains[i][nwild] == '.' ||
hidedomains[i][nwild] == '*'; nwild ++)
;
nw = nwild;
nwild /= 2;
bp = cp = ptr->ap_obvalue;
if ( ! hidedomains[i][nw] ) {
PP_LOG (LLOG_EXCEPTIONS,
("Format/rfc822norm/hiddenDomain: Too wild - Reality error"));
continue;
}
while ( (nwild -- > 0) && (bp = index(bp, '.')) != NULL)
bp ++;
if ( !bp )
continue;
while ((bp = index(bp,'.')) != NULL) {
if (++bp =='\0')
break;
cp = index(cp,'.');
cp++;
if ((strcmp(&hidedomains[i][nw], bp) == 0)) {
hidden = TRUE;
strcpy(ptr->ap_obvalue, cp);
break;
}
}
}
return hidden;
}
static int recognisedDomain(ptr)
AP_ptr ptr;
{
char official[LINESIZE], *subdom = NULLCP;
while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN))
ptr = ptr->ap_next;
if ((ptr != NULL)
&& (tb_getdomain(ptr->ap_obvalue, NULLCP,
official, order_pref, &subdom) == OK)) {
if (subdom != NULL) free(subdom);
return TRUE;
}else {
if (subdom != NULL) free(subdom);
return FALSE;
}
}
static int endOfRoute(ptr, group_ptr, name_ptr, loc_ptr, dom_ptr)
AP_ptr ptr,
group_ptr,
name_ptr,
loc_ptr,
dom_ptr;
{
if ((ptr == group_ptr) || (ptr == name_ptr)
|| (ptr == loc_ptr) || (ptr == dom_ptr))
return TRUE;
else
return FALSE;
}
static AP_ptr recur_stripdomain(ptr, group_ptr, name_ptr, loc_ptr, dom_ptr)
AP_ptr ptr,
group_ptr,
name_ptr,
loc_ptr,
dom_ptr;
{
if (ptr == NULL)
return NULL;
if (endOfRoute(ptr->ap_next, group_ptr, name_ptr,
loc_ptr, dom_ptr) == TRUE) {
if ((specifiedDomain(ptr) == TRUE)
&& (specifiedDomain(dom_ptr) == TRUE
|| recognisedDomain(dom_ptr) == TRUE))
return ptr->ap_next;
else
return ptr;
}
if ((specifiedDomain(ptr) == TRUE)
&& (specifiedDomain(ptr->ap_next) == TRUE
|| recognisedDomain(ptr->ap_next) == TRUE))
return recur_stripdomain(ptr->ap_next, group_ptr, name_ptr,
loc_ptr, dom_ptr);
else {
ptr->ap_next = recur_stripdomain(ptr->ap_next, group_ptr,
name_ptr, loc_ptr, dom_ptr);
return ptr;
}
}
static char *do_stripdomains(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr)
AP_ptr group_ptr,
name_ptr,
loc_ptr,
dom_ptr,
route_ptr;
{
char *retval;
AP_ptr ptr;
int cont = TRUE;
if (route_ptr == NULL)
retval = ap_p2s(group_ptr, name_ptr, loc_ptr,
dom_ptr, (AP_ptr) NULL);
else {
/* route ptr is least significant domain */
ptr = route_ptr;
while ((endOfRoute(ptr->ap_next, group_ptr, name_ptr,
loc_ptr, dom_ptr) == FALSE)
&& (cont == TRUE)) {
cont = FALSE;
if ((specifiedDomain(ptr) == TRUE)
&& (specifiedDomain(ptr->ap_next) == TRUE
|| recognisedDomain(ptr->ap_next) == TRUE)) {
cont = TRUE;
ptr = ptr->ap_next;
}
}
if (cont == TRUE) {
/* must have reached end of route */
/* check with dom_ptr */
if ((specifiedDomain(ptr) == TRUE)
&& (specifiedDomain(dom_ptr) == TRUE
|| recognisedDomain(dom_ptr) == TRUE))
/* strip all routes */
ptr = NULL;
}
retval = ap_p2s(group_ptr, name_ptr, loc_ptr,
dom_ptr, ptr);
}
return retval;
}
static char *do_striproutes(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr)
AP_ptr group_ptr,
name_ptr,
loc_ptr,
dom_ptr,
route_ptr;
{
char *retval;
AP_ptr ix_ptr,
strip_start;
if ((recognisedDomain(dom_ptr) == TRUE)
|| (route_ptr == NULL))
retval = ap_p2s(group_ptr, name_ptr, loc_ptr,
dom_ptr, (AP_ptr) NULL);
else {
ix_ptr = route_ptr;
while ((ix_ptr->ap_next != NULL)
&& (recognisedDomain(ix_ptr) != TRUE))
ix_ptr = ix_ptr->ap_next;
strip_start = ix_ptr->ap_next;
ix_ptr->ap_next = NULL;
retval = ap_p2s(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr);
ix_ptr->ap_next = strip_start;
}
return retval;
}
static
do_hidedomains(dom_ptr, route_ptr)
AP_ptr dom_ptr,
route_ptr;
{
int retval = 0;
AP_ptr ptr;
if ( ptr = route_ptr )
while ( ptr ) {
retval += hiddenDomain(ptr);
ptr = ptr->ap_next;
}
return retval += hiddenDomain(dom_ptr);
}
static int tidy_up()
{
if (random() % 10000 != 42)
return;
/* lucky person gets a message */
switch (random() % 3) {
case 0:
printf ("Checked-by: NSA, MI5, CIA, KGB\n");
break;
case 1:
printf ("Green-Message: This message is stored on recycled memory\n");
break;
default:
printf ("Congratulations: You are the recipient of our %d message\n", random() % 1000000);
break;
}
}
static AP_ptr parse_and_norm(ap, pgroup, pname, ploc, pdom, proute)
AP_ptr ap,
*pgroup,
*pname,
*ploc,
*pdom,
*proute;
{
char *str, *oldlocal, *newlocal;
AP_ptr group, name, loc, dom, route;
AP_ptr newtree, newgroup, newname, newloc, newdom, newroute;
ADDR *adr;
RP_Buf rp;
int oldap_outtype;
ap = ap_normalize(ap, order_pref);
(void) ap_t2p (ap, &group, &name, &loc, &dom, &route);
oldap_outtype = ap_outtype;
ap_outtype = AP_PARSE_822;
str = ap_p2s_nc (group, name, loc, dom, route);
adr = adr_new (str, AD_822_TYPE, 0);
adr -> ad_resp = NO;
if (!rp_isbad(ad_parse(adr, &rp, order_pref))) {
/* may have to munge */
ap_s2p(adr->ad_r822adr, &newtree, &newgroup,
&newname, &newloc, &newdom, &newroute);
oldlocal = ap_p2s_nc(NULLAP, NULLAP, loc, NULLAP, NULLAP);
newlocal = ap_p2s_nc(NULLAP, NULLAP, newloc, NULLAP, NULLAP);
if (lexequ(oldlocal, newlocal) != 0) {
AP_ptr hdr, ix, tmp;
AP_ptr firstdom = NULLAP, firstloc = NULLAP;
/* oh oh munge address */
/* add header */
hdr = ap_new(AP_COMMENT, "header");
hdr -> ap_next = ap;
hdr -> ap_ptrtype = AP_PTR_MORE;
ix = hdr;
/* delete everything except comments from old tree */
while (ix -> ap_next != NULLAP) {
switch (ix -> ap_next -> ap_obtype) {
case AP_DOMAIN:
case AP_DOMAIN_LITERAL:
if (firstloc != NULLAP
&& firstdom == NULLAP)
firstdom = ix;
ap_delete(ix);
break;
case AP_MAILBOX:
case AP_GENERIC_WORD:
if (firstloc == NULLAP)
firstloc = ix;
ap_delete(ix);
break;
default:
case AP_COMMENT:
ix = ix -> ap_next;
break;
}
}
/* now splice new tree into old tree */
for (ix = newdom; ix -> ap_next != NULLAP;
ix = ix -> ap_next);
/* put newdom -> ix in after firstdom */
tmp = firstdom -> ap_next;
firstdom -> ap_next = newdom;
ix -> ap_next = tmp;
for (ix = newloc; ix -> ap_next != NULLAP
&& ix -> ap_next != newdom
&& ix -> ap_next != newroute;
ix = ix -> ap_next);
/* put newloc -> ix in after firstloc */
tmp = firstloc -> ap_next;
firstloc -> ap_next = newloc;
ix -> ap_next = tmp;
ap = hdr -> ap_next;
ap_free(hdr);
/* reset parts */
(void) ap_t2p (ap, &group, &name, &loc, &dom, &route);
} else
ap_sqdelete (newtree, NULLAP);
free (oldlocal);
free (newlocal);
adr_free(adr);
}
ap_outtype = oldap_outtype;
*pgroup = group,
*pname = name;
*ploc = loc;
*pdom = dom;
*proute = route;
return ap;
}
static char *re_parse_ptr;
static int get_rp_char()
{
char ret = *re_parse_ptr;
if (ret != 0) re_parse_ptr++;
return (ret == 0) ? EOF : ret;
}
static int out_adr(ap)
register AP_ptr ap;
{
AP_ptr loc_ptr, /* -- in case fake personal name needed -- */
group_ptr,
name_ptr,
dom_ptr,
route_ptr;
char *addrp;
int len;
static rd = 0;
if (ap->ap_obtype == AP_NIL)
return OK;
rd++;
ap = parse_and_norm(ap, &group_ptr, &name_ptr,
&loc_ptr, &dom_ptr, &route_ptr);
if (from && equalWithJntsender(loc_ptr))
noFrom = 0;
/* do all stripping then create addrp */
if (rd < 3 && (dom_ptr != NULL)
&& (num_to_hide != 0)
&& do_hidedomains(dom_ptr, route_ptr)) {
/* This might be local now, so go through the whole expansion
* process again. Remember though that we might be exremely
* silly, and cause `infinite' recursion. Hence the rd variable.
*/
re_parse_ptr = addrp = ap_p2s(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr);
ap_sqdelete (ap, NULLAP);
ap_free (ap);
ap = ap_pstrt = ap_pcur = ap_alloc ();
ap_ppush(get_rp_char);
ap_clear();
if (ap_1adr() == OK)
out_adr(ap);
ap_ppop();
free(addrp);
rd--;
return OK;
/* NOTREACHED */
}
if ((dom_ptr != NULL)
&& (striproutes == TRUE))
addrp = do_striproutes(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr);
else if ((dom_ptr != NULL)
&& (num_domains != 0))
addrp = do_stripdomains(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr);
else
addrp = ap_p2s(group_ptr, name_ptr, loc_ptr,
dom_ptr, route_ptr);
if (addrp == (char *)NOTOK) {
PP_LOG (LLOG_EXCEPTIONS,
("Lib/addr/ap_t2s: error from ap_p2s()"));
addrp = strdup ("(PP Error!)");
}
if (rd == 3) {
PP_LOG (LLOG_EXCEPTIONS,
("Format/rfc822norm: Excessive local hiding - cannot resolve address"));
free(addrp);
addrp = strdup ("(PP Configuration Error!)");
}
if (nadrs != 0) {
printf(", ");
pcol += 2;
}
PP_TRACE(("output '%s'",addrp));
if ((len = strlen(addrp)) > 0) { /* print */
pcol += len;
if (fold_width != -1 && pcol > fold_width && nonempty) {
pcol = strlen(fieldbuf) + 2 + len;
printf("\n%*s", strlen(fieldbuf) + 2, "");
} else
nonempty = TRUE;
printf("%s",addrp);
nadrs++;
}
free(addrp);
/* ap_sqdelete (ap, NULLAP);
ap_free (ap);*/
rd--;
return OK;
}
/* \f
*/
static char *reverse(str)
char *str;
{
char *ret = malloc((unsigned) strlen(str)+1),
*dup = strdup(str),
*ix;
ret[0] = '\0';
while ((ix = rindex(dup,'.')) != NULL) {
if (ret[0] == '\0')
sprintf(ret, "%s", ix+1);
else
sprintf(ret,"%s.%s",ret,ix+1);
*ix = '\0';
}
if (ret[0] == '\0')
sprintf(ret, "%s", dup);
else
sprintf(ret,"%s.%s",ret,dup);
free(dup);
return ret;
}