diff --git a/test/server.cpp b/test/server.cpp index 3966e36f..97bb2b5a 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -828,74 +828,6 @@ TEST_F(ServerTest, Http404HtmlError)

)" }, - { /* url */ "/ROOT%23%3F/content/invalid-book/whatever", - expected_kiwix_response_data==R"({ "CSS_URL" : false, "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ { "p" : { "msgid" : "url-not-found", "params" : { "url" : "/ROOT%23%3F/content/invalid-book/whatever" } } }, { "p" : { "msgid" : "suggest-search", "params" : { "PATTERN" : "whatever", "SEARCH_URL" : "/ROOT%23%3F/search?pattern=whatever" } } } ] })" && - expected_body==R"( -

Not Found

-

- The requested URL "/ROOT%23%3F/content/invalid-book/whatever" was not found on this server. -

-

- Make a full text search for whatever -

-)" }, - - { /* url */ "/ROOT%23%3F/content/zimfile/invalid-article", - book_name=="zimfile" && - book_title=="Ray Charles" && - expected_kiwix_response_data==R"({ "CSS_URL" : false, "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ { "p" : { "msgid" : "url-not-found", "params" : { "url" : "/ROOT%23%3F/content/zimfile/invalid-article" } } }, { "p" : { "msgid" : "suggest-search", "params" : { "PATTERN" : "invalid-article", "SEARCH_URL" : "/ROOT%23%3F/search?content=zimfile&pattern=invalid-article" } } } ] })" && - expected_body==R"( -

Not Found

-

- The requested URL "/ROOT%23%3F/content/zimfile/invalid-article" was not found on this server. -

-

- Make a full text search for invalid-article -

-)" }, - - { /* url */ R"(/ROOT%23%3F/content/">)", - expected_kiwix_response_data==R"({ "CSS_URL" : false, "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ { "p" : { "msgid" : "url-not-found", "params" : { "url" : "/ROOT%23%3F/content/\">" } } }, { "p" : { "msgid" : "suggest-search", "params" : { "PATTERN" : "\">", "SEARCH_URL" : "/ROOT%23%3F/search?pattern=%22%3E%3Csvg%20onload%3Dalert(1)%3E" } } } ] })" && - expected_body==R"( -

Not Found

-

- The requested URL "/ROOT%23%3F/content/"><svg onload%3Dalert(1)>" was not found on this server. -

-

- Make a full text search for "><svg onload=alert(1)> -

-)" }, - - { /* url */ R"(/ROOT%23%3F/content/zimfile/">)", - book_name=="zimfile" && - book_title=="Ray Charles" && - expected_kiwix_response_data==R"({ "CSS_URL" : false, "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ { "p" : { "msgid" : "url-not-found", "params" : { "url" : "/ROOT%23%3F/content/zimfile/\">" } } }, { "p" : { "msgid" : "suggest-search", "params" : { "PATTERN" : "\">", "SEARCH_URL" : "/ROOT%23%3F/search?content=zimfile&pattern=%22%3E%3Csvg%20onload%3Dalert(1)%3E" } } } ] })" && - expected_body==R"( -

Not Found

-

- The requested URL "/ROOT%23%3F/content/zimfile/"><svg onload%3Dalert(1)>" was not found on this server. -

-

- Make a full text search for "><svg onload=alert(1)> -

-)" }, - - // XXX: This test case is against a "" string appearing inside - // XXX: javascript code that will confuse the HTML parser - { /* url */ R"(/ROOT%23%3F/content/zimfile/)", - book_name=="zimfile" && - book_title=="Ray Charles" && - expected_kiwix_response_data==R"({ "CSS_URL" : false, "PAGE_HEADING" : { "msgid" : "404-page-heading", "params" : { } }, "PAGE_TITLE" : { "msgid" : "404-page-title", "params" : { } }, "details" : [ { "p" : { "msgid" : "url-not-found", "params" : { "url" : "/ROOT%23%3F/content/zimfile/" } } }, { "p" : { "msgid" : "suggest-search", "params" : { "PATTERN" : "script>", "SEARCH_URL" : "/ROOT%23%3F/search?content=zimfile&pattern=script%3E" } } } ] })" && - expected_body==R"( -

Not Found

-

- The requested URL "/ROOT%23%3F/content/zimfile/</script>" was not found on this server. -

-

- Make a full text search for script> -

-)" }, - { /* url */ "/ROOT%23%3F/content/zimfile/invalid-article?userlang=test", expected_page_title=="[I18N TESTING] Not Found - Try Again" && book_name=="zimfile" && @@ -981,6 +913,85 @@ TEST_F(ServerTest, Http404HtmlError) } } +std::string htmlEscape(std::string s) +{ + s = replace(s, "&", "&"); + s = replace(s, "<", "<"); + s = replace(s, ">", ">"); + s = replace(s, "\"", """); + return s; +} + +std::string expectedSexy404ErrorHtml(const std::string& url) +{ + const auto htmlSafeUrl = htmlEscape(url); + + return R"RAWSTRINGLITERAL( + + + + + Page not found + + + +
+ Not found! +
+
+

Oops. Page not found.

+

The requested path was not found:

+

)RAWSTRINGLITERAL" + + // inject the URL + htmlSafeUrl // inject the URL + + // inject the URL + R"RAWSTRINGLITERAL(

+
+
+

The content you're looking for may still be available, but it might be located at a different place within the ZIM file.

+

Please:

+ +

This approach should help you locate the desired content, even if the original link isn't working properly.

+
+ + +)RAWSTRINGLITERAL"; +} + +TEST_F(ServerTest, HttpSexy404HtmlError) +{ + using namespace TestingOfHtmlResponses; + const std::vector testUrls { + // XXX: Nicer 404 error page no longer hints whether the error + // XXX: is because of the missing book/ZIM-file or a missing article + // XXX: inside a valid/existing book/ZIM-file. However it makes sense + // XXX: to preserve both cases. + "/ROOT%23%3F/content/invalid-book/whatever", + "/ROOT%23%3F/content/zimfile/invalid-article", + + // malicious URLs + R"(/ROOT%23%3F/content/">)", + R"(/ROOT%23%3F/content/zimfile/">)", + + // XXX: This test case is against a "" string appearing inside + // XXX: javascript code that will confuse the HTML parser + R"(/ROOT%23%3F/content/zimfile/)", + }; + + for ( const auto& url : testUrls ) { + const TestContext ctx{ {"url", url} }; + const auto r = zfs1_->GET(url.c_str()); + EXPECT_EQ(r->status, 404) << ctx; + EXPECT_EQ(r->body, expectedSexy404ErrorHtml(url)) << ctx; + } +} + TEST_F(ServerTest, Http400HtmlError) { using namespace TestingOfHtmlResponses;