/*
* Copyright (c) 2005 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: rfc2821parts.c,v 1.7 2007/11/14 06:03:08 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/ctype.h"
#include "sm/str.h"
#include "sm/mta.h"
#include "sm/rfc2821.h"
/*
** T2821_PARTS -- split address into parts: local, detail, domain
**
** Parameters:
** addr -- address
** delims -- list of delimiter (e.g., "+" or "-")
** observequotes -- observe quotes?
** local -- local part of address without detail (output)
** detail -- detail part of address, without delim (output)
** domain -- domain part of address (output)
**
** Returns:
** >0: position of delimiter
** 0: no delimiter found
** position can't be 0 due to <>
** <0: usual error code
**
** Note: quotes around a delimiter are not preserved by the
** the address parsing function unless the quotes are required.
** Hence something like <"a+b"@c.d> will be split if delim=='+'.
** however, <"a+b@x"@c.d> will not be split.
*/
sm_ret_T
t2821_parts(sm_a2821_T *addr, const uchar *delims, bool observequotes, sm_str_P local, sm_str_P detail, sm_str_P domain, uchar *pdelim)
{
sm_ret_T ret, res;
uint i;
sm_str_P str;
sm_a2821_T a_part;
sm_a2821_P pa_part;
SM_REQUIRE(addr != NULL);
/* how to allow for these? should check entire string! */
SM_REQUIRE(NULL == delims || *delims != (uchar) '"');
SM_REQUIRE(NULL == delims || *delims != (uchar) '\\');
str = NULL;
A2821_INIT_RP(&a_part, NULL);
pa_part = &a_part;
ret = t2821_extract_local(NULL, addr, T2821_ENDTOK, &pa_part);
if (sm_is_err(ret))
return ret;
str = sm_str_new(NULL, MAXADDRLEN, MAXADDRLEN + 2);
if (NULL == str) {
ret = sm_error_temp(SM_EM_ADDR, ENOMEM);
goto error;
}
ret = t2821_str(pa_part, str, 0);
if (sm_is_err(ret))
goto error;
a2821_free(&a_part);
/*
** Need an unquote function here?
** `<"a@z"@x.y>' should return `a@z' as localpart instead of `"a@z"'
** The logic here is broken?
** Check the sequence of finding delim and unquoting!
*/
if (observequotes)
ret = sm_str_fchrquoted(str, delims, &i);
else {
ret = sm_str_unquote(str);
ret = sm_str_fchr(str, delims, &i);
}
if (SM_SUCCESS == ret) {
ret = sm_str_splitidx(str, i, true, local, detail);
res = i;
if (pdelim != NULL)
*pdelim = sm_str_rd_elem(str, i);
}
else {
ret = sm_str_cat(local, str);
res = SM_SUCCESS;
}
if (sm_is_err(ret))
goto error;
if (observequotes) {
ret = sm_str_unquote(local);
if (sm_is_err(ret))
goto error;
}
if (domain != NULL) {
A2821_INIT_RP(&a_part, NULL);
pa_part = &a_part;
ret = t2821_extract_domain(NULL, addr, &pa_part);
if (sm_is_err(ret))
goto error;
ret = t2821_str(pa_part, domain, 0);
if (sm_is_err(ret))
goto error;
}
SM_STR_FREE(str);
a2821_free(&a_part);
return res;
error:
SM_STR_FREE(str);
a2821_free(&a_part);
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1