Port kiwix-serve to new api in kiwix-lib to serve a content. (#315)
Port kiwix-serve to new api in kiwix-lib to serve a content.
@ -25,5 +25,4 @@ if static_linkage
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
#subdir('include')
|
#subdir('include')
|
||||||
subdir('static')
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
|
@ -98,7 +98,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
if (reader) {
|
if (reader) {
|
||||||
searcher = new kiwix::Searcher();
|
searcher = new kiwix::Searcher();
|
||||||
searcher->add_reader(reader, "");
|
searcher->add_reader(reader);
|
||||||
} else {
|
} else {
|
||||||
cerr << "Unable to search through zim '" << zimPath << "'." << endl;
|
cerr << "Unable to search through zim '" << zimPath << "'." << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
sources = ['kiwix-serve.cpp', 'request_context.cpp']
|
sources = ['kiwix-serve.cpp']
|
||||||
sources += server_resources
|
|
||||||
|
|
||||||
executable('kiwix-serve', sources,
|
executable('kiwix-serve', sources,
|
||||||
dependencies:all_deps,
|
dependencies:all_deps,
|
||||||
|
@ -1,201 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009-2016 Emmanuel Engelhart <kelson@kiwix.org>
|
|
||||||
* Copyright 2017 Matthieu Gautier<mgautier@kymeria.fr>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "request_context.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
RequestContext::RequestContext(struct MHD_Connection* connection,
|
|
||||||
std::string rootLocation,
|
|
||||||
const std::string& _url,
|
|
||||||
const std::string& method,
|
|
||||||
const std::string& version) :
|
|
||||||
full_url(_url),
|
|
||||||
url(_url),
|
|
||||||
valid_url(true),
|
|
||||||
version(version),
|
|
||||||
acceptEncodingDeflate(false),
|
|
||||||
accept_range(false),
|
|
||||||
range_pair(0, -1)
|
|
||||||
{
|
|
||||||
if (method == "GET") {
|
|
||||||
this->method = RequestMethod::GET;
|
|
||||||
} else if (method == "HEAD") {
|
|
||||||
this->method = RequestMethod::HEAD;
|
|
||||||
} else if (method == "POST") {
|
|
||||||
this->method = RequestMethod::POST;
|
|
||||||
} else if (method == "PUT") {
|
|
||||||
this->method = RequestMethod::PUT;
|
|
||||||
} else if (method == "DELETE") {
|
|
||||||
this->method = RequestMethod::DELETE_;
|
|
||||||
} else if (method == "CONNECT") {
|
|
||||||
this->method = RequestMethod::CONNECT;
|
|
||||||
} else if (method == "OPTIONS") {
|
|
||||||
this->method = RequestMethod::OPTIONS;
|
|
||||||
} else if (method == "TRACE") {
|
|
||||||
this->method = RequestMethod::TRACE;
|
|
||||||
} else if (method == "PATCH") {
|
|
||||||
this->method = RequestMethod::PATCH;
|
|
||||||
} else {
|
|
||||||
this->method = RequestMethod::OTHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
MHD_get_connection_values(connection, MHD_HEADER_KIND, &RequestContext::fill_header, this);
|
|
||||||
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &RequestContext::fill_argument, this);
|
|
||||||
|
|
||||||
valid_url = true;
|
|
||||||
if (rootLocation.empty()) {
|
|
||||||
// nothing special to handle.
|
|
||||||
url = full_url;
|
|
||||||
} else {
|
|
||||||
if (full_url.size() > rootLocation.size() &&
|
|
||||||
full_url.substr(0, rootLocation.size()+1) == rootLocation + "/") {
|
|
||||||
url = full_url.substr(rootLocation.size());
|
|
||||||
} else {
|
|
||||||
valid_url = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
acceptEncodingDeflate =
|
|
||||||
(get_header(MHD_HTTP_HEADER_ACCEPT_ENCODING).find("deflate") != std::string::npos);
|
|
||||||
} catch (const std::out_of_range&) {}
|
|
||||||
|
|
||||||
/*Check if range is requested. */
|
|
||||||
try {
|
|
||||||
auto range = get_header(MHD_HTTP_HEADER_RANGE);
|
|
||||||
int start = 0;
|
|
||||||
int end = -1;
|
|
||||||
std::istringstream iss(range);
|
|
||||||
char c;
|
|
||||||
|
|
||||||
iss >> start >> c;
|
|
||||||
if (iss.good() && c=='-') {
|
|
||||||
iss >> end;
|
|
||||||
if (iss.fail()) {
|
|
||||||
// Something went wrong will extracting.
|
|
||||||
end = -1;
|
|
||||||
}
|
|
||||||
if (iss.eof()) {
|
|
||||||
accept_range = true;
|
|
||||||
range_pair = std::pair<int, int>(start, end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (const std::out_of_range&) {}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestContext::~RequestContext()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
int RequestContext::fill_header(void *__this, enum MHD_ValueKind kind,
|
|
||||||
const char *key, const char *value)
|
|
||||||
{
|
|
||||||
RequestContext *_this = static_cast<RequestContext*>(__this);
|
|
||||||
_this->headers[key] = value;
|
|
||||||
return MHD_YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RequestContext::fill_argument(void *__this, enum MHD_ValueKind kind,
|
|
||||||
const char *key, const char* value)
|
|
||||||
{
|
|
||||||
RequestContext *_this = static_cast<RequestContext*>(__this);
|
|
||||||
_this->arguments[key] = value == nullptr ? "" : value;
|
|
||||||
return MHD_YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RequestContext::print_debug_info() {
|
|
||||||
printf("method : %s (%d)\n", method==RequestMethod::GET ? "GET" :
|
|
||||||
method==RequestMethod::POST ? "POST" :
|
|
||||||
"OTHER", (int)method);
|
|
||||||
printf("version : %s\n", version.c_str());
|
|
||||||
printf("headers :\n");
|
|
||||||
for (auto it=headers.begin(); it!=headers.end(); it++) {
|
|
||||||
printf(" - %s : '%s'\n", it->first.c_str(), it->second.c_str());
|
|
||||||
}
|
|
||||||
printf("arguments :\n");
|
|
||||||
for (auto it=arguments.begin(); it!=arguments.end(); it++) {
|
|
||||||
printf(" - %s : '%s'\n", it->first.c_str(), it->second.c_str());
|
|
||||||
}
|
|
||||||
printf("Parsed : \n");
|
|
||||||
printf("url : %s\n", url.c_str());
|
|
||||||
printf("acceptEncodingDeflate : %d\n", acceptEncodingDeflate);
|
|
||||||
printf("has_range : %d\n", accept_range);
|
|
||||||
printf(".............\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RequestMethod RequestContext::get_method() {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RequestContext::get_url() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RequestContext::get_url_part(int number) {
|
|
||||||
size_t start = 1;
|
|
||||||
while(true) {
|
|
||||||
auto found = url.find('/', start);
|
|
||||||
if (number == 0) {
|
|
||||||
if (found == std::string::npos) {
|
|
||||||
return url.substr(start);
|
|
||||||
} else {
|
|
||||||
return url.substr(start, found-start);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (found == std::string::npos) {
|
|
||||||
throw std::out_of_range("No parts");
|
|
||||||
}
|
|
||||||
start = found + 1;
|
|
||||||
number -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RequestContext::get_full_url() {
|
|
||||||
return full_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RequestContext::is_valid_url() {
|
|
||||||
return valid_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RequestContext::has_range() {
|
|
||||||
return accept_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<int, int> RequestContext::get_range() {
|
|
||||||
return range_pair;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
std::string RequestContext::get_argument(const std::string& name) {
|
|
||||||
return arguments.at(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RequestContext::get_header(const std::string& name) {
|
|
||||||
return headers.at(name);
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009-2016 Emmanuel Engelhart <kelson@kiwix.org>
|
|
||||||
* Copyright 2017 Matthieu Gautier<mgautier@kymeria.fr>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef REQUEST_CONTEXT_H
|
|
||||||
#define REQUEST_CONTEXT_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <map>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <microhttpd.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class RequestMethod {
|
|
||||||
GET,
|
|
||||||
HEAD,
|
|
||||||
POST,
|
|
||||||
PUT,
|
|
||||||
DELETE_,
|
|
||||||
CONNECT,
|
|
||||||
OPTIONS,
|
|
||||||
TRACE,
|
|
||||||
PATCH,
|
|
||||||
OTHER
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyError : public std::runtime_error {};
|
|
||||||
class IndexError: public std::runtime_error {};
|
|
||||||
|
|
||||||
|
|
||||||
class RequestContext {
|
|
||||||
public:
|
|
||||||
RequestContext(struct MHD_Connection* connection,
|
|
||||||
std::string rootLocation,
|
|
||||||
const std::string& url,
|
|
||||||
const std::string& method,
|
|
||||||
const std::string& version);
|
|
||||||
~RequestContext();
|
|
||||||
|
|
||||||
void print_debug_info();
|
|
||||||
|
|
||||||
bool is_valid_url();
|
|
||||||
|
|
||||||
std::string get_header(const std::string& name);
|
|
||||||
template<typename T=std::string>
|
|
||||||
T get_argument(const std::string& name) {
|
|
||||||
std::istringstream stream(arguments.at(name));
|
|
||||||
T v;
|
|
||||||
stream >> v;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RequestMethod get_method();
|
|
||||||
std::string get_url();
|
|
||||||
std::string get_url_part(int part);
|
|
||||||
std::string get_full_url();
|
|
||||||
|
|
||||||
bool has_range();
|
|
||||||
std::pair<int, int> get_range();
|
|
||||||
|
|
||||||
bool can_compress() { return acceptEncodingDeflate; }
|
|
||||||
|
|
||||||
// [TODO] Move this to the response builder
|
|
||||||
int httpResponseCode;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string full_url;
|
|
||||||
std::string url;
|
|
||||||
bool valid_url;
|
|
||||||
RequestMethod method;
|
|
||||||
std::string version;
|
|
||||||
|
|
||||||
bool acceptEncodingDeflate;
|
|
||||||
|
|
||||||
bool accept_range;
|
|
||||||
std::pair<int, int> range_pair;
|
|
||||||
std::map<std::string, std::string> headers;
|
|
||||||
std::map<std::string, std::string> arguments;
|
|
||||||
|
|
||||||
static int fill_header(void *, enum MHD_ValueKind, const char*, const char*);
|
|
||||||
static int fill_argument(void *, enum MHD_ValueKind, const char*, const char*);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<> std::string RequestContext::get_argument(const std::string& name);
|
|
||||||
|
|
||||||
|
|
||||||
#endif //REQUEST_CONTEXT_H
|
|
@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
res_compiler = find_program('kiwix-compile-resources', 'compile_resources.py')
|
|
||||||
|
|
||||||
subdir('server')
|
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1,13 +0,0 @@
|
|||||||
<span class="kiwix">
|
|
||||||
<span id="kiwixtoolbar" class="ui-widget-header">
|
|
||||||
<div class="kiwix_centered">
|
|
||||||
<div class="kiwix_searchform" style="margin: auto auto;float: none;">
|
|
||||||
<form class="kiwixsearch" method="GET" action="__ROOT_LOCATION__/search" id="kiwixsearchform">
|
|
||||||
<label for="kiwixsearchbox" style="line-height: 30px;">🔍</label>
|
|
||||||
<input autocomplete="off" class="ui-autocomplete-input" id="kiwixsearchbox" name="pattern" type="text">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<div style="display: block; height: 5em;"></div>
|
|
@ -1,56 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Welcome to Kiwix Server</title>
|
|
||||||
<script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/external/jquery/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.js"></script>
|
|
||||||
<link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.css" rel="Stylesheet" />
|
|
||||||
<link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.theme.min.css" rel="Stylesheet" />
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background:
|
|
||||||
radial-gradient(#EEEEEE 15%, transparent 16%) 0 0,
|
|
||||||
radial-gradient(#EEEEEE 15%, transparent 16%) 8px 8px,
|
|
||||||
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
|
|
||||||
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
|
|
||||||
background-color:#E8E8E8;
|
|
||||||
background-size:16px 16px;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
max-width: 1100px;
|
|
||||||
}
|
|
||||||
.book__list { text-align: center; }
|
|
||||||
.book {
|
|
||||||
display: inline-block; vertical-align: bottom; margin: 8px; padding: 12px 15px; width: 300px;
|
|
||||||
border: 1px solid #ccc; border-radius: 8px;
|
|
||||||
text-align: left; color: #000; font-family: sans-serif; font-size: 13px;
|
|
||||||
background-color:#F1F1F1;
|
|
||||||
box-shadow: 2px 2px 5px 0px #ccc;
|
|
||||||
}
|
|
||||||
.book:hover { background-color: #F9F9F9; box-shadow: none;}
|
|
||||||
.book__background { background-repeat: no-repeat; background-size: auto; background-position: top right; }
|
|
||||||
.book__title {
|
|
||||||
padding: 0 55px 0 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
||||||
font-size: 18px; color: #0645ad;
|
|
||||||
}
|
|
||||||
.book__description {
|
|
||||||
padding: 5px 55px 5px 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
.book__info { line-height: 18px; color: #777; font-weight: bold; font-size: 13px; }
|
|
||||||
</style>
|
|
||||||
<script type="text/javascript" src="__ROOT_LOCATION__/skin/taskbar.js" async></script>
|
|
||||||
</head>
|
|
||||||
<body class="kiwix">
|
|
||||||
|
|
||||||
<div class="kiwix">
|
|
||||||
__BOOKS__
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="kiwixfooter">
|
|
||||||
Powered by <a href="https://kiwix.org">Kiwix</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,28 +0,0 @@
|
|||||||
<link type="text/css" href="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.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="__ROOT_LOCATION__/skin/taskbar.css" rel="Stylesheet" />
|
|
||||||
<script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/external/jquery/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="__ROOT_LOCATION__/skin/jquery-ui/jquery-ui.min.js"></script>
|
|
||||||
<script>
|
|
||||||
var jk = jQuery.noConflict();
|
|
||||||
jk(function() {
|
|
||||||
jk( "#kiwixsearchbox" ).autocomplete({
|
|
||||||
|
|
||||||
source: "__ROOT_LOCATION__/suggest?content=__CONTENT_ESCAPED__",
|
|
||||||
dataType: "json",
|
|
||||||
cache: false,
|
|
||||||
|
|
||||||
select: function(event, ui) {
|
|
||||||
jk( "#kiwixsearchbox" ).val(ui.item.value);
|
|
||||||
jk( "#kiwixsearchform" ).submit();
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* cybook hack */
|
|
||||||
if (navigator.userAgent.indexOf("bookeen/cybook") != -1) {
|
|
||||||
jk("html").addClass("cybook");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="__ROOT_LOCATION__/skin/taskbar.js" async></script>
|
|
9789
static/server/jquery-ui/external/jquery/jquery.js
vendored
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 212 B |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 280 B |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB |
7
static/server/jquery-ui/jquery-ui.min.css
vendored
13
static/server/jquery-ui/jquery-ui.min.js
vendored
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
server_resources = custom_target('resources',
|
|
||||||
input: 'resources_list.txt',
|
|
||||||
output: ['server-resources.cpp', 'server-resources.h'],
|
|
||||||
command:[res_compiler, '--cxxfile', '@OUTPUT0@', '--hfile', '@OUTPUT1@', '@INPUT@'],
|
|
||||||
build_always: true
|
|
||||||
)
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
|
||||||
<ShortName>Zim catalog search</ShortName>
|
|
||||||
<Description>Search zim files in the catalog.</Description>
|
|
||||||
<Url type="application/atom+xml;profile=opds-catalog"
|
|
||||||
xmlns:atom="http://www.w3.org/2005/Atom"
|
|
||||||
indexOffset="0"
|
|
||||||
template="/__ROOT_LOCATION__/catalog/search?q={searchTerms}&lang={language}&count={count}&start={startIndex}"/>
|
|
||||||
</OpenSearchDescription>
|
|
@ -1,27 +0,0 @@
|
|||||||
jquery-ui/jquery-ui.structure.min.css
|
|
||||||
jquery-ui/jquery-ui.min.js
|
|
||||||
jquery-ui/external/jquery/jquery.js
|
|
||||||
jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png
|
|
||||||
jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png
|
|
||||||
jquery-ui/images/ui-icons_222222_256x240.png
|
|
||||||
jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png
|
|
||||||
jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png
|
|
||||||
jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png
|
|
||||||
jquery-ui/images/ui-icons_2e83ff_256x240.png
|
|
||||||
jquery-ui/images/ui-icons_cd0a0a_256x240.png
|
|
||||||
jquery-ui/images/ui-icons_888888_256x240.png
|
|
||||||
jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png
|
|
||||||
jquery-ui/images/animated-overlay.gif
|
|
||||||
jquery-ui/images/ui-bg_glass_75_dadada_1x400.png
|
|
||||||
jquery-ui/images/ui-icons_454545_256x240.png
|
|
||||||
jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png
|
|
||||||
jquery-ui/jquery-ui.theme.min.css
|
|
||||||
jquery-ui/jquery-ui.min.css
|
|
||||||
home.html.tmpl
|
|
||||||
include.html.part
|
|
||||||
caret.png
|
|
||||||
taskbar.js
|
|
||||||
taskbar.css
|
|
||||||
taskbar.html.part
|
|
||||||
global_taskbar.html.part
|
|
||||||
opensearchdescription.xml
|
|
@ -1,186 +0,0 @@
|
|||||||
#kiwixtoolbar {
|
|
||||||
position: fixed;
|
|
||||||
padding: .5em;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
z-index: 100;
|
|
||||||
background-position-y: 0px;
|
|
||||||
transition: 0.3s;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwixtoolbar>a {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwixfooter {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.height_separator {
|
|
||||||
height: 3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwixsearch {
|
|
||||||
position: relative;
|
|
||||||
height: 26px;
|
|
||||||
width: 100%;
|
|
||||||
left: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix_searchform {
|
|
||||||
width: 20em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwix_serve_taskbar_home_button button {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix .kiwix_centered {
|
|
||||||
max-width: 720px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwix_button_show_toggle {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwix_button_show_toggle:checked~label~.kiwix_button_cont,
|
|
||||||
#kiwix_button_show_toggle:checked~label~.kiwix_button_cont>a {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwix_button_show_toggle:not(:checked)~label~.kiwix_button_cont {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="kiwix_button_show_toggle"] {
|
|
||||||
display: inline-block;
|
|
||||||
height: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="kiwix_button_show_toggle"] img {
|
|
||||||
transition: 0.1s;
|
|
||||||
height: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kiwix_button_show_toggle:checked~label img {
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="kiwix_button_show_toggle"],
|
|
||||||
.kiwix_button_cont {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix .kiwix_searchform {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix #kiwixtoolbar button,
|
|
||||||
.kiwix #kiwixtoolbar input[type="submit"] {
|
|
||||||
box-sizing: border-box !important;
|
|
||||||
height: 26px !important;
|
|
||||||
line-height: 20px !important;
|
|
||||||
margin-right: 5px !important;
|
|
||||||
padding: 2px 6px !important;
|
|
||||||
border: 1px solid #999 !important;
|
|
||||||
border-radius: 3px !important;
|
|
||||||
background-color: #ededed !important;
|
|
||||||
font-weight: normal !important;
|
|
||||||
cursor: pointer !important;
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix #kiwixtoolbar #kiwixsearchform input[type='text'] {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
box-sizing: border-box !important;
|
|
||||||
width: 100%;
|
|
||||||
height: 26px !important;
|
|
||||||
line-height: 20px !important;
|
|
||||||
border: 1px solid #999 !important;
|
|
||||||
border-radius: 3px !important;
|
|
||||||
background-color: #fff !important;
|
|
||||||
padding: 2px 2px 2px 27px !important;
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for=kiwixsearchbox] {
|
|
||||||
z-index: 1;
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
left: 5px;
|
|
||||||
font-size: 90%;
|
|
||||||
line-height: 26px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
padding-top: 40px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to fix buggy stuff in jquery-ui autocomplete */
|
|
||||||
#ui-id-1,
|
|
||||||
.ui-autocomplete {
|
|
||||||
background: white !important;
|
|
||||||
border: solid 1px grey !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
li.ui-state-focus {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(min-width:420px) {
|
|
||||||
.kiwix_button_cont {
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix_button_cont>a {
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="kiwix_button_show_toggle"] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 645px) {
|
|
||||||
|
|
||||||
#kiwix_button_show_toggle~label~.kiwix_button_cont.searching {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="kiwix_button_show_toggle"].searching {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix_searchform.full_width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwixsearch {
|
|
||||||
float: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kiwix_searchform {
|
|
||||||
width: 36%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.height_separator {
|
|
||||||
height: 6em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(max-width:415px) {
|
|
||||||
.kiwix_searchform {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
<span class="kiwix">
|
|
||||||
<span id="kiwixtoolbar" class="ui-widget-header">
|
|
||||||
<div class="kiwix_centered">
|
|
||||||
<div class="kiwix_searchform">
|
|
||||||
<form class="kiwixsearch" method="GET" action="__ROOT_LOCATION__/search" id="kiwixsearchform">
|
|
||||||
<input type="hidden" name="content" value="__CONTENT__" />
|
|
||||||
<label for="kiwixsearchbox">🔍</label>
|
|
||||||
<input autocomplete="off" class="ui-autocomplete-input" id="kiwixsearchbox" name="pattern" type="text">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<input type="checkbox" id="kiwix_button_show_toggle">
|
|
||||||
<label for="kiwix_button_show_toggle"><img src="__ROOT_LOCATION__/skin/caret.png" alt=""></label>
|
|
||||||
<div class="kiwix_button_cont">
|
|
||||||
<a id="kiwix_serve_taskbar_library_button" href="__ROOT_LOCATION__/"><button>🏠</button></a>
|
|
||||||
<a id="kiwix_serve_taskbar_home_button" href="__ROOT_LOCATION__/__CONTENT__/"><button>__ZIM_TITLE__</button></a>
|
|
||||||
<a id="kiwix_serve_taskbar_random_button"
|
|
||||||
href="__ROOT_LOCATION__/random?content=__CONTENT_ESCAPED__"><button>🎲</button></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
(function ($) {
|
|
||||||
if ($(window).width() < 520) {
|
|
||||||
var didScroll;
|
|
||||||
var lastScrollTop = 0;
|
|
||||||
var delta = 5;
|
|
||||||
// on scroll, let the interval function know the user has scrolled
|
|
||||||
$(window).scroll(function (event) {
|
|
||||||
didScroll = true;
|
|
||||||
});
|
|
||||||
// run hasScrolled() and reset didScroll status
|
|
||||||
setInterval(function () {
|
|
||||||
if (didScroll) {
|
|
||||||
hasScrolled();
|
|
||||||
didScroll = false;
|
|
||||||
}
|
|
||||||
}, 250);
|
|
||||||
function hasScrolled() {
|
|
||||||
var st = $(this).scrollTop();
|
|
||||||
|
|
||||||
// Make sure they scroll more than delta
|
|
||||||
if (Math.abs(lastScrollTop - st) <= delta)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If they scrolled down and are past the navbar, add class .nav-up.
|
|
||||||
// This is necessary so you never see what is "behind" the navbar.
|
|
||||||
if (st > lastScrollTop) {
|
|
||||||
// Scroll Down
|
|
||||||
$('#kiwixtoolbar').css({ top: '-100%' });
|
|
||||||
} else {
|
|
||||||
// Scroll Up
|
|
||||||
$('#kiwixtoolbar').css({ top: '0' });
|
|
||||||
}
|
|
||||||
|
|
||||||
lastScrollTop = st;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#kiwixsearchbox').on({
|
|
||||||
focus: function () {
|
|
||||||
$('.kiwix_searchform').addClass('full_width');
|
|
||||||
$('label[for="kiwix_button_show_toggle"], .kiwix_button_cont').addClass('searching');
|
|
||||||
},
|
|
||||||
blur: function () {
|
|
||||||
$('.kiwix_searchform').removeClass('full_width');
|
|
||||||
$('label[for="kiwix_button_show_toggle"], .kiwix_button_cont').removeClass('searching');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})(jQuery);
|
|