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

📄 rfc1847.cpp

📁 著名的加密软件的应用于电子邮件中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 *  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 + -