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
|
#include "opmlurlreader.h"
#include <cstring>
#include "logger.h"
#include "utils.h"
namespace newsboat {
OpmlUrlReader::OpmlUrlReader(ConfigContainer& c)
: cfg(c)
{
}
nonstd::optional<utils::ReadTextFileError> OpmlUrlReader::reload()
{
urls.clear();
tags.clear();
alltags.clear();
std::vector<std::string> urls =
utils::tokenize_quoted(this->get_source(), " ");
for (const auto& url : urls) {
LOG(Level::DEBUG,
"OpmlUrlReader::reload: downloading `%s'",
url);
std::string urlcontent = utils::retrieve_url(url, cfg);
xmlDoc* doc =
xmlParseMemory(urlcontent.c_str(), urlcontent.length());
if (doc == nullptr) {
LOG(Level::ERROR,
"OpmlUrlReader::reload: parsing XML file `%s'"
"failed", url);
continue;
}
xmlNode* root = xmlDocGetRootElement(doc);
if (root) {
for (xmlNode* node = root->children; node != nullptr;
node = node->next) {
if (strcmp((const char*)node->name, "body") ==
0) {
LOG(Level::DEBUG,
"OpmlUrlReader::reload: found "
"body");
rec_find_rss_outlines(
node->children, "");
}
}
}
xmlFreeDoc(doc);
}
return {};
}
void OpmlUrlReader::handle_node(xmlNode* node, const std::string& tag)
{
if (node) {
char* rssurl =
(char*)xmlGetProp(node, (const xmlChar*)"xmlUrl");
if (rssurl && strlen(rssurl) > 0) {
std::string theurl(rssurl);
urls.push_back(theurl);
if (tag.length() > 0) {
std::vector<std::string> tmptags;
tmptags.push_back(tag);
tags[theurl] = tmptags;
alltags.insert(tag);
}
}
if (rssurl) {
xmlFree(rssurl);
}
}
}
void OpmlUrlReader::rec_find_rss_outlines(xmlNode* node, std::string tag)
{
while (node) {
char* type = (char*)xmlGetProp(node, (const xmlChar*)"type");
std::string newtag = tag;
if (strcmp((const char*)node->name, "outline") == 0) {
if (type && strcmp(type, "rss") == 0) {
handle_node(node, tag);
xmlFree(type);
} else {
char* text = (char*)xmlGetProp(
node, (const xmlChar*)"title");
if (text) {
if (newtag.length() > 0) {
newtag.append("/");
}
newtag.append(text);
xmlFree(text);
}
}
}
rec_find_rss_outlines(node->children, newtag);
node = node->next;
}
}
std::string OpmlUrlReader::get_source()
{
return cfg.get_configvalue("opml-url");
}
}
|