mirror of
https://github.com/kiwix/libkiwix.git
synced 2026-09-09 20:18:19 -04:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46b599fb2c | ||
|
|
940abd2e8f | ||
|
|
2f987ee727 | ||
|
|
d072e57f05 | ||
|
|
a7df774f54 | ||
|
|
7693557065 | ||
|
|
58e458b658 | ||
|
|
fb1b8b85e0 | ||
|
|
5cc3ce1895 | ||
|
|
7e50bf611b | ||
|
|
59ba61fcd2 | ||
|
|
40b9e2b876 | ||
|
|
90867968c1 | ||
|
|
fcebc2d4f6 | ||
|
|
d24bd1ea3e | ||
|
|
20b3dd77bc |
No files matched your search
@@ -1,3 +1,10 @@
|
||||
libkiwix 14.2.1
|
||||
===============
|
||||
|
||||
* Documentation fix (@bperlakih #1277)
|
||||
* Fix kiwix-serve unit-test for libmicrohttpd 1.x (@veloman-yunkan #1293)
|
||||
* Fix kiwix-server error message for requests with wrong root URL prefix (@veloman-yunkan #1294)
|
||||
|
||||
libkiwix 14.2.0
|
||||
===============
|
||||
|
||||
|
||||
+3
-3
@@ -444,11 +444,11 @@ class Library: public std::enable_shared_from_this<Library>
|
||||
|
||||
|
||||
/**
|
||||
* Sort (in place) bookIds using the given comparator.
|
||||
* Sort (in place) bookIds using the given arguments.
|
||||
*
|
||||
* @param bookIds the list of book Ids to sort
|
||||
* @param comparator how to sort the books
|
||||
* @return The sorted list of books
|
||||
* @param sortBy how to sort the books (UNSORTED, TITLE, SIZE, DATE, CREATOR, PUBLISHER)
|
||||
* @param ascending ascending or descending
|
||||
*/
|
||||
void sort(BookIdCollection& bookIds, supportedListSortBy sortBy, bool ascending) const;
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
project('libkiwix', 'cpp',
|
||||
version : '14.2.0',
|
||||
version : '14.2.1',
|
||||
license : 'GPLv3+',
|
||||
default_options : ['c_std=c11', 'cpp_std=c++17', 'werror=true'])
|
||||
|
||||
|
||||
@@ -181,16 +181,6 @@ int getMHDFlags(IpMode ipMode, bool verbose)
|
||||
return flags;
|
||||
}
|
||||
|
||||
std::string
|
||||
fullURL2LocalURL(const std::string& fullUrl, const std::string& rootLocation)
|
||||
{
|
||||
if ( kiwix::startsWith(fullUrl, rootLocation) ) {
|
||||
return fullUrl.substr(rootLocation.size());
|
||||
} else {
|
||||
return "INVALID URL";
|
||||
}
|
||||
}
|
||||
|
||||
std::string getSearchComponent(const RequestContext& request)
|
||||
{
|
||||
const std::string query = request.get_query();
|
||||
@@ -645,11 +635,15 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
|
||||
printf("full_url : %s\n", fullUrl);
|
||||
}
|
||||
|
||||
const auto url = fullURL2LocalURL(fullUrl, m_rootPrefixOfDecodedURL);
|
||||
RequestContext::NameValuePairs headers, queryArgs;
|
||||
MHD_get_connection_values(connection, MHD_HEADER_KIND, add_name_value_pair, &headers);
|
||||
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, add_name_value_pair, &queryArgs);
|
||||
RequestContext request(m_root, url, method, version, headers, queryArgs);
|
||||
|
||||
const int rootPrefixLen = kiwix::startsWith(fullUrl, m_rootPrefixOfDecodedURL)
|
||||
? int(m_rootPrefixOfDecodedURL.size())
|
||||
: -1;
|
||||
|
||||
RequestContext request(fullUrl, rootPrefixLen, method, version, headers, queryArgs);
|
||||
|
||||
if (m_verbose.load() ) {
|
||||
request.print_debug_info();
|
||||
|
||||
@@ -51,14 +51,14 @@ RequestMethod str2RequestMethod(const std::string& method) {
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
RequestContext::RequestContext(const std::string& _rootLocation, // URI-encoded
|
||||
const std::string& unrootedUrl, // URI-decoded
|
||||
RequestContext::RequestContext(const std::string& _fullUrl, // URI-decoded
|
||||
int _rootPrefixLength,
|
||||
const std::string& _method,
|
||||
const std::string& version,
|
||||
const NameValuePairs& headers,
|
||||
const NameValuePairs& queryArgs) :
|
||||
rootLocation(_rootLocation),
|
||||
url(unrootedUrl),
|
||||
fullUrl(_fullUrl),
|
||||
rootPrefixLength(_rootPrefixLength),
|
||||
method(str2RequestMethod(_method)),
|
||||
version(version),
|
||||
requestIndex(s_requestIndex++),
|
||||
@@ -128,7 +128,8 @@ void RequestContext::print_debug_info() const {
|
||||
printf("\n");
|
||||
}
|
||||
printf("Parsed : \n");
|
||||
printf("url : %s\n", url.c_str());
|
||||
printf("full url: %s\n", fullUrl.c_str());
|
||||
printf("derooted url: %s\n", get_url().c_str());
|
||||
printf("acceptEncodingGzip : %d\n", acceptEncodingGzip);
|
||||
printf("has_range : %d\n", byteRange_.kind() != ByteRange::NONE);
|
||||
printf("is_valid_url : %d\n", is_valid_url());
|
||||
@@ -141,11 +142,14 @@ RequestMethod RequestContext::get_method() const {
|
||||
}
|
||||
|
||||
std::string RequestContext::get_url() const {
|
||||
return url;
|
||||
return rootPrefixLength < 0
|
||||
? ""
|
||||
: fullUrl.substr(rootPrefixLength);
|
||||
}
|
||||
|
||||
std::string RequestContext::get_url_part(int number) const {
|
||||
size_t start = 1;
|
||||
const std::string url = get_url();
|
||||
while(true) {
|
||||
auto found = url.find('/', start);
|
||||
if (number == 0) {
|
||||
@@ -165,14 +169,14 @@ std::string RequestContext::get_url_part(int number) const {
|
||||
}
|
||||
|
||||
std::string RequestContext::get_full_url() const {
|
||||
return rootLocation + urlEncode(url);
|
||||
}
|
||||
|
||||
std::string RequestContext::get_root_path() const {
|
||||
return rootLocation.empty() ? "/" : rootLocation;
|
||||
return urlEncode(fullUrl);
|
||||
}
|
||||
|
||||
bool RequestContext::is_valid_url() const {
|
||||
if ( rootPrefixLength < 0 )
|
||||
return false;
|
||||
|
||||
const std::string url = get_url();
|
||||
return url.empty() || url[0] == '/';
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ class RequestContext {
|
||||
typedef std::vector<std::pair<const char*, const char*>> NameValuePairs;
|
||||
|
||||
public: // functions
|
||||
RequestContext(const std::string& rootLocation, // URI-encoded
|
||||
const std::string& unrootedUrl, // URI-decoded
|
||||
RequestContext(const std::string& fullUrl, // URI-decoded
|
||||
int rootPrefixLength,
|
||||
const std::string& method,
|
||||
const std::string& version,
|
||||
const NameValuePairs& headers,
|
||||
@@ -96,7 +96,6 @@ class RequestContext {
|
||||
std::string get_url() const;
|
||||
std::string get_url_part(int part) const;
|
||||
std::string get_full_url() const;
|
||||
std::string get_root_path() const;
|
||||
|
||||
std::string get_query() const { return queryString; }
|
||||
|
||||
@@ -139,8 +138,8 @@ class RequestContext {
|
||||
};
|
||||
|
||||
private: // data
|
||||
std::string rootLocation;
|
||||
std::string url;
|
||||
const std::string fullUrl; // URI-decoded
|
||||
const int rootPrefixLength;
|
||||
RequestMethod method;
|
||||
std::string version;
|
||||
unsigned long long requestIndex;
|
||||
|
||||
@@ -228,12 +228,6 @@ function updateToolbarVisibilityState() {
|
||||
previousScrollTop = st;
|
||||
}
|
||||
|
||||
function handle_visual_viewport_change() {
|
||||
const wh = window.visualViewport
|
||||
? window.visualViewport.height
|
||||
: window.innerHeight;
|
||||
contentIframe.height = wh - contentIframe.offsetTop - 4;
|
||||
}
|
||||
|
||||
function setIframeUrl(path) {
|
||||
try {
|
||||
@@ -583,9 +577,7 @@ function setupViewer() {
|
||||
// Defer the call of handle_visual_viewport_change() until after the
|
||||
// presence or absence of the taskbar as determined by this function
|
||||
// has been settled.
|
||||
setTimeout(handle_visual_viewport_change, 0);
|
||||
|
||||
window.onresize = handle_visual_viewport_change;
|
||||
|
||||
const kiwixToolBarWrapper = document.getElementById('kiwixtoolbarwrapper');
|
||||
if ( ! viewerSettings.toolbarEnabled ) {
|
||||
|
||||
@@ -7,6 +7,16 @@
|
||||
frame-src 'self';
|
||||
object-src 'none';">
|
||||
<title>ZIM Viewer</title>
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
html, body, #content_iframe {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link type="text/css" href="./skin/kiwix.css?KIWIXCACHEID" rel="Stylesheet" />
|
||||
<link type="text/css" href="./skin/taskbar.css?KIWIXCACHEID" rel="Stylesheet" />
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ RequestContext makeHttpGetRequest(const std::string& url,
|
||||
const RequestContext::NameValuePairs& headers,
|
||||
const RequestContext::NameValuePairs& queryArgs)
|
||||
{
|
||||
return RequestContext("", url, "GET", "1.1", headers, queryArgs);
|
||||
return RequestContext(url, 0, "GET", "1.1", headers, queryArgs);
|
||||
}
|
||||
|
||||
std::string getResponseContent(const ContentResponseBlueprint& crb)
|
||||
|
||||
+52
-2
@@ -9,6 +9,9 @@
|
||||
#include "../src/tools/stringTools.h"
|
||||
|
||||
#include "testing_tools.h"
|
||||
|
||||
#include "../src/server/microhttpd_wrapper.h" // for MHD_VERSION
|
||||
|
||||
using namespace kiwix::testing;
|
||||
|
||||
const std::string ROOT_PREFIX("/ROOT%23%3F");
|
||||
@@ -79,7 +82,7 @@ const ResourceCollection resources200Compressible{
|
||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css" },
|
||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css?cacheid=42e90cb9" },
|
||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/viewer.js" },
|
||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=6192cae1" },
|
||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=f78c03d9" },
|
||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf" },
|
||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf?cacheid=af705837" },
|
||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Roboto.ttf" },
|
||||
@@ -340,7 +343,7 @@ R"EXPECTEDRESULT( <link type="text/css" href="./skin/kiwix.css?cacheid=b4e29e
|
||||
<script type="text/javascript" src="./skin/polyfills.js?cacheid=a0e0343d"></script>
|
||||
<script type="module" src="./skin/i18n.js?cacheid=e9a10ac1" defer></script>
|
||||
<script type="text/javascript" src="./skin/languages.js?cacheid=d2d6933b" defer></script>
|
||||
<script type="text/javascript" src="./skin/viewer.js?cacheid=6192cae1" defer></script>
|
||||
<script type="text/javascript" src="./skin/viewer.js?cacheid=f78c03d9" defer></script>
|
||||
<script type="text/javascript" src="./skin/autoComplete/autoComplete.min.js?cacheid=1191aaaf"></script>
|
||||
const blankPageUrl = root + "/skin/blank.html?cacheid=6b1fa032";
|
||||
<label for="kiwix_button_show_toggle"><img src="./skin/caret.png?cacheid=22b942b4" alt=""></label>
|
||||
@@ -439,6 +442,10 @@ TEST_F(ServerTest, CacheIdsOfStaticResourcesMatchTheSha1HashOfResourceContent)
|
||||
}
|
||||
|
||||
const char* urls400[] = {
|
||||
#if MHD_VERSION >= 0x01000300
|
||||
"/ROOT%23%",
|
||||
"/ROOT%23%3",
|
||||
#endif // MHD_VERSION
|
||||
"/ROOT%23%3F/search",
|
||||
"/ROOT%23%3F/search?content=non-existing-book&pattern=asdfqwerty",
|
||||
"/ROOT%23%3F/search?content=non-existing-book&pattern=asd<qwerty",
|
||||
@@ -461,8 +468,10 @@ const char* urls404[] = {
|
||||
"/",
|
||||
"/zimfile",
|
||||
"/ROOT",
|
||||
#if MHD_VERSION < 0x01000300
|
||||
"/ROOT%23%",
|
||||
"/ROOT%23%3",
|
||||
#endif // MHD_VERSION
|
||||
"/ROOT%23%3Fxyz",
|
||||
"/ROOT%23%3F/skin/non-existent-skin-resource",
|
||||
"/ROOT%23%3F/skin/autoComplete/autoComplete.min.js?cacheid=wrongcacheid",
|
||||
@@ -779,6 +788,47 @@ TEST_F(ServerTest, Http404HtmlError)
|
||||
{
|
||||
using namespace TestingOfHtmlResponses;
|
||||
const std::vector<TestContentIn404HtmlResponse> testData{
|
||||
|
||||
// wrong root URL (root URL missing completely)
|
||||
{ /* url */ "/",
|
||||
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" : "/" } } } ] })" &&
|
||||
expected_body==R"(
|
||||
<h1>Not Found</h1>
|
||||
<p>
|
||||
The requested URL "/" was not found on this server.
|
||||
</p>
|
||||
)" },
|
||||
|
||||
// (conspicuously) wrong root URL
|
||||
{ /* url */ "/WRONGROOT",
|
||||
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" : "/WRONGROOT" } } } ] })" &&
|
||||
expected_body==R"(
|
||||
<h1>Not Found</h1>
|
||||
<p>
|
||||
The requested URL "/WRONGROOT" was not found on this server.
|
||||
</p>
|
||||
)" },
|
||||
|
||||
// wrong root URL with the correct root URL appearing as a suffix
|
||||
{ /* url */ "/WRONGROOT/ROOT%23%3F",
|
||||
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" : "/WRONGROOT/ROOT%23%3F" } } } ] })" &&
|
||||
expected_body==R"(
|
||||
<h1>Not Found</h1>
|
||||
<p>
|
||||
The requested URL "/WRONGROOT/ROOT%23%3F" was not found on this server.
|
||||
</p>
|
||||
)" },
|
||||
|
||||
// wrong root URL (with the correct root URL appearing as a prefix)
|
||||
{ /* url */ "/ROOT%23%3FWRONGROOT",
|
||||
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%3FWRONGROOT" } } } ] })" &&
|
||||
expected_body==R"(
|
||||
<h1>Not Found</h1>
|
||||
<p>
|
||||
The requested URL "/ROOT%23%3FWRONGROOT" was not found on this server.
|
||||
</p>
|
||||
)" },
|
||||
|
||||
{ /* url */ "/ROOT%23%3F/random?content=non-existent-book",
|
||||
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" : "no-such-book", "params" : { "BOOK_NAME" : "non-existent-book" } } } ] })" &&
|
||||
expected_body==R"(
|
||||
|
||||
Reference in new issue
Block a user