⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfc1847.cpp

📁 著名的加密软件的应用于电子邮件中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *  Functions to aide manipulation and parsing of MIME RFC1847 objects.
 *
 *  Last Edited: Wednesday, October 2, 1996
 *
 *  Last Edited: Monday, September 9, 1996
 *
 *  Author: Scott Manjourides
 *
 *  Copyright 1995, 1996 QUALCOMM Inc.
 *
 *  Send comments and questions to <emsapi-info@qualcomm.com>
 *
 */

#include <stdlib.h> /* rand() */
#include <time.h> /* time() */
#include <stdio.h> /* sprintf() */
#include <windows.h> /* Must be included for ems-win.h */

#include "ems-win.h"
#include "RFC822.H"
#include "RFC1847.H"
#include "BUFTYPE.H"
#include "MIMETYPE.H"

/* ------------------------------------------------------------------------- */

static char *kBoundaryParameterName = "boundary";
static char *kBoundaryPrefixSuffix = "=-=-=-=";

/* ------------------------------------------------------------------------- */

#define safefree(p) { if (p) { free(p); (p) = NULL; } }

/* ------------------------------------------------------------------------- */

static int rfc1847_create_init(createStatePtr pState);
static int rfc1847_parse_init(parseStatePtr pState);

/* ------------------------------------------------------------------------- */

/*
 *  Allocates and returns a pointer to an initialized createState structure.
 *   
 *  NOTE: The user of this function is responsible for properly
 *        deleting the returned data by calling delete_create_state()
 *        when the state data is no longer needed.
 *
 *  No arguments.
 *
 *  Pointer to newly created createState structure. NULL if error.
 */
createStatePtr new_create_state()
{
	createStatePtr p;
	p = (createStatePtr) malloc(sizeof(createState));

	if (!p)
		return (NULL);

	p->stage = p->next_stage = p->afterout_stage = CSE_Fail;

	p->pBoundaryStr = NULL;
	p->current_part = 0;

	p->pTmpBuf = make_buf();
	p->pOutputBuf = NULL;

	p->bInitialized = FALSE;

	return (p);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Frees all memory within the state structure, including the structure
 *  itself.
 *   
 *  NOTE: The pointer argument should be assumed invalid after this call.
 *
 *  Args:
 *    pState [IN] Pointer to the state structure to be deleted.
 *
 *  No return value.
 */
void delete_create_state(createStatePtr p)
{
	if (!p)
		return;

	delete_buf(p->pTmpBuf);
	safefree(p->pBoundaryStr);

	safefree(p);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Allocates and returns a pointer to an initialized parseState structure.
 *   
 *  NOTE: The user of this function is responsible for properly
 *        deleting the returned data by calling delete_create_state()
 *        when the state data is no longer needed.
 *
 *  No arguments.
 *
 *  Pointer to newly created parseState structure. NULL if error.
 */
parseStatePtr new_parse_state()
{
	parseStatePtr p;
	p = (parseStatePtr) malloc(sizeof(parseState));

	if (!p)
		return (NULL);

	p->stage = p->next_stage = p->afterout_stage = PSE_Fail;

	p->current_part = 0;

	p->nOutputCount = 0;
	p->nAfteroutSkip = 0;
	p->nLeftSpanCount = 0;

	p->pOutputBuf = NULL;
	p->pSearchBuf = NULL;

//	p->pTmpBuf = make_buf();
	p->pPrevBuf = make_buf();
	p->pBoundaryBuf = make_buf();
	p->pDblNewlineBuf = make_buf();
	p->pNewlineBuf = make_buf();

	p->bInitialized = FALSE;

	return (p);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Frees all memory within the state structure, including the structure
 *  itself.
 *   
 *  NOTE: The pointer argument should be assumed invalid after this call.
 *
 *  Args:
 *    pState [IN] Pointer to the state structure to be deleted.
 *
 *  No return value.
 */
void delete_parse_state(parseStatePtr p)
{
	if (!p)
		return;
		
//	delete_buf(p->pTmpBuf);
	delete_buf(p->pPrevBuf);
	delete_buf(p->pBoundaryBuf);
	delete_buf(p->pDblNewlineBuf);
	delete_buf(p->pNewlineBuf);

	safefree(p);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Performs necessary initialization for rfc1847_create().
 *   
 *  Args:
 *    pState [IN] Pointer to the state structure.
 *
 *  Return value: BOOLEAN indicating success.
 */
static int rfc1847_create_init(createStatePtr pState)
{
	char *pBoundaryTxt = (char *) malloc(128);

	if (!pBoundaryTxt)
		return (FALSE);

	/* Create a random boundary; max 68 chars */
	srand((unsigned)time(NULL));

	sprintf(pBoundaryTxt, "%s%d%d%d%s",
		kBoundaryPrefixSuffix,
		rand(),
		rand(),
		rand(),
		kBoundaryPrefixSuffix);

	pState->pBoundaryStr = pBoundaryTxt;
	pState->stage = CSE_Start;

	pState->bInitialized = TRUE;

	return (TRUE);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Creates RFC1847 MIME structure.
 *   
 *  Args:
 *    mimePtr  [IN]     MIME content info, used to create the MIME headers.
 *    pOutBuf  [OUT]    Output buffer (RFC1847 MIME structure).
 *    pInPart1 [IN]     Input buffer used for first part.
 *    pInPart2 [IN]     Input buffer used for second part.
 *    pState   [IN/OUT] Pointer to state info, caller must preserve.
 *
 *  Return values:
 *    RFC1847_COMPLETED   Input was sucessfully and completely parsed.
 *    RFC1847_BUFFERFULL  The output buffer is full; input partially parsed.
 *    RFC1847_FAIL        Parsing error.
 */

int rfc1847_create(emsMIMEtypeP mimePtr,
				   BufTypePtr pOutBuf,
				   BufTypePtr pInPart1,
				   BufTypePtr pInPart2,
				   createStatePtr pState)
{
	if (!pState->bInitialized)
		if (!rfc1847_create_init(pState))
			pState->stage = CSE_Fail;

	while (pState->stage != CSE_Done)
	{
		switch (pState->stage)
		{
			case CSE_Start:
				pState->stage = CSE_DoHeader; /* Just an entry point */
			break;

			case CSE_DoHeader:
			{
				pState->stage = CSE_Fail; // If not changed, then something failed

				if ((mimePtr) && (pState->pBoundaryStr))
				{
					/* Remove the boundary parameter from the MIME struct -- if it's there */
					remove_mime_parameter(mimePtr, kBoundaryParameterName);

					/* Add the boundary to the MIME type struct */
					if (add_mime_parameter(mimePtr, kBoundaryParameterName, pState->pBoundaryStr))
					{
						char *pCT = NULL;

						/* Create an RFC822 Content-Type header line from the MIME struct*/
						if ((pCT = string_mime_type(mimePtr)) != NULL)
						{
							strcpy_buf(pState->pTmpBuf, pCT); /* Content-Type: */
							strcat_buf(pState->pTmpBuf, "\r\n"); /* Not the blank line, just end of CT: */
							resetpos_buf(pState->pTmpBuf);

							safefree(pCT);

							pState->pOutputBuf = pState->pTmpBuf;
							pState->afterout_stage = CSE_DoBoundary;
							pState->stage = CSE_DoOutput;
						}
					}
				}
			}
			break;

			case CSE_DoBoundary:
			{
				strcpy_buf(pState->pTmpBuf, "\r\n");
				strcat_buf(pState->pTmpBuf, "--");
				strcat_buf(pState->pTmpBuf, pState->pBoundaryStr);

				if ((pState->current_part) < 2) /* End the header and first part */
				{
					pState->current_part++;
					pState->afterout_stage = CSE_DoPart;
				}
				else /* End of second part */
				{
					strcat_buf(pState->pTmpBuf, "--");
					pState->afterout_stage = CSE_Done;
				}

				strcat_buf(pState->pTmpBuf, "\r\n");
				resetpos_buf(pState->pTmpBuf);

				pState->stage = CSE_DoOutput;
				pState->pOutputBuf = pState->pTmpBuf;
			}
			break;

			case CSE_DoPart:
			{
				switch (pState->current_part)
				{
					case 1: /* We're doing part 1 now */
					{
						if (poslen_buf(pInPart1) > 0)
						{
							pState->stage = CSE_DoOutput;
							pState->pOutputBuf = pInPart1;

							if (pInPart2)
								pState->afterout_stage = CSE_DoBoundary;
							else
								pState->afterout_stage = CSE_DoPart;
						}
						else /* pInPart1 is empty/completed/non-existant */
						{
							if (pInPart2)
								pState->stage = CSE_DoBoundary;
							else /* !pInPart2 */
								return (RFC1847_COMPLETED); /* We've eaten all of part 1, and there is no part 2 */
						}
					}
					break;

					case 2: /* We're doing part 2 now */
					{
						if (poslen_buf(pInPart2) > 0)
						{
							pState->stage = CSE_DoOutput;
							pState->pOutputBuf = pInPart2;
							pState->afterout_stage = CSE_DoPart;
						}
						else /* pInPart1 is empty/completed/non-existant */
						{
							if (pInPart2)
								return (RFC1847_COMPLETED); /* We've eaten all of part 2 */
							else /* !pInPart2 */
								pState->stage = CSE_DoBoundary;
						}
					}
					break;
				}
			}
			break;

			case CSE_DoOutput:
			{
				if (pOutBuf)
				{
					unsigned int nLen = poslen_buf(pState->pOutputBuf);
					unsigned int nOut = bufins_buf(pOutBuf, pState->pOutputBuf);

					if (nOut < nLen) /* Anything left to output */
						return (RFC1847_BUFFERFULL);

					pState->stage = pState->afterout_stage;
				}
				else
					return (RFC1847_BUFFERFULL); /* No output buffer */
			}
			break;

			case CSE_Fail:
				return (RFC1847_FAIL);
			break;
		} /* switch (stage) */
	} /* while */

	return (RFC1847_COMPLETED);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -