/*
 * 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: verpify.c,v 1.3 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/misc.h"

/*
**  SM_VERPIFY -- convert sender address in to VERP format
**
**	Parameters:
**		mail_pa -- (MAIL) address
**		rcpt_pa -- RCPT address
**		delim1 -- first delimiter ('+')
**		delim2 -- second delimiter ('=')
**		verp_pa -- VERP address (output)
**
**	Returns:
**		usual error code
*/

sm_ret_T
sm_verpify(sm_str_P mail_pa, sm_str_P rcpt_pa, uchar delim1, uchar delim2, sm_str_P verp_pa)
{
	sm_ret_T ret;
	uint mail_at, rcpt_at, mail_len, rcpt_len;

	SM_REQUIRE(mail_pa != NULL);
	SM_REQUIRE(rcpt_pa != NULL);
	SM_REQUIRE(verp_pa != NULL);

	mail_len = sm_str_getlen(mail_pa);
	rcpt_len = sm_str_getlen(rcpt_pa);
	SM_REQUIRE(mail_len > 2);
	SM_REQUIRE(rcpt_len > 2);

	if ('\0' == delim1)
		delim1 = (uchar)'+';
	if ('\0' == delim2)
		delim2 = (uchar)'=';

	/*
	**  "assume" that the addresses are in the correct format,
	**  do not try to parse them.
	*/

	ret = sm_str_lchr(mail_pa, (const uchar *)"@", &mail_at);
	if (sm_is_err(ret))
		goto error;
	if (mail_at < 2 || mail_at + 1 >= mail_len)
		goto error;
	ret = sm_str_lchr(rcpt_pa, (const uchar *)"@", &rcpt_at);
	if (sm_is_err(ret))
		goto error;
	if (rcpt_at < 2 || rcpt_at + 1 >= rcpt_len)
		goto error;
	sm_str_clr(verp_pa);

	/*
	**  <lm@mail> <lr@rcpt> -> <lm+lr=rcpt@mail>
	**  "<lm"	0		- mail_at-1
	**  "lr"	1		- rcpt_at-1
	**  "rcpt"	rcpt_at+1	- rcpt_len-2
	**  "@mail>"	mail_at		- mail_len-1
	*/

	ret = sm_str_catpart(verp_pa, (const sm_rdstr_P) mail_pa, 0,
			mail_at - 1);
	if (sm_is_err(ret))
		goto error;
	ret = sm_str_put(verp_pa, delim1);
	if (sm_is_err(ret))
		goto error;
	ret = sm_str_catpart(verp_pa, (const sm_rdstr_P) rcpt_pa, 1,
			rcpt_at - 1);
	if (sm_is_err(ret))
		goto error;
	ret = sm_str_put(verp_pa, delim2);
	if (sm_is_err(ret))
		goto error;
	ret = sm_str_catpart(verp_pa, (const sm_rdstr_P) rcpt_pa, rcpt_at + 1,
			rcpt_len - 2);
	if (sm_is_err(ret))
		goto error;
	ret = sm_str_catpart(verp_pa, (const sm_rdstr_P) mail_pa, mail_at,
			mail_len - 1);
	if (sm_is_err(ret))
		goto error;
	return ret;

  error:
	if (sm_is_success(ret))
		ret = sm_err_perm(EINVAL);
	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1