📄 file1847.cpp
字号:
}
else
return (FALSE); // Could not create buffer
return (ret != RFC1847_FAIL);
}
/* ------------------------------------------------------------------------ */
/* DoCreateOnePart (static)
*
* Private function used to pipe a given file through the 1847 creator as
* either part 1 or part 2. All De-mime stuff is also done here.
*/
static int DoCreateOnePart(emsMIMEtypeP InPartMimePtr,
emsMIMEtypeP OutMimePtr,
TrEncType InPartCTE,
FILE *fIn,
FILE *fOut,
int nPart,
long nPreLen,
long nTotalInLen,
createStatePtr pState,
emsProgress progress)
{
BufTypePtr pInBuf = makesize_buf(kBufferSize);
if (!pInBuf)
return (FILE1847_FAIL); // Could not create buffer -- error
int nStatus = FILE1847_OK;
// Do InPartMimePtr (Content-Type) header
if ((nStatus == FILE1847_OK) && (InPartMimePtr))
{
char *pCT = string_mime_type(InPartMimePtr);
if (pCT)
{
if (!DoCreateStringOutput(pCT, nPart, OutMimePtr, pState, fOut))
nStatus = FILE1847_FAIL;
else
if (!DoCreateStringOutput("\r\n", nPart, OutMimePtr, pState, fOut))
nStatus = FILE1847_FAIL;
}
else
nStatus = FILE1847_FAIL;
safefree(pCT);
}
// Do InPartCTE (Content-Transfer-Encoding) header
if ((nStatus == FILE1847_OK) && (InPartCTE != CTE_NONE))
{
char *pCTE = rfc822_make_cte(InPartCTE);
if (pCTE)
{
if (!DoCreateStringOutput(pCTE, nPart, OutMimePtr, pState, fOut))
nStatus = FILE1847_FAIL;
else
if (!DoCreateStringOutput("\r\n", nPart, OutMimePtr, pState, fOut))
nStatus = FILE1847_FAIL;
}
else
nStatus = FILE1847_FAIL;
safefree(pCTE);
}
// Do blank line -- only if we put out some header already
if ((nStatus == FILE1847_OK) && ((InPartMimePtr) || (InPartCTE != CTE_NONE)))
{
if (!DoCreateStringOutput("\r\n", nPart, OutMimePtr, pState, fOut))
nStatus = FILE1847_FAIL;
}
char *preEncBuffer = NULL;
unsigned int preEncBufLen;
Enc64Ptr e64state = NULL; // Used by Encode64()
EncQPPtr eQPstate = NULL; // Used by EucodeQP()
if (nStatus == FILE1847_OK)
{
switch (InPartCTE)
{
// BASE64
case CTE_Base64:
{
// BASE64 expands about 1/3
preEncBufLen = ((kBufferSize * 6) / 10);
preEncBuffer = (char *) malloc(preEncBufLen);
if (!preEncBuffer)
nStatus = FILE1847_FAIL; // Could not create buffer
e64state = (Enc64Ptr) malloc(sizeof(Enc64)); // Used by Encode64()
e64state->partialCount = e64state->bytesOnLine = 0;
}
break;
// QUOTED-PRINTABLE
case CTE_QP:
{
// QP expands max of 3 times
preEncBufLen = (kBufferSize / 4);
preEncBuffer = (char *) malloc(preEncBufLen);
if (!preEncBuffer)
nStatus = FILE1847_FAIL; // Could not create buffer
eQPstate = (EncQPPtr) malloc(sizeof(EncQP)); // Used by Encode64()
eQPstate->nCurLineLen = 0;
eQPstate->cLastChar = '\0';
}
break;
// Otherwise, no encoding
default:
{
preEncBufLen = 0;
}
break;
}
}
size_t nReadLen = 0;
int nPercentComplete = 0;
// Do pInPartFilename
while ((nStatus == FILE1847_OK) && (!feof(fIn)) && (!ferror(fIn)))
{
emptybuf_buf(pInBuf);
switch (InPartCTE)
{
case CTE_Base64:
{
nReadLen = fread(preEncBuffer, sizeof(char), preEncBufLen, fIn);
nReadLen = Encode64(preEncBuffer, nReadLen, getbuf_buf(pInBuf), e64state);
}
break;
case CTE_QP:
{
nReadLen = fread(preEncBuffer, sizeof(char), preEncBufLen, fIn);
nReadLen = EncodeQP(preEncBuffer, nReadLen, getbuf_buf(pInBuf), eQPstate);
}
break;
default: /* 7bit, 8bit, binary, none */
{
nReadLen = fread(getbuf_buf(pInBuf), sizeof(char), bufsize_buf(pInBuf), fIn);
}
break;
}
if (nReadLen > 0)
{
setlen_buf(pInBuf, nReadLen);
if (!DoCreatePartsOutput(OutMimePtr,
((nPart == 1) ? pInBuf : NULL), /* Part 1 */
((nPart == 2) ? pInBuf : NULL), /* Part 2 */
pState,
fOut))
nStatus = FILE1847_FAIL;
}
if ((nStatus == FILE1847_OK) && (progress))
{
// Update the progress and check for abort
nPercentComplete = (int) (((((double)ftell(fIn) + nPreLen))/nTotalInLen) * 100.0);
if (progress(nPercentComplete) ? 1 : 0)
nStatus = FILE1847_ABORT;
}
}
if (nStatus == FILE1847_OK)
{
// Finish part -- if needed
switch (InPartCTE)
{
case CTE_Base64:
{
nReadLen = Encode64(NULL, 0, getbuf_buf(pInBuf), e64state);
}
break;
case CTE_QP:
{
nReadLen = EncodeQP(NULL, 0, getbuf_buf(pInBuf), eQPstate);
}
break;
default: /* 7bit, 8bit, binary, none */
{
nReadLen = 0;
}
break;
}
if (nReadLen > 0)
{
setlen_buf(pInBuf, nReadLen);
if (!DoCreatePartsOutput(OutMimePtr,
((nPart == 1) ? pInBuf : NULL), /* Part 1 */
((nPart == 2) ? pInBuf : NULL), /* Part 2 */
pState,
fOut))
nStatus = FILE1847_FAIL;
}
}
safefree(e64state);
safefree(eQPstate);
safefree(preEncBuffer);
delete_buf(pInBuf);
return (nStatus);
}
/* ------------------------------------------------------------------------ */
/* DoParsePart (static)
*
* Private function used to pipe the output of 1847 parsing into a file.
*/
static int DoParsePart(BufTypePtr pInBuf,
FILE *fOut,
emsMIMEtypeP *mimePtr,
int bDeMime,
PartParseStatePtr pState)
{
if (!pInBuf) // Input buf NULL indicates 'cleanup'
{
if (!pState->bFoundHeader)
return (FALSE);
else
return (TRUE);
}
if (!pState->bFoundHeader)
{
resetpos_buf(pState->pSearchBuf);
if (pState->nPrevEndMatch > 0)
{
/* 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->nPrevEndMatch);
if (nNewMatched == buflen_buf(pState->pSearchBuf)) /* complete match made */
{
pState->bFoundHeader = TRUE;
pState->nPrevEndMatch = 0;
bufncat_buf(pState->pBuf, pInBuf, (buflen_buf(pState->pSearchBuf) - (pState->nPrevEndMatch)));
}
else if (nNewMatched != 0) /* Continued to match, but not completed yet -- the input buffer is smaller than the pSearchBuf */
{
bufncat_buf(pState->pBuf, pInBuf, poslen_buf(pInBuf));
pState->nPrevEndMatch = nNewMatched;
return (TRUE);
}
else /* No match continuation */
{
pState->nPrevEndMatch = 0;
}
}
resetpos_buf(pState->pSearchBuf);
// Still not found -- no span
if (!pState->bFoundHeader)
{
// 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 = poslen_buf(pInBuf) - nSkip;
if (nRemain == 0) // Not found
{
bufncat_buf(pState->pBuf, pInBuf, poslen_buf(pInBuf));
return (TRUE);
}
else
if (nRemain > buflen_buf(pState->pSearchBuf)) /* Found 'complete' */
{
pState->bFoundHeader = TRUE;
bufncat_buf(pState->pBuf, pInBuf, (nSkip + buflen_buf(pState->pSearchBuf)) );
}
else // Partial possible
{
pState->nPrevEndMatch = nRemain;
bufncat_buf(pState->pBuf, pInBuf, poslen_buf(pInBuf));
return (TRUE);
}
}
// ---------- Now we know it is found ----------
unsigned int nLen = buflen_buf(pState->pBuf);
char *pHeader = (char *) malloc(nLen + 1);
strncpy(pHeader, getbuf_buf(pState->pBuf), nLen);
char *pCT = rfc822_extract_header(pHeader, "Content-Type:");
if (mimePtr)
*mimePtr = parse_make_mime_type(pCT);
if (bDeMime)
{
char *pCTE = rfc822_extract_cte(pHeader);
if (pCTE)
pState->cte = rfc822_parse_cte(pCTE);
else
pState->cte = CTE_NONE; /* No CTE header, so no encoding */
switch (pState->cte)
{
// BASE64
case CTE_Base64:
{
// BASE64 expands about 1/3
unsigned int preEncBufLen = ((kBufferSize * 10) / 6);
pState->preEncBuffer = (char *) malloc(preEncBufLen);
pState->d64state = (Dec64Ptr) malloc(sizeof(Dec64)); // Used by Decode64()
pState->d64state->decoderState = 0;
pState->d64state->invalCount = 0;
pState->d64state->padCount = 0;
pState->d64state->partial = 0;
pState->d64state->wasCR = FALSE;
}
break;
// QUOTED-PRINTABLE
case CTE_QP:
{
// QP expands max of 3 times
unsigned int preEncBufLen = (kBufferSize * 4);
pState->preEncBuffer = (char *) malloc(preEncBufLen);
pState->dQPstate = (DecQPPtr) malloc(sizeof(EncQP));
pState->dQPstate->CurState = qpNormal;
pState->dQPstate->cLastChar = 0;
}
break;
// Otherwise, no encoding
default:
break;
}
}
else
{
fwrite(getbuf_buf(pState->pBuf), sizeof(char), nLen, fOut);
}
free_buf(pState->pBuf);
}
// ---------- Now we know it is found and header is init'd ----------
long errorcnt;
switch (pState->cte)
{
case CTE_Base64:
{
unsigned int nReadLen = Decode64(getpos_buf(pInBuf), poslen_buf(pInBuf), pState->preEncBuffer, pState->d64state, &errorcnt);
fwrite(pState->preEncBuffer, sizeof(char), nReadLen, fOut);
}
break;
case CTE_QP:
{
unsigned int nReadLen = DecodeQP(getpos_buf(pInBuf), poslen_buf(pInBuf), pState->preEncBuffer, pState->dQPstate, &errorcnt);
fwrite(pState->preEncBuffer, sizeof(char), nReadLen, fOut);
}
break;
default: /* 7bit, 8bit, binary, none */
{
fwrite(getpos_buf(pInBuf), sizeof(char), poslen_buf(pInBuf), fOut);
}
break;
}
return (TRUE);
}
/* ------------------------------------------------------------------------ */
/* create_PartParseState (static)
*
* Private function used initialize the parse state.
*/
static PartParseStatePtr create_PartParseState()
{
PartParseStatePtr p = (PartParseStatePtr) malloc(sizeof(PartParseState));
if (p)
{
p->bFoundHeader = FALSE;
p->pBuf = make_buf();
p->pSearchBuf = make_buf();
strcpy_buf(p->pSearchBuf, "\r\n\r\n");
p->cte = CTE_NONE;
p->nPrevEndMatch = 0;
p->preEncBuffer = NULL;
p->d64state = NULL;
p->dQPstate = NULL;
}
return (p);
}
/* ------------------------------------------------------------------------ */
/* delete_PartParseState (static)
*
* Private function used to delete the parse state.
*/
static void delete_PartParseState(PartParseStatePtr p)
{
if (p)
{
delete_buf(p->pBuf);
delete_buf(p->pSearchBuf);
safefree(p->preEncBuffer);
safefree(p->d64state);
safefree(p->dQPstate);
safefree(p);
}
}
/* ------------------------------------------------------------------------ */
/* DoBufOutput (static)
*
* Private function used to output a buffer.
*/
static void DoBufOutput(FILE *fOut, BufTypePtr pBuf)
{
fwrite(getpos_buf(pBuf), sizeof(char), poslen_buf(pBuf), fOut);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -