📄 file1847.cpp
字号:
/*
* 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 + -