/*
 * 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: pmilter_hdr.c,v 1.5 2006/10/05 04:27:38 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/types.h"
#include "sm/sm_extracthdr.h"
#include "sm/io.h"
#include "sm/smreplycodes.h"

#include "pmilter.h"
#include "sm/pmilter.h"
#include "sm/pmfapi.h"

#if MTA_USE_PMILTER
/*
How to use this?
as library: doesn't work so well as it needs to access some context.
as macro? (similar to bsd-tree.h?)
*/

/* context per SMTP session */
typedef struct pmexse_ctx_S	pmexse_ctx_T, *pmexse_ctx_P;
struct pmexse_ctx_S
{
	uint32_t	 pmexse_flags;
	sm_xhdr_ctx_P	 pmexse_xhdr_ctx;
};

#define PMSE_FL_NONE		0x0000
#define PMSE_FL_MSG_INIT	0x0001
#define PMSE_FL_MSG_HDR		0x0002
#define PMSE_FL_MSG_EOH		0x0004
#define PMSE_FL_MSG_BODY	0x0008

#define PMSE_SET_FLAG(pmexse_ctx, fl)	(pmexse_ctx)->pmexse_flags |= (fl)
#define PMSE_CLR_FLAG(pmexse_ctx, fl)	(pmexse_ctx)->pmexse_flags &= ~(fl)
#define PMSE_IS_FLAG(pmexse_ctx, fl)	(((pmexse_ctx)->pmexse_flags & (fl)) != 0)

static sfsistat_T
pm_hdr(pmexse_ctx_P pmexse_ctx, unsigned char *buf, size_t len)
{
	sm_ret_T ret;
	bool newchunk;
	sm_xhdr_ctx_P sm_xhdr_ctx;

	newchunk = true;
	sm_xhdr_ctx = pmexse_ctx->pmexse_xhdr_ctx;
	do
	{
		ret = sm_xhdr(buf, len, newchunk, sm_xhdr_ctx);
		newchunk = false;
		if (ret == SM_XHDR_GOT1 || ret == SM_XHDR_GOTA ||
		    ret == SM_XHDR_GOTL)
		{
			/* invoke header function */
			sm_io_fprintf(smioout, "name: %#S\n",
				sm_xhdr_ctx->sm_xhdr_name);
			sm_io_fprintf(smioout, "value: %#S\n",
				sm_xhdr_ctx->sm_xhdr_value);
		}
	} while (!sm_is_err(ret) && ret == SM_XHDR_GOTA);
	if (ret == SM_XHDR_EOHDR || ret == SM_XHDR_GOTL)
	{
		PMSE_CLR_FLAG(pmexse_ctx, PMSE_FL_MSG_HDR);
		PMSE_SET_FLAG(pmexse_ctx, PMSE_FL_MSG_EOH);
		/* invoke end-of-header function */

		PMSE_CLR_FLAG(pmexse_ctx, PMSE_FL_MSG_EOH);
		PMSE_SET_FLAG(pmexse_ctx, PMSE_FL_MSG_BODY);
	}
	return ret;
}

extern sfsistat_T
pm_body(pmse_ctx_P _pmse_ctx, unsigned char *_buf, size_t _len);

sfsistat_T
pm_msg(pmse_ctx_P pmse_ctx, unsigned char *buf, size_t len)
{
	sm_ret_T ret;
	pmexse_ctx_P pmexse_ctx;

	pmexse_ctx = (pmexse_ctx_P) sm_pmfi_get_ctx_se(pmse_ctx);
	if (pmexse_ctx == NULL)
		return SMTP_R_TEMP;

	ret = SMTP_R_CONT;
	if (!PMSE_IS_FLAG(pmexse_ctx, PMSE_FL_MSG_INIT))
	{
		ret = sm_xhdr_init(SM_XHDR_FL_SKIP_FIRST_BLANK,
				&pmexse_ctx->pmexse_xhdr_ctx);
		if (sm_is_err(ret))
			return SMTP_R_TEMP;
		PMSE_SET_FLAG(pmexse_ctx, PMSE_FL_MSG_INIT|PMSE_FL_MSG_HDR);
	}

	if (PMSE_IS_FLAG(pmexse_ctx, PMSE_FL_MSG_HDR))
	{
		ret = pm_hdr(pmexse_ctx, buf, len);
		if (PMSE_IS_FLAG(pmexse_ctx, PMSE_FL_MSG_BODY))
		{
			sm_xhdr_ctx_P sm_xhdr_ctx;

			sm_xhdr_ctx = pmexse_ctx->pmexse_xhdr_ctx;
			if (sm_xhdr_ctx->sm_xhdr_chunk_off < len)
			{
				len -= sm_xhdr_ctx->sm_xhdr_chunk_off;
				buf += sm_xhdr_ctx->sm_xhdr_chunk_off;
				ret = sm_xhdr_end(sm_xhdr_ctx);
			}
			else
				len = 0;
		}
	}
	if (PMSE_IS_FLAG(pmexse_ctx, PMSE_FL_MSG_BODY) && len > 0)
		ret = pm_body(pmse_ctx, buf, len);
	return ret;
}

#endif /* MTA_USE_PMILTER */


syntax highlighted by Code2HTML, v. 0.9.1