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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/*****************************************************************************/
/* Mime.h Copyright (c) Ladislav Zezula 2021 */
/*---------------------------------------------------------------------------*/
/* MIME parsing functions for CascLib */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 21.01.21 1.00 Lad Created */
/*****************************************************************************/
#ifndef __MIME_H__
#define __MIME_H__
//-----------------------------------------------------------------------------
// MIME constants
#define MAX_LENGTH_BOUNDARY 128
// Flags returned by CASC_MIME_HTTP::IsDataComplete()
#define HTTP_HEADER_COMPLETE 0x01 // HTML header is complete
#define HTTP_DATA_COMPLETE 0x02 // HTML data is complete
enum CASC_MIME_ENCODING
{
MimeEncodingTextPlain,
MimeEncodingBase64,
MimeEncodingQuotedPrintable,
MimeEncodingMax
};
//-----------------------------------------------------------------------------
// Structure for caching parsed HTTP response information
struct CASC_MIME_HTTP
{
CASC_MIME_HTTP()
{
total_length = content_offset = content_length = http_flags = 0;
}
size_t IsDataComplete(const char * response, size_t response_length, size_t * ptr_content_length = NULL);
size_t content_length; // Parsed value of "Content-Length"
size_t content_offset; // Offset of the HTTP data, relative to the begin of the response
size_t total_length; // Expected total length of the HTTP response (content_offset + content_size)
size_t http_flags; // Nonzero if this is an already parsed HTTP response
};
//-----------------------------------------------------------------------------
// MIME blob class
struct CASC_MIME_BLOB
{
CASC_MIME_BLOB(char * mime_ptr, char * mime_end);
~CASC_MIME_BLOB();
char * GetNextLine();
char * ptr;
char * end;
};
//-----------------------------------------------------------------------------
// MIME class
class CASC_MIME_ELEMENT
{
public:
CASC_MIME_ELEMENT();
~CASC_MIME_ELEMENT();
unsigned char * GiveAway(size_t * ptr_data_length);
DWORD Load(char * mime_data_begin, char * mime_data_end, const char * boundary_ptr = NULL);
CASC_MIME_ELEMENT * GetChild() { return folder.pChild; }
#ifdef _DEBUG
void Print(size_t nLevel, size_t nIndex);
#endif
protected:
CASC_MIME_ELEMENT * AllocateAndLoadElement(char * a_mime_data, char * a_mime_data_end, const char * boundary_begin);
bool ExtractEncoding(const char * line, CASC_MIME_ENCODING & Encoding);
bool ExtractBoundary(const char * line);
DWORD DecodeTextPlain(char * content_begin, char * content_end, unsigned char * data_ptr, size_t * ptr_length);
DWORD DecodeQuotedPrintable(char * content_begin, char * content_end, unsigned char * data_ptr, size_t * ptr_length);
DWORD DecodeBase64(char * content_begin, char * content_end, unsigned char * data_ptr, size_t * ptr_length);
struct
{
CASC_MIME_ELEMENT * pChild; // Pointer to the first child
CASC_MIME_ELEMENT * pNext; // Pointer to the next-in-folder element
} folder;
struct
{
unsigned char * begin;
size_t length;
} data;
char boundary[MAX_LENGTH_BOUNDARY];
};
class CASC_MIME
{
public:
CASC_MIME();
~CASC_MIME();
unsigned char * GiveAway(size_t * ptr_data_length);
DWORD Load(char * data, size_t length);
DWORD Load(LPCTSTR fileName);
#ifdef _DEBUG
void Print();
#endif
protected:
CASC_MIME_ELEMENT root;
};
#endif // __MIME_H__
|