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

📄 file1847.cpp

📁 著名的加密软件的应用于电子邮件中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *  Filename: file1847.cpp
 *
 *  Last Edited: Wednesday, October 2, 1996
 *
 *  Author: Scott Manjourides
 *
 *  Copyright 1995, 1996 QUALCOMM Inc.
 *
 *  Send comments and questions to <emsapi-info@qualcomm.com>
 */

#include <stdlib.h>
#include <stdio.h>
#include <windows.h>

#include "ems-win.h" // The EMS API
#include "mimetype.h"
#include "encoding.h"
#include "rfc822.h"
#include "rfc1847.h"

#include "file1847.h"

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

typedef struct {
	int bFoundHeader;
	BufTypePtr pBuf, pSearchBuf;
	TrEncType cte;
	unsigned int nPrevEndMatch;
	char *preEncBuffer;
	Dec64Ptr d64state;
	DecQPPtr dQPstate;
} PartParseState;

typedef PartParseState *PartParseStatePtr;

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

static int DoCreateOnePart(emsMIMEtypeP InPartMimePtr,
					 emsMIMEtypeP OutMimePtr,
					 TrEncType InPartCTE,
					 FILE *fIn,
					 FILE *fOut,
					 int nPart,
					 long nPreLen,
					 long nTotalInLen,
					 createStatePtr pState,
					 emsProgress progress);

static int DoCreatePartsOutput(emsMIMEtypeP mimePtr,
				   BufTypePtr pInPart1,
				   BufTypePtr pInPart2,
				   createStatePtr pState,
				   FILE *fOut);

static int DoCreateStringOutput(const char *pStr,
				   int nPart,
				   emsMIMEtypeP mimePtr,
				   createStatePtr pState,
				   FILE *fOut);

static int DoParsePart(BufTypePtr pInBuf,
				 FILE *fOut,
				 emsMIMEtypeP *mimePtr,
				 int bDeMime,
				 PartParseStatePtr pState);

static PartParseStatePtr create_PartParseState();
static void delete_PartParseState(PartParseStatePtr p);

static void DoBufOutput(FILE *fOut, BufTypePtr pBuf);

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

#define kBufferSize (1024)

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

const char *kMimeVersionStr = "Mime-Version: 1.0\r\n";

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

/*  CreateTmpFile
 *
 *  Creates a empty, unique, temporary file in the users 'TEMP'
 *    directory.
 *
 *  No arguments.
 *
 *  Returns a pointer to the filename string. This should be
 *    considered temporary data, and should never be free()'d.
 */
char *CreateTmpFile()
{
	static char tmpName[_MAX_PATH + 1];

#ifdef WIN32 // 32-bit
	char path[_MAX_PATH + 1];			
	GetTempPath(_MAX_PATH, path);
	GetTempFileName(path, "tmp", 0, tmpName);
#else // 16-bit
	BYTE btmpDrv = GetTempDrive(0);
	GetTempFileName(btmpDrv,"tmp", 0, tmpName);
#endif

	return (tmpName);
}

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

/*  rfc1847_file_create
 *
 *  Creates RFC1847 MIME structure.
 *
 *  Args:
 *    pOutFilename     [IN]     Output filename ** WRITE-ONLY **
 *    OutMimePtr       [IN/OUT] MIME type of output -- boundary param will be added
 *    InPart1MimePtr   [IN]     MIME type of part 1
 *    InPart1CTE       [IN]     Content-transfer-encoding for part 1
 *    pInPart1Filename [IN]     Input filename for part 1 ** READ-ONLY **
 *    InPart2MimePtr   [IN]     MIME type of part 2
 *    InPart2CTE       [IN]     Content-transfer-encoding for part 2
 *    pInPart2Filename [IN]     Input filename for part 2 ** READ-ONLY **
 *    progress         [IN]     EMS progress callback function
 *
 *  Returns boolean. TRUE for success, FALSE for failure.
 */
int rfc1847_file_create(const char *pOutFilename,
				   emsMIMEtypeP OutMimePtr,

				   emsMIMEtypeP InPart1MimePtr,
				   TrEncType InPart1CTE,
				   const char *pInPart1Filename,

				   emsMIMEtypeP InPart2MimePtr,
				   TrEncType InPart2CTE,
				   const char *pInPart2Filename,

				   emsProgress progress)
{
	FILE *fOut = NULL, *fIn1 = NULL, *fIn2 = NULL;

	fOut = fopen(pOutFilename, "ab");     /* WRITE - Append: Binary */
	fIn1 = fopen(pInPart1Filename, "rb"); /* READ-ONLY: Binary */
	fIn2 = fopen(pInPart2Filename, "rb"); /* READ-ONLY: Binary */

	int nStatus = FILE1847_OK;

	if (fOut && fIn1 && fIn2)
	{
		fwrite(kMimeVersionStr, sizeof(char), strlen(kMimeVersionStr), fOut);

		long nLen1 = 0, nTotalInLen = 0;

		if (progress)
		{
			// get the file length of the two input files -- use for progress
			rewind(fIn1);
			fseek(fIn1, 0, SEEK_END);
			nLen1 = ftell(fIn1);
			rewind(fIn1);

			rewind(fIn2);
			fseek(fIn2, 0, SEEK_END);
			nTotalInLen = nLen1 + ftell(fIn2);
			rewind(fIn2);
		}

		createStatePtr pState = new_create_state();

		if (!pState)
			nStatus = FILE1847_FAIL;

		/* ---------- PART 1 ---------- */

		if (nStatus == FILE1847_OK)
			nStatus = DoCreateOnePart(InPart1MimePtr, OutMimePtr, InPart1CTE, fIn1, fOut, 1, 0, nTotalInLen, pState, progress);

		/* ---------- PART 2 ---------- */

		if (nStatus == FILE1847_OK)
			nStatus = DoCreateOnePart(InPart2MimePtr, OutMimePtr, InPart2CTE, fIn2, fOut, 2, nLen1, nTotalInLen, pState, progress);

		// Do 1847 cleanup
		if (nStatus == FILE1847_OK)
		{
			if (!DoCreatePartsOutput(OutMimePtr, NULL, NULL, pState, fOut))
				nStatus = FILE1847_FAIL;
		}

		// Do final progress indicator
		if ((nStatus == FILE1847_OK) && (progress))
		{
			if (progress(100) ? 1 : 0)
				nStatus = FILE1847_ABORT;
		}

		// Done with the state data
		delete_create_state(pState);
	}

	safeclose(fOut);
	safeclose(fIn1);
	safeclose(fIn2);

	return(nStatus);
}

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

/*  rfc1847_file_parse
 *
 *  Parses RFC1847 MIME structure.
 *
 *  Args:
 *    pInFilename       [IN]  Input filename of file to parse ** READ-ONLY **
 *    InMimePtr         [OUT] MIME type of input file
 *    pOutPart1Filename [IN]  Output filename for part 1 ** WRITE-ONLY **
 *    OutPart1MimePtr   [OUT] MIME type of created part 1
 *    bPart1DeMime      [IN]  Boolean: Remove header and transfer encoding, part 1?
 *    pOutPart2Filename [IN]  Output filename for part 2 ** WRITE-ONLY **
 *    OutPart2MimePtr   [OUT] MIME type of created part 2
 *    bPart2DeMime      [IN]  Boolean: Remove header and transfer encoding, part 2?
 *    progress          [IN]  EMS progress callback function
 *
 *  Returns boolean. TRUE for success, FALSE for failure.
 */
int rfc1847_file_parse(const char *pInFilename,
					   emsMIMEtypeP *InMimePtr,

					   const char *pOutPart1Filename,
					   emsMIMEtypeP *OutPart1MimePtr,
					   int bPart1DeMime,

					   const char *pOutPart2Filename,
					   emsMIMEtypeP *OutPart2MimePtr,
					   int bPart2DeMime,
				  
					   emsProgress progress)
{
	FILE *fIn = NULL, *fOut1 = NULL, *fOut2 = NULL;

	fIn = fopen(pInFilename, "rb");       /* READ-ONLY: Binary */
	fOut1 = fopen(pOutPart1Filename, "ab"); /* READ-ONLY: Binary */
	fOut2 = fopen(pOutPart2Filename, "ab"); /* WRITE - Append: Binary */

	int nStatus = FILE1847_OK;

	if (fIn && fOut1 && fOut2)
	{
		BufTypePtr pOutPart1= makesize_buf(kBufferSize),
			pOutPart2 = makesize_buf(kBufferSize),
			pInBuf = makesize_buf(kBufferSize);

		if ((!pOutPart1) || (!pOutPart2) || (!pInBuf))
			nStatus = FILE1847_FAIL;

		parseStatePtr pState;
		PartParseStatePtr pParsePart1State, pParsePart2State;
		unsigned int nRead;
		int ret;

		long nTotalInLen = 0;
		int nPercentComplete = 0;

		// Check to see if we need to parse the parts
		int bReallyParse1 = FALSE, bReallyParse2 = FALSE;
		if ((OutPart1MimePtr) || (bPart1DeMime))
			bReallyParse1 = TRUE;
		if ((OutPart2MimePtr) || (bPart2DeMime))
			bReallyParse2 = TRUE;

		if ((nStatus == FILE1847_OK) && progress)
		{
			// get the file length of the two input files -- use for progress
			rewind(fIn);
			fseek(fIn, 0, SEEK_END);
			nTotalInLen = ftell(fIn);
			rewind(fIn);

			if (progress(nPercentComplete) ? 1 : 0)
				nStatus = FILE1847_ABORT;
		}

		pParsePart1State = create_PartParseState();
		pParsePart2State = create_PartParseState();
		pState = new_parse_state();

		if ((nStatus == FILE1847_OK) && (pParsePart1State) && (pParsePart2State) && (pState))
		{
			do {
				/* Fill the input buffer from the input file */
				emptybuf_buf(pInBuf);
				if ((nRead = fread(getbuf_buf(pInBuf), sizeof(char), (bufsize_buf(pInBuf)), fIn)) > 0)
					setlen_buf(pInBuf, nRead);

				/* Parse the input, producing output until completed input */
				do {
					emptybuf_buf(pOutPart1);
					emptybuf_buf(pOutPart2);

					ret = rfc1847_parse(InMimePtr, pOutPart1, pOutPart2, pInBuf, pState);

					if (ret != RFC1847_FAIL)
					{
						if (bReallyParse1) /* Parse part #1 */
						{
							if (!DoParsePart(pOutPart1, fOut1, OutPart1MimePtr, bPart1DeMime, pParsePart1State))
								nStatus = FILE1847_FAIL;
						}
						else /* Raw output part #1 */
							DoBufOutput(fOut1, pOutPart1);

						if (bReallyParse2) /* Parse part #2 */
						{
							if (!DoParsePart(pOutPart2, fOut2, OutPart2MimePtr, bPart2DeMime, pParsePart2State))
								nStatus = FILE1847_FAIL;
						}
						else /* Raw output part #2 */
							DoBufOutput(fOut2, pOutPart2);
					}
				} while ((nStatus == FILE1847_OK) && (ret == RFC1847_BUFFERFULL));

				if (ret == RFC1847_FAIL)
					nStatus = FILE1847_FAIL;

				if ((nStatus == FILE1847_OK) && (progress))
				{
					// Update the progress and check for abort
					nPercentComplete = (int) ((((double)ftell(fIn))/nTotalInLen) * 100.0);
					if (progress(nPercentComplete) ? 1 : 0)
						nStatus = FILE1847_ABORT;
				}
			} while ((nStatus == FILE1847_OK) && (!feof(fIn)) && (!ferror(fIn)));

			if (nStatus == FILE1847_OK)
			{
				if (bReallyParse1) /* Parse part #1 */
					if (!DoParsePart(NULL, fOut1, OutPart1MimePtr, bPart1DeMime, pParsePart1State))
						nStatus = FILE1847_FAIL;

				if (bReallyParse2) /* Parse part #2 */
					if (!DoParsePart(NULL, fOut2, OutPart2MimePtr, bPart2DeMime, pParsePart2State))
						nStatus = FILE1847_FAIL;
			}
		}
		else
			nStatus = FILE1847_FAIL;

		delete_PartParseState(pParsePart1State);
		delete_PartParseState(pParsePart2State);
		
		delete_parse_state(pState);
	
		delete_buf(pOutPart1);
		delete_buf(pOutPart2);
		delete_buf(pInBuf);
	}
	else
		nStatus = FILE1847_FAIL; // Files did not open -- error

	safeclose(fIn);
	safeclose(fOut1);
	safeclose(fOut2);

	return(nStatus);
}

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

/*  DoCreatePartsOutput (static)
 *
 *  Private function used to pipe 1847 output to a file.
 */
static int DoCreatePartsOutput(emsMIMEtypeP mimePtr,
				   BufTypePtr pInPart1,
				   BufTypePtr pInPart2,
				   createStatePtr pState,
				   FILE *fOut)
{
	BufTypePtr pOutBuf = makesize_buf(kBufferSize);
	unsigned int nOutLen, ret;
	char *cp;

	if (pOutBuf)
	{
		if (pInPart1)
			resetpos_buf(pInPart1);

		if (pInPart2)
			resetpos_buf(pInPart2);

		do {
			// Clear the output
			emptybuf_buf(pOutBuf);

			// Do the 1847-dance
			ret = rfc1847_create(mimePtr, pOutBuf, pInPart1, pInPart2, pState);

			// Output whatever we got
			if ((nOutLen = buflen_buf(pOutBuf)) > 0)
			{
				cp = getbuf_buf(pOutBuf);
				fwrite(cp, 1, nOutLen, fOut);
			}
		} while (ret == RFC1847_BUFFERFULL);
	}
	else
		return (FALSE); // Could not create buffer

	delete_buf(pOutBuf);

	return (ret != RFC1847_FAIL);
}

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

/*  DoCreateStringOutput (static)
 *
 *  Private function used to send a C-string through the 1847 creator and
 *  eventually pipe the 1847 output to a file.
 */
static int DoCreateStringOutput(const char *pStr,
				   int nPart,
				   emsMIMEtypeP mimePtr,
				   createStatePtr pState,
				   FILE *fOut)
{
	BufTypePtr pTmpBuf = make_buf();
	int ret = RFC1847_FAIL;

	if (pTmpBuf)
	{
		// Manually setup the buffer structure -- kind of ugly, but
		// more effiecient than copying the string
		pTmpBuf->buf = (char *) pStr;
		pTmpBuf->len = strlen(pStr);
		pTmpBuf->buf_size = pTmpBuf->len + 1;
		resetpos_buf(pTmpBuf);

		// Now output the buffer
		ret = DoCreatePartsOutput(mimePtr,
			((nPart == 1) ? pTmpBuf : NULL), /* Part 1 */
			((nPart == 2) ? pTmpBuf : NULL), /* Part 2 */
			pState,
			fOut);

		clear_buf(pTmpBuf); // Unassociate buffer with string
		delete_buf(pTmpBuf); // Delete buffer struct -- AFTER we clear it's contents

⌨️ 快捷键说明

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