/*++
/* NAME
/*	strip_addr 3
/* SUMMARY
/*	strip extension from full or localpart-only address
/* SYNOPSIS
/*	#include <strip_addr.h>
/*
/*	char	*strip_addr_internal(address, extension, delimiter_set)
/*	const char *address;
/*	char	**extension;
/*	const char *delimiter_set;
/* LEGACY SUPPORT
/*	char	*strip_addr(address, extension, delimiter_set)
/*	const char *address;
/*	char	**extension;
/*	const char *delimiter_set;
/* DESCRIPTION
/*	strip_addr*() takes an address and either returns a null
/*	pointer when the address contains no address extension,
/*	or returns a copy of the address without address extension.
/*	The caller is expected to pass the copy to myfree().
/*
/*	With strip_addr_internal(), the input and result are in
/*	internal form.
/*
/*	strip_addr() is a backwards-compatible form for legacy code.
/*
/*	Arguments:
/* .IP address
/*	Address localpart or user@domain form.
/* .IP extension
/*	A null pointer, or the address of a pointer that is set to
/*	the address of a dynamic memory copy of the address extension
/*	that had to be chopped off.
/*	The copy includes the recipient address delimiter.
/*	The caller is expected to pass the copy to myfree().
/* .IP delimiter_set
/*	Set of recipient address delimiter characters.
/* SEE ALSO
/*	split_addr(3) strip extension from localpart
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*
/*	Wietse Venema
/*	Google, Inc.
/*	111 8th Avenue
/*	New York, NY 10011, USA
/*--*/

/* System library. */

#include <sys_defs.h>
#include <string.h>

/* Utility library. */

#include <mymalloc.h>

/* Global library. */

#include <split_addr.h>
#include <strip_addr.h>

/* strip_addr - strip extension from address */

char   *strip_addr_internal(const char *full, char **extension,
			            const char *delimiter_set)
{
    char   *ratsign;
    char   *extent;
    char   *saved_ext;
    char   *stripped;

    /*
     * A quick test to eliminate inputs without delimiter anywhere.
     */
    if (*delimiter_set == 0 || full[strcspn(full, delimiter_set)] == 0) {
	stripped = saved_ext = 0;
    } else {
	stripped = mystrdup(full);
	if ((ratsign = strrchr(stripped, '@')) != 0)
	    *ratsign = 0;
	if ((extent = split_addr(stripped, delimiter_set)) != 0) {
	    extent -= 1;
	    if (extension) {
		*extent = full[strlen(stripped)];
		saved_ext = mystrdup(extent);
		*extent = 0;
	    } else
		saved_ext = 0;
	    if (ratsign != 0) {
		*ratsign = '@';
		memmove(extent, ratsign, strlen(ratsign) + 1);
	    }
	} else {
	    myfree(stripped);
	    stripped = saved_ext = 0;
	}
    }
    if (extension)
	*extension = saved_ext;
    return (stripped);
}

#ifdef TEST

#include <msg.h>
#include <mail_params.h>

char   *var_double_bounce_sender = DEF_DOUBLE_BOUNCE;

int     main(int unused_argc, char **unused_argv)
{
    char   *extension;
    char   *stripped;
    char   *delim = "+-";

#define NO_DELIM	""

    /*
     * Incredible. This function takes only three arguments, and the tests
     * already take more lines of code than the code being tested.
     */
    stripped = strip_addr_internal("foo", (char **) 0, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 1");

    stripped = strip_addr_internal("foo", &extension, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 2");
    if (extension != 0)
	msg_panic("strip_addr botch 3");

    stripped = strip_addr_internal("foo", (char **) 0, delim);
    if (stripped != 0)
	msg_panic("strip_addr botch 4");

    stripped = strip_addr_internal("foo", &extension, delim);
    if (stripped != 0)
	msg_panic("strip_addr botch 5");
    if (extension != 0)
	msg_panic("strip_addr botch 6");

    stripped = strip_addr_internal("foo@bar", (char **) 0, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 7");

    stripped = strip_addr_internal("foo@bar", &extension, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 8");
    if (extension != 0)
	msg_panic("strip_addr botch 9");

    stripped = strip_addr_internal("foo@bar", (char **) 0, delim);
    if (stripped != 0)
	msg_panic("strip_addr botch 10");

    stripped = strip_addr_internal("foo@bar", &extension, delim);
    if (stripped != 0)
	msg_panic("strip_addr botch 11");
    if (extension != 0)
	msg_panic("strip_addr botch 12");

    stripped = strip_addr_internal("foo-ext", (char **) 0, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 13");

    stripped = strip_addr_internal("foo-ext", &extension, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 14");
    if (extension != 0)
	msg_panic("strip_addr botch 15");

    stripped = strip_addr_internal("foo-ext", (char **) 0, delim);
    if (stripped == 0)
	msg_panic("strip_addr botch 16");
    msg_info("wanted:    foo-ext -> %s", "foo");
    msg_info("strip_addr foo-ext -> %s", stripped);
    myfree(stripped);

    stripped = strip_addr_internal("foo-ext", &extension, delim);
    if (stripped == 0)
	msg_panic("strip_addr botch 17");
    if (extension == 0)
	msg_panic("strip_addr botch 18");
    msg_info("wanted:    foo-ext -> %s %s", "foo", "-ext");
    msg_info("strip_addr foo-ext -> %s %s", stripped, extension);
    myfree(stripped);
    myfree(extension);

    stripped = strip_addr_internal("foo-ext@bar", (char **) 0, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 19");

    stripped = strip_addr_internal("foo-ext@bar", &extension, NO_DELIM);
    if (stripped != 0)
	msg_panic("strip_addr botch 20");
    if (extension != 0)
	msg_panic("strip_addr botch 21");

    stripped = strip_addr_internal("foo-ext@bar", (char **) 0, delim);
    if (stripped == 0)
	msg_panic("strip_addr botch 22");
    msg_info("wanted:    foo-ext@bar -> %s", "foo@bar");
    msg_info("strip_addr foo-ext@bar -> %s", stripped);
    myfree(stripped);

    stripped = strip_addr_internal("foo-ext@bar", &extension, delim);
    if (stripped == 0)
	msg_panic("strip_addr botch 23");
    if (extension == 0)
	msg_panic("strip_addr botch 24");
    msg_info("wanted:    foo-ext@bar -> %s %s", "foo@bar", "-ext");
    msg_info("strip_addr foo-ext@bar -> %s %s", stripped, extension);
    myfree(stripped);
    myfree(extension);

    stripped = strip_addr_internal("foo+ext@bar", &extension, delim);
    if (stripped == 0)
	msg_panic("strip_addr botch 25");
    if (extension == 0)
	msg_panic("strip_addr botch 26");
    msg_info("wanted:    foo+ext@bar -> %s %s", "foo@bar", "+ext");
    msg_info("strip_addr foo+ext@bar -> %s %s", stripped, extension);
    myfree(stripped);
    myfree(extension);

    stripped = strip_addr_internal("foo bar+ext", &extension, delim);
    if (stripped == 0)
	msg_panic("strip_addr botch 27");
    if (extension == 0)
	msg_panic("strip_addr botch 28");
    msg_info("wanted:    foo bar+ext -> %s %s", "foo bar", "+ext");
    msg_info("strip_addr foo bar+ext -> %s %s", stripped, extension);
    myfree(stripped);
    myfree(extension);

    return (0);
}

#endif
