/*
 * Copyright (c) 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: pmilter_rcptmod.c,v 1.5 2006/10/05 04:27:38 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "pmilter.h"
#include "sm/pmfdef.h"
#include "sm/pmfapi.h"
#include "sm/pmilter.h"

#if MTA_USE_PMILTER

/*
**  PM_RCPTS_NEW -- add a new recipient to the recipient list
**
**	Parameters:
**		pmse_ctx -- SMTP server transaction context
**		rcpt_pa -- recipient (printable address, RFC 2821)
**		len -- len of rcpt_pa
**		ppm_rcpt -- (pointer to) new recipient (output)
**
**	Returns:
**		usual return code
*/

static sm_ret_T
pm_rcpt_add(pmse_ctx_P pmse_ctx, const char *rcpt_pa, uint len, rcpt_idx_T rcpt_idx, pm_rcpt_P *ppm_rcpt)
{
	pm_rcpt_P pm_rcpt;

	SM_REQUIRE(ppm_rcpt != NULL);
	pm_rcpt = (pm_rcpt_P) sm_zalloc(sizeof(*pm_rcpt));
	if (NULL == pm_rcpt)
		return sm_err_temp(ENOMEM);
	pm_rcpt->pmr_pa = sm_str_scpyn0(NULL, rcpt_pa, len + 1, len + 2);
	if (NULL == pm_rcpt->pmr_pa)
		goto error;
	PM_RCPTS_INSERT_TAIL(&pmse_ctx->pmse_rcpts_hd, pm_rcpt);
	pm_rcpt->pmr_idx = rcpt_idx;
	*ppm_rcpt = pm_rcpt;
	return SM_SUCCESS;

  error:
	SM_STR_FREE(pm_rcpt->pmr_pa);
	SM_FREE(pm_rcpt);
	*ppm_rcpt = NULL;
	return sm_err_temp(ENOMEM);
}

/*
**  PM_RCPTS_FREE -- free an entire recipient list
**
**	Parameters:
**		pmse_ctx -- SMTP server transaction context
**
**	Returns:
**		usual return code
*/

sm_ret_T
pm_rcpts_free(pmse_ctx_P pmse_ctx)
{
	pm_rcpt_P pm_rcpt;

	while (!PM_RCPTS_EMPTY(&pmse_ctx->pmse_rcpts_hd))
	{
		pm_rcpt = PM_RCPTS_FIRST(&pmse_ctx->pmse_rcpts_hd);
		PM_RCPTS_REMOVE_HEAD(&pmse_ctx->pmse_rcpts_hd);
		SM_STR_FREE(pm_rcpt->pmr_pa);
		SM_FREE(pm_rcpt);
	}
	PM_RCPTS_INIT(&pmse_ctx->pmse_rcpts_hd);
	return SM_SUCCESS;
}

/*
**  PM_RCPT_MOD -- Add or delete recipient
**
**	Parameters:
**		pmse_ctx -- pmilter/SMTP server session context
**		rcpt_pa -- recipient (rfc 2821 format)
**		rcpt_idx -- recipient index
**		type -- add/delete
**
**	Returns:
**		usual sm_error code
*/

static sm_ret_T
pm_rcpt_mod(pmse_ctx_P pmse_ctx, const char *rcpt_pa, rcpt_idx_T rcpt_idx, uint type)
{
	sm_ret_T ret;
	pm_rcpt_P pm_rcpt;
	size_t len;

	SM_IS_PMSE_CTX(pmse_ctx);
	if (NULL == rcpt_pa)
		return sm_error_perm(SM_EM_PMILTER, EINVAL);
	if (!SM_IS_FLAG(pmse_ctx->pmse_pmss_ctx->pmss_pmcap,
			SM_SCAP_PM_RCPTMOD))
		return sm_error_perm(SM_EM_PMILTER, SM_E_PR_ERR);
	if (pmse_ctx->pmse_state != PMSE_ST_DOT)
		return sm_error_perm(SM_EM_PMILTER, SM_E_PR_ERR);
	pm_rcpt = NULL;

	len = strlen((const char *) rcpt_pa);
	if (len < 5 || len > MAXADDRLEN)
		return sm_error_perm(SM_EM_PMILTER, EINVAL);
	if (rcpt_pa[0] != '<' || rcpt_pa[len - 1] != '>')
		return sm_error_perm(SM_EM_PMILTER, EINVAL);
	/* do a full syntax check here?? */

	ret = pm_rcpt_add(pmse_ctx, rcpt_pa, len, rcpt_idx, &pm_rcpt);
	if (sm_is_err(ret))
		return ret;
	pm_rcpt->pmr_type = type;
	return SM_SUCCESS;
}


/*
**  SM_PMFI_RCPT_ADD -- Add recipient
**
**	Parameters:
**		pmse_ctx -- pmilter/SMTP server session context
**		rcpt_pa -- recipient (rfc 2821 format)
**		argv -- list of SMTP parameter for RCPT; NULL terminated list.
**			(currently ignored)
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_rcpt_add(pmse_ctx_P pmse_ctx, const char *rcpt_pa, char **argv)
{
	return pm_rcpt_mod(pmse_ctx, rcpt_pa, 0, PM_RCPT_ADD);
}

/*
**  SM_PMFI_RCPT_DEL -- Delete recipient
**
**	Parameters:
**		pmse_ctx -- pmilter/SMTP server session context
**		rcpt_pa -- recipient (rfc 2821 format)
**		rcpt_idx -- recipient index
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_pmfi_rcpt_del(pmse_ctx_P pmse_ctx, const char *rcpt_pa, rcpt_idx_T rcpt_idx)
{
	return pm_rcpt_mod(pmse_ctx, rcpt_pa, rcpt_idx, PM_RCPT_DEL);
}
#endif /* MTA_USE_PMILTER */


syntax highlighted by Code2HTML, v. 0.9.1