/*
* 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