/*
 * Copyright (c) 2003, 2005, 2006 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: rfc2821local.c,v 1.6 2006/06/11 03:37:32 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/ctype.h"
#include "sm/rfc2821.h"
#include "sm/rfc2822.h"

/*
**  T2821_EXTRACT_LOCAL -- extract localpart from a valid address
**
**	Parameters:
**		rpool -- rpool
**		addr -- address
**		delim_type -- type of delimiter (e.g., '+' or T2821_ENDTOK)
**		plocal -- local part of address (output)
**
**	Returns:
**		usual error code
**
**	NOTE: delim_type doesn't work, because '+', '-', ...
**		are NOT delimiters right now.
**		What will break if those are made delimiters?
**		a@b-c.d would be parsed differently
**		Make them only delimiters in localpart? Context sensitive
**		scanning is probably a bad idea...
**		Moreover, it breaks syntax checks in the parser.
**		Summary: the local part should be treated only here...
**		Do we need a real scanner/parse for it? It might be
**		possible to "escape" delimiters, e.g., \+, even though
**		that's not allowed in RFC 2821, so a simple strchr()
**		doesn't work reliably.
*/

sm_ret_T
t2821_extract_local(sm_rpool_P rpool, sm_a2821_T *addr, int delim_type, sm_a2821_T **plocal)
{
	sm_t2821_P tok;
	sm_t2821_P t;
	sm_ret_T ret;

	SM_REQUIRE(addr != NULL);
	SM_REQUIRE(plocal != NULL);

	tok = A2821_FIRST(addr);
	if (tok->sm_t2821_type != T2821_LEFT)
		return sm_error_perm(SM_EM_ADDR, R2821_ERR_LEFT); /* XXX? */
	tok = T2821_NEXT(tok);
	if (tok == NULL || tok == A2821_END(addr)
	    || tok->sm_t2821_type == T2821_AT)
		return sm_error_perm(SM_EM_ADDR, R2821_ERR_LOCAL); /* XXX? */

	/*
	**  Copy localpart of address.
	**  Note: if there's only a localpart (allowed for <postmaster>)
	**  then it "stops" at T2821_RIGHT, not T2821_AT.
	*/

	while (tok != NULL && tok != A2821_END(addr)
	       && tok->sm_t2821_type != T2821_AT
	       && tok->sm_t2821_type != T2821_RIGHT
	       && tok->sm_t2821_type != delim_type)
	{
		ret = t2821_cp_token(rpool, tok, &t);
		if (sm_is_err(ret))
			goto error;
		tok = T2821_NEXT(tok);
		A2821_INSERT_TAIL(*plocal, t);
	}
	return SM_SUCCESS;

  error:
	/* remove unconnected token */
	if (t != NULL)
		t2821_free(rpool, t);

	/* should cleanup addr, need to remember old value, free new ones */
	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1