// MIME.cpp : implementation of the CPostEView class // #include "stdafx.h" #include "MIME.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //////////////////////////////////////////////////////////////////////////////// //Attachment Handlers static const CString NL("\r\n"); BOOL File2QPTxt(const char* inFilePath, const char* outFilePath) { CFile inFile,outFile; if(!inFile.Open(inFilePath,CFile::modeRead|CFile::shareDenyNone)) return FALSE; if(!outFile.Open(outFilePath, CFile::modeCreate|CFile::modeWrite)) return FALSE; CString S; CArchive src(& inFile,CArchive::load); CArchive dst(&outFile,CArchive::store); while(src.ReadString(S)) dst.WriteString(String2QPTxt(S)); return TRUE; } BOOL QPTxt2File(const char* inFilePath, const char* outFilePath) { CFile inFile,outFile; if(!inFile.Open(inFilePath,CFile::modeRead|CFile::shareDenyNone)) return FALSE; if(!outFile.Open(outFilePath, CFile::modeCreate|CFile::modeWrite)) return FALSE; CString S; CArchive src(& inFile,CArchive::load); CArchive dst(&outFile,CArchive::store); while(src.ReadString(S)) dst.WriteString(QPTxt2String(S)); return TRUE; } //////////////////////////////////////////////////////////////////////////////// BOOL MIME2File(const char* inFilePath, const char* outFilePath) { CString S; CFile inFile,outFile; if(!inFile.Open(inFilePath,CFile::modeRead|CFile::shareDenyNone)) return FALSE; if(!outFile.Open(outFilePath,CFile::modeCreate|CFile::modeWrite)) return FALSE; CArchive ar(&inFile,CArchive::load); char Result[57+1]; while(ar.ReadString(S)) { char Len=Base64ToString(S, Result); outFile.Write(Result, Len); } return TRUE; } BOOL File2MIME(const char* inFilePath, const char* outFilePath) { CFile inFile,outFile; if(!inFile.Open(inFilePath,CFile::modeRead|CFile::shareDenyNone)) return FALSE; if(!outFile.Open(outFilePath, CFile::modeCreate|CFile::modeWrite)) return FALSE; int Len=inFile.GetLength(); BYTE src[57]; char dst[76+1]; int Count=Len/57; for(int i=0; i>=6; *dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6; *dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6; *dst =Bit6ToBase64[EncodeShifter & 0x3F]; dst+=7; } *(dst-3)=0; switch(mod) { case 1: { EncodeShifter=*src; EncodeShifter<<=4;//111111 112222 222233 333333 *(dst+1)=0; // ==== *dst--='='; *dst--='='; *dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6; *dst =Bit6ToBase64[EncodeShifter & 0x3F]; break; }case 2: { EncodeShifter=*src++; EncodeShifter=(EncodeShifter<<8)|*src; EncodeShifter<<=2;//111111 112222 222233 333333 *(dst+1)=0; // == *dst--='='; *dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6; *dst--=Bit6ToBase64[EncodeShifter & 0x3F]; EncodeShifter>>=6; *dst =Bit6ToBase64[EncodeShifter & 0x3F]; } } } //////////////////////////////////////////////////////////////////////////////// char Base64ToString(const char* src, char* Result) { static const BYTE Base64ToBit6[128]={ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, 52,53,54,55,56,57,58,59,60,61,-1,-1,-1, 0,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, }; register char* dst=Result+2; register DWORD DecodeShifter=0; int div=strlen(src)>>2; //no mod: the Law says its divisible by 4. BYTE B; for(int i=0; i>=4; *--dst=(char)DecodeShifter; return dst-Result+1; } DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B]; if((B=*src++) & 0x80 || B<0) return *Result=0; //crap characters in stream if(B=='=') {//11 11112222 22333333 *dst--=0; //== DecodeShifter>>=2; *dst--=(char)DecodeShifter; DecodeShifter>>=8; *dst =(char)DecodeShifter; return dst-Result+2; } DecodeShifter=(DecodeShifter<<6) | Base64ToBit6[B]; *dst--=(char)DecodeShifter; DecodeShifter>>=8; *dst--=(char)DecodeShifter; DecodeShifter>>=8; *dst =(char)DecodeShifter; dst+=5; } *(dst-=2)=0; if(dst-Result>127) return *Result=0; //We're not looking at a valid Base64 section! return dst-Result; } //////////////////////////////////////////////////////////////////////////////// CString String2QPTxt(const char* S) { static const CString Q="?=!\"#$@[\\]^`{|}~"; CString Result; int Len=0; while(BYTE b=*S++) { if(b>127 || (Q.Find(b)!=-1) || (!*S && (b==' ' || b=='\t'))) {//Preserve trailing spaces BYTE B=b>>4; b&=0x0F; B=(B>9) ? B-10+'A' : B+'0'; b=(b>9) ? b-10+'A' : b+'0'; char Buffer[3]; char* ptr=Buffer; *ptr++=B; *ptr++=b; *ptr =0; Result=Result+'='+ Buffer; }else{ Result+=b; Len++; } if((Len==75) && b!='\r' && b!='\n') { Len=0; Result+="=\r\n"; //Soft break for long lines } } return Result+NL; //May append a NL at EOF } //////////////////////////////////////////////////////////////////////////////// CString QPTxt2String(const char* S) { CString Result; char* dst=Result.GetBufferSetLength(strlen(S)+3); if(*S) { const char* src=S; BYTE b; while(b=*src++) { if(b=='=') { if(b=*src++) { b|=0x20; BYTE B=(*src++)|0x20; b=(b>'9') ? b-'a'+10 : b-'0'; B=(B>'9') ? B-'a'+10 : B-'0'; b=(b<<4)|B; }else{ //Soft Break *dst=0; Result.ReleaseBuffer(); return Result; } } *dst++=b; } } *dst++='\r'; *dst++='\n'; *dst=0; Result.ReleaseBuffer(); return Result; }