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
23 using namespace std;
\r
25 #pragma warning(disable:4786) // identifier was truncated to 'number' characters in the debug information
\r
27 #if !defined(ASSERT)
\r
30 #define ASSERT(exp) assert(exp)
\r
32 #define ASSERT(exp) ((void)0)
\r
36 #if defined(_DEBUG) && !defined(DEBUG_NEW)
\r
37 #define DEBUG_NEW new
\r
40 // maximum length of an encoded line (RFC 2045)
\r
41 #define MAX_MIME_LINE_LEN 76
\r
42 #define MAX_ENCODEDWORD_LEN 75
\r
44 //////////////////////////////////////////////////////////////////////
\r
45 // CMimeEnvironment - global environment to manage encoding/decoding
\r
46 //////////////////////////////////////////////////////////////////////
\r
47 class CMimeCodeBase;
\r
48 class CFieldCodeBase;
\r
50 class CMimeEnvironment
\r
57 static void SetAutoFolding(bool bAutoFolding=true);
\r
58 static bool AutoFolding() { return m_bAutoFolding; }
\r
59 static void SetGlobalCharset(const char* pszCharset) { m_strCharset = pszCharset; }
\r
60 static const char* GetGlobalCharset() { return m_strCharset.c_str(); }
\r
62 // Content-Transfer-Encoding coder management
\r
63 typedef CMimeCodeBase* (*CODER_FACTORY)();
\r
64 static void RegisterCoder(const char* pszCodingName, CODER_FACTORY pfnCreateObject=NULL);
\r
65 static CMimeCodeBase* CreateCoder(const char* pszCodingName);
\r
67 // header fields encoding/folding management
\r
68 typedef CFieldCodeBase* (*FIELD_CODER_FACTORY)();
\r
69 static void RegisterFieldCoder(const char* pszFieldName, FIELD_CODER_FACTORY pfnCreateObject=NULL);
\r
70 static CFieldCodeBase* CreateFieldCoder(const char* pszFieldName);
\r
72 // media type management
\r
73 typedef CMimeBody* (*BODY_PART_FACTORY)();
\r
74 static void RegisterMediaType(const char* pszMediaType, BODY_PART_FACTORY pfnCreateObject=NULL);
\r
75 static CMimeBody* CreateBodyPart(const char* pszMediaType);
\r
78 static bool m_bAutoFolding;
\r
79 static string m_strCharset;
\r
81 typedef pair<const char*, CODER_FACTORY> CODER_PAIR;
\r
82 static list<CODER_PAIR> m_listCoders;
\r
84 typedef pair<const char*, FIELD_CODER_FACTORY> FIELD_CODER_PAIR;
\r
85 static list<FIELD_CODER_PAIR> m_listFieldCoders;
\r
87 typedef pair<const char*, BODY_PART_FACTORY> MEDIA_TYPE_PAIR;
\r
88 static list<MEDIA_TYPE_PAIR> m_listMediaTypes;
\r
90 static CMimeEnvironment m_globalMgr;
\r
93 #define DECLARE_MIMECODER(class_name) \
\r
94 public: static CMimeCodeBase* CreateObject() { return new class_name; }
\r
96 #define REGISTER_MIMECODER(coding_name, class_name) \
\r
97 CMimeEnvironment::RegisterCoder(coding_name, class_name::CreateObject)
\r
99 #define DEREGISTER_MIMECODER(coding_name) \
\r
100 CMimeEnvironment::RegisterCoder(coding_name, 0)
\r
102 #define DECLARE_FIELDCODER(class_name) \
\r
103 public: static CFieldCodeBase* CreateObject() { return new class_name; }
\r
105 #define REGISTER_FIELDCODER(field_name, class_name) \
\r
106 CMimeEnvironment::RegisterFieldCoder(field_name, class_name::CreateObject)
\r
108 #define DEREGISTER_FIELDCODER(field_name) \
\r
109 CMimeEnvironment::RegisterFieldCoder(field_name, 0)
\r
111 #define DECLARE_MEDIATYPE(class_name) \
\r
112 public: static CMimeBody* CreateObject() { return new class_name; }
\r
114 #define REGISTER_MEDIATYPE(media_type, class_name) \
\r
115 CMimeEnvironment::RegisterMediaType(media_type, class_name::CreateObject)
\r
117 #define DEREGISTER_MEDIATYPE(media_type) \
\r
118 CMimeEnvironment::RegisterMediaType(media_type, 0)
\r
120 //////////////////////////////////////////////////////////////////////
\r
121 // CMimeCodeBase - base class for MIME encoding/decoding
\r
122 // default implementation for binary/unknown encoding mechanism
\r
123 //////////////////////////////////////////////////////////////////////
\r
124 class CMimeCodeBase
\r
130 m_bIsEncoding(false) {}
\r
133 void SetInput(const char* pbInput, int nInputSize, bool bEncoding)
\r
135 m_pbInput = (const unsigned char*) pbInput;
\r
136 m_nInputSize = nInputSize;
\r
137 m_bIsEncoding = bEncoding;
\r
139 int GetOutputLength() const
\r
141 return m_bIsEncoding ? GetEncodeLength() : GetDecodeLength();
\r
143 int GetOutput(unsigned char* pbOutput, int nMaxSize)
\r
145 return m_bIsEncoding ? Encode(pbOutput, nMaxSize) : Decode(pbOutput, nMaxSize);
\r
150 virtual int GetEncodeLength() const { return m_nInputSize; }
\r
151 virtual int GetDecodeLength() const { return m_nInputSize; }
\r
152 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const
\r
154 int nSize = min(nMaxSize, m_nInputSize);
\r
155 ::memcpy(pbOutput, m_pbInput, nSize);
\r
158 virtual int Decode(unsigned char* pbOutput, int nMaxSize)
\r
160 return CMimeCodeBase::Encode(pbOutput, nMaxSize);
\r
164 const unsigned char* m_pbInput;
\r
166 bool m_bIsEncoding;
\r
169 //////////////////////////////////////////////////////////////////////
\r
170 // CMimeCode7bit - for 7bit/8bit encoding mechanism (fold long line)
\r
171 //////////////////////////////////////////////////////////////////////
\r
172 class CMimeCode7bit : public CMimeCodeBase
\r
174 DECLARE_MIMECODER(CMimeCode7bit)
\r
177 virtual int GetEncodeLength() const;
\r
178 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
181 //////////////////////////////////////////////////////////////////////
\r
182 // CMimeCodeQP - for quoted-printable encoding mechanism
\r
183 //////////////////////////////////////////////////////////////////////
\r
184 class CMimeCodeQP : public CMimeCodeBase
\r
188 m_bQuoteLineBreak(false) {}
\r
191 DECLARE_MIMECODER(CMimeCodeQP)
\r
192 void QuoteLineBreak(bool bQuote=true) { m_bQuoteLineBreak = bQuote; }
\r
195 virtual int GetEncodeLength() const;
\r
196 //virtual int GetDecodeLength() const;
\r
197 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
198 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
201 bool m_bQuoteLineBreak;
\r
204 //////////////////////////////////////////////////////////////////////
\r
205 // CMimeCodeBase64 - for base64 encoding mechanism
\r
206 //////////////////////////////////////////////////////////////////////
\r
207 class CMimeCodeBase64 : public CMimeCodeBase
\r
210 CMimeCodeBase64() :
\r
211 m_bAddLineBreak(true) {}
\r
214 DECLARE_MIMECODER(CMimeCodeBase64)
\r
215 void AddLineBreak(bool bAdd=true) { m_bAddLineBreak = bAdd; }
\r
218 virtual int GetEncodeLength() const;
\r
219 virtual int GetDecodeLength() const;
\r
220 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
221 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
224 bool m_bAddLineBreak;
\r
227 static inline int DecodeBase64Char(unsigned int nCode)
\r
229 if (nCode >= 'A' && nCode <= 'Z')
\r
230 return nCode - 'A';
\r
231 if (nCode >= 'a' && nCode <= 'z')
\r
232 return nCode - 'a' + 26;
\r
233 if (nCode >= '0' && nCode <= '9')
\r
234 return nCode - '0' + 52;
\r
243 //////////////////////////////////////////////////////////////////////
\r
244 // CMimeEncodedWord - encoded word for non-ascii text (RFC 2047)
\r
245 //////////////////////////////////////////////////////////////////////
\r
246 class CMimeEncodedWord : public CMimeCodeBase
\r
249 CMimeEncodedWord() :
\r
252 void SetEncoding(int nEncoding, const char* pszCharset)
\r
254 m_nEncoding = nEncoding;
\r
255 m_strCharset = pszCharset;
\r
257 int GetEncoding() const { return m_nEncoding; }
\r
258 const char* GetCharset() const { return m_strCharset.c_str(); }
\r
261 virtual int GetEncodeLength() const;
\r
262 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
263 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
267 string m_strCharset;
\r
269 int BEncode(unsigned char* pbOutput, int nMaxSize) const;
\r
270 int QEncode(unsigned char* pbOutput, int nMaxSize) const;
\r
273 //////////////////////////////////////////////////////////////////////
\r
274 // CFieldCodeBase - base class to encode/decode header fields
\r
275 // default coder for any unregistered fields
\r
276 //////////////////////////////////////////////////////////////////////
\r
277 class CFieldCodeBase : public CMimeCodeBase
\r
280 void SetCharset(const char* pszCharset) { m_strCharset = pszCharset; }
\r
281 const char* GetCharset() const { return m_strCharset.c_str(); }
\r
284 string m_strCharset;
\r
286 virtual bool IsFoldingChar(char /*ch*/) const { return false; }
\r
287 virtual int GetDelimeter() const { return 0; }
\r
288 int FindSymbol(const char* pszData, int nSize, int& nDelimeter, int& nNonAscChars) const;
\r
289 void UnfoldField(string& strField) const;
\r
290 int SelectEncoding(int nLength, int nNonAsciiChars) const
\r
292 int nQEncodeSize = nLength + nNonAsciiChars * 2;
\r
293 int nBEncodeSize = (nLength + 2) / 3 * 4;
\r
294 return (nQEncodeSize <= nBEncodeSize || nNonAsciiChars*5 <= nLength) ? 'Q' : 'B';
\r
298 virtual int GetEncodeLength() const;
\r
299 virtual int Encode(unsigned char* pbOutput, int nMaxSize) const;
\r
300 virtual int Decode(unsigned char* pbOutput, int nMaxSize);
\r
303 //////////////////////////////////////////////////////////////////////
\r
304 // CFieldCodeText - encode/decode header fields defined as *text
\r
305 //////////////////////////////////////////////////////////////////////
\r
306 class CFieldCodeText : public CFieldCodeBase
\r
308 DECLARE_FIELDCODER(CFieldCodeText)
\r
311 virtual int GetDelimeter() const { return 0xff; }
\r
314 //////////////////////////////////////////////////////////////////////
\r
315 // CFieldCodeAddress - encode/decode header fields defined as address
\r
316 //////////////////////////////////////////////////////////////////////
\r
317 class CFieldCodeAddress : public CFieldCodeBase
\r
319 DECLARE_FIELDCODER(CFieldCodeAddress)
\r
322 virtual bool IsFoldingChar(char ch) const { return ch == ',' || ch == ':'; }
\r
325 //////////////////////////////////////////////////////////////////////
\r
326 // CFieldCodeParameter - encode/decode header fields have parameters
\r
327 //////////////////////////////////////////////////////////////////////
\r
328 class CFieldCodeParameter : public CFieldCodeBase
\r
330 DECLARE_FIELDCODER(CFieldCodeParameter)
\r
333 virtual bool IsFoldingChar(char ch) const { return ch == ';'; }
\r
336 #endif // !defined(_MIME_CODING_H)
\r