Merge pull request #86 from kiwix/swiftugandan_root

Swiftugandan root
This commit is contained in:
Matthieu Gautier 2017-10-17 16:21:04 +02:00 committed by GitHub
commit ee5333bb91
5 changed files with 72 additions and 49 deletions

View File

@ -91,6 +91,7 @@ static bool noLibraryButtonFlag = false;
static bool noSearchBarFlag = false; static bool noSearchBarFlag = false;
static string welcomeHTML; static string welcomeHTML;
static std::atomic_bool isVerbose(false); static std::atomic_bool isVerbose(false);
static std::string rootLocation = "";
static std::map<std::string, std::string> extMimeTypes; static std::map<std::string, std::string> extMimeTypes;
static std::map<std::string, kiwix::Reader*> readers; static std::map<std::string, kiwix::Reader*> readers;
static std::map<std::string, kiwix::Searcher*> searchers; static std::map<std::string, kiwix::Searcher*> searchers;
@ -181,6 +182,7 @@ void introduceTaskbar(string& content, const string& humanReadableBookId)
humanReadableBookId, humanReadableBookId,
"__CONTENT__")); "__CONTENT__"));
} }
content = replaceRegex(content, rootLocation, "__ROOT_LOCATION__");
} }
pthread_mutex_unlock(&regexLock); pthread_mutex_unlock(&regexLock);
} }
@ -430,7 +432,7 @@ static struct MHD_Response* handle_skin(RequestContext* request_context)
{ {
std::string content; std::string content;
try { try {
content = getResource(request_context->urlStr.substr(6)); content = getResource(request_context->urlStr.substr(rootLocation.size() + 6));
} catch (const ResourceNotFound& e) { } catch (const ResourceNotFound& e) {
return build_404(request_context); return build_404(request_context);
} }
@ -466,7 +468,7 @@ static struct MHD_Response* handle_search(RequestContext* request_context)
/* If article found then redirect directly to it */ /* If article found then redirect directly to it */
if (!patternCorrespondingUrl.empty()) { if (!patternCorrespondingUrl.empty()) {
httpRedirection httpRedirection
= "/" + request_context->humanReadableBookId + "/" + patternCorrespondingUrl; = rootLocation + "/" + request_context->humanReadableBookId + "/" + patternCorrespondingUrl;
request_context->httpResponseCode = MHD_HTTP_FOUND; request_context->httpResponseCode = MHD_HTTP_FOUND;
return build_response("", 0, httpRedirection, "", false, true); return build_response("", 0, httpRedirection, "", false, true);
} }
@ -515,7 +517,7 @@ static struct MHD_Response* handle_random(RequestContext* request_context)
if (request_context->reader != NULL) { if (request_context->reader != NULL) {
std::string randomUrl = request_context->reader->getRandomPageUrl(); std::string randomUrl = request_context->reader->getRandomPageUrl();
httpRedirection httpRedirection
= "/" + request_context->humanReadableBookId + "/" + kiwix::urlEncode(randomUrl); = rootLocation + "/" + request_context->humanReadableBookId + "/" + kiwix::urlEncode(randomUrl);
} }
return build_response("", 0, httpRedirection, "", false, false); return build_response("", 0, httpRedirection, "", false, false);
} }
@ -578,22 +580,22 @@ static struct MHD_Response* handle_content(RequestContext* request_context)
+ article.getUrl(); + article.getUrl();
pthread_mutex_lock(&regexLock); pthread_mutex_lock(&regexLock);
content = replaceRegex(content, content = replaceRegex(content,
"$1$2" + request_context->humanReadableBookId + "/$3/", "$1$2" + rootLocation + "/" + request_context->humanReadableBookId + "/$3/",
"(href|src)(=[\"|\']{0,1}/)([A-Z|\\-])/"); "(href|src)(=[\"|\']{0,1})/([A-Z|\\-])/");
content = replaceRegex(content, content = replaceRegex(content,
"$1$2" + request_context->humanReadableBookId + "/$3/", "$1$2" + rootLocation + "/" + request_context->humanReadableBookId + "/$3/",
"(@import[ ]+)([\"|\']{0,1}/)([A-Z|\\-])/"); "(@import[ ]+)([\"|\']{0,1})/([A-Z|\\-])/");
content = replaceRegex( content = replaceRegex(
content, content,
"<head><base href=\"/" + request_context->humanReadableBookId + baseUrl + "\" />", "<head><base href=\"" + rootLocation + "/" + request_context->humanReadableBookId + baseUrl + "\" />",
"<head>"); "<head>");
pthread_mutex_unlock(&regexLock); pthread_mutex_unlock(&regexLock);
introduceTaskbar(content, request_context->humanReadableBookId); introduceTaskbar(content, request_context->humanReadableBookId);
} else if (mimeType.find("text/css") != string::npos) { } else if (mimeType.find("text/css") != string::npos) {
pthread_mutex_lock(&regexLock); pthread_mutex_lock(&regexLock);
content = replaceRegex(content, content = replaceRegex(content,
"$1$2" + request_context->humanReadableBookId + "/$3/", "$1$2" + rootLocation + "/" + request_context->humanReadableBookId + "/$3/",
"(url|URL)(\\([\"|\']{0,1}/)([A-Z|\\-])/"); "(url|URL)(\\([\"|\']{0,1})/([A-Z|\\-])/");
pthread_mutex_unlock(&regexLock); pthread_mutex_unlock(&regexLock);
} }
@ -624,7 +626,7 @@ static struct MHD_Response* handle_default(RequestContext* request_context)
bool deflated = request_context->acceptEncodingDeflate && compress_content(content, mimeType); bool deflated = request_context->acceptEncodingDeflate && compress_content(content, mimeType);
return build_response( return build_response(
content.data(), content.size(), "", mimeType, deflated, true); content.data(), content.size(), "", mimeType, deflated, false);
} }
int print_out_key (void *cls, enum MHD_ValueKind kind, int print_out_key (void *cls, enum MHD_ValueKind kind,
@ -698,20 +700,25 @@ static int accessHandlerCallback(void* cls,
/* Get searcher and reader */ /* Get searcher and reader */
std::string humanReadableBookId = ""; std::string humanReadableBookId = "";
if (!(urlStr.size() > 5 && urlStr.substr(0, 6) == "/skin/")) {
if (!strcmp(url, "/search") || !strcmp(url, "/suggest") if (!rootLocation.empty() && urlStr.substr(0, rootLocation.size() + 1) != rootLocation + "/"){
|| !strcmp(url, "/random")) { humanReadableBookId = "";
}
else if (!(urlStr.size() > rootLocation.size() + 5 && urlStr.substr(rootLocation.size() , 6) == "/skin/")) {
if ((urlStr == rootLocation + "/" + "search") || (urlStr == rootLocation + "/" + "suggest")
|| (urlStr == rootLocation + "/" + "random")) {
const char* tmpGetValue = MHD_lookup_connection_value( const char* tmpGetValue = MHD_lookup_connection_value(
connection, MHD_GET_ARGUMENT_KIND, "content"); connection, MHD_GET_ARGUMENT_KIND, "content");
humanReadableBookId = (tmpGetValue != NULL ? string(tmpGetValue) : ""); humanReadableBookId = (tmpGetValue != NULL ? string(tmpGetValue) : "");
} else { } else {
humanReadableBookId = urlStr.substr(1, humanReadableBookId = urlStr.substr(rootLocation.size() + 1,
urlStr.find("/", 1) != string::npos urlStr.find("/", rootLocation.size() + 1) != string::npos
? urlStr.find("/", 1) - 1 ? urlStr.find("/", rootLocation.size() + 1) - (rootLocation.size() + 1)
: urlStr.size() - 2); : urlStr.size() - (rootLocation.size() + 2));
if (!humanReadableBookId.empty()) { if (!humanReadableBookId.empty()) {
urlStr = urlStr.substr(urlStr.find("/", 1) != string::npos urlStr = urlStr.substr(urlStr.find("/", rootLocation.size() + 1) != string::npos
? urlStr.find("/", 1) ? urlStr.find("/", rootLocation.size() + 1)
: humanReadableBookId.size()); : humanReadableBookId.size());
} }
} }
@ -736,22 +743,22 @@ static int accessHandlerCallback(void* cls,
/* Get suggestions */ /* Get suggestions */
if (!strcmp(url, "/suggest") && reader != NULL) { if ((urlStr == (rootLocation + "/" + "suggest")) && reader != NULL) {
response = handle_suggest(&request_context); response = handle_suggest(&request_context);
} }
/* Get static skin stuff */ /* Get static skin stuff */
else if (urlStr.substr(0, 6) == "/skin/") { else if (urlStr.size() > rootLocation.size() + 5 && urlStr.substr(rootLocation.size() , 6) == "/skin/") {
response = handle_skin(&request_context); response = handle_skin(&request_context);
} }
/* Display the search restults */ /* Display the search restults */
else if (!strcmp(url, "/search")) { else if (urlStr == (rootLocation + "/" + "search")) {
response = handle_search(&request_context); response = handle_search(&request_context);
} }
/* Display a random article */ /* Display a random article */
else if (!strcmp(url, "/random")) { else if (urlStr == (rootLocation + "/" + "random")) {
response = handle_random(&request_context); response = handle_random(&request_context);
} }
@ -799,13 +806,14 @@ int main(int argc, char** argv)
{"port", required_argument, 0, 'p'}, {"port", required_argument, 0, 'p'},
{"interface", required_argument, 0, 'f'}, {"interface", required_argument, 0, 'f'},
{"threads", required_argument, 0, 't'}, {"threads", required_argument, 0, 't'},
{"urlRootLocation", required_argument, 0, 'r'},
{0, 0, 0, 0}}; {0, 0, 0, 0}};
/* Argument parsing */ /* Argument parsing */
while (true) { while (true) {
int option_index = 0; int option_index = 0;
int c int c
= getopt_long(argc, argv, "mndvli:a:p:f:t:", long_options, &option_index); = getopt_long(argc, argv, "mndvli:a:p:f:t:r:", long_options, &option_index);
if (c != -1) { if (c != -1) {
switch (c) { switch (c) {
@ -839,6 +847,20 @@ int main(int argc, char** argv)
break; break;
case 't': case 't':
nb_threads = atoi(optarg); nb_threads = atoi(optarg);
break;
case 'r':
rootLocation = string(optarg);
/* prepend prefix "/" if not provided*/
if (rootLocation[0] != '/'){
rootLocation = "/" + rootLocation;
}
/* remove the trailing slash if provided*/
if (rootLocation.back() == '/'){
rootLocation.erase(rootLocation.size() - 1);
}
break; break;
} }
} else { } else {
@ -859,12 +881,13 @@ int main(int argc, char** argv)
cerr << "Usage: kiwix-serve [--index=INDEX_PATH] [--port=PORT] [--verbose] " cerr << "Usage: kiwix-serve [--index=INDEX_PATH] [--port=PORT] [--verbose] "
"[--nosearchbar] [--nolibrarybutton] [--daemon] " "[--nosearchbar] [--nolibrarybutton] [--daemon] "
"[--attachToProcess=PID] [--interface=IF_NAME] " "[--attachToProcess=PID] [--interface=IF_NAME] "
"[--urlRootLocation=/URL_ROOT] "
"[--threads=NB_THREAD(" << nb_threads << ")] ZIM_PATH+" "[--threads=NB_THREAD(" << nb_threads << ")] ZIM_PATH+"
<< endl; << endl;
cerr << " kiwix-serve --library [--port=PORT] [--verbose] [--daemon] " cerr << " kiwix-serve --library [--port=PORT] [--verbose] [--daemon] "
"[--nosearchbar] [--nolibrarybutton] [--attachToProcess=PID] " "[--nosearchbar] [--nolibrarybutton] [--attachToProcess=PID] "
"[--interface=IF_NAME] [--threads=NB_THREAD(" << nb_threads << ")] " "[--interface=IF_NAME] [--urlRootLocation=/URL_ROOT] "
"LIBRARY_PATH" "[--threads=NB_THREAD(" << nb_threads << ")] LIBRARY_PATH "
<< endl; << endl;
cerr << "\n If you set more than one ZIM_PATH, you cannot set a " cerr << "\n If you set more than one ZIM_PATH, you cannot set a "
"INDEX_PATH." "INDEX_PATH."
@ -930,8 +953,8 @@ int main(int argc, char** argv)
vector<string>::iterator itr; vector<string>::iterator itr;
kiwix::Book currentBook; kiwix::Book currentBook;
globalSearcher = new kiwix::Searcher(); globalSearcher = new kiwix::Searcher();
globalSearcher->setProtocolPrefix("/"); globalSearcher->setProtocolPrefix(rootLocation + "/");
globalSearcher->setSearchProtocolPrefix("/search?"); globalSearcher->setSearchProtocolPrefix(rootLocation + "/" + "search?");
for (itr = booksIds.begin(); itr != booksIds.end(); ++itr) { for (itr = booksIds.begin(); itr != booksIds.end(); ++itr) {
bool zimFileOk = false; bool zimFileOk = false;
libraryManager.getBookById(*itr, currentBook); libraryManager.getBookById(*itr, currentBook);
@ -955,16 +978,16 @@ int main(int argc, char** argv)
if ( reader->hasFulltextIndex()) { if ( reader->hasFulltextIndex()) {
kiwix::Searcher* searcher = new kiwix::Searcher(); kiwix::Searcher* searcher = new kiwix::Searcher();
searcher->setProtocolPrefix("/"); searcher->setProtocolPrefix(rootLocation + "/");
searcher->setSearchProtocolPrefix("/search?"); searcher->setSearchProtocolPrefix(rootLocation + "/" + "search?");
searcher->add_reader(reader, humanReadableId); searcher->add_reader(reader, humanReadableId);
globalSearcher->add_reader(reader, humanReadableId); globalSearcher->add_reader(reader, humanReadableId);
searchers[humanReadableId] = searcher; searchers[humanReadableId] = searcher;
} else if ( !indexPath.empty() ) { } else if ( !indexPath.empty() ) {
try { try {
kiwix::Searcher* searcher = new kiwix::Searcher(indexPath, reader, humanReadableId); kiwix::Searcher* searcher = new kiwix::Searcher(indexPath, reader, humanReadableId);
searcher->setProtocolPrefix("/"); searcher->setProtocolPrefix(rootLocation + "/");
searcher->setSearchProtocolPrefix("/search?"); searcher->setSearchProtocolPrefix(rootLocation + "/" + "search?");
searchers[humanReadableId] = searcher; searchers[humanReadableId] = searcher;
} catch (...) { } catch (...) {
cerr << "Unable to open the search index '" << indexPath << "'." cerr << "Unable to open the search index '" << indexPath << "'."
@ -989,7 +1012,7 @@ int main(int argc, char** argv)
&& readers.find(currentBook.getHumanReadableIdFromPath()) && readers.find(currentBook.getHumanReadableIdFromPath())
!= readers.end()) { != readers.end()) {
welcomeBooksHtml += "" welcomeBooksHtml += ""
"<a href='/" + currentBook.getHumanReadableIdFromPath() + "/'>" "<a href='" + rootLocation + "/" + currentBook.getHumanReadableIdFromPath() + "/'>"
"<div class='book'>" "<div class='book'>"
"<div class='book__background' style='background-image: url(data:" + currentBook.faviconMimeType+ ";base64," + currentBook.favicon + ");'>" "<div class='book__background' style='background-image: url(data:" + currentBook.faviconMimeType+ ";base64," + currentBook.favicon + ");'>"
"<div class='book__title' title='" + currentBook.title + "'>" + currentBook.title + "</div>" "<div class='book__title' title='" + currentBook.title + "'>" + currentBook.title + "</div>"

View File

@ -2,7 +2,7 @@
<span id="kiwixtoolbar" class="ui-widget-header"> <span id="kiwixtoolbar" class="ui-widget-header">
<div class="kiwix_centered"> <div class="kiwix_centered">
<div class="kiwix_searchform"> <div class="kiwix_searchform">
<form class="kiwixsearch" method="GET" action="/search" id="kiwixsearchform"> <form class="kiwixsearch" method="GET" action="__ROOT_LOCATION__/search" id="kiwixsearchform">
<input autocomplete="off" class="ui-autocomplete-input" id="kiwixsearchbox" name="pattern" type="text"> <input autocomplete="off" class="ui-autocomplete-input" id="kiwixsearchbox" name="pattern" type="text">
<input type="submit" value="Search"> <input type="submit" value="Search">
</form> </form>

View File

@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Welcome to Kiwix Server</title> <title>Welcome to Kiwix Server</title>
<script type="text/javascript" src="/skin/jquery-ui/external/jquery/jquery.js"></script> <script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/external/jquery/jquery.js"></script>
<script type="text/javascript" src="/skin/jquery-ui/jquery-ui.min.js"></script> <script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.js"></script>
<link type="text/css" href="/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" /> <link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" />
<link type="text/css" href="/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" /> <link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" />
<style> <style>
body { body {
background: background:

View File

@ -1,14 +1,14 @@
<link type="text/css" href="/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" /> <link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" />
<link type="text/css" href="/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" /> <link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" />
<link type="text/css" href="/skin/taskbar.css" rel="Stylesheet" /> <link type="text/css" href="__ROOT_LOCATION__/skin/taskbar.css" rel="Stylesheet" />
<script type="text/javascript" src="/skin/jquery-ui/external/jquery/jquery.js"></script> <script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/external/jquery/jquery.js"></script>
<script type="text/javascript" src="/skin/jquery-ui/jquery-ui.min.js"></script> <script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.js"></script>
<script> <script>
var jk = jQuery.noConflict(); var jk = jQuery.noConflict();
jk(function() { jk(function() {
jk( "#kiwixsearchbox" ).autocomplete({ jk( "#kiwixsearchbox" ).autocomplete({
source: "/suggest?content=__CONTENT__", source: "__ROOT_LOCATION__/suggest?content=__CONTENT__",
dataType: "json", dataType: "json",
cache: false, cache: false,

View File

@ -2,12 +2,12 @@
<span id="kiwixtoolbar" class="ui-widget-header"> <span id="kiwixtoolbar" class="ui-widget-header">
<div class="kiwix_centered"> <div class="kiwix_centered">
<div class="kiwix_button_wrapper"> <div class="kiwix_button_wrapper">
<a id="kiwix_serve_taskbar_library_button" href="/"><button>Library</button></a> <a id="kiwix_serve_taskbar_library_button" href="__ROOT_LOCATION__/"><button>Library</button></a>
<a id="kiwix_serve_taskbar_home_button" href="/__CONTENT__/"><button>Home</button></a> <a id="kiwix_serve_taskbar_home_button" href="__ROOT_LOCATION__/__CONTENT__/"><button>Home</button></a>
<a id="kiwix_serve_taskbar_random_button" href="/random?content=__CONTENT__"><button>Random</button></a> <a id="kiwix_serve_taskbar_random_button" href="__ROOT_LOCATION__/random?content=__CONTENT__"><button>Random</button></a>
</div> </div>
<div class="kiwix_searchform"> <div class="kiwix_searchform">
<form class="kiwixsearch" method="GET" action="/search" id="kiwixsearchform"> <form class="kiwixsearch" method="GET" action="__ROOT_LOCATION__/search" id="kiwixsearchform">
<input type="hidden" name="content" value="__CONTENT__" /> <input type="hidden" name="content" value="__CONTENT__" />
<input autocomplete="off" class="ui-autocomplete-input" id="kiwixsearchbox" name="pattern" type="text"> <input autocomplete="off" class="ui-autocomplete-input" id="kiwixsearchbox" name="pattern" type="text">
<input type="submit" value="Search"> <input type="submit" value="Search">