1 #include "gzip_utils.hpp"
2
3 #include <libxml/parser.h>
4 #include <libxml/xpath.h>
5 #include <unistd.h>
6 #include <zlib.h>
7
8 #include <optional>
9 #include <span>
10 #include <string>
11 #include <vector>
12
gzipInflate(std::span<uint8_t> compressedBytes)13 std::optional<std::string> gzipInflate(std::span<uint8_t> compressedBytes)
14 {
15 std::string uncompressedBytes;
16 if (compressedBytes.empty())
17 {
18 return std::nullopt;
19 }
20
21 z_stream strm{
22
23 };
24 strm.next_in = (Bytef*)compressedBytes.data();
25 strm.avail_in = static_cast<uInt>(compressedBytes.size());
26 strm.total_out = 0;
27
28 if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK)
29 {
30 return std::nullopt;
31 }
32
33 while (strm.avail_in > 0)
34 {
35 constexpr size_t chunkSize = 1024;
36 uncompressedBytes.resize(uncompressedBytes.size() + chunkSize);
37 strm.next_out =
38 std::bit_cast<Bytef*>(uncompressedBytes.end() - chunkSize);
39 strm.avail_out = chunkSize;
40
41 // Inflate another chunk.
42 int err = inflate(&strm, Z_SYNC_FLUSH);
43 if (err == Z_STREAM_END)
44 {
45 break;
46 }
47 if (err != Z_OK)
48 {
49 return std::nullopt;
50 }
51 }
52
53 if (inflateEnd(&strm) != Z_OK)
54 {
55 return std::nullopt;
56 }
57 uncompressedBytes.resize(strm.total_out);
58
59 return {uncompressedBytes};
60 }
61
xpathText(xmlDocPtr doc,const char * xp)62 static std::vector<std::string> xpathText(xmlDocPtr doc, const char* xp)
63 {
64 std::vector<std::string> val;
65 xmlXPathContextPtr ctx = xmlXPathNewContext(doc);
66 if (ctx == nullptr)
67 {
68 return val;
69 }
70 const unsigned char* xpptr = std::bit_cast<const unsigned char*>(xp);
71 xmlXPathObjectPtr obj = xmlXPathEvalExpression(xpptr, ctx);
72 if (obj != nullptr)
73 {
74 if (obj->type == XPATH_NODESET && obj->nodesetval != nullptr)
75 {
76 xmlNodeSetPtr nodeTab = obj->nodesetval;
77 size_t nodeNr = static_cast<size_t>(nodeTab->nodeNr);
78 std::span<xmlNodePtr> nodes{nodeTab->nodeTab, nodeNr};
79 for (xmlNodePtr node : nodes)
80 {
81 unsigned char* keyword = xmlNodeGetContent(node);
82 val.emplace_back(std::bit_cast<const char*>(keyword));
83 xmlFree(keyword);
84 }
85 }
86 }
87
88 xmlXPathFreeObject(obj);
89 xmlXPathFreeContext(ctx);
90 return val;
91 }
92
getNodeFromXml(std::string_view xml,const char * nodeName)93 std::vector<std::string> getNodeFromXml(std::string_view xml,
94 const char* nodeName)
95 {
96 std::vector<std::string> node;
97 if (xml.empty())
98 {
99 return node;
100 }
101 xmlDocPtr doc = xmlReadMemory(
102 xml.data(), xml.size(), nullptr, nullptr,
103 XML_PARSE_RECOVER | XML_PARSE_NONET | XML_PARSE_NOWARNING);
104 if (doc == nullptr)
105 {
106 return {};
107 }
108 node = xpathText(doc, nodeName);
109 xmlFreeDoc(doc);
110 return node;
111 }
112