aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/common/Mime.h
blob: af20435226379248369541774cdf199d7b370cf2 (plain)
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
130
131
132
133
134
135
136
137
138
139
/*****************************************************************************/
/* 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::GetHttpReplyFlags()
#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
};

enum CASC_PRESENCE
{
    FieldPresenceUnknown,
    FieldPresencePresent,
    FieldPresenceNotPresent
};

//-----------------------------------------------------------------------------
// Structure for caching parsed HTTP response information

struct CASC_MIME_RESPONSE
{
    CASC_MIME_RESPONSE()
    {
        header_offset = header_length = CASC_INVALID_SIZE_T;
        content_offset = content_length = CASC_INVALID_SIZE_T;
        http_code = CASC_INVALID_SIZE_T;
        clength_presence = http_presence = FieldPresenceUnknown;
        response_length = 0;
    }

    bool ParseResponse(const char * response, size_t length, bool final = false);

    size_t response_length;             // Previous length of the response
    size_t header_offset;               // Offset of the response header, usually 0
    size_t header_length;               // Length of the header, if known
    size_t content_offset;              // Offset of the content
    size_t content_length;              // Length of the content, if known
    size_t http_code;                   // HTTP code, if present
    CASC_PRESENCE clength_presence;     // State of the "content length" field
    CASC_PRESENCE http_presence;        // Presence of the "HTTP" field
};

//-----------------------------------------------------------------------------
// 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();

    DWORD GiveAway(CASC_BLOB & target);

    DWORD LoadSingle(char * data, size_t 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 CASCLIB_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, CASC_BLOB & output);
    DWORD DecodeQuotedPrintable(char * content_begin, char * content_end, CASC_BLOB & output);
    DWORD DecodeBase64(char * content_begin, char * content_end, CASC_BLOB & output);

    struct
    {
        CASC_MIME_ELEMENT * pChild;     // Pointer to the first child
        CASC_MIME_ELEMENT * pNext;      // Pointer to the next-in-folder element
    } folder;

    CASC_BLOB data;
    char boundary[MAX_LENGTH_BOUNDARY];
};

class CASC_MIME
{
    public:

    CASC_MIME();
    ~CASC_MIME();

    DWORD GiveAway(CASC_BLOB & target);

    DWORD Load(char * data, CASC_MIME_RESPONSE & MimeResponse);

#ifdef CASCLIB_DEBUG
    void Print();
#endif

    protected:

    CASC_MIME_ELEMENT root;
};

#endif // __MIME_H__