diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index c78cd448e..086068f23 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -68,6 +68,7 @@ extern "C" { #include #include #include +#include #include "kiwixlib-resources.h" #ifndef _WIN32 @@ -212,6 +213,12 @@ void checkBookNumber(const Library::BookIdSet& bookIds, size_t limit) { } } +struct CustomizedResourceData +{ + std::string mimeType; + std::string resourceFilePath; +}; + } // unnamed namespace std::pair InternalServer::selectBooks(const RequestContext& request) const @@ -327,7 +334,6 @@ zim::Query SearchInfo::getZimQuery(bool verbose) const { return query; } - static IdNameMapper defaultNameMapper; static MHD_Result staticHandlerCallback(void* cls, @@ -339,6 +345,27 @@ static MHD_Result staticHandlerCallback(void* cls, size_t* upload_data_size, void** cont_cls); +class InternalServer::CustomizedResources : public std::map +{ +public: + CustomizedResources() + { + const char* fname = ::getenv("KIWIX_SERVE_CUSTOMIZED_RESOURCES"); + if ( fname ) + { + std::cout << "Populating customized resources" << std::endl; + std::ifstream file(fname); + std::string url, mimeType, resourceFilePath; + while ( file >> url >> mimeType >> resourceFilePath ) + { + std::cout << "Got " << url << " " << mimeType << " " << resourceFilePath << std::endl; + (*this)[url] = CustomizedResourceData{mimeType, resourceFilePath}; + } + std::cout << "Done populating customized resources" << std::endl; + } + } +}; + InternalServer::InternalServer(Library* library, NameMapper* nameMapper, @@ -368,9 +395,12 @@ InternalServer::InternalServer(Library* library, mp_library(library), mp_nameMapper(nameMapper ? nameMapper : &defaultNameMapper), searchCache(getEnvVar("KIWIX_SEARCH_CACHE_SIZE", DEFAULT_CACHE_SIZE)), - suggestionSearcherCache(getEnvVar("KIWIX_SUGGESTION_SEARCHER_CACHE_SIZE", std::max((unsigned int) (mp_library->getBookCount(true, true)*0.1), 1U))) + suggestionSearcherCache(getEnvVar("KIWIX_SUGGESTION_SEARCHER_CACHE_SIZE", std::max((unsigned int) (mp_library->getBookCount(true, true)*0.1), 1U))), + m_customizedResources(new CustomizedResources) {} +InternalServer::~InternalServer() = default; + bool InternalServer::start() { #ifdef _WIN32 int flags = MHD_USE_SELECT_INTERNALLY; @@ -507,6 +537,9 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r if ( etag ) return Response::build_304(*this, etag); + if ( isLocallyCustomizedResource(request.get_url()) ) + return handle_locally_customized_resource(request); + if (startsWith(request.get_url(), "/skin/")) return handle_skin(request); @@ -1067,4 +1100,34 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque } } +bool InternalServer::isLocallyCustomizedResource(const std::string& url) const +{ + return m_customizedResources->find(url) != m_customizedResources->end(); +} + +std::unique_ptr InternalServer::handle_locally_customized_resource(const RequestContext& request) +{ + if (m_verbose.load()) { + printf("** running handle_locally_customized_resource\n"); + } + + const CustomizedResourceData& crd = m_customizedResources->at(request.get_url()); + + if (m_verbose.load()) { + std::cout << "Reading " << crd.resourceFilePath << std::endl; + } + const auto resourceData = getFileContent(crd.resourceFilePath); + + auto byteRange = request.get_range().resolve(resourceData.size()); + if (byteRange.kind() != ByteRange::RESOLVED_FULL_CONTENT) { + return Response::build_416(*this, resourceData.size()); + } + + return ContentResponse::build(*this, + resourceData, + crd.mimeType, + /*isHomePage=*/false, + /*raw=*/true); +} + } diff --git a/src/server/internalServer.h b/src/server/internalServer.h index a0cffa95b..7ffc9a8b6 100644 --- a/src/server/internalServer.h +++ b/src/server/internalServer.h @@ -109,7 +109,7 @@ class InternalServer { bool blockExternalLinks, std::string indexTemplateString, int ipConnectionLimit); - virtual ~InternalServer() = default; + virtual ~InternalServer(); MHD_Result handlerCallback(struct MHD_Connection* connection, const char* url, @@ -142,6 +142,7 @@ class InternalServer { std::unique_ptr handle_captured_external(const RequestContext& request); std::unique_ptr handle_content(const RequestContext& request); std::unique_ptr handle_raw(const RequestContext& request); + std::unique_ptr handle_locally_customized_resource(const RequestContext& request); std::vector search_catalog(const RequestContext& request, kiwix::OPDSDumper& opdsDumper); @@ -153,6 +154,8 @@ class InternalServer { std::pair selectBooks(const RequestContext& r) const; SearchInfo getSearchInfo(const RequestContext& r) const; + bool isLocallyCustomizedResource(const std::string& url) const; + private: // data std::string m_addr; int m_port; @@ -176,6 +179,9 @@ class InternalServer { std::string m_server_id; std::string m_library_id; + class CustomizedResources; + std::unique_ptr m_customizedResources; + friend std::unique_ptr Response::build(const InternalServer& server); friend std::unique_ptr ContentResponse::build(const InternalServer& server, const std::string& content, const std::string& mimetype, bool isHomePage, bool raw); friend std::unique_ptr ItemResponse::build(const InternalServer& server, const RequestContext& request, const zim::Item& item, bool raw);