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

📄 encoding.cpp

📁 PGP—Pretty Good Privacy
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 *   eQPstate [IN/OUT] state; caller must preserve
 *
 *  Returns: The length of the quoted-printable data
 */
long EncodeQP(
	char *pBin,
	long nLen,
	char *pQP,
	EncQPPtr eQPstate)
{
	/* These characters are legal to leave UNQUOTED, everything else must be quoted */
	const char *gQPEncodeChars
		= "\t\n\r %&'()*+,-./0123456789:;<>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";

	/* The hex digits -- in order */
	const char *pHexArr = "0123456789ABCDEF";
	const char *pQPStart = pQP; /* Remember the start pos */
	char *pEnd, ch, cLastChar;
	int nLineChars, bEncode;

	/* Check if this call is to close the encoding */
	if ((pBin == NULL) || (nLen < 1))
	{
		/* If there is anything on the current line, cap it with an equal */
		/* This avoids having trailing whitespace that would be ignored */
		/* Newline is added for good measure, because we assume TEXT, this */
		/*  shouldn't be a problem */
		if ((eQPstate->nCurLineLen) > 0)
		{
			*pQP++ = '=';
			pQP = newline_copy(pQP);

			eQPstate->nCurLineLen = 0;
			return (pQP - pQPStart);
		}

		return (0);
	}

	/* Restore the state from the caller data */
	nLineChars = eQPstate->nCurLineLen;
	cLastChar = eQPstate->cLastChar;

	/* Loop through the binary data */
	for (pEnd = pBin + nLen; pBin < pEnd; pBin++)
	{
		/* Check if the binary character must be encoded */
		bEncode = (strchr(gQPEncodeChars, (ch = *pBin)) ? 0 : 1);

		/* Will this action put us past the 76 char limit? */
		if ((nLineChars + (bEncode ? 3 : 1)) > 76)
		{
			/* Cap the line, and add a newline */
			*pQP++ = '=';
			pQP = newline_copy(pQP);

			nLineChars = 0; /* Starting new line */
		}

		if (bEncode) /* Encode the character using hex (ie. "A" -> "=41") */
		{
			*pQP++ = '=';
			*pQP++ = pHexArr[(ch>>4) & 0xF];
			*pQP++ = pHexArr[ch & 0xF];
			
			nLineChars += 3;
		}
		else /* No encoding needed, just copy character over */
		{
			*pQP++ = ch;

			/* If we copied a newline, then we need to reset the line char count */
			if (newline_test(cLastChar, ch))
				nLineChars = 0;
			else
				nLineChars++;
		}

		/* Keep track of the last character */
		cLastChar = ch;
	}

	/* Save the state */
	eQPstate->nCurLineLen = nLineChars;
	eQPstate->cLastChar = cLastChar;

	/* Return the number of characters we but in the buffer */
	return (pQP - pQPStart);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Convert quoted printable data to binary
 *
 *  Args:
 *   pQP       [IN]     the quoted printable data (or NULL to close the decoder)
 *   nLen      [IN]     the length of the quoted printable data (or 0 to close the decoder)
 *   pBin      [IN]     pointer to buffer to hold binary data
 *   dQPstate  [IN/OUT] pointer to decoder state; caller must preserve
 *   decErrCnt [OUT]    the number of decoding errors found
 *
 *  Returns: The length of the binary data
 */
long DecodeQP(
	char *pQP,
	long nLen,
	char *pBin,
	DecQPPtr dQPstate,
	long *decErrCnt)
{
	const char *pBinStart = pBin;
	char *pEnd, ch;
	
	/* Restore the state from the caller */
	QPStates CurState = dQPstate->CurState;
	char cLastChar = dQPstate->cLastChar;

	/* Check if this call is to close the decoding */
	if ((pQP == NULL) || (nLen < 1))
	{
		/* If the state is in the middle of doing something, then error */
		if ((CurState == qpEqual) || (CurState == qpEncoded))
		{
			(*decErrCnt)++;
			CurState = qpNormal;
		}

		return (0);
	}

	/* Loop through the QP data */
	for (pEnd = pQP + nLen; pQP < pEnd; pQP++)
	{
		/* Get the current character */
		ch = *pQP;

		/* What state are we in? */
		switch (CurState)
		{
			case qpNormal: /* Normal: copy everything until an 'equal' */
				if (ch == '=')
					CurState = qpEqual; /* Found an 'equal' char */
				else
					*pBin++ = ch;
			break;
					
			case qpEqual: /* qpEqual: Last char was an equal */
				if (isxdigit(ch))                     /* This char should be a hex digit */
					CurState = qpEncoded;
				else if (newline_test(cLastChar, ch)) /* Or it could be a newline */
					CurState = qpNormal;
				else if (isspace(ch))                 /* Or some whitespace before the newline */
					CurState = qpTrailingWhitespace;
				else
					CurState = qpError;               /* Otherwise, an error */
			break;
				
			case qpEncoded: /* qpEncoded: Last char was the first hex digit of an encoding */
				if ((isxdigit(ch)) && (isxdigit(cLastChar)))
				{
					int left = hex2dec(cLastChar);
					int right = hex2dec(ch);
					int leftshift = left << 4;
					int final = leftshift | right;
					/* Decode the hex digits into a character */
					*pBin++ = final;
					CurState = qpNormal;
				}
				else
					CurState = qpError; /* This char is not a hex digit: an error */
			break;

			case qpTrailingWhitespace: /* qpTrailingWhitespace: whitespace is allowed after */
				                       /*  an equals and before the newline */
				if (newline_test(cLastChar, ch))
					CurState = qpNormal; /* When we find the newline, don't copy it */
				else if (!isspace(ch))
					CurState = qpError; /* If we get to some char BEFORE a newline: an error */
			break;
		}

		if (CurState == qpError) /* Count the errors, reset to normal state (keep trying) */
		{
			(*decErrCnt)++;
			CurState = qpNormal;
		}

		/* Keep track of the last character */
		cLastChar = ch;
	}

	/* Save the state for next time */
	dQPstate->CurState = CurState;
	dQPstate->cLastChar = cLastChar;

	/* Return the number of characters we but in the buffer */
	return (pBin - pBinStart);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Parse Content-Transer-Encoding header line
 *
 *  Args:
 *   src [IN] Valid Transfer-Encoding header.
 *
 *  Returns: enumerated integer 'TrEncType' type specifying CTE.
 */
TrEncType rfc822_parse_cte(const char *src)
{
	const char *kPrefixStr = "Content-Transfer-Encoding:";
	const unsigned int kPrefixStrLen = strlen(kPrefixStr);

	char *cp = (char *) src + kPrefixStrLen, *mechanism = NULL;
	TrEncType cte = CTE_Error;

	// Check prefix
	if (strnicmp(src, kPrefixStr, kPrefixStrLen) == 0)
	{
		// Get first token (skips whitespace/comments)
		mechanism = rfc822_extract_token(&cp);

		// If we got something
		if ((mechanism) && (strlen(mechanism) > 0))
		{
			if (stricmp(mechanism, "base64") == 0)
				cte = CTE_Base64;
			else if (stricmp(mechanism, "quoted-printable") == 0)
				cte = CTE_QP;
			else if (stricmp(mechanism, "7bit") == 0)
				cte = CTE_7bit;
			else if (stricmp(mechanism, "8bit") == 0)
				cte = CTE_8bit;
			else if (stricmp(mechanism, "binary") == 0)
				cte = CTE_Binary;
		}

		safefree(mechanism);
	}

	return (cte);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Create Content-Transer-Encoding header line
 *
 *  NOTE: The user of this function is responsible for freeing the
 *        returned string.
 *
 *  Args:
 *   mechanism [IN] Enumerated integer 'TrEncType' type specifying CTE.
 *
 *  Returns: Content tranfer encoding header line string.
 */
char *rfc822_make_cte(TrEncType mechanism)
{
	const char *kPrefix = "Content-Transfer-Encoding: ";
	char pBuf[40], *pCTE;

	switch (mechanism)
	{
		case CTE_Base64:	strcpy(pBuf, "base64");				break;
		case CTE_QP:		strcpy(pBuf, "quoted-printable");	break;
		case CTE_7bit:		strcpy(pBuf, "7bit");				break;
		case CTE_8bit:		strcpy(pBuf, "8bit");				break;
		case CTE_Binary:	strcpy(pBuf, "binary");				break;

		default:
			return (NULL);
	}

	pCTE = (char *) malloc(strlen(pBuf) + strlen(kPrefix) + 1);
	strcpy(pCTE, kPrefix);
	strcat(pCTE, pBuf);

	return (pCTE);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/*
 *  Finds and extracts the content transfer encoding header line from a full
 *  multi-lined header. All unfolding (removing newlines) is done before
 *  header line is returned.
 *
 *  NOTE: The user of this function is responsible for freeing the
 *        returned string.
 *
 *  Args:
 *   pFullHeader [IN] Pointer to a full RFC822 header, including newlines
 *
 *  Returns: Extracted header line string; dynamically allocated.
 */
char *rfc822_extract_cte(const char *pFullHeader)
{
	return rfc822_extract_header(pFullHeader, "Content-Transfer-Encoding:");
}

/* ========================================================================== */
/*                              LOCAL FUNCTIONS                               */
/* ========================================================================== */

/*  NEWLINE STUFF: Used locally to copy and test for newlines  */
static const char gNewlineCh1 = '\r';
static const char gNewlineCh2 = '\n';

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/* Insert a newline, returning position after newline */
/* static */ char *newline_copy(char *dst)
{
	*dst++ = gNewlineCh1;
	*dst++ = gNewlineCh2;

	return dst;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/* Check if these two characters represent a newline */
/* static */ int newline_test(const char prev, const char curr)
{
	return ((prev == gNewlineCh1) && (curr == gNewlineCh2));
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/* Convert a single HEX character-digit (0123456789ABCDEF) to the decimal */
/* value.  NOTE: This function assumes the character is a valid hex digit */
/* static */ int hex2dec(const char ch)
{
	if (isdigit(ch))
		return (ch -'0');

	return ((toupper(ch) - 'A') + 10);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -