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

📄 encoding.cpp

📁 著名的加密软件的应用于电子邮件中
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *  Functions to encode and decode using BASE64 or Quoted-Printable
 *  Also a transfer-encoding header line parser
 *
 *  Filename: encoding.cpp
 *
 *  Last Edited: Friday, August 30, 1996
 *
 *  Author: Scott Manjourides
 *
 *  Portions adopted from code originally written by Stever Dorner.
 *  Copyright 1995, 1996 QUALCOMM Inc.
 *
 *  Send comments and questions to <emsapi-info@qualcomm.com>
 */

#include <windows.h>
#include "ems-win.h"

#include "encoding.h"
#include "rfc822.h"    
#include "string.h" 
#include "ctype.h"   
#include "stdlib.h"

/* ========================================================================= */

#define safefree(p) { if (p) { free(p); (p) = NULL; } }

/* ========================================================================= */

/* Local util functions */
static char *newline_copy(char *dst);
static int newline_test(const char prev, const char curr);
static int hex2dec(const char ch);

/*****************************************************************************/
/*                                B A S E 6 4                                */
/*****************************************************************************/

/* Base64 encoder/decoder ported from Macintosh source by Myra Callen */

#define SKIP (-1)
#define FAIL (-2)
#define PAD  (-3)

#define kNewLine			"\015\012"
#define kNewLineLength (2)

#define ABS(x)   ((x)<0 ? -(x) : (x))

static char *g64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static short g64DecodeArr[] = 
{
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,SKIP,SKIP,FAIL,FAIL,SKIP,FAIL,FAIL,	/* 0 */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* 1 */
	SKIP,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,0x3e,FAIL,FAIL,FAIL,0x3f,	/* 2 */
	0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,FAIL,FAIL,FAIL,PAD ,FAIL,FAIL,	/* 3 */
	FAIL,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,	/* 4 */
	0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,FAIL,FAIL,FAIL,FAIL,FAIL,	/* 5 */
	FAIL,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,	/* 6 */
	0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,FAIL,FAIL,FAIL,FAIL,FAIL,	/* 7 */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* 8 */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* 9 */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* A */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* B */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* C */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* D */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* E */
	FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,FAIL,	/* F */
  /* 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F  */
};

/*
 * Bit extracting macros
 */
#define Bot2(b) ((b)&0x3)
#define Bot4(b) ((b)&0xf)
#define Bot6(b) ((b)&0x3f)
#define Top2(b) Bot2((b)>>6)
#define Top4(b) Bot4((b)>>4)
#define Top6(b) Bot6((b)>>2)

/*
 * the decoder
 */
#define EncodeThree64(bin,b64,bpl)	EncodeThreeFour(bin,b64,bpl,g64EncodeChars)

#define EncodeThreeFour(bin,b64,bpl,vector)                     \
	do                                                          \
	{                                                           \
		if ((bpl)==68)                                          \
		{                                                       \
			(b64) = newline_copy(b64);                          \
			(bpl) = 0;                                          \
		}                                                       \
		(bpl) += 4;                                             \
		*(b64)++ = vector[Top6((bin)[0])];                      \
		*(b64)++ = vector[Bot2((bin)[0])<<4 | Top4((bin)[1])];  \
		*(b64)++ = vector[Bot4((bin)[1])<<2 | Top2((bin)[2])];  \
		*(b64)++ = vector[Bot6((bin)[2])];                      \
	}                                                           \
	while (0)

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

/*
 *  Convert binary data to base64
 *
 *  Args:
 *   binPtr     [IN]     the binary data (or NULL to close encoder)
 *   binLen     [IN]     the length of the binary data
 *   sixFourPtr [IN]     pointer to buffer for the base64 data
 *   e64        [IN/OUT] state; caller must preserve
 *
 *  Returns: The length of the base64 data
 */
long Encode64(
	char *binPtr,
	long binLen,
	char *sixFourPtr,
	Enc64Ptr e64)
{
	char *binSpot;									/* the byte currently being decoded */
	char *sixFourSpot = sixFourPtr;	/* the spot to which to copy the encoded chars */
	short bpl;
	char *end;											/* end of integral decoding */

	bpl = e64->bytesOnLine;	/* in inner loop; want local copy */
	
	if (binLen)
	{
		
		/*
		 * do we have any stuff left from last time?
		 */
		if (e64->partialCount)
		{
			short needMore = 3 - e64->partialCount;
			if (binLen >= needMore)
			{
				/*
				 * we can encode some bytes
				 */
				memcpy(e64->partial+e64->partialCount,binPtr,needMore);
				binLen -= needMore;
				binPtr += needMore;
				EncodeThree64(e64->partial,sixFourSpot,bpl);
				e64->partialCount = 0;
			}
			/*
			 * if we don't have enough bytes to complete the leftovers, we
			 * obviously don't have 3 bytes.  So the encoding code will fall
			 * through to the point where we copy the leftovers to the partial
			 * buffer.  As long as we're careful to append and not copy blindly,
			 * we'll be fine.
			 */
		}
		
		/*
		 * we encode the integral multiples of three
		 */
		end = binPtr + 3*(binLen/3);
		for (binSpot = binPtr; binSpot < end; binSpot += 3)
		{
			EncodeThree64(binSpot,sixFourSpot,bpl);
			/* *sixFourLen = sixFourSpot - sixFourPtr; */
		}
		
		/*
		 * now, copy the leftovers to the partial buffer
		 */
		binLen = binLen % 3;
		if (binLen)
		{
			memcpy(e64->partial+e64->partialCount,binSpot,binLen);
			e64->partialCount += (short)binLen;
		}
	}
	else
	{
		/*
		 * we've been called to cleanup the leftovers
		 */
		if (e64->partialCount)
		{
			if (e64->partialCount<2) e64->partial[1] = 0;
			e64->partial[2] = 0;
			EncodeThree64(e64->partial,sixFourSpot,bpl);
			
			/*
			 * now, replace the unneeded bytes with ='s
			 */
			sixFourSpot[-1] = '=';
			if (e64->partialCount==1) sixFourSpot[-2] = '=';
		}
	}

	e64->bytesOnLine = bpl;	/* copy back to state buffer */

	return (sixFourSpot - sixFourPtr);
}

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

/*
 *  Convert base64 data to binary
 *
 *  Args:
 *   sixFourPtr [IN]     the base64 data (or nil to close decoder)
 *   sixFourLen [IN]     the length of the base64 data
 *   binPtr     [IN]     pointer to buffer to hold binary data
 *   d64        [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 Decode64(
	char *sixFourPtr,
	long sixFourLen,
	char *binPtr,
	Dec64Ptr d64,
	long *decErrCnt)
{
	short 	decode;													/* the decoded short */
	unsigned char 		c;															/* the decoded byte */
	/* we separate the short & the byte to the compiler can worry about byteorder */
	char *end = sixFourPtr + sixFourLen;	/* stop decoding here */
	char *binSpot = binPtr;								/* current output character */
	short 	decoderState;		/* which of 4 bytes are we seeing now? */
	long 		invalCount;			/* how many bad chars found this time around? */
	long 		padCount;				/* how many pad chars found so far? */
	unsigned char 		partial;				/* partially decoded byte from/for last/next time */
	short wasCR;
	char *sixFourStartPtr;
	
	/*
	 * fetch state from caller's buffer
	 */
	decoderState = d64->decoderState;
	invalCount = 0;	/* we'll add the invalCount to the buffer later */
	padCount = d64->padCount;
	partial = d64->partial;
	wasCR = d64->wasCR;
	
	if (sixFourLen)
	{
		sixFourStartPtr = sixFourPtr;
		for (;sixFourPtr<end;sixFourPtr++)
		{
			switch(decode=g64DecodeArr[*sixFourPtr])
			{
				case SKIP: break;									/* skip whitespace */
				case FAIL: invalCount++; break;		/* count invalid characters */
				case PAD: padCount++; break;			/* count pad characters */
				default:
					/*
					 * found a non-pad character, so if we had previously found a pad,
					 * that pad was an error
				 	*/
					if (padCount) {invalCount+=padCount;padCount=0;}
					
					/*
					 * extract the right bits
					 */
					c = (char) decode;
					switch (decoderState)
					{
						case 0:
							partial = c<<2;
							decoderState++;
							break;
						case 1:
							*binSpot++ = partial|Top4(c);
							partial = Bot4(c)<<4;
							decoderState++;
							break;
						case 2:
							*binSpot++ = partial|Top6(c);
							partial = Bot2(c)<<6;
							decoderState++;
							break;
						case 3:
							*binSpot++ = partial|c;
							decoderState=0;
							break;
					} /* switch decoderState */
			} /* switch decode */
		} /* for sixFourPtr */
	} /* if sixFourLen */
	else
	{
		/*
		 * all done.  Did all end up evenly?
		 */
		switch (decoderState)
		{
			case 0:
				invalCount += padCount;		/* came out evenly, so should be no pads */
				break;
			case 1:
				invalCount++;							/* data missing */
				invalCount += padCount;		/* since data missing; should be no pads */
				break;
			case 2:
				invalCount += ABS(padCount-2);	/* need exactly 2 pads */
				break;
			case 3:
				invalCount += ABS(padCount-1);	/* need exactly 1 pad */
				break;
		}
	}
	
	/*
	 * save state in caller's buffer
	 */
	d64->decoderState = decoderState;
	d64->invalCount += invalCount;
	d64->padCount = padCount;
	d64->partial = partial;
	d64->wasCR = wasCR;

	*decErrCnt = invalCount;

	return (binSpot - binPtr);
}

/*****************************************************************************/
/*                      Q U O T E D - P R I N T A B L E                      */
/*****************************************************************************/

/* ------------------------------------------------------------------------- */
/* NOTE: To handle BINARY data, you must always quote newline characters,    */
/*   this implementation assumes TEXT data and thus does not encode newlines */
/* ------------------------------------------------------------------------- */

/*
 *  Convert binary data to quoted-printable
 *
 *  Args:
 *   pBin     [IN]     the binary data (or NULL to close the encoder)
 *   nLen     [IN]     the length of the binary data (or 0 to close the encoder)
 *   pQP      [IN]     pointer to buffer for the quoted-printable data

⌨️ 快捷键说明

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