lovehtml 0.0.1
 
Loading...
Searching...
No Matches
lovehtml.h
1#ifndef LOVEHTML_H
2#define LOVEHTML_H
3
4#include <filesystem>
5#include <map>
6#include <string>
7#include <vector>
8
9class ToHTML
10{
11public:
12 enum class MHTMLHeaderType: std::size_t {
13 Origin,
14 Location,
15 Subject,
16 Date,
17 MIMEVersion,
18 ContentType,
19 CTType,
20 CTBoundary
21 };
22
23 enum class MHTMLPartHeaderType: std::size_t {
24 Type,
25 ID,
26 Encoding,
27 Location
28 };
29
30 enum class ContentType {
31 TextHTML,
32 TextCss,
33 ImageSvgXml,
34 ImagePng,
35 ImageJpeg,
36 ImageXCitrixJpeg,
37 MultipartRelated
38 };
39
40 enum class Encoding {
41 QuotedPrintable,
42 Base64
43 };
44
45 enum class LoadError {
46 InputNotFound,
47 UnableToOpenInput
48 };
49
50 enum class ParseError {
51 InputEmpty,
52 HeaderNotFound,
53 BoundaryEmpty,
54 LineIndexOutOfBounds,
55 UnsupportedEncoding,
56 UnsupportedContentType,
57 MissingPartLocation,
58 MissingPartEncoding
59 };
60
61 enum class BuildError {
62 EmptyDocumentBody,
63 MissingPartContentType,
64 UnsupportedPartContentType,
65 MissingPartEncoding
66 };
67
68 enum class DecodeError {
69 InvalidHexASCIIEncoding
70 };
71
72 class MHTMLPart {
73 public:
74 std::map<MHTMLPartHeaderType, std::string> header;
75 std::vector<std::string> content;
76 };
77
78 class MHTML {
79 public:
80 std::map<MHTMLHeaderType, std::string> header;
81 std::map<MHTMLPartHeaderType, std::string> bodyHeader;
82 std::string body;
83 std::map<std::string, MHTMLPart> resources;
84 };
85
86 template<typename T>
88 public:
89 T type;
90 std::string_view content;
91 };
92
93 using MHTMLHeader = std::map<MHTMLHeaderType, std::string>;
94 using MHTMLPartHeader = std::map<MHTMLPartHeaderType, std::string>;
95 using MHTMLParseResult = std::variant<MHTML, ParseError>;
96 using HeaderLineParseResult = std::variant<MHTMLHeaderLine<MHTMLHeaderType>, ParseError>;
97 using PartHeaderLineParseResult = std::variant<MHTMLHeaderLine<MHTMLPartHeaderType>, ParseError>;
98 using PartParseResult = std::variant<MHTMLPart, ParseError>;
99 using HeaderParseResult = std::variant<MHTMLHeader, ParseError>;
100 using PartHeaderParseResult = std::variant<MHTMLPartHeader, ParseError>;
101 using FileLoadResult = std::variant<std::vector<std::string>, LoadError>;
102 using PartDecodeResult = std::variant<std::vector<std::string>, DecodeError>;
103 using LineDecodeResult = std::variant<std::string, DecodeError>;
104 using CharDecodeResult = std::variant<char, DecodeError>;
105 using EncodingParseResult = std::variant<Encoding, ParseError>;
106 using ContentTypeParseResult = std::variant<ContentType, ParseError>;
107 using BuildResult = std::variant<std::string, BuildError>;
108
109 explicit ToHTML(const std::filesystem::path& mhtml_file);
110 explicit ToHTML(const std::vector<std::string>& mhtml);
111 virtual ~ToHTML();
112
113 std::string input();
114 std::string output();
115
116private:
117 static FileLoadResult LoadFile(const std::filesystem::path& path);
118
119 static MHTMLParseResult ParseMHTML(const std::vector<std::string>& mhtml);
120 static HeaderLineParseResult ParseHeaderLine(std::string_view line);
121 static PartParseResult ParsePart(const std::vector<std::string>& mhtml, std::size_t& index, const std::string_view& boundary);
122 static PartHeaderParseResult ParsePartHeader(const std::vector<std::string>& mhtml, std::size_t& index, const std::string_view& boundary);
123 static PartHeaderLineParseResult ParsePartHeaderLine(std::string_view line);
124 static EncodingParseResult EncodingFromString(const std::string_view& str);
125 static ContentTypeParseResult ContentTypeFromString(const std::string_view& str);
126
127 template<Encoding enc> static PartDecodeResult DecodePart(const std::vector<std::string>& mhtml, std::size_t& index, const std::string_view& boundary);
128 template<Encoding enc> static LineDecodeResult DecodeLine(std::string_view mhtml);
129 static CharDecodeResult HexToASCII(const std::string& hex);
130
131 static BuildResult BuildHTML(const MHTML& mhtml);
132 template<ContentType ct> static BuildResult BuildSubstitute(const MHTMLPart& part, const std::string_view& contentType);
133 static BuildResult BuildImageSubstitute(const MHTMLPart& part, const std::string_view& contentType);
134
135 static void RemovePrefix(std::string_view& str, const std::string_view& prefix);
136 static void RemoveSuffix(std::string_view& str, const std::string_view& prefix);
137
138 static bool IsBoundary(std::string_view line, const std::string_view& boundary);
139 static bool IsHexadecimal(std::string_view line);
140
141 static std::string GetEncoding(const MHTMLPartHeader& header);
142 static std::string GetContentType(const MHTMLPartHeader& header);
143
144 static constexpr std::string_view WHITE_SPACE = " \t\n\r\f\v";
145 static constexpr std::array<std::string_view, static_cast<std::size_t>(MHTMLHeaderType::CTBoundary) + 1> meta_starts =
146 {
147 "From:",
148 "Snapshot-Content-Location:",
149 "Subject:",
150 "Date:",
151 "MIME-Version:",
152 "Content-Type:",
153 "type=",
154 "boundary="
155 };
156 static constexpr std::array<std::string_view, static_cast<std::size_t>(MHTMLPartHeaderType::Location) + 1> part_starts =
157 {
158 "Content-Type:",
159 "Content-ID:",
160 "Content-Transfer-Encoding:",
161 "Content-Location:"
162 };
163
164private:
165 std::string m_input;
166 std::string m_output;
167};
168
169#endif // LOVEHTML_H
Definition lovehtml.h:87
Definition lovehtml.h:72
Definition lovehtml.h:78