diff options
author | John Ankarström <john@ankarstrom.se> | 2022-09-03 15:28:56 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2022-09-03 15:28:56 +0200 |
commit | 6ae7e24675cff4ff6b808c3024f45083f35ced97 (patch) | |
tree | 2a47273f325d8367db2a8669691273f02ca83eb9 /c/data.cpp | |
parent | 2cd22c671c67deaf2c1fcb659e3262bf57552557 (diff) | |
download | EpisodeBrowser-6ae7e24675cff4ff6b808c3024f45083f35ced97.tar.gz |
Improve error handling.
Diffstat (limited to 'c/data.cpp')
-rw-r--r-- | c/data.cpp | 42 |
1 files changed, 20 insertions, 22 deletions
@@ -7,28 +7,31 @@ #include "data.h" #include "episodelistview.h" +#include "err.h" #include "res.h" #include "util.h" #include "win32.h" #include "window.h" +using namespace std::string_literals; + UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> RemoteParserCtxt(const wchar_t* wszUrl, const char* szUrl) { static Unique<HINTERNET, InternetCloseHandle> hi = InternetOpenW(L"Episode Browser", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0); if (hi.Bad(0)) - throw Win32Error(); + throw Err(WINDOWS, L"Internet handle could not be opened: %s"); Unique<HINTERNET, InternetCloseHandle> hiUrl = InternetOpenUrlW( hi.v, wszUrl, nullptr, 0, INTERNET_FLAG_NO_UI, 0); if (hiUrl.Bad(0)) - throw InternetError(); + throw Err(WININET, L"Could not open "s + wszUrl + L": %s"); char bufX[1024]; Unique<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = htmlCreatePushParserCtxt( nullptr, nullptr, bufX, sizeof(bufX), szUrl, XML_CHAR_ENCODING_UTF8); if (ctx.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"HTML parser context could not be created: %s"); htmlCtxtUseOptions(ctx.v, HTML_PARSE_RECOVER|HTML_PARSE_NOERROR|HTML_PARSE_NOWARNING); @@ -37,9 +40,9 @@ UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> RemoteParserCtxt(const wchar_t* w char bufI[1024]; while (r = InternetReadFile(hiUrl.v, bufI, sizeof(bufI), &cbRead), cbRead) { if (!r) - throw InternetError(); + throw Err(WININET, L"HTML could not be retrieved: %s"); if (!htmlParseChunk(ctx.v, bufI, cbRead, 0)) - throw XmlError(); + throw Err(LIBXML2, L"HTML could not be parsed: %s"); } htmlParseChunk(ctx.v, bufI, 0, 1); /* Stop parsing. */ @@ -52,7 +55,7 @@ template <size_t N> bool WcharsFromXmlchars(wchar_t (&dst)[N], Unique<xmlChar*, XmlFree> utf8) { if (utf8.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"Node content could not be retrieved: %s"); /* Truncate if source is larger than destination. */ int lenUtf8 = xmlStrlen(utf8.v); @@ -125,8 +128,7 @@ void WaitFor(Window& window, void (*f)(unsigned char*)) sig |= DONE; } catch (...) { sig |= DONE; - ShowException(L"Remote data could not be fetched due to an error while %s: %s", - L"Error", MB_ICONWARNING); + EBMessageBox(What(), L"Remote Data Retrieval Error"); } }; @@ -155,8 +157,6 @@ void WaitFor(Window& window, void (*f)(unsigned char*)) void FetchData(unsigned char* sig) { - Act(L"fetching and parsing general episode data"); - /* The remote data is retrieved using WinINet from the * Detective Conan World wiki. Using libxml2's "push parser", * the HTML is parsed piece by piece as it is retrieved. The @@ -164,26 +164,26 @@ void FetchData(unsigned char* sig) * specific XPath query. This is fragile theoretically, but * unlikely to break practically. */ + wchar_t url[_countof(s_window->cfg.prefixUrl)+46+1]; + Swprintf(url, L"%shttps://www.detectiveconanworld.com/wiki/Anime", s_window->cfg.prefixUrl); + UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = - RemoteParserCtxt(L"https://www.detectiveconanworld.com/wiki/Anime", - "https://www.detectiveconanworld.com/wiki/Anime"); + RemoteParserCtxt(url, "https://www.detectiveconanworld.com/wiki/Anime"); Unique<xmlXPathContextPtr, xmlXPathFreeContext> xpathCtx = xmlXPathNewContext(ctx.v->myDoc); if (xpathCtx.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"XPath context could not be created: %s"); Unique<xmlXPathObjectPtr, xmlXPathFreeObject> xpathObj = xmlXPathEvalExpression( reinterpret_cast<const xmlChar*>("//tr[./td[1] != '' and ./td[3][@style='background:#f2fde9;']]"), xpathCtx.v); if (xpathObj.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"XPath object could not be created: %s"); xmlNodeSetPtr nodes = xpathObj.v->nodesetval; if (!nodes || !nodes->nodeNr) - throw std::runtime_error("could not find remote episode information"); - - Act(L"inserting remote data"); + throw Err(GENERIC, L"Data retrieval failed: No matching HTML nodes found."); for (int i = 0; i < nodes->nodeNr; i++) { if (*sig & ABORT) @@ -191,7 +191,7 @@ void FetchData(unsigned char* sig) const xmlNodePtr node = nodes->nodeTab[i]; if (xmlChildElementCount(node) != 8) - throw std::runtime_error("unexpected remote data format"); + throw Err(GENERIC, L"Data retrieval failed: Unexcepted number of columns in table."); ElvDataA& e = s_window->fvElv.At(i); DlvDataA& d = s_window->fvDlv.At(i); @@ -226,8 +226,6 @@ void FetchData(unsigned char* sig) void FetchScreenwriters(unsigned char* sig) { - Act(L"fetching and parsing screenwriter data"); - /* Screenwriters are expensive to fetch, so we try to avoid * fetching screenwriters for episodes that already have a * screenwriter. Additionally, in the same session, we don't @@ -271,13 +269,13 @@ void FetchScreenwriters(unsigned char* sig) UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = RemoteParserCtxt(url, nullptr); xpathCtx = xmlXPathNewContext(ctx.v->myDoc); if (xpathCtx.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"XPath context could not be created: %s"); xpathObj = xmlXPathEvalExpression(reinterpret_cast<const xmlChar*>( "//th[contains(text(), 'Screenplay:')]/following-sibling::td"), xpathCtx.v); if (xpathObj.Bad(0)) - throw XmlError(); + throw Err(LIBXML2, L"XPath object could not be created: %s"); xmlNodeSetPtr nodes = xpathObj.v->nodesetval; if (nodes && nodes->nodeNr) |