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