38{
39 std::vector<LeakRecord> results;
40
41 if (email.empty() ||
apiKey.empty())
42 return results;
43
44 const std::string encodedEmail =
46
47 const std::string url =
48 "https://haveibeenpwned.com/api/v3/breachedaccount/" +
49 encodedEmail +
50 "?truncateResponse=false";
51
52 std::map<std::string, std::string> headers;
53 headers[
"hibp-api-key"] =
apiKey;
54 headers["User-Agent"] = "BastionGuard/IdentityLeak";
55 headers["Accept"] = "application/json";
56
58
60 return results;
61 }
62
64 throw std::runtime_error(
_(
"HIBP: API key non valida (401)"));
65 }
66
68 throw std::runtime_error(
_(
"HIBP: rate limit superato (429)"));
69 }
70
72 throw std::runtime_error(
73 "HIBP: errore HTTP " + std::to_string(resp.
status));
74 }
75
76
78 try {
79 root = json::parse(resp.
body);
80 } catch (...) {
81 throw std::runtime_error(
_(
"HIBP: JSON non valido"));
82 }
83
84 if (!root.is_array())
85 return results;
86
87 for (const auto& item : root) {
88
89 LeakRecord rec;
91 rec.
breachName = item.value(
"Name",
"Unknown");
94
95
96 std::vector<std::string> dataClasses;
97 if (item.contains("DataClasses") &&
98 item["DataClasses"].is_array())
99 {
100 for (const auto& dc : item["DataClasses"]) {
101 dataClasses.push_back(dc.get<std::string>());
102 }
103 }
104
107
108 results.push_back(std::move(rec));
109 }
110
111 return results;
112}
LeakRecord::Severity computeSeverity(const std::vector< std::string > &dataClasses) const
static HttpResponse get(const std::string &url, const std::map< std::string, std::string > &headers={}, long timeoutSeconds=20)
static std::string urlEncode(const std::string &value)
std::vector< std::string > dataClasses