📄 rfc1847.cpp
字号:
* Performs necessary initialization for rfc1847_parse().
*
* Args:
* pState [IN] Pointer to the state structure.
*
* Return value: BOOLEAN indicating success.
*/
static int rfc1847_parse_init(parseStatePtr pState)
{
if (!pState)
return (FALSE);
strcpy_buf(pState->pNewlineBuf, "\r\n");
strcpy_buf(pState->pDblNewlineBuf, "\r\n\r\n");
resetpos_buf(pState->pNewlineBuf);
resetpos_buf(pState->pDblNewlineBuf);
pState->stage = PSE_Start;
pState->bInitialized = TRUE;
return (TRUE);
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* Parses RFC1847 MIME structure, returning MIME info and separated parts.
*
* Args:
* mimePtr [OUT] Returns a pointer to a newly created emsMIMEtype.
* pOutPart1 [OUT] Output buffer, part 1.
* pOutPart2 [OUT] Output buffer, part 2.
* pInBuf [IN] Input buffer containing full RFC1847 MIME structure.
* 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_parse(emsMIMEtypeP *mimePtr,
BufTypePtr pOutPart1,
BufTypePtr pOutPart2,
BufTypePtr pInBuf,
parseStatePtr pState)
{
int bForceJumpState = FALSE;
if (!pState->bInitialized)
if (!rfc1847_parse_init(pState))
pState->stage = PSE_Fail;
while ((bForceJumpState) || (poslen_buf(pInBuf) > 0))
{
bForceJumpState = FALSE;
switch (pState->stage)
{
case PSE_Start:
{
/* Just an entry point */
pState->stage = PSE_SkipHeader;
}
break;
case PSE_SkipHeader:
{
pState->stage = PSE_KeepUntil;
pState->next_stage = PSE_ParseHeader;
pState->pSearchBuf = pState->pDblNewlineBuf;
}
break;
case PSE_ParseHeader: /* Do all the mimePtr stuff */
{
resetpos_buf(pState->pPrevBuf);
unsigned int nPrevLen = poslen_buf(pState->pPrevBuf);
char *pHeader = (char *) malloc(nPrevLen + 1);
if (!pHeader)
{
pState->stage = PSE_Fail;
{ bForceJumpState = TRUE; continue; };
}
strncpy(pHeader, getpos_buf(pState->pPrevBuf), nPrevLen);
*(pHeader + nPrevLen) = '\0';
char *pCT = rfc822_extract_header(pHeader, "Content-Type:");
safefree(pHeader);
if (!pCT)
{
pState->stage = PSE_Fail;
{ bForceJumpState = TRUE; continue; };
}
*mimePtr = parse_make_mime_type(pCT);
safefree(pCT);
/* get boundary info */
const char *cp = get_mime_parameter(*mimePtr, kBoundaryParameterName);
if (!cp)
{
pState->stage = PSE_Fail;
{ bForceJumpState = TRUE; continue; };
}
strcpy_buf(pState->pBoundaryBuf, "\r\n--");
strcat_buf(pState->pBoundaryBuf, cp);
// DO NOT free() cp
resetpos_buf(pState->pBoundaryBuf);
unsigned int nSkip = skipcount_buf(pState->pPrevBuf, pState->pBoundaryBuf);
unsigned int nRemain = nPrevLen - nSkip;
pState->nLeftSpanCount = nRemain;
clear_buf(pState->pPrevBuf);
pState->stage = PSE_SkipFirst;
}
break;
case PSE_SkipFirst:
{
pState->stage = PSE_IgnoreUntil;
pState->pSearchBuf = pState->pBoundaryBuf;
pState->next_stage = PSE_PrePart;
}
break;
case PSE_PrePart:
{
pState->stage = PSE_IgnoreUntil;
pState->pSearchBuf = pState->pNewlineBuf;
pState->next_stage = PSE_OutPart;
}
break;
case PSE_OutPart:
{
pState->current_part++;
if (pState->current_part <= 2)
{
pState->stage = PSE_OutputUntil;
pState->pSearchBuf = pState->pBoundaryBuf;
pState->next_stage = PSE_PrePart;
}
else
pState->stage = PSE_Done;
}
break;
case PSE_Done:
{
delpos_buf(pInBuf);
}
break;
case PSE_Fail:
{
return (RFC1847_FAIL);
}
break;
/* ----- ----- */
case PSE_KeepUntil:
case PSE_IgnoreUntil:
case PSE_OutputUntil:
{
int bFound = FALSE;
unsigned int nPrefixCount = 0, nAfterSkip = 0;
resetpos_buf(pState->pSearchBuf);
const unsigned int nInLen = poslen_buf(pInBuf);
const unsigned int nSearchLen = poslen_buf(pState->pSearchBuf);
/* Did we have a partial span at the end of last buffer? */
if (pState->nLeftSpanCount > 0)
{
//unsigned int nRemainingCount = nSearchLen - (pState->nLeftSpanCount);
/* Check for completion of span */
// If doesn't continue match, returns zero
// otherwise returns number of chars of pSearchBuf that have been matched
unsigned int nNewMatched = completecount_buf(pInBuf, pState->pSearchBuf, pState->nLeftSpanCount);
if (nNewMatched == nSearchLen) /* complete match made */
{
bFound = TRUE;
nPrefixCount = 0; /* No chars in this buffer are before the match */
nAfterSkip = nSearchLen - (pState->nLeftSpanCount); /* Move buffer position to AFTER match */
pState->nLeftSpanCount = 0;
}
else if (nNewMatched == 0) /* match failed */
{
/* need to 'do' pState->nLeftSpanCount of pState->pSearchBuf */
switch (pState->stage)
{
case PSE_KeepUntil:
bufncat_buf(pState->pPrevBuf, pState->pSearchBuf, pState->nLeftSpanCount);
break;
case PSE_IgnoreUntil:
/* Ignore -- do nothing */
break;
case PSE_OutputUntil:
pState->pOutputBuf = pState->pSearchBuf;
pState->nOutputCount = pState->nLeftSpanCount;
pState->afterout_stage = pState->stage; /* Stay in same stage */
pState->stage = PSE_DoOutput;
break;
}
pState->nLeftSpanCount = 0;
if (pState->stage == PSE_DoOutput)
{ bForceJumpState = TRUE; continue; };
}
else /* Continued to match, but not completed yet -- the input buffer is smaller than the pSearchBuf */
{
// Remainder of pInBuf matches, so we need to gobble it
delpos_buf(pInBuf);
pState->nLeftSpanCount = nNewMatched;
continue; // We want to 'return', because we are done with input
}
}
resetpos_buf(pState->pSearchBuf);
if (!bFound)
{
if (pState->pSearchBuf) // nSearchLen?
{
// Find match of pSearchBuf, either complete or end-spanning
// return number of chars to skip before match
unsigned int nSkip = skipcount_buf(pInBuf, pState->pSearchBuf);
unsigned int nRemain = nInLen - nSkip;
if (nRemain > nSearchLen) /* Found 'complete' */
{
bFound = TRUE;
nPrefixCount = nSkip;
nAfterSkip = nSearchLen;
}
else /* Either not found or partial possible */
{
nPrefixCount = nSkip;
nAfterSkip = nRemain; /* Gobble up the remaining (known to match) */
pState->nLeftSpanCount = nRemain;
}
}
else
{
nPrefixCount = nInLen;
nAfterSkip = 0;
}
}
resetpos_buf(pState->pSearchBuf);
if (bFound) /* Found */
{
switch (pState->stage)
{
case PSE_KeepUntil:
bufncat_buf(pState->pPrevBuf, pInBuf, nPrefixCount + nAfterSkip);
pState->stage = pState->next_stage;
break;
case PSE_IgnoreUntil: /* Ignore -- do nothing */
incpos_buf(pInBuf, nPrefixCount + nAfterSkip);
pState->stage = pState->next_stage;
break;
case PSE_OutputUntil:
pState->pOutputBuf = pInBuf;
pState->nOutputCount = nPrefixCount;
pState->afterout_stage = pState->next_stage;
pState->nAfteroutSkip = nAfterSkip;
pState->stage = PSE_DoOutput;
break;
default:
pState->stage = PSE_Fail;
break;
}
}
else /* not found */
{
switch (pState->stage)
{
case PSE_KeepUntil:
bufncat_buf(pState->pPrevBuf, pInBuf, nPrefixCount + nAfterSkip);
break;
case PSE_IgnoreUntil: /* Ignore -- do nothing */
incpos_buf(pInBuf, nPrefixCount + nAfterSkip);
break;
case PSE_OutputUntil:
pState->pOutputBuf = pInBuf;
pState->nOutputCount = nPrefixCount;
pState->afterout_stage = pState->stage; /* Same stage */
pState->nAfteroutSkip = nAfterSkip;
pState->stage = PSE_DoOutput;
break;
default:
pState->stage = PSE_Fail;
break;
}
}
}
break;
case PSE_DoOutput:
{
// Need to distiguish between the two output paths
BufTypePtr p = NULL;
switch (pState->current_part)
{
case 1: p = pOutPart1;
break;
case 2: p = pOutPart2;
break;
default: pState->stage = PSE_Fail;
break;
}
if (p)
{
unsigned int nOut = bufnins_buf(p, pState->pOutputBuf, pState->nOutputCount);
// Need to check if not everything was outputted
// If not -- buffer is full, adjust 'nOutputCount', return BUFFERFULL;
pState->nOutputCount -= nOut;
if ((pState->nOutputCount) > 0) /* Anything left to output */
return (RFC1847_BUFFERFULL);
pState->stage = pState->afterout_stage;
if (pState->nAfteroutSkip > 0)
incpos_buf(pState->pOutputBuf, pState->nAfteroutSkip);
}
else
return (RFC1847_BUFFERFULL); /* No output buffer */
}
break;
}
}
return (RFC1847_COMPLETED);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -