1 //////////////////////////////////////////////////////////////////////
\r
3 // MIME Encoding/Decoding:
\r
4 // Quoted-printable and Base64 for content encoding;
\r
5 // Encoded-word for header field encoding.
\r
10 //////////////////////////////////////////////////////////////////////
\r
12 #if !defined(_MIME_CODING_H)
\r
13 #define _MIME_CODING_H
\r
17 #endif // _MSC_VER > 1000
\r
22 using namespace std;
\r
24 #pragma warning(disable:4786) // identifier was truncated to 'number' characters in the debug information
\r
26 #if !defined(ASSERT)
\r
29 #define ASSERT(exp) assert(exp)
\r
31 #define ASSERT(exp) ((void)0)
\r
35 #if defined(_DEBUG) && !defined(DEBUG_NEW)
\r
36 #define DEBUG_NEW new
\r
39 // maximum length of an encoded line (RFC 2045)
\r
40 #define MAX_MIME_LINE_LEN 76
\r
41 #define MAX_ENCODEDWORD_LEN 75
\r
43 //////////////////////////////////////////////////////////////////////
\r
44 // CMimeEnvironment - global environment to manage encoding/decoding
\r
45 //////////////////////////////////////////////////////////////////////
\r
46 class CMimeCodeBase;
\r
47 class CFieldCodeBase;
\r
49 class CMimeEnvironment
\r
56 static void SetAutoFolding(bool bAutoFolding=true);
\r
57 static bool AutoFolding() { return m_bAutoFolding; }
\r
58 static void SetGlobalCharset(const char* pszCharset) { m_strCharset = pszCharset; }
\r
59 static const char* GetGlobalCharset() { return m_strCharset.c_str(); }
\r
61 // Content-Transfer-Encoding coder management
\r
62 typedef CMimeCodeBase* (*CODER_FACTORY)();
\r
63 static void RegisterCoder(const char* pszCodingName, CODER_FACTORY pfnCreateObject=NULL);
\r
64 static CMimeCodeBase* CreateCoder(const char* pszCodingName);
\r
66 // header fields encoding/folding management
\r
67 typedef CFieldCodeBase* (*FIELD_CODER_FACTORY)();
\r
68 static void RegisterFieldCoder(const char* pszFieldName, FIELD_CODER_FACTORY pfnCreateObject=NULL);
\r
69 static CFieldCodeBase* CreateFieldCoder(const char* pszFieldName);
\r
71 // media type management
\r
72 typedef CMimeBody* (*BODY_PART_FACTORY)();
\r
73 static void RegisterMediaType(const char* pszMediaType, BODY_PART_FACTORY pfnCreateObject=NULL);
\r
74 static CMimeBody* CreateBodyPart(const char* pszMediaType);
\r
77 static bool m_bAutoFolding;
\r
78 static string m_strCharset;
\r
80 typedef pair<const char*, CODER_FACTORY> CODER_PAIR;
\r
81 static list<CODER_PAIR> m_listCoders;
\r
83 typedef pair<const char*, FIELD_CODER_FACTORY> FIELD_CODER_PAIR;
\r
84 static list<FIELD_CODER_PAIR> m_listFieldCoders;
\r
86 typedef pair<const char*, BODY_PART_FACTORY> MEDIA_TYPE_PAIR;
\r
87 static list<MEDIA_TYPE_PAIR> m_listMediaTypes;
\r
89 static CMimeEnvironment m_globalMgr;
\r
92 #define DECLARE_MIMECODER(class_name) \
\r
93 public: static CMimeCodeBase* CreateObject() { return new class_name; }
\r
95 #define REGISTER_MIMECODER(coding_name, class_name) \
\r
96 CMimeEnvironment::RegisterCoder(coding_name, class_name::CreateObject)
\r
98 #define DEREGISTER_MIMECODER(coding_name) \
\r
99 CMimeEnvironment::RegisterCoder(coding_name, 0)
\r
101 #define DECLARE_FIELDCODER(class_name) \
\r
102 public: static CFieldCodeBase* CreateObject() { return new class_name; }
\r
104 #define REGISTER_FIELDCODER(field_name, class_name) \
\r
105 CMimeEnvironment::RegisterFieldCoder(field_name, class_name::CreateObject)
\r
107 #define DEREGISTER_FIELDCODER(field_name) \
\r
108 CMimeEnvironment::RegisterFieldCoder(field_name, 0)
\r
110 #define DECLARE_MEDIATYPE(class_name) \
\r
111 public: static CMimeBody* CreateObject() { return new class_name; }
\r
113 #define REGISTER_MEDIATYPE(media_type, class_name) \
\r
114 CMimeEnvironment::RegisterMediaType(media_type, class_name::CreateObject)
\r
116 #define DEREGISTER_MEDIATYPE(media_type) \
\r
117 CMimeEnvironment::RegisterMediaType(media_type, 0)
\r
119 //////////////////////////////////////////////////////////////////////
\r
120 // CMimeCodeBase - base class for MIME encoding/decoding
\r
121 // default implementation for binary/unknown encoding mechanism
\r
122 //////////////////////////////////////////////////////////////////////
\r
123 class CMimeCodeBase
\r
129 m_bIsEncoding(false) {}
\r
132 void SetInput(const char* pbInput, int nInputSize, bool bEncoding)
\r
134 m_pbInput = (const unsigned char*) pbInput;
\r
135 m_nInputSize = nInputSize;
\r
136 m_bIsEncoding = bEncoding;
\r
138 int GetOutputLength() const
\r
140 return m_bIsEncoding ? GetEncodeLength() : GetDecodeLength();
\r
142 int GetOutput(unsigned char* pbOutput, int nMaxSize)
\r
144 return m_bIsEncoding ? Encode(pbOutput, nMaxSize) : Decode(pbOutput, nMaxSize);
\r
149 virtual int GetEncodeLength() const { return m_nInputSize; }
\r
150 virtual int GetDecodeLength() const { return m_nInputSize; }
\r
151 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const
\r
153 int nSize = min(nMaxSize, m_nInputSize);
\r
154 ::memcpy(pbOutput, m_pbInput, nSize);
\r
157 virtual int Decode(unsigned char* pbOutput, int nMaxSize)
\r
159 return CMimeCodeBase::Encode(pbOutput, nMaxSize);
\r
163 const unsigned char* m_pbInput;
\r
165 bool m_bIsEncoding;
\r
168 //////////////////////////////////////////////////////////////////////
\r
169 // CMimeCode7bit - for 7bit/8bit encoding mechanism (fold long line)
\r
170 //////////////////////////////////////////////////////////////////////
\r
171 class CMimeCode7bit : public CMimeCodeBase
\r
173 DECLARE_MIMECODER(CMimeCode7bit)
\r
176 virtual int GetEncodeLength() const;
\r
177 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
180 //////////////////////////////////////////////////////////////////////
\r
181 // CMimeCodeQP - for quoted-printable encoding mechanism
\r
182 //////////////////////////////////////////////////////////////////////
\r
183 class CMimeCodeQP : public CMimeCodeBase
\r
187 m_bQuoteLineBreak(false) {}
\r
190 DECLARE_MIMECODER(CMimeCodeQP)
\r
191 void QuoteLineBreak(bool bQuote=true) { m_bQuoteLineBreak = bQuote; }
\r
194 virtual int GetEncodeLength() const;
\r
195 //virtual int GetDecodeLength() const;
\r
196 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
197 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
200 bool m_bQuoteLineBreak;
\r
203 //////////////////////////////////////////////////////////////////////
\r
204 // CMimeCodeBase64 - for base64 encoding mechanism
\r
205 //////////////////////////////////////////////////////////////////////
\r
206 class CMimeCodeBase64 : public CMimeCodeBase
\r
209 CMimeCodeBase64() :
\r
210 m_bAddLineBreak(true) {}
\r
213 DECLARE_MIMECODER(CMimeCodeBase64)
\r
214 void AddLineBreak(bool bAdd=true) { m_bAddLineBreak = bAdd; }
\r
217 virtual int GetEncodeLength() const;
\r
218 virtual int GetDecodeLength() const;
\r
219 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
220 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
223 bool m_bAddLineBreak;
\r
226 static inline int DecodeBase64Char(unsigned int nCode)
\r
228 if (nCode >= 'A' && nCode <= 'Z')
\r
229 return nCode - 'A';
\r
230 if (nCode >= 'a' && nCode <= 'z')
\r
231 return nCode - 'a' + 26;
\r
232 if (nCode >= '0' && nCode <= '9')
\r
233 return nCode - '0' + 52;
\r
242 //////////////////////////////////////////////////////////////////////
\r
243 // CMimeEncodedWord - encoded word for non-ascii text (RFC 2047)
\r
244 //////////////////////////////////////////////////////////////////////
\r
245 class CMimeEncodedWord : public CMimeCodeBase
\r
248 CMimeEncodedWord() :
\r
251 void SetEncoding(int nEncoding, const char* pszCharset)
\r
253 m_nEncoding = nEncoding;
\r
254 m_strCharset = pszCharset;
\r
256 int GetEncoding() const { return m_nEncoding; }
\r
257 const char* GetCharset() const { return m_strCharset.c_str(); }
\r
260 virtual int GetEncodeLength() const;
\r
261 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
262 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
266 string m_strCharset;
\r
268 int BEncode(unsigned char* pbOutput, int nMaxSize) const;
\r
269 int QEncode(unsigned char* pbOutput, int nMaxSize) const;
\r
272 //////////////////////////////////////////////////////////////////////
\r
273 // CFieldCodeBase - base class to encode/decode header fields
\r
274 // default coder for any unregistered fields
\r
275 //////////////////////////////////////////////////////////////////////
\r
276 class CFieldCodeBase : public CMimeCodeBase
\r
279 void SetCharset(const char* pszCharset) { m_strCharset = pszCharset; }
\r
280 const char* GetCharset() const { return m_strCharset.c_str(); }
\r
283 string m_strCharset;
\r
285 virtual bool IsFoldingChar(char /*ch*/) const { return false; }
\r
286 virtual int GetDelimeter() const { return 0; }
\r
287 int FindSymbol(const char* pszData, int nSize, int& nDelimeter, int& nNonAscChars) const;
\r
288 void UnfoldField(string& strField) const;
\r
289 int SelectEncoding(int nLength, int nNonAsciiChars) const
\r
291 int nQEncodeSize = nLength + nNonAsciiChars * 2;
\r
292 int nBEncodeSize = (nLength + 2) / 3 * 4;
\r
293 return (nQEncodeSize <= nBEncodeSize || nNonAsciiChars*5 <= nLength) ? 'Q' : 'B';
\r
297 virtual int GetEncodeLength() const;
\r
298 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
299 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
302 //////////////////////////////////////////////////////////////////////
\r
303 // CFieldCodeText - encode/decode header fields defined as *text
\r
304 //////////////////////////////////////////////////////////////////////
\r
305 class CFieldCodeText : public CFieldCodeBase
\r
307 DECLARE_FIELDCODER(CFieldCodeText)
\r
310 virtual int GetDelimeter() const { return 0xff; }
\r
313 //////////////////////////////////////////////////////////////////////
\r
314 // CFieldCodeAddress - encode/decode header fields defined as address
\r
315 //////////////////////////////////////////////////////////////////////
\r
316 class CFieldCodeAddress : public CFieldCodeBase
\r
318 DECLARE_FIELDCODER(CFieldCodeAddress)
\r
321 virtual bool IsFoldingChar(char ch) const { return ch == ',' || ch == ':'; }
\r
324 //////////////////////////////////////////////////////////////////////
\r
325 // CFieldCodeParameter - encode/decode header fields have parameters
\r
326 //////////////////////////////////////////////////////////////////////
\r
327 class CFieldCodeParameter : public CFieldCodeBase
\r
329 DECLARE_FIELDCODER(CFieldCodeParameter)
\r
332 virtual bool IsFoldingChar(char ch) const { return ch == ';'; }
\r
335 #endif // !defined(_MIME_CODING_H)
\r