This repository has been archived by the owner on Oct 4, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathQuery.cpp
96 lines (82 loc) · 2.49 KB
/
Query.cpp
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
#include "foo_musicbrainz.h"
#include "Query.h"
#include "Metadata.h"
#include "Parser.h"
using namespace foo_musicbrainz;
Query::Query(const char *entity, const char *id) {
url << "http://musicbrainz.org/ws/2/" << entity;
if (id != nullptr) {
url << "/" << id;
}
url << "?";
}
char Query::to_hex(char c) {
return c < 0xa ? '0' + c : 'a' - 0xa + c;
}
void Query::add_param(const char *param, const char *value, bool encode) {
url << param << "=" << (encode ? url_encode(value) : value) << "&";
}
void Query::add_param(const char *param, int value) {
pfc::string8 str;
str << value;
add_param(param, str, false);
}
pfc::string8 Query::url_encode(const char *in) {
pfc::string8 out;
out.prealloc(strlen(in) * 3 + 1);
for (register const char *tmp = in; *tmp != '\0'; tmp++) {
auto c = static_cast<unsigned char>(*tmp);
if (isalnum(c)) {
out.add_char(c);
} else if (isspace(c)) {
out.add_char('+');
} else {
out.add_char('%');
out.add_char(to_hex(c >> 4));
out.add_char(to_hex(c % 16));
}
}
return out;
}
TiXmlElement *Query::parse(pfc::string8 &buffer, TiXmlDocument &xml) {
// Parsing XML
xml.Parse(buffer, 0, TIXML_ENCODING_UTF8);
if (xml.Error()) {
#ifdef DEBUG
pfc::string8 error = "Error parsing XML, response from musicbrainz.org:\n\n";
error << buffer;
throw XmlParseError(error);
#else
throw XmlParseError();
#endif
}
// Accessing <metadata> element
auto metadata = xml.FirstChildElement("metadata");
if (metadata != nullptr) return metadata;
// No metadata, look for <error> element
auto error = xml.FirstChildElement("error");
if (error == nullptr) throw XmlParseError();
auto text = error->FirstChildElement("text");
if (text == nullptr) throw XmlParseError();
pfc::string8 message = "Response from MusicBrainz: ";
message << Parser::text(text);
// FIXME: not only not found (404), but also 401 and 404
throw NotFound(message);
}
Metadata *Query::perform(abort_callback &callback) {
#ifdef DEBUG
auto logger = uDebugLog();
logger << "MusicBrainz tagger: accessing " << url;
#endif
// Download
static_api_ptr_t<http_client> http;
auto request = http->create_request("GET");
request->add_header("User-Agent", "foo_musicbrainz/" COMPONENT_VERSION);
auto response = request->run_ex(url, callback);
// Get string
pfc::string8 buffer;
response->read_string_raw(buffer, callback);
// Parse
TiXmlDocument xml;
return Parser::metadata(parse(buffer, xml));
}