├── docs ├── .gitignore ├── requirements.txt ├── meson.build ├── index.rst ├── usage.rst └── conf.py ├── subprojects ├── .gitignore └── gtest.wrap ├── test ├── data │ ├── corner_cases │ │ ├── c# │ │ ├── empty.css │ │ ├── empty.html │ │ ├── empty.js │ │ ├── empty.png │ │ ├── c_sharp.html │ │ └── c#.html │ ├── zimfile&other.zim │ ├── helloworld.txt │ ├── zimfile_raycharles.zim │ ├── zimfile_raycharles_uncategorized.zim │ ├── welcome.html │ ├── poor.zim │ ├── example.zim │ ├── zimfile.zim │ ├── corner_cases#&.zim │ ├── customized_resources.txt │ ├── lib_for_server_search_test.xml │ ├── create_corner_cases_zim_file │ └── library.xml ├── kiwixserve.cpp ├── languageTools.cpp ├── i18n.cpp ├── opds_catalog.cpp ├── meson.build └── regex.cpp ├── debian ├── source │ └── format ├── libkiwix14.install ├── copyright ├── libkiwix-dev.install ├── libkiwix-dev.manpages ├── changelog ├── rules └── control ├── src ├── config.h.in ├── tools │ ├── base64.h │ ├── networkTools.h │ ├── regexTools.h │ ├── pathTools.h │ ├── opdsParsingTools.cpp │ ├── archiveTools.h │ ├── languageTools.cpp │ ├── otherTools.h │ └── regexTools.cpp ├── subprocess_unix.h ├── subprocess_windows.h ├── subprocess.h ├── subprocess.cpp ├── server │ ├── microhttpd_wrapper.h │ ├── i18n_utils.h │ ├── etag.h │ └── byte_range.h ├── aria2.h ├── html_dumper.h ├── subprocess_unix.cpp ├── meson.build ├── library_dumper.cpp ├── bookmark.cpp ├── kiwixserve.cpp ├── opds_catalog.cpp ├── libxml_dumper.h ├── opds_dumper.h ├── library_dumper.h ├── server.cpp ├── subprocess_windows.cpp └── version.cpp ├── static ├── skin │ ├── print.css │ ├── caret.png │ ├── feed.png │ ├── hash.png │ ├── magnet.png │ ├── bittorrent.png │ ├── download.png │ ├── fonts │ │ ├── Roboto.ttf │ │ ├── Poppins.ttf │ │ └── DMSans-Regular.ttf │ ├── favicon │ │ ├── favicon.ico │ │ ├── mstile-70x70.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── site.webmanifest │ │ ├── browserconfig.xml │ │ └── safari-pinned-tab.svg │ ├── blank.html │ ├── download-white.svg │ ├── i18n │ │ ├── ms.json │ │ ├── dga.json │ │ ├── ja.json │ │ ├── hy.json │ │ ├── el.json │ │ ├── skr-arab.json │ │ ├── cs.json │ │ ├── sk.json │ │ ├── hu.json │ │ ├── ku-latn.json │ │ ├── pl.json │ │ ├── bn.json │ │ ├── br.json │ │ ├── fi.json │ │ ├── ar.json │ │ ├── nqo.json │ │ ├── lb.json │ │ ├── dag.json │ │ ├── or.json │ │ ├── te.json │ │ ├── zh-hans.json │ │ └── sc.json │ ├── polyfills.js │ ├── search-icon.svg │ ├── feed.svg │ ├── search_results.css │ ├── langSelector.svg │ ├── blocklink.svg │ ├── autoComplete │ │ └── css │ │ │ └── autoComplete.css │ ├── error.css │ └── kiwix.css ├── templates │ ├── url_of_search_results_css.tmpl │ ├── error.xml │ ├── viewer_settings.js │ ├── suggestion.json │ ├── catalog_v2_partial_entry.xml │ ├── error.html │ ├── catalog_entries.xml │ ├── catalog_v2_categories.xml │ ├── sexy500.html │ ├── no_js_download.html │ ├── catalog_v2_entries.xml │ ├── catalog_v2_languages.xml │ ├── catalog_v2_entry.xml │ ├── captured_external.html │ ├── sexy404.html │ ├── search_result.xml │ └── catalog_v2_root.xml ├── opensearchdescription.xml ├── catalog_v2_searchdescription.xml ├── ft_opensearchdescription.xml ├── navigation_feed.tmpl ├── i18n_resources_list.txt ├── resources_list.txt ├── meson.build └── generate_i18n_resources_list.py ├── .gitignore ├── .codecov.yml ├── meson_options.txt ├── include ├── meson.build ├── common.h ├── kiwixserve.h ├── kiwix.h ├── opds_catalog.h ├── version.h ├── name_mapper.h ├── i18n.h ├── bookmark.h └── server.h ├── scripts ├── format_code.sh ├── meson.build ├── kiwix-compile-i18n.1 └── kiwix-compile-resources.1 ├── .clang-format ├── .github ├── stale.yml └── FUNDING.yml ├── .readthedocs.yaml └── AUTHORS /docs/.gitignore: -------------------------------------------------------------------------------- 1 | api 2 | xml 3 | -------------------------------------------------------------------------------- /subprojects/.gitignore: -------------------------------------------------------------------------------- 1 | gtest 2 | -------------------------------------------------------------------------------- /test/data/corner_cases/c#: -------------------------------------------------------------------------------- 1 | c#.html -------------------------------------------------------------------------------- /test/data/corner_cases/empty.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/data/corner_cases/empty.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/data/corner_cases/empty.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/data/corner_cases/empty.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /test/data/zimfile&other.zim: -------------------------------------------------------------------------------- 1 | zimfile.zim -------------------------------------------------------------------------------- /test/data/corner_cases/c_sharp.html: -------------------------------------------------------------------------------- 1 | c#.html -------------------------------------------------------------------------------- /test/data/helloworld.txt: -------------------------------------------------------------------------------- 1 | Hello world! 2 | -------------------------------------------------------------------------------- /test/data/zimfile_raycharles.zim: -------------------------------------------------------------------------------- 1 | zimfile.zim -------------------------------------------------------------------------------- /debian/libkiwix14.install: -------------------------------------------------------------------------------- 1 | usr/lib/*/libkiwix.so.* 2 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | See COPYING in the repository root. 2 | -------------------------------------------------------------------------------- /test/data/zimfile_raycharles_uncategorized.zim: -------------------------------------------------------------------------------- 1 | zimfile.zim -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | 2 | #mesondefine LIBKIWIX_VERSION 3 | 4 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | breathe 2 | exhale 3 | sphinx_rtd_theme 4 | -------------------------------------------------------------------------------- /test/data/welcome.html: -------------------------------------------------------------------------------- 1 | Welcome 2 | -------------------------------------------------------------------------------- /static/skin/print.css: -------------------------------------------------------------------------------- 1 | #kiwixtoolbarwrapper { 2 | display: none !important; 3 | } 4 | -------------------------------------------------------------------------------- /test/data/poor.zim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/test/data/poor.zim -------------------------------------------------------------------------------- /static/skin/caret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/caret.png -------------------------------------------------------------------------------- /static/skin/feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/feed.png -------------------------------------------------------------------------------- /static/skin/hash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/hash.png -------------------------------------------------------------------------------- /test/data/example.zim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/test/data/example.zim -------------------------------------------------------------------------------- /test/data/zimfile.zim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/test/data/zimfile.zim -------------------------------------------------------------------------------- /static/skin/magnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/magnet.png -------------------------------------------------------------------------------- /static/templates/url_of_search_results_css.tmpl: -------------------------------------------------------------------------------- 1 | {{root}}/skin/search_results.css?KIWIXCACHEID 2 | -------------------------------------------------------------------------------- /static/skin/bittorrent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/bittorrent.png -------------------------------------------------------------------------------- /static/skin/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/download.png -------------------------------------------------------------------------------- /debian/libkiwix-dev.install: -------------------------------------------------------------------------------- 1 | usr/include 2 | usr/lib/*/libkiwix.so 3 | usr/lib/*/pkgconfig 4 | usr/bin 5 | -------------------------------------------------------------------------------- /static/skin/fonts/Roboto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/fonts/Roboto.ttf -------------------------------------------------------------------------------- /test/data/corner_cases#&.zim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/test/data/corner_cases#&.zim -------------------------------------------------------------------------------- /static/skin/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/favicon.ico -------------------------------------------------------------------------------- /static/skin/fonts/Poppins.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/fonts/Poppins.ttf -------------------------------------------------------------------------------- /debian/libkiwix-dev.manpages: -------------------------------------------------------------------------------- 1 | usr/share/man/man1/kiwix-compile-resources.1* 2 | usr/share/man/man1/kiwix-compile-i18n.1* 3 | -------------------------------------------------------------------------------- /static/skin/favicon/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/mstile-70x70.png -------------------------------------------------------------------------------- /static/skin/fonts/DMSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/fonts/DMSans-Regular.ttf -------------------------------------------------------------------------------- /static/skin/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /static/skin/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /static/skin/favicon/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/mstile-144x144.png -------------------------------------------------------------------------------- /static/skin/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /static/skin/favicon/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/mstile-310x150.png -------------------------------------------------------------------------------- /static/skin/favicon/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/mstile-310x310.png -------------------------------------------------------------------------------- /static/skin/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /static/skin/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/skin/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hean01/libkiwix/main/static/skin/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.swp 3 | subprojects/googletest-release* 4 | *.class 5 | build/ 6 | .vscode/ 7 | builddir/ 8 | .cache/ 9 | .clangd/ 10 | -------------------------------------------------------------------------------- /src/tools/base64.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::string base64_encode(const std::string& inString); 4 | std::string base64_decode(const std::string& s); 5 | -------------------------------------------------------------------------------- /static/templates/error.xml: -------------------------------------------------------------------------------- 1 | 2 | {{PAGE_TITLE}} 3 | {{#details}} 4 | {{{p}}} 5 | {{/details}} 6 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | libkiwix (0.0.0) unstable; urgency=medium 2 | 3 | * Initial release 4 | 5 | -- Kunal Mehta Wed, 08 Jul 2020 18:12:32 -0700 6 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all 3 | 4 | %: 5 | dh $@ --buildsystem=meson 6 | 7 | override_dh_auto_test: 8 | dh_auto_test -- -t 3 9 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | notify: 3 | require_ci_to_pass: yes 4 | 5 | coverage: 6 | status: 7 | project: 8 | default: 9 | threshold: 1% 10 | 11 | ignore: 12 | - "test" 13 | -------------------------------------------------------------------------------- /static/templates/viewer_settings.js: -------------------------------------------------------------------------------- 1 | const viewerSettings = { 2 | toolbarEnabled: {{enable_toolbar}}, 3 | linkBlockingEnabled: {{enable_link_blocking}}, 4 | libraryButtonEnabled: {{enable_library_button}} 5 | } 6 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('static-linkage', type : 'boolean', value : false, 2 | description : 'Link statically with the dependencies.') 3 | option('doc', type : 'boolean', value : false, 4 | description : 'Build the documentations.') 5 | -------------------------------------------------------------------------------- /docs/meson.build: -------------------------------------------------------------------------------- 1 | 2 | sphinx = find_program('sphinx-build', native:true) 3 | 4 | sphinx_target = run_target('doc', 5 | command: [sphinx, '-bhtml', 6 | meson.current_source_dir(), 7 | meson.current_build_dir()]) 8 | -------------------------------------------------------------------------------- /static/skin/blank.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Blank page 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /static/templates/suggestion.json: -------------------------------------------------------------------------------- 1 | [ 2 | {{#suggestions}}{{^first}},{{/first}} 3 | { 4 | "value" : "{{value}}", 5 | "label" : "{{label}}", 6 | "kind" : "{{kind}}" 7 | {{#path}} 8 | , "path" : "{{path}}" 9 | {{/path}} 10 | }{{/suggestions}} 11 | ] 12 | -------------------------------------------------------------------------------- /static/templates/catalog_v2_partial_entry.xml: -------------------------------------------------------------------------------- 1 | 2 | urn:uuid:{{id}} 3 | {{title}} 4 | {{updated}} 5 | 8 | 9 | -------------------------------------------------------------------------------- /include/meson.build: -------------------------------------------------------------------------------- 1 | headers = [ 2 | 'book.h', 3 | 'bookmark.h', 4 | 'common.h', 5 | 'library.h', 6 | 'manager.h', 7 | 'downloader.h', 8 | 'search_renderer.h', 9 | 'server.h', 10 | 'kiwixserve.h', 11 | 'name_mapper.h', 12 | 'tools.h', 13 | 'version.h', 14 | 'i18n.h' 15 | ] 16 | 17 | install_headers(headers, subdir:'kiwix') 18 | -------------------------------------------------------------------------------- /scripts/format_code.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | # Compute 'src' path 4 | SCRIPT_DIR=$(dirname "$0") 5 | REPO_DIR=$(readlink -f "$SCRIPT_DIR"/..) 6 | DIRS="src include" 7 | 8 | # Apply formating to all *.cpp and *.h files 9 | cd "$REPO_DIR" 10 | for FILE in $(find $DIRS -name '*.h' -o -name '*.cpp') 11 | do 12 | echo $FILE 13 | clang-format -i -style=file "$FILE" 14 | done 15 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | BinPackArguments: false 3 | BinPackParameters: false 4 | BreakBeforeBinaryOperators: All 5 | BreakBeforeBraces: Linux 6 | DerivePointerAlignment: false 7 | SpacesInContainerLiterals: false 8 | Standard: Cpp11 9 | 10 | AllowShortFunctionsOnASingleLine: Inline 11 | AllowShortIfStatementsOnASingleLine: false 12 | AllowShortLoopsOnASingleLine: false 13 | -------------------------------------------------------------------------------- /test/kiwixserve.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "../include/kiwixserve.h" 3 | 4 | TEST(KiwixServeTest, PortTest) 5 | { 6 | kiwix::KiwixServe kiwixServe("libraryPath", 8181); 7 | EXPECT_EQ(kiwixServe.getPort(), 8181); 8 | kiwixServe.setPort(8484); 9 | EXPECT_EQ(kiwixServe.getPort(), 8484); 10 | EXPECT_EQ(kiwixServe.setPort(0), -1); 11 | EXPECT_EQ(kiwixServe.setPort(3456789), -1); 12 | } 13 | -------------------------------------------------------------------------------- /test/data/customized_resources.txt: -------------------------------------------------------------------------------- 1 | /non-existent-item text/plain ./test/helloworld.txt 2 | / text/html ./test/welcome.html 3 | /skin/index.css application/json ./test/helloworld.txt 4 | /zimfile/A/Ray_Charles ray/charles ./test/welcome.html 5 | /content/zimfile/A/Ray_Charles charles/ray ./test/welcome.html 6 | /search text/html ./test/helloworld.txt 7 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. libkiwix documentation master file, created by 2 | sphinx-quickstart on Fri Jul 24 15:40:50 2020. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to libkiwix's documentation! 7 | ================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | usage 14 | api/ref_api 15 | -------------------------------------------------------------------------------- /scripts/meson.build: -------------------------------------------------------------------------------- 1 | 2 | res_manager = find_program('kiwix-resources') 3 | res_compiler = find_program('kiwix-compile-resources') 4 | 5 | install_data(res_compiler.path(), install_dir:get_option('bindir')) 6 | 7 | install_man('kiwix-compile-resources.1') 8 | 9 | i18n_compiler = find_program('kiwix-compile-i18n') 10 | 11 | install_data(i18n_compiler.path(), install_dir:get_option('bindir')) 12 | 13 | install_man('kiwix-compile-i18n.1') 14 | -------------------------------------------------------------------------------- /test/data/corner_cases/c#.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | C# 6 | 7 | 8 |

C# (pronounced see sharp) is a general-purpose, high-level multi-paradigm programming language. C# encompasses static typing, strong typing, lexically scoped, imperative, declarative, functional, generic, object-oriented (class-based), and component-oriented programming disciplines

9 | 10 | 11 | -------------------------------------------------------------------------------- /subprojects/gtest.wrap: -------------------------------------------------------------------------------- 1 | [wrap-file] 2 | directory = googletest-release-1.8.1 3 | 4 | source_url = https://github.com/google/googletest/archive/release-1.8.1.zip 5 | source_filename = gtest-1.8.1.zip 6 | source_hash = 927827c183d01734cc5cfef85e0ff3f5a92ffe6188e0d18e909c5efebf28a0c7 7 | 8 | patch_url = https://wrapdb.mesonbuild.com/v1/projects/gtest/1.8.1/1/get_zip 9 | patch_filename = gtest-1.8.1-1-wrap.zip 10 | patch_hash = f79f5fd46e09507b3f2e09a51ea6eb20020effe543335f5aee59f30cc8d15805 11 | -------------------------------------------------------------------------------- /docs/usage.rst: -------------------------------------------------------------------------------- 1 | Libkiwix programming 2 | ==================== 3 | 4 | Introduction 5 | ------------ 6 | 7 | libkiwix is written in C++. To use the library, you need the include files of libkiwix have 8 | to link against libzim. 9 | 10 | Errors are handled with exceptions. When something goes wrong, libkiwix throws an error, 11 | which is always derived from std::exception. 12 | 13 | All classes are defined in the namespace kiwix. 14 | 15 | libkiwix is a set of tools to manage zim files and provide some common functionnality. 16 | -------------------------------------------------------------------------------- /static/skin/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | daysUntilClose: false 2 | staleLabel: stale 3 | 4 | issues: 5 | daysUntilStale: 60 6 | markComment: > 7 | This issue has been automatically marked as stale because it has not had 8 | recent activity. It will be now be reviewed manually. Thank you 9 | for your contributions. 10 | pulls: 11 | daysUntilStale: 7 12 | markComment: > 13 | This pull request has been automatically marked as stale because it has not had 14 | recent activity. It will be now be reviewed manually. Thank you 15 | for your contributions. 16 | -------------------------------------------------------------------------------- /static/skin/download-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /scripts/kiwix-compile-i18n.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX-COMPILE-I18N "1" "January 2022" "Kiwix" "User Commands" 2 | .SH NAME 3 | kiwix-compile-i18n \- helper to compile Kiwix i18n (internationalization) data 4 | .SH SYNOPSIS 5 | \fBkiwix\-compile\-i18n\fR [\-h] \-\-cxxfile CXXFILE i18n_resource_files ...\fR 6 | .SH DESCRIPTION 7 | .TP 8 | i18n_resource_files ... 9 | The list of i18n resources to compile. 10 | .TP 11 | \fB\-h\fR, \fB\-\-help\fR 12 | show a help message and exit 13 | .TP 14 | \fB\-\-cxxfile\fR CXXFILE 15 | The Cpp file name to generate 16 | .TP 17 | .SH AUTHOR 18 | Veloman Yunkan 19 | -------------------------------------------------------------------------------- /static/skin/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | #da532c 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _KIWIX_COMMON_H_ 3 | #define _KIWIX_COMMON_H_ 4 | 5 | #include 6 | 7 | #ifdef __GNUC__ 8 | #define DEPRECATED __attribute__((deprecated)) 9 | #elif defined(_MSC_VER) 10 | #define DEPRECATED __declspec(deprecated) 11 | #else 12 | #praga message("WARNING: You need to implement DEPRECATED for this compiler") 13 | #define DEPRECATED 14 | #endif 15 | 16 | 17 | namespace kiwix { 18 | 19 | enum class IpMode { IPV4, IPV6, ALL, AUTO }; // AUTO: Server decides the protocol 20 | typedef zim::size_type size_type; 21 | typedef zim::offset_type offset_type; 22 | 23 | } 24 | 25 | #endif //_KIWIX_COMMON_H_ 26 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the version of Python and other tools you might need 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.11" 12 | 13 | # Build documentation in the docs/ directory with Sphinx 14 | sphinx: 15 | configuration: docs/conf.py 16 | 17 | # We recommend specifying your dependencies to enable reproducible builds: 18 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 19 | python: 20 | install: 21 | - requirements: docs/requirements.txt 22 | -------------------------------------------------------------------------------- /src/subprocess_unix.h: -------------------------------------------------------------------------------- 1 | #ifndef KIWIX_SUBPROCESS_UNIX_H_ 2 | #define KIWIX_SUBPROCESS_UNIX_H_ 3 | 4 | #include "subprocess.h" 5 | 6 | #include 7 | #include 8 | 9 | class UnixImpl : public SubprocessImpl 10 | { 11 | private: 12 | int m_pid; 13 | std::atomic m_running; 14 | std::atomic m_shouldQuit; 15 | std::thread m_waitingThread; 16 | 17 | public: 18 | UnixImpl(); 19 | virtual ~UnixImpl(); 20 | 21 | void run(commandLine_t& commandLine); 22 | bool kill(); 23 | bool isRunning(); 24 | 25 | static void* waitForPID(void* self); 26 | }; 27 | 28 | #endif //KIWIX_SUBPROCESS_UNIX_H_ 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: kiwix 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # https://kiwix.org/support-us/ 13 | -------------------------------------------------------------------------------- /static/opensearchdescription.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Zim catalog search 4 | Search zim files in the catalog. 5 | 10 | 11 | -------------------------------------------------------------------------------- /scripts/kiwix-compile-resources.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX-COMPILE-RESOURCES "1" "August 2017" "Kiwix" "User Commands" 2 | .SH NAME 3 | kiwix-compile-resources \- helper to compile and generate some Kiwix resources 4 | .SH SYNOPSIS 5 | \fBkiwix\-compile\-resources\fR [\-h] [\-\-cxxfile CXXFILE] [\-\-hfile HFILE] resource_file ...\fR 6 | .SH DESCRIPTION 7 | .TP 8 | resource_file 9 | The list of resources to compile. 10 | .TP 11 | \fB\-h\fR, \fB\-\-help\fR 12 | show a help message and exit 13 | .TP 14 | \fB\-\-cxxfile\fR CXXFILE 15 | The Cpp file name to generate 16 | .TP 17 | \fB\-\-hfile\fR HFILE 18 | The h file name to generate 19 | .SH AUTHOR 20 | Matthieu Gautier 21 | -------------------------------------------------------------------------------- /static/catalog_v2_searchdescription.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Zim catalog search 4 | Search zim files in the catalog. 5 | 10 | 11 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Automactic 2 | Ayoub DARDORY 3 | Cristian Patrasciuc 4 | Dattaz 5 | Elad Keyshawn 6 | Emmanuel Engelhart 7 | Isaac 8 | jleow00 9 | Julian Harty 10 | Kiran Mathew Koshy 11 | Kunal Mehta 12 | Matthieu Gautier 13 | Rashiq Ahmad 14 | Renaud Gaudin 15 | Shivam 16 | Steve Wills 17 | Synhershko 18 | -------------------------------------------------------------------------------- /static/ft_opensearchdescription.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Fulltext articles search 4 | Search for articles in the Library. 5 | 10 | 11 | -------------------------------------------------------------------------------- /include/kiwixserve.h: -------------------------------------------------------------------------------- 1 | #ifndef KIWIXLIB_KIWIX_SERVE_H_ 2 | #define KIWIXLIB_KIWIX_SERVE_H_ 3 | 4 | #include 5 | #include 6 | 7 | class Subprocess; 8 | namespace kiwix { 9 | 10 | class KiwixServe 11 | { 12 | public: 13 | KiwixServe(const std::string& libraryPath, int port = 8181); 14 | ~KiwixServe(); 15 | 16 | void run(); 17 | void shutDown(); 18 | bool isRunning(); 19 | int getPort() { return m_port; } 20 | int setPort(int port); 21 | 22 | private: 23 | std::unique_ptr mp_kiwixServe; 24 | int m_port; 25 | std::string m_libraryPath; 26 | }; 27 | 28 | }; //end namespace kiwix 29 | 30 | #endif // KIWIXLIB_KIWIX_SERVE_H_ 31 | -------------------------------------------------------------------------------- /src/subprocess_windows.h: -------------------------------------------------------------------------------- 1 | #ifndef KIWIX_SUBPROCESS_WINDOWS_H_ 2 | #define KIWIX_SUBPROCESS_WINDOWS_H_ 3 | 4 | #include "subprocess.h" 5 | 6 | #include 7 | #include 8 | 9 | class WinImpl : public SubprocessImpl 10 | { 11 | private: 12 | int m_pid; 13 | bool m_running; 14 | HANDLE m_subprocessHandle; 15 | HANDLE m_waitingThreadHandle; 16 | CRITICAL_SECTION m_criticalSection; 17 | 18 | public: 19 | WinImpl(); 20 | virtual ~WinImpl(); 21 | 22 | void run(commandLine_t& commandLine); 23 | bool kill(); 24 | bool isRunning(); 25 | 26 | static DWORD WINAPI waitForPID(void* self); 27 | }; 28 | 29 | #endif //KIWIX_SUBPROCESS_WINDOWS_H_ 30 | -------------------------------------------------------------------------------- /static/skin/i18n/ms.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Tofeiku" 5 | ] 6 | }, 7 | "name": "Bahasa Melayu", 8 | "404-page-heading": "Tidak Dijumpai", 9 | "500-page-title": "Ralat Pelayan Dalaman", 10 | "500-page-heading": "Ralat Pelayan Dalaman", 11 | "library-button-text": "Pergi ke laman selamat datang", 12 | "searchbox-tooltip": "Cari '{{BOOK_TITLE}}'", 13 | "search": "Cari", 14 | "book-filtering-all-categories": "Semua kategori", 15 | "book-filtering-all-languages": "Semua bahasa", 16 | "download": "Muat turun", 17 | "direct-download-link-text": "Langsung", 18 | "direct-download-alt-text": "muat turun langsung", 19 | "download-links-title": "Muat turun buku" 20 | } 21 | -------------------------------------------------------------------------------- /static/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{PAGE_TITLE}} 6 | {{#CSS_URL}} 7 | 8 | {{/CSS_URL}}{{#KIWIX_RESPONSE_DATA}} {{/KIWIX_RESPONSE_DATA}} 12 | 13 | 14 |

{{PAGE_HEADING}}

15 | {{#details}} 16 |

17 | {{{p}}} 18 |

19 | {{/details}} 20 | 21 | 22 | -------------------------------------------------------------------------------- /static/skin/i18n/dga.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Alhaji Yakubu" 5 | ] 6 | }, 7 | "welcome-page-overzealous-filter": "Duoro kyebe. E na boɔra ka fo?", 8 | "search": "Bo", 9 | "book-filtering-all-categories": "Zagre zaa", 10 | "book-filtering-all-languages": "Kɔkɔrɛɛ zaa", 11 | "count-of-matching-books": "{{COUNT}} gama", 12 | "download": "Tagebo", 13 | "direct-download-link-text": "Toribu", 14 | "direct-download-alt-text": "Toribu tagebo", 15 | "hash-download-alt-text": "Tage bonmannaa", 16 | "magnet-link-text": "Kurimaraa sobie", 17 | "magnet-alt-text": "Tage kurimaraa", 18 | "filter-by-tag": "Guy yi kpuli {{TAG}}", 19 | "stop-filtering-by-tag": "Bare gyɛɛbo kpuli {{TAG}}" 20 | } 21 | -------------------------------------------------------------------------------- /static/templates/catalog_entries.xml: -------------------------------------------------------------------------------- 1 | 4 | {{feed_id}} 5 | {{^filter}}All zims{{/filter}}{{#filter}}Filtered zims ({{filter}}){{/filter}} 6 | {{date}} 7 | {{#filter}} 8 | {{totalResults}} 9 | {{startIndex}} 10 | {{itemsPerPage}} 11 | {{/filter}} 12 | 13 | 14 | {{#books}}{{{entry}}}{{/books}} 15 | -------------------------------------------------------------------------------- /test/data/lib_for_server_search_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /static/navigation_feed.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{id}} 4 | 7 | 10 | {{title}} 11 | {{updated}} 12 | 13 | {{author_name}} 14 | {{author_uri}} 15 | 16 | 17 | {{#entries}} 18 | 19 | {{title}} 20 | 23 | {{updated}} 24 | {{id}} 25 | 26 | {{/entries}} 27 | 28 | -------------------------------------------------------------------------------- /src/subprocess.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef KIWIX_SUBPROCESS_H_ 3 | #define KIWIX_SUBPROCESS_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | typedef std::vector commandLine_t; 10 | 11 | class SubprocessImpl 12 | { 13 | public: 14 | virtual void run(commandLine_t& commandLine) = 0; 15 | virtual bool kill() = 0; 16 | virtual bool isRunning() = 0; 17 | virtual ~SubprocessImpl() = default; 18 | }; 19 | 20 | class Subprocess 21 | { 22 | private: 23 | // Impl depends of the system (window, unix, ...) 24 | std::unique_ptr mp_impl; 25 | Subprocess(std::unique_ptr impl, commandLine_t& commandLine); 26 | 27 | public: 28 | static std::unique_ptr run(commandLine_t& commandLine); 29 | ~Subprocess(); 30 | 31 | bool isRunning(); 32 | bool kill(); 33 | }; 34 | 35 | 36 | #endif // KIWIX_SUBPROCESS_H_ 37 | -------------------------------------------------------------------------------- /src/subprocess.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "subprocess.h" 4 | 5 | #ifdef _WIN32 6 | # include "subprocess_windows.h" 7 | #else 8 | # include "subprocess_unix.h" 9 | #endif 10 | 11 | Subprocess::Subprocess(std::unique_ptr impl, commandLine_t& commandLine) : 12 | mp_impl(std::move(impl)) 13 | { 14 | mp_impl->run(commandLine); 15 | } 16 | 17 | Subprocess::~Subprocess() 18 | { 19 | mp_impl->kill(); 20 | } 21 | 22 | std::unique_ptr Subprocess::run(commandLine_t& commandLine) 23 | { 24 | #ifdef _WIN32 25 | auto impl = std::unique_ptr(new WinImpl); 26 | #else 27 | auto impl = std::unique_ptr(new UnixImpl); 28 | #endif 29 | return std::unique_ptr(new Subprocess(std::move(impl), commandLine)); 30 | } 31 | 32 | bool Subprocess::isRunning() 33 | { 34 | return mp_impl->isRunning(); 35 | } 36 | 37 | bool Subprocess::kill() 38 | { 39 | return mp_impl->kill(); 40 | } 41 | -------------------------------------------------------------------------------- /include/kiwix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_H 21 | #define KIWIX_H 22 | 23 | #include "library.h" 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/server/microhttpd_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | 22 | #if MHD_VERSION < 0x00097002 23 | typedef int MHD_Result; 24 | #endif 25 | -------------------------------------------------------------------------------- /static/templates/catalog_v2_categories.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | {{feed_id}} 5 | 8 | 11 | List of categories 12 | {{date}} 13 | 14 | {{#categories}} 15 | 16 | {{name}} 17 | 20 | {{updated}} 21 | {{id}} 22 | All entries with category of '{{name}}'. 23 | 24 | {{/categories}} 25 | 26 | -------------------------------------------------------------------------------- /src/tools/networkTools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_NETWORKTOOLS_H 21 | #define KIWIX_NETWORKTOOLS_H 22 | 23 | #include 24 | 25 | namespace kiwix 26 | { 27 | std::string download(const std::string& url); 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /static/templates/sexy500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{PAGE_TITLE}} 7 | 8 | 12 | 13 | 14 |
15 | {{500_img_text}} 19 |
20 |
21 |

{{PAGE_HEADING}}

22 |

{{PAGE_TEXT}}

23 |

{{url_path}}

24 |
25 | {{#error}} 26 |
27 |

{{error}}

28 |
29 | {{/error}} 30 | 31 | 32 | -------------------------------------------------------------------------------- /static/templates/no_js_download.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{translations.download-links-title}} 8 | 9 | 16 | 17 |
18 | {{{translations.download-links-heading}}} 19 |
20 | 21 |
{{translations.direct-download-link-text}}
22 |
23 | 24 |
{{translations.hash-download-link-text}}
25 |
26 | 27 |
{{translations.magnet-link-text}}
28 |
29 | 30 |
{{translations.torrent-download-link-text}}
31 |
32 | 33 | -------------------------------------------------------------------------------- /include/opds_catalog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_OPDS_CATALOG_H 21 | #define KIWIX_OPDS_CATALOG_H 22 | 23 | 24 | #include "library.h" 25 | 26 | namespace kiwix 27 | { 28 | 29 | std::string getSearchUrl(const Filter& f); 30 | 31 | } // namespace kiwix 32 | 33 | #endif // KIWIX_OPDS_CATALOG_H 34 | -------------------------------------------------------------------------------- /static/i18n_resources_list.txt: -------------------------------------------------------------------------------- 1 | skin/i18n/ar.json 2 | skin/i18n/bn.json 3 | skin/i18n/br.json 4 | skin/i18n/cs.json 5 | skin/i18n/dag.json 6 | skin/i18n/de.json 7 | skin/i18n/dga.json 8 | skin/i18n/el.json 9 | skin/i18n/en.json 10 | skin/i18n/es.json 11 | skin/i18n/fi.json 12 | skin/i18n/fr.json 13 | skin/i18n/ha.json 14 | skin/i18n/he.json 15 | skin/i18n/hi.json 16 | skin/i18n/hu.json 17 | skin/i18n/hy.json 18 | skin/i18n/ia.json 19 | skin/i18n/id.json 20 | skin/i18n/ig.json 21 | skin/i18n/it.json 22 | skin/i18n/ja.json 23 | skin/i18n/ko.json 24 | skin/i18n/ku-latn.json 25 | skin/i18n/lb.json 26 | skin/i18n/mk.json 27 | skin/i18n/ms.json 28 | skin/i18n/nb.json 29 | skin/i18n/nl.json 30 | skin/i18n/nqo.json 31 | skin/i18n/or.json 32 | skin/i18n/pl.json 33 | skin/i18n/pt-br.json 34 | skin/i18n/pt.json 35 | skin/i18n/ro.json 36 | skin/i18n/ru.json 37 | skin/i18n/sc.json 38 | skin/i18n/sk.json 39 | skin/i18n/skr-arab.json 40 | skin/i18n/sl.json 41 | skin/i18n/sq.json 42 | skin/i18n/sv.json 43 | skin/i18n/sw.json 44 | skin/i18n/te.json 45 | skin/i18n/test.json 46 | skin/i18n/tr.json 47 | skin/i18n/zh-hans.json 48 | skin/i18n/zh-hant.json 49 | -------------------------------------------------------------------------------- /static/templates/catalog_v2_entries.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | {{feed_id}} 7 | 8 | 11 | 14 | 17 | 18 | {{^filter}}All Entries{{/filter}}{{#filter}}Filtered Entries ({{filter}}){{/filter}} 19 | {{date}} 20 | {{#filter}} 21 | {{totalResults}} 22 | {{startIndex}} 23 | {{itemsPerPage}} 24 | {{/filter}} 25 | {{#books}}{{{entry}}}{{/books}} 26 | -------------------------------------------------------------------------------- /static/skin/i18n/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "MathXplore", 5 | "もなー(偽物)" 6 | ] 7 | }, 8 | "name": "日本語", 9 | "no-query": "クエリを指定していません。", 10 | "400-page-title": "無効なリクエストです", 11 | "400-page-heading": "無効なリクエストです", 12 | "404-page-title": "コンテンツが見つかりませんでした", 13 | "404-page-heading": "見つかりません", 14 | "500-page-title": "内部サーバーエラー", 15 | "500-page-heading": "内部サーバーエラー", 16 | "fulltext-search-unavailable": "全文検索は利用できません", 17 | "no-search-results": "このコンテンツでは全文検索エンジンが利用できません", 18 | "library-button-text": "ウェルカムページに移動", 19 | "random-page-button-text": "無作為に選ばれたページに移動する", 20 | "search": "検索", 21 | "book-filtering-all-categories": "すべてのカテゴリー", 22 | "book-filtering-all-languages": "すべての言語", 23 | "download": "ダウンロード", 24 | "direct-download-link-text": "直ダウンロードリンク", 25 | "direct-download-alt-text": "直ダウンロード", 26 | "hash-download-link-text": "Sha256 ハッシュ", 27 | "hash-download-alt-text": "ハッシュをダウンロード", 28 | "magnet-link-text": "マグネットリンク", 29 | "magnet-alt-text": "マグネットをダウンロード", 30 | "torrent-download-link-text": "Torrentファイル", 31 | "torrent-download-alt-text": "Torrentをダウンロード", 32 | "preview-book": "プレビュー" 33 | } 34 | -------------------------------------------------------------------------------- /static/templates/catalog_v2_languages.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | {{feed_id}} 7 | 10 | 13 | List of languages 14 | {{date}} 15 | 16 | {{#languages}} 17 | 18 | {{lang_self_name}} 19 | {{{lang_code}}} 20 | {{book_count}} 21 | 24 | {{updated}} 25 | {{id}} 26 | 27 | {{/languages}} 28 | 29 | -------------------------------------------------------------------------------- /static/templates/catalog_v2_entry.xml: -------------------------------------------------------------------------------- 1 | 2 | urn:uuid:{{id}} 3 | {{title}} 4 | {{updated}} 5 | {{description}} 6 | {{language}} 7 | {{name}} 8 | {{flavour}} 9 | {{category}} 10 | {{tags}} 11 | {{article_count}} 12 | {{media_count}} 13 | {{#icons}} 16 | {{/icons}} 17 | 18 | {{author_name}} 19 | 20 | 21 | {{publisher_name}} 22 | 23 | {{book_date}} 24 | {{#url}} 25 | 26 | {{/url}} 27 | 28 | -------------------------------------------------------------------------------- /static/skin/polyfills.js: -------------------------------------------------------------------------------- 1 | // A few browsers do not support the use of String.prototype.replaceAll method. 2 | // Hence we define it once we verify that it isn't supported. For documentation 3 | // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll 4 | if (!String.prototype.replaceAll) { 5 | String.prototype.replaceAll = function (pattern, replacement) { 6 | // verify parameter: It must either be a string or a RegExp with a global flag. 7 | if (typeof pattern[Symbol.replace] === 'function') { 8 | // the pattern is a RegExp check for the presence of g flag. 9 | if (pattern.global) { 10 | return this.replace(pattern, replacement); 11 | } else { 12 | throw new TypeError('Global flag for regular expressions') 13 | } 14 | } 15 | // the pattern is not a RegExp, hence it must be a string. 16 | if (typeof pattern !== 'string') { 17 | throw new TypeError('pattern must either be a string or a RegExp with a global (g) flag.') 18 | } 19 | return this.replace(new RegExp(pattern, 'g'), replacement); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /static/skin/search-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Layer 1 5 | 6 | -------------------------------------------------------------------------------- /src/tools/regexTools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_REGEXTOOLS_H 21 | #define KIWIX_REGEXTOOLS_H 22 | 23 | #include 24 | 25 | bool matchRegex(const std::string& content, const std::string& regex); 26 | std::string replaceRegex(const std::string& content, 27 | const std::string& replacement, 28 | const std::string& regex); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /static/skin/feed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_VERSION_H 21 | #define KIWIX_VERSION_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace kiwix 28 | { 29 | typedef std::vector> LibVersions; 30 | LibVersions getVersions(); 31 | void printVersions(std::ostream& out = std::cout); 32 | } 33 | 34 | #endif // KIWIX_VERSION_H 35 | -------------------------------------------------------------------------------- /static/templates/captured_external.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{external_link_detected}} 7 | 8 | 9 | 13 | 14 | 15 |
16 | {{caution_warning}} 20 |
21 |
22 |

{{external_link_detected}}

23 |

{{external_link_intro}}

24 |

{{ url }}

25 |
26 |
27 |

{{advice.p1}}

28 |

{{advice.p2}}

29 |

{{advice.p3}}

30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /static/templates/sexy404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{PAGE_TITLE}} 7 | 8 | {{#KIWIX_RESPONSE_DATA}} {{/KIWIX_RESPONSE_DATA}} 12 | 13 | 14 |
15 | {{404_img_text}} 19 |
20 |
21 |

{{PAGE_HEADING}}

22 |

{{path_was_not_found_msg}}

23 |

{{url_path}}

24 |
25 |
26 |

{{advice.p1}}

27 |

{{advice.p2}}

28 |
    29 |
  • {{advice.p3}}
  • 30 |
  • {{advice.p4}}
  • 31 |
32 |

{{advice.p5}}

33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /static/skin/i18n/hy.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Kareyac" 5 | ] 6 | }, 7 | "name": "Հայերեն", 8 | "suggest-full-text-search": "որոնել '{{{SEARCH_TERMS}}}'...", 9 | "no-such-book": "Գիրքը բացակայում է՝ {{BOOK_NAME}}", 10 | "url-not-found": "Սխալ հասցե՝ {{url}}", 11 | "suggest-search": "Որոնել {{PATTERN}}", 12 | "400-page-title": "Անվավեր հարցում", 13 | "400-page-heading": "Անվավեր հարցում", 14 | "404-page-title": "Սխալ հասցե", 15 | "404-page-heading": "Սխալ հասցե", 16 | "500-img-text": "Էջը չի աշխատում", 17 | "library-button-text": "Գրադարանի էջ", 18 | "home-button-text": "Դեպի '{{BOOK_TITLE}}'֊ի գլխավոր էջը", 19 | "random-page-button-text": "Բացել պատահական էջ", 20 | "searchbox-tooltip": "Որոնել '{{BOOK_TITLE}}'֊ում", 21 | "book-filtering-all-categories": "Բոլոր կատեգորիաներ", 22 | "book-category.wikibooks": "Վիքիգրքեր", 23 | "book-category.wikinews": "Վիքիլուրեր", 24 | "book-category.wikipedia": "Վիքիպեդիա", 25 | "book-category.wikiquote": "Վիքիքաղվածք", 26 | "book-category.wikisource": "Վիքիդարան", 27 | "book-category.wikispecies": "Վիքիցեղեր", 28 | "book-category.wikiversity": "Վիքիլսարան", 29 | "book-category.wikivoyage": "Վիքիճամփորդ", 30 | "book-category.wiktionary": "Վիքիբառարան", 31 | "book-category.other": "Այլ" 32 | } 33 | -------------------------------------------------------------------------------- /src/aria2.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef KIWIXLIB_ARIA2_H_ 4 | #define KIWIXLIB_ARIA2_H_ 5 | 6 | #ifdef _WIN32 7 | // winsock2.h need to be included before windows.h (included by curl.h) 8 | # include 9 | #endif 10 | 11 | #include "subprocess.h" 12 | #include "xmlrpc.h" 13 | 14 | #include 15 | #include 16 | 17 | namespace kiwix { 18 | 19 | class Aria2 20 | { 21 | private: 22 | std::unique_ptr mp_aria; 23 | int m_port; 24 | std::string m_secret; 25 | std::string doRequest(const MethodCall& methodCall); 26 | 27 | public: 28 | explicit Aria2(std::string sessionFileDir); 29 | virtual ~Aria2() = default; 30 | void close(); 31 | 32 | std::string addUri(const std::vector& uri, const std::vector>& options = {}); 33 | std::string tellStatus(const std::string& gid, const std::vector& statusKey); 34 | static std::string getNewRpcSecret(); 35 | std::vector tellActive(); 36 | std::vector tellWaiting(); 37 | void saveSession(); 38 | void shutdown(); 39 | void pause(const std::string& gid); 40 | void unpause(const std::string& gid); 41 | void remove(const std::string& gid); 42 | }; 43 | 44 | }; //end namespace kiwix 45 | 46 | #endif // KIWIXLIB_ARIA2_H_ 47 | -------------------------------------------------------------------------------- /test/data/create_corner_cases_zim_file: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "$0")" 4 | 5 | # The following symbols (that would be nice to include in testing) are not 6 | # allowed under NTFS and/or FAT32 filesystems, and would result in the 7 | # impossibility to git clone (or rather checkout) the libkiwix repository under 8 | # Windows: 9 | # 10 | # ? 11 | # = 12 | # + (that's a pity, since the + symbol in a ZIM filename is replaced with the 13 | # text 'plus' when the ZIM file is added to kiwix-serve's library and it 14 | # would be nice to test that functionality) 15 | # 16 | # Assuming that tests are NOT run under Windows, above symbols can be included 17 | # in testing if the file is renamed while copying to the build directory (see 18 | # test/meson.build), though that would make maintenance slightly more confusing. 19 | zimfilename='corner_cases#&.zim' 20 | 21 | rm -f "$zimfilename" 22 | zimwriterfs --withoutFTIndex --dont-check-arguments \ 23 | -w empty.html \ 24 | -I empty.png \ 25 | -l en \ 26 | -t "ZIM corner cases" \ 27 | -d "" \ 28 | -c "" \ 29 | -p "" \ 30 | corner_cases \ 31 | "$zimfilename" \ 32 | && echo "$zimfilename was successfully created" \ 33 | || echo '!!! Failed to create' "$zimfilename" '!!!' >&2 34 | -------------------------------------------------------------------------------- /static/skin/search_results.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background-color: white; 3 | color: #000000; 4 | font: small/normal Arial,Helvetica,Sans-Serif; 5 | margin-top: 0.5em; 6 | font-size: 90%; 7 | } 8 | 9 | a{ 10 | color: #04c; 11 | } 12 | 13 | a:visited { 14 | color: #639 15 | } 16 | 17 | a:hover { 18 | text-decoration: underline 19 | } 20 | 21 | h1 { 22 | font-size: 120%; 23 | } 24 | 25 | ul { 26 | margin:0; 27 | padding:0 28 | } 29 | 30 | .results { 31 | font-size: 110%; 32 | } 33 | 34 | .results li { 35 | list-style-type:none; 36 | margin-top: 0.5em; 37 | } 38 | 39 | .results a { 40 | font-size: 110%; 41 | text-decoration: underline 42 | } 43 | 44 | cite { 45 | font-style:normal; 46 | word-wrap:break-word; 47 | display: block; 48 | font-size: 100%; 49 | } 50 | 51 | .informations { 52 | color: #388222; 53 | font-size: 100%; 54 | } 55 | 56 | .footer { 57 | padding: 0; 58 | margin-top: 1em; 59 | width: 100%; 60 | float: left 61 | } 62 | 63 | .footer a, .footer span { 64 | display: block; 65 | padding: .3em .7em; 66 | margin: 0 .38em 0 0; 67 | text-align:center; 68 | text-decoration: none; 69 | } 70 | 71 | .footer a:hover { 72 | background: #ededed; 73 | } 74 | 75 | .footer ul, .footer li { 76 | list-style:none; 77 | margin: 0; 78 | padding: 0; 79 | } 80 | 81 | .footer li { 82 | float: left; 83 | } 84 | 85 | .selected { 86 | background: #ededed; 87 | } 88 | -------------------------------------------------------------------------------- /static/skin/i18n/el.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Kelson", 5 | "Norhorn", 6 | "Ανώνυμος Βικιπαιδιστής" 7 | ] 8 | }, 9 | "name": "Αγγλικά", 10 | "no-such-book": "Δεν υπάρχει τέτοιο βιβλίο: {{BOOK_NAME}}", 11 | "welcome-page-overzealous-filter": "Κανένα αποτέλεσμα. Θέλετε να επαναφέρετε το φίλτρο;", 12 | "powered-by-kiwix-html": "Με την υποστήριξη by Kiwix", 13 | "search": "Αναζήτηση", 14 | "book-filtering-all-categories": "Όλες οι κατηγορίες", 15 | "book-filtering-all-languages": "Όλες οι γλώσσες", 16 | "count-of-matching-books": "{{COUNT}} βιβλίο(α)", 17 | "download": "Λήψη", 18 | "direct-download-link-text": "Απευθείας", 19 | "direct-download-alt-text": "άμεση λήψη", 20 | "hash-download-alt-text": "λήψη αναγνωριστικού", 21 | "magnet-alt-text": "λήψη μαγνήτη", 22 | "torrent-download-link-text": "Αρχείο torrent", 23 | "torrent-download-alt-text": "λήψη torrent", 24 | "filter-by-tag": "Φίλτρο ανά ετικέτα \"{{TAG}}\"", 25 | "stop-filtering-by-tag": "Διακοπή φίλτρου ανά ετικέτα \"{{TAG}}\"", 26 | "welcome-to-kiwix-server": "Καλώς ορίσατε στον διακομιστή Kiwix", 27 | "download-links-heading": "Λήψη συνδέσμων για {{BOOK_TITLE}}", 28 | "download-links-title": "Κατεβάστε το βιβλίο", 29 | "preview-book": "Προεπισκόπηση", 30 | "unknown-error": "Άγνωστο σφάλμα" 31 | } 32 | -------------------------------------------------------------------------------- /test/languageTools.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2023 Nikhil Tanwar (2002nikhiltanwar@gmail.com) 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied 11 | * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and 12 | * NON-INFRINGEMENT. See the GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | */ 19 | 20 | #include "gtest/gtest.h" 21 | #include "../include/tools.h" 22 | 23 | namespace 24 | { 25 | 26 | TEST(LanguageToolsTest, englishTest) 27 | { 28 | EXPECT_EQ(kiwix::getLanguageSelfName("eng"), "English"); 29 | } 30 | 31 | TEST(LanguageToolsTest, manualValuesTest) 32 | { 33 | EXPECT_EQ(kiwix::getLanguageSelfName("dty"), "डोटेली"); 34 | } 35 | 36 | TEST(LanguageToolsTest, emptyStringTest) 37 | { 38 | EXPECT_EQ(kiwix::getLanguageSelfName(""), "Undetermined"); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/tools/pathTools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_PATHTOOLS_H 21 | #define KIWIX_PATHTOOLS_H 22 | 23 | #include 24 | 25 | #ifdef _WIN32 26 | std::string WideToUtf8(const std::wstring& wstr); 27 | std::wstring Utf8ToWide(const std::string& str); 28 | #endif 29 | 30 | unsigned int getFileSize(const std::string& path); 31 | std::string getFileSizeAsString(const std::string& path); 32 | std::string makeTmpDirectory(); 33 | bool copyFile(const std::string& sourcePath, const std::string& destPath); 34 | bool writeTextFile(const std::string& path, const std::string& content); 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /src/html_dumper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Nikhil Tanwar <2002nikhiltanwar@gmail.com> 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_HTML_DUMPER_H 21 | #define KIWIX_HTML_DUMPER_H 22 | 23 | #include 24 | 25 | #include "library_dumper.h" 26 | 27 | namespace kiwix 28 | { 29 | 30 | /** 31 | * A class to dump Library in HTML format. 32 | */ 33 | class HTMLDumper : public LibraryDumper 34 | { 35 | public: 36 | HTMLDumper(const Library* library, const NameMapper* NameMapper); 37 | ~HTMLDumper(); 38 | 39 | 40 | /** 41 | * Dump library in HTML 42 | * 43 | * @return HTML content 44 | */ 45 | std::string dumpPlainHTML(kiwix::Filter filter) const; 46 | }; 47 | 48 | } 49 | 50 | #endif // KIWIX_HTML_DUMPER_H 51 | -------------------------------------------------------------------------------- /static/skin/i18n/skr-arab.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Saraiki" 5 | ] 6 | }, 7 | "name": "سرائیکی", 8 | "400-page-title": "غلط ارداس", 9 | "400-page-heading": "غلط ارداس", 10 | "404-page-title": "مواد کائنی لبھیا", 11 | "404-page-heading": "کائنی لبھا", 12 | "new-404-page-title": "ورقہ کائنی لبھیا", 13 | "404-img-text": "کائنی لبھا!", 14 | "500-page-title": "اندرلا سرور نقص", 15 | "500-page-heading": "اندرلا سرور نقص", 16 | "search": "ڳولو", 17 | "book-filtering-all-categories": "ساریاں ونکیاں", 18 | "book-filtering-all-languages": "ساریاں زباناں", 19 | "count-of-matching-books": "{{COUNT}} کتاب(اں)", 20 | "download": "ڈاؤن لوڈ", 21 | "direct-download-link-text": "ڈائرکٹ", 22 | "direct-download-alt-text": "ڈائرکٹ ڈاؤن لوڈ", 23 | "hash-download-alt-text": "ڈاؤن لوڈ ہیش", 24 | "torrent-download-link-text": "ٹورنٹ فائل", 25 | "torrent-download-alt-text": "ٹورںٹ ݙاؤن لوڈ کرو", 26 | "download-links-title": "کتاب ڈاؤن لوڈ کرو", 27 | "preview-book": "پیشگی ݙکھالا", 28 | "book-category.vikidia": "وکی ڈیا", 29 | "book-category.wikibooks": "وکی کتاباں", 30 | "book-category.wikinews": "وکی خبراں", 31 | "book-category.wikipedia": "وکیپیڈیا", 32 | "book-category.wikiquote": "وکی ٻول", 33 | "book-category.wikisource": "وکی ماخذ", 34 | "book-category.wikispecies": "وکی سپیشیز", 35 | "book-category.wikiversity": "وکی ورسٹی", 36 | "book-category.wikivoyage": "وکی سیرسپاٹا", 37 | "book-category.wiktionary": "وکشنری", 38 | "book-category.other": "ٻیا" 39 | } 40 | -------------------------------------------------------------------------------- /static/templates/search_result.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Search: {{query.pattern}} 7 | {{query.unpaginatedQuery}}&format=xml&start={{results.start}}&pageLength={{pagination.itemsPerPage}} 8 | Search result for {{query.pattern}} 9 | {{results.count}} 10 | {{results.start}} 11 | {{pagination.itemsPerPage}} 12 | 37 | 38 | -------------------------------------------------------------------------------- /static/skin/langSelector.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 13 | 16 | 17 | 18 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /static/skin/i18n/cs.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Spotter" 5 | ] 6 | }, 7 | "name": "Čeština", 8 | "suggest-full-text-search": "obsahující '{{{SEARCH_TERMS}}}'...", 9 | "no-such-book": "Žádná taková kniha: {{BOOK_NAME}}", 10 | "too-many-books": "Bylo požadováno příliš mnoho knih ({{NB_BOOKS}}), kde je limit {{LIMIT}}", 11 | "no-book-found": "Výběrovým kritériím nevyhovuje žádná kniha", 12 | "url-not-found": "Požadovaná adresa URL \"{{url}}\" nebyla na tomto serveru nalezena.", 13 | "suggest-search": "Proveďte fulltextové vyhledávání {{PATTERN}}", 14 | "random-article-failure": "Jejda! Nepodařilo se vybrat náhodný článek :(", 15 | "invalid-raw-data-type": "{{DATATYPE}} není platný požadavek na nezpracovaný obsah.", 16 | "no-value-for-arg": "Pro argument {{ARGUMENT}} nebyla zadána žádná hodnota", 17 | "no-query": "Nebyl poskytnut žádný dotaz.", 18 | "raw-entry-not-found": "Nelze najít položku {{DATATYPE}} {{ENTRY}}", 19 | "400-page-title": "Neplatný požadavek", 20 | "400-page-heading": "Neplatný požadavek", 21 | "404-page-title": "Obsah nenalezen", 22 | "404-page-heading": "Nenalezeno", 23 | "500-page-title": "Interní chyba serveru", 24 | "500-page-heading": "Interní chyba serveru", 25 | "fulltext-search-unavailable": "Fulltextové vyhledávání není k dispozici", 26 | "no-search-results": "Fulltextový vyhledávač není pro tento obsah dostupný.", 27 | "library-button-text": "Přejít na uvítací stránku", 28 | "home-button-text": "Přejít na hlavní stránku '{{BOOK_TITLE}}'", 29 | "random-page-button-text": "Přejít na náhodně vybranou stránku", 30 | "searchbox-tooltip": "Hledat '{{BOOK_TITLE}}'" 31 | } 32 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: libkiwix 2 | Priority: optional 3 | Maintainer: Kiwix team 4 | Build-Depends: debhelper-compat (= 13), 5 | meson, 6 | pkgconf, 7 | libzim-dev (>= 9.0), libzim-dev (<< 10.0), 8 | libcurl4-gnutls-dev, 9 | libicu-dev, 10 | libgtest-dev, 11 | libkainjow-mustache-dev, 12 | libmicrohttpd-dev, 13 | libpugixml-dev, 14 | zlib1g-dev 15 | Standards-Version: 4.5.0 16 | Section: libs 17 | Homepage: https://github.com/kiwix/libkiwix 18 | Rules-Requires-Root: no 19 | 20 | Package: libkiwix-dev 21 | Section: libdevel 22 | Architecture: any 23 | Multi-Arch: same 24 | Depends: libkiwix14 (= ${binary:Version}), ${misc:Depends}, python3, 25 | libzim-dev (>= 9.0), libzim-dev (<< 10.0), 26 | libicu-dev, 27 | libpugixml-dev, 28 | libcurl4-gnutls-dev, 29 | libmicrohttpd-dev, 30 | zlib1g-dev 31 | Description: library of common code for Kiwix (development) 32 | Kiwix is an offline Wikipedia reader. libkiwix provides the 33 | software core for Kiwix, and contains the code shared by all 34 | Kiwix ports (Windows, Linux, OSX, Android, etc.). 35 | . 36 | This package contains development files. 37 | 38 | Package: libkiwix14 39 | Architecture: any 40 | Multi-Arch: same 41 | Depends: ${shlibs:Depends}, ${misc:Depends}, aria2 42 | Conflicts: libkiwix0, libkiwix3, libkiwix9, libkiwix10, libkiwix11, libkiwix12, libkiwix13 43 | Replaces: libkiwix0, libkiwix3, libkiwix9, libkiwix10, libkiwix11, libkiwix12, libkiwix13 44 | Description: library of common code for Kiwix 45 | Kiwix is an offline Wikipedia reader. libkiwix provides the 46 | software core for Kiwix, and contains the code shared by all 47 | Kiwix ports (Windows, Linux, OSX, Android, etc.). 48 | -------------------------------------------------------------------------------- /src/subprocess_unix.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "subprocess_unix.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | UnixImpl::UnixImpl(): 13 | m_pid(0), 14 | m_running(false), 15 | m_shouldQuit(false) 16 | { 17 | } 18 | 19 | UnixImpl::~UnixImpl() 20 | { 21 | kill(); 22 | m_shouldQuit = true; 23 | m_waitingThread.join(); 24 | } 25 | 26 | void* UnixImpl::waitForPID(void* _self) 27 | { 28 | UnixImpl* self = static_cast(_self); 29 | while (true) { 30 | if (!waitpid(self->m_pid, NULL, WNOHANG)) { 31 | break; 32 | } 33 | if (self->m_shouldQuit) { 34 | return nullptr; 35 | } 36 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 37 | } 38 | 39 | self->m_running = false; 40 | 41 | return self; 42 | } 43 | 44 | void UnixImpl::run(commandLine_t& commandLine) 45 | { 46 | const char* binary = commandLine[0]; 47 | int pid = fork(); 48 | switch(pid) { 49 | case -1: 50 | std::cerr << "cannot fork" << std::endl; 51 | break; 52 | case 0: 53 | commandLine.push_back(NULL); 54 | if (execvp(binary, const_cast(commandLine.data()))) { 55 | perror("Cannot launch\n"); 56 | _exit(-1); 57 | } 58 | 59 | break; 60 | default: 61 | m_pid = pid; 62 | m_running = true; 63 | m_waitingThread = std::thread(waitForPID, this); 64 | break; 65 | } 66 | } 67 | 68 | bool UnixImpl::kill() 69 | { 70 | return (::kill(m_pid, SIGKILL) == 0); 71 | } 72 | 73 | bool UnixImpl::isRunning() 74 | { 75 | return m_running; 76 | } 77 | -------------------------------------------------------------------------------- /static/skin/i18n/sk.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Yardom78" 5 | ] 6 | }, 7 | "name": "slovenčina", 8 | "suggest-full-text-search": "obsahuje '{{{SEARCH_TERMS}}}'...", 9 | "no-such-book": "Žiadna kniha ako: {{BOOK_NAME}}", 10 | "too-many-books": "Príliš veľa požadovaných kníh ({{NB_BOOKS}}), limit je {{LIMIT}}", 11 | "no-book-found": "Kritériám výberu nevyhovuje žiadna kniha", 12 | "url-not-found": "Požadovaná adresa URL \"{{url}}\" na tomto serveri nebola nájdená.", 13 | "suggest-search": "Spustite hľadanie celého textu {{PATTERN}}", 14 | "random-article-failure": "Nepodarilo sa vybrať náhodný článok :(", 15 | "invalid-raw-data-type": "{{DATATYPE}} nie je platná požiadavka pre surový obsah.", 16 | "no-value-for-arg": "Pre argument {{ARGUMENT}} nebola poskytnutá žiadna hodnota", 17 | "no-query": "Nebol poskytnutý žiadny dopyt.", 18 | "raw-entry-not-found": "Nepodarilo sa nájsť {{DATATYPE}} položka {{ENTRY}}", 19 | "400-page-title": "Neplatná požiadavka", 20 | "400-page-heading": "Neplatná požiadavka", 21 | "404-page-title": "Obsah nebol nájdený", 22 | "404-page-heading": "Nenájdené", 23 | "500-page-title": "Chyba interného servera", 24 | "500-page-heading": "Chyba interného servera", 25 | "fulltext-search-unavailable": "Vyhľadávanie celého textu nie je dostupné", 26 | "no-search-results": "Funkcia na vyhľadávanie celého textu nie je pre tento obsah dostupná.", 27 | "library-button-text": "Prejsť na uvítaciu stránku", 28 | "home-button-text": "Prejsť na hlavnú stránku knihy {{BOOK_TITLE}}", 29 | "random-page-button-text": "Prejsť na náhodne vybranú stránku", 30 | "searchbox-tooltip": "Vyhľadať {{BOOK_TITLE}}" 31 | } 32 | -------------------------------------------------------------------------------- /static/skin/i18n/hu.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Eukarióta", 5 | "Urbalazs" 6 | ] 7 | }, 8 | "name": "Magyar", 9 | "400-page-title": "Érvénytelen kérés", 10 | "400-page-heading": "Érvénytelen kérés", 11 | "404-page-title": "A tartalom nem található", 12 | "404-page-heading": "Nem található", 13 | "new-404-page-title": "Az oldal nem található", 14 | "new-404-page-heading": "Hoppá! Az oldal nem található.", 15 | "404-img-text": "Nem található!", 16 | "path-was-not-found": "A kért útvonal nem található:", 17 | "404-advice.p1": "A keresett tartalom továbbra is elérhető lehet, de előfordulhat, hogy más helyen található a ZIM-fájlon belül.", 18 | "search": "Keresés", 19 | "download": "Letöltés", 20 | "hash-download-link-text": "SHA-256 ellenőrzőösszeg", 21 | "hash-download-alt-text": "SHA-256 fájl-ellenőrzőösszeg megjelenítése", 22 | "torrent-download-link-text": "BitTorrent", 23 | "welcome-to-kiwix-server": "Üdvözli a Kiwix-kiszolgáló!", 24 | "download-links-heading": "Letöltési hivatkozások ehhez: {{BOOK_TITLE}}", 25 | "download-links-title": "Könyv letöltése", 26 | "preview-book": "Előnézet", 27 | "unknown-error": "Ismeretlen hiba", 28 | "book-category.wikibooks": "Wikikönyvek", 29 | "book-category.wikinews": "Wikihírek", 30 | "book-category.wikipedia": "Wikipédia", 31 | "book-category.wikiquote": "Wikidézet", 32 | "book-category.wikisource": "Wikiforrás", 33 | "book-category.wikispecies": "Wikifajok", 34 | "book-category.wikiversity": "Wikiegyetem", 35 | "book-category.wikivoyage": "Wikivoyage", 36 | "book-category.wiktionary": "Wikiszótár", 37 | "book-category.other": "Egyéb", 38 | "text-loading-content": "Tartalom betöltése" 39 | } 40 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | kiwix_sources = [ 2 | 'book.cpp', 3 | 'bookmark.cpp', 4 | 'library.cpp', 5 | 'manager.cpp', 6 | 'libxml_dumper.cpp', 7 | 'opds_dumper.cpp', 8 | 'html_dumper.cpp', 9 | 'library_dumper.cpp', 10 | 'downloader.cpp', 11 | 'server.cpp', 12 | 'search_renderer.cpp', 13 | 'subprocess.cpp', 14 | 'aria2.cpp', 15 | 'tools/base64.cpp', 16 | 'tools/pathTools.cpp', 17 | 'tools/regexTools.cpp', 18 | 'tools/stringTools.cpp', 19 | 'tools/networkTools.cpp', 20 | 'tools/opdsParsingTools.cpp', 21 | 'tools/languageTools.cpp', 22 | 'tools/otherTools.cpp', 23 | 'tools/archiveTools.cpp', 24 | 'kiwixserve.cpp', 25 | 'name_mapper.cpp', 26 | 'server/byte_range.cpp', 27 | 'server/etag.cpp', 28 | 'server/request_context.cpp', 29 | 'server/response.cpp', 30 | 'server/internalServer.cpp', 31 | 'server/internalServer_catalog.cpp', 32 | 'server/i18n.cpp', 33 | 'opds_catalog.cpp', 34 | 'version.cpp' 35 | ] 36 | kiwix_sources += lib_resources 37 | kiwix_sources += i18n_resources 38 | 39 | if host_machine.system() == 'windows' 40 | kiwix_sources += 'subprocess_windows.cpp' 41 | else 42 | kiwix_sources += 'subprocess_unix.cpp' 43 | endif 44 | 45 | install_dir = get_option('libdir') 46 | 47 | config_h = configure_file(output : 'kiwix_config.h', 48 | configuration : conf, 49 | input : 'config.h.in') 50 | install_headers(config_h, subdir:'kiwix') 51 | 52 | libkiwix = library('kiwix', 53 | kiwix_sources, 54 | include_directories : inc, 55 | dependencies : all_deps, 56 | link_args: extra_libs, 57 | version: meson.project_version(), 58 | install: true, 59 | install_dir: install_dir) 60 | -------------------------------------------------------------------------------- /static/skin/i18n/ku-latn.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Bikarhêner" 5 | ] 6 | }, 7 | "name": "kurdî", 8 | "suggest-full-text-search": "'{{{SEARCH_TERMS}}}' dihewîne...", 9 | "no-such-book": "Kitêbeke wisa nîne: {{BOOK_NAME}}", 10 | "too-many-books": "Pir zêde kitêb hatiye xwestin ({{NB_BOOKS}}) ku sînor {{LIMIT}} ye", 11 | "no-book-found": "Ti kitêbekê ku li krîterên te bê peyda nebû", 12 | "url-not-found": "URLya xwestî \"{{url}}\" li ser vê serverê nehate dîtin.", 13 | "suggest-search": "Ji bo {{PATTERN}} lêgerîneke nivîsa temamî pêk bîne", 14 | "random-article-failure": "Ha ho! Bi ser neket ku gotareke ketober bibijêre :(", 15 | "invalid-raw-data-type": "{{DATATYPE}} ne daxwazeke derbasdar e ji bo naveroka xav.", 16 | "no-value-for-arg": "Ti tişt nehatiye diyarkirin ji bo mijara {{ARGUMENT}}", 17 | "no-query": "Ti tiştekî xwestî nîne.", 18 | "raw-entry-not-found": "Hêmana {{ENTRY}} {{DATATYPE}} peyda nebû", 19 | "400-page-title": "Xwesteka nederbasdar", 20 | "400-page-heading": "Xwesteka nederbasdar", 21 | "404-page-title": "Naverok nehat dîtin", 22 | "404-page-heading": "Nehat dîtin", 23 | "500-page-title": "Çewtiya Serverê yê Daxilî", 24 | "500-page-heading": "Çewtiya Serverê yê Daxilî", 25 | "fulltext-search-unavailable": "Lêgerîna Temamê Nivîsê Neberdest e", 26 | "no-search-results": "Motora lêgerînê yê temamê metnê ne berdest e ji bo vê naverokê.", 27 | "library-button-text": "Here rûpela xêrhatinê", 28 | "home-button-text": "Here rûpela destpêkê yê {{BOOK_TITLE}}", 29 | "random-page-button-text": "Here rûpeleke ketober bijartî", 30 | "searchbox-tooltip": "Li {{BOOK_TITLE}} bigere", 31 | "confusion-of-tongues": "Du an zêdetir kitêbên bi zimanên cihê wê beşdarî lêgerînê bibin, ev jî dibe ku bibe sedema tevliheviya encaman." 32 | } 33 | -------------------------------------------------------------------------------- /static/skin/i18n/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Strebski", 5 | "WaldiSt" 6 | ] 7 | }, 8 | "name": "Polski", 9 | "suggest-full-text-search": "zawierający '{{{SEARCH_TERMS}}}'...", 10 | "no-such-book": "Brak takiej książki: {{BOOK_NAME}}", 11 | "url-not-found": "Żądany adres URL „{{url}}” nie został znaleziony na tym serwerze.", 12 | "suggest-search": "Wykonaj wyszukiwanie pełnotekstowe dla {{PATTERN}}", 13 | "random-article-failure": "Ups! Nie udało się wybrać losowego artykułu :(", 14 | "invalid-raw-data-type": "{{DATATYPE}} nie jest prawidłowym żądaniem zawartości nieprzetworzonej.", 15 | "raw-entry-not-found": "Nie można znaleźć {{DATATYPE}} wpisu {{ENTRY}}", 16 | "400-page-title": "Nieprawidłowe żądanie", 17 | "400-page-heading": "Nieprawidłowe żądanie", 18 | "404-page-title": "Zawartość nie została znaleziona", 19 | "404-page-heading": "Nie znaleziono", 20 | "500-page-title": "Wewnętrzny błąd serwera", 21 | "500-page-heading": "Wewnętrzny błąd serwera", 22 | "fulltext-search-unavailable": "Wyszukiwanie pełnotekstowe jest niedostępne", 23 | "no-search-results": "Wyszukiwarka pełnotekstowa nie jest dostępna dla tej zawartości.", 24 | "library-button-text": "Przejdź do strony powitalnej", 25 | "home-button-text": "Przejdź do głównej strony '{{BOOK_TITLE}}'", 26 | "random-page-button-text": "Przejdź do losowo wybranej strony", 27 | "searchbox-tooltip": "Szukaj '{{BOOK_TITLE}}'", 28 | "search": "Szukaj", 29 | "book-filtering-all-categories": "Wszystkie Kategorie", 30 | "book-filtering-all-languages": "Wszystkie języki", 31 | "download": "Pobierz", 32 | "direct-download-link-text": "Bezpośrednio", 33 | "direct-download-alt-text": "bezpośrednie pobieranie", 34 | "torrent-download-link-text": "Plik torrent", 35 | "welcome-to-kiwix-server": "Witamy na serwerze Kiwix", 36 | "download-links-title": "Pobierz książkę", 37 | "preview-book": "Podgląd", 38 | "book-category.other": "Inne" 39 | } 40 | -------------------------------------------------------------------------------- /src/tools/opdsParsingTools.cpp: -------------------------------------------------------------------------------- 1 | #include "tools.h" 2 | #include 3 | 4 | namespace kiwix 5 | { 6 | 7 | namespace 8 | { 9 | #define VALUE(name) entryNode.child(name).child_value() 10 | FeedLanguages parseLanguages(const pugi::xml_document& doc) 11 | { 12 | pugi::xml_node feedNode = doc.child("feed"); 13 | FeedLanguages langs; 14 | 15 | for (pugi::xml_node entryNode = feedNode.child("entry"); entryNode; 16 | entryNode = entryNode.next_sibling("entry")) { 17 | auto title = VALUE("title"); 18 | auto code = VALUE("dc:language"); 19 | langs.push_back({code, title}); 20 | } 21 | 22 | return langs; 23 | } 24 | 25 | FeedCategories parseCategories(const pugi::xml_document& doc) 26 | { 27 | pugi::xml_node feedNode = doc.child("feed"); 28 | FeedCategories categories; 29 | 30 | for (pugi::xml_node entryNode = feedNode.child("entry"); entryNode; 31 | entryNode = entryNode.next_sibling("entry")) { 32 | auto title = VALUE("title"); 33 | categories.push_back(title); 34 | } 35 | 36 | return categories; 37 | } 38 | 39 | } // unnamed namespace 40 | 41 | FeedLanguages readLanguagesFromFeed(const std::string& content) 42 | { 43 | pugi::xml_document doc; 44 | pugi::xml_parse_result result 45 | = doc.load_buffer((void*)content.data(), content.size()); 46 | 47 | if (result) { 48 | auto langs = parseLanguages(doc); 49 | return langs; 50 | } 51 | 52 | return FeedLanguages(); 53 | } 54 | 55 | FeedCategories readCategoriesFromFeed(const std::string& content) 56 | { 57 | pugi::xml_document doc; 58 | pugi::xml_parse_result result 59 | = doc.load_buffer((void*)content.data(), content.size()); 60 | 61 | FeedCategories categories; 62 | if (result) { 63 | categories = parseCategories(doc); 64 | return categories; 65 | } 66 | 67 | return categories; 68 | } 69 | 70 | } // namespace kiwix 71 | -------------------------------------------------------------------------------- /src/library_dumper.cpp: -------------------------------------------------------------------------------- 1 | #include "library_dumper.h" 2 | #include "tools/stringTools.h" 3 | #include "tools/otherTools.h" 4 | #include "tools.h" 5 | 6 | namespace kiwix 7 | { 8 | /* Constructor */ 9 | LibraryDumper::LibraryDumper(const Library* library, const NameMapper* nameMapper) 10 | : library(library), 11 | nameMapper(nameMapper) 12 | { 13 | } 14 | /* Destructor */ 15 | LibraryDumper::~LibraryDumper() 16 | { 17 | } 18 | 19 | void LibraryDumper::setOpenSearchInfo(int totalResults, int startIndex, int count) 20 | { 21 | m_totalResults = totalResults; 22 | m_startIndex = startIndex, 23 | m_count = count; 24 | } 25 | 26 | kainjow::mustache::list LibraryDumper::getCategoryData() const 27 | { 28 | const auto now = gen_date_str(); 29 | kainjow::mustache::list categoryData; 30 | for ( const auto& category : library->getBooksCategories() ) { 31 | const auto urlencodedCategoryName = urlEncode(category); 32 | categoryData.push_back(kainjow::mustache::object{ 33 | {"name", category}, 34 | {"urlencoded_name", urlencodedCategoryName}, 35 | {"updated", now}, 36 | {"id", gen_uuid(libraryId + "/categories/" + urlencodedCategoryName)} 37 | }); 38 | } 39 | return categoryData; 40 | } 41 | 42 | kainjow::mustache::list LibraryDumper::getLanguageData() const 43 | { 44 | const auto now = gen_date_str(); 45 | kainjow::mustache::list languageData; 46 | for ( const auto& langAndBookCount : library->getBooksLanguagesWithCounts() ) { 47 | const std::string languageCode = langAndBookCount.first; 48 | const int bookCount = langAndBookCount.second; 49 | const auto languageSelfName = getLanguageSelfName(languageCode); 50 | languageData.push_back(kainjow::mustache::object{ 51 | {"lang_code", languageCode}, 52 | {"lang_self_name", languageSelfName}, 53 | {"book_count", to_string(bookCount)}, 54 | {"updated", now}, 55 | {"id", gen_uuid(libraryId + "/languages/" + languageCode)} 56 | }); 57 | } 58 | return languageData; 59 | } 60 | 61 | } // namespace kiwix 62 | -------------------------------------------------------------------------------- /src/bookmark.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #include "bookmark.h" 21 | #include "book.h" 22 | 23 | #include 24 | 25 | namespace kiwix 26 | { 27 | /* Constructor */ 28 | Bookmark::Bookmark() 29 | { 30 | } 31 | 32 | Bookmark::Bookmark(const Book& book, const std::string& path, const std::string& title): 33 | m_bookId(book.getId()), 34 | m_bookTitle(book.getTitle()), 35 | m_bookName(book.getName()), 36 | m_bookFlavour(book.getFlavour()), 37 | m_url(path), 38 | m_title(title), 39 | m_language(book.getCommaSeparatedLanguages()), 40 | m_date(book.getDate()) 41 | {} 42 | 43 | /* Destructor */ 44 | Bookmark::~Bookmark() 45 | { 46 | } 47 | 48 | void Bookmark::updateFromXml(const pugi::xml_node& node) 49 | { 50 | auto bookNode = node.child("book"); 51 | m_bookId = bookNode.child("id").child_value(); 52 | m_bookTitle = bookNode.child("title").child_value(); 53 | m_bookName = bookNode.child("name").child_value(); 54 | m_bookFlavour = bookNode.child("flavour").child_value(); 55 | m_language = bookNode.child("language").child_value(); 56 | m_date = bookNode.child("date").child_value(); 57 | m_title = node.child("title").child_value(); 58 | m_url = node.child("url").child_value(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /static/skin/blocklink.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/resources_list.txt: -------------------------------------------------------------------------------- 1 | skin/caret.png 2 | skin/bittorrent.png 3 | skin/magnet.png 4 | skin/404.svg 5 | skin/500.svg 6 | skin/blocklink.svg 7 | skin/feed.svg 8 | skin/langSelector.svg 9 | skin/download.png 10 | skin/download-white.svg 11 | skin/hash.png 12 | skin/search-icon.svg 13 | skin/iso6391To3.js 14 | skin/isotope.pkgd.min.js 15 | skin/index.js 16 | skin/autoComplete/autoComplete.min.js 17 | skin/error.css 18 | skin/print.css 19 | skin/kiwix.css 20 | skin/taskbar.css 21 | skin/index.css 22 | skin/fonts/DMSans-Regular.ttf 23 | skin/fonts/Poppins.ttf 24 | skin/fonts/Roboto.ttf 25 | skin/search_results.css 26 | skin/blank.html 27 | skin/polyfills.js 28 | skin/viewer.js 29 | skin/i18n.js 30 | skin/languages.js 31 | skin/mustache.min.js 32 | viewer.html 33 | templates/search_result.html 34 | templates/search_result.xml 35 | templates/error.html 36 | templates/error.xml 37 | templates/index.html 38 | templates/suggestion.json 39 | templates/captured_external.html 40 | templates/catalog_entries.xml 41 | templates/catalog_v2_root.xml 42 | templates/catalog_v2_entries.xml 43 | templates/catalog_v2_entry.xml 44 | templates/catalog_v2_partial_entry.xml 45 | templates/catalog_v2_categories.xml 46 | templates/catalog_v2_languages.xml 47 | templates/url_of_search_results_css.tmpl 48 | templates/viewer_settings.js 49 | templates/no_js_library_page.html 50 | templates/no_js_download.html 51 | templates/sexy404.html 52 | templates/sexy500.html 53 | opensearchdescription.xml 54 | ft_opensearchdescription.xml 55 | catalog_v2_searchdescription.xml 56 | skin/autoComplete/css/autoComplete.css 57 | skin/favicon/android-chrome-192x192.png 58 | skin/favicon/android-chrome-512x512.png 59 | skin/favicon/apple-touch-icon.png 60 | skin/favicon/browserconfig.xml 61 | skin/favicon/favicon-16x16.png 62 | skin/favicon/favicon-32x32.png 63 | skin/favicon/favicon.ico 64 | skin/favicon/mstile-70x70.png 65 | skin/favicon/mstile-144x144.png 66 | skin/favicon/mstile-150x150.png 67 | skin/favicon/mstile-310x150.png 68 | skin/favicon/mstile-310x310.png 69 | skin/favicon/safari-pinned-tab.svg 70 | skin/favicon/site.webmanifest 71 | -------------------------------------------------------------------------------- /static/skin/i18n/bn.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Nokib Sarkar", 5 | "আফতাবুজ্জামান" 6 | ] 7 | }, 8 | "name": "বাংলা", 9 | "404-page-heading": "পাওয়া যায়নি", 10 | "new-404-page-title": "পাতা পাওয়া যায়নি", 11 | "new-404-page-heading": "ওহ! পাতা খুঁজে পাওয়া যায়নি", 12 | "404-img-text": "পাওয়া যায়নি!", 13 | "path-was-not-found": "অনুরোধ করা পথটি পাওয়া যায়নি:", 14 | "404-advice.p1": "আপনি যে বিষয়বস্তু খুঁজছেন তা এখনও উপলব্ধ থাকতে পারে, তবে এটি জিম ফাইলের মধ্যে অন্য কোনও জায়গায় অবস্থিত হতে পারে।", 15 | "404-advice.p4": "আপনি যে তথ্য খুঁজছেন তার সাথে সম্পর্কিত কীওয়ার্ড বা শিরোনাম খুঁজুন।", 16 | "500-page-title": "অভ্যন্তরীণ সার্ভার ত্রুটি", 17 | "500-page-heading": "অভ্যন্তরীণ সার্ভার ত্রুটি", 18 | "external-link-intro": "আপনি অনলাইনে যাওয়ার জন্য কিউইক্সের জিম রিডার ছেড়ে দিতে চলেছেন", 19 | "external-link-advice.p1": "আপনি যে লিঙ্কটিতে প্রবেশ করার চেষ্টা করছেন তা আপনার অফলাইন প্যাকেজের অংশ নয় এবং এর জন্য ইন্টারনেট সংযোগ প্রয়োজন।", 20 | "external-link-advice.p2": "আপনি যদি অনলাইনে যেতে পারেন, তাহলে লিঙ্কটি খোলার চেষ্টা করতে পারেন।", 21 | "external-link-advice.p3": "অন্যথায়, আপনি আপনার ব্রাউজারের পিছন বোতাম ব্যবহার করে আপনার ZIM-এর অফলাইন বিষয়বস্তুতে ফিরে যেতে পারেন।", 22 | "search-result-book-info": "{{BOOK_TITLE}} থেকে", 23 | "word-count": "{{COUNT}}টি শব্দ", 24 | "library-button-text": "স্বাগত পাতায় চলুন", 25 | "home-button-text": "'{{BOOK_TITLE}}'-এর প্রধান পাতায় চলুন", 26 | "searchbox-tooltip": "'{{BOOK_TITLE}}' অনুসন্ধান করুন", 27 | "search": "অনুসন্ধান", 28 | "welcome-to-kiwix-server": "কিউইক্স সার্ভারে স্বাগতম", 29 | "download-links-title": "বই ডাউনলোড করুন", 30 | "preview-book": "প্রাকদর্শন", 31 | "book-category.wikibooks": "উইকিবই", 32 | "book-category.wikinews": "উইকিসংবাদ", 33 | "book-category.wikipedia": "উইকিপিডিয়া", 34 | "book-category.wikiquote": "উইকিউক্তি", 35 | "book-category.wikisource": "উইকিসংকলন", 36 | "book-category.wikispecies": "উইকিপ্রজাতি", 37 | "book-category.wikiversity": "উইকিবিশ্ববিদ্যালয়", 38 | "book-category.wikivoyage": "উইকিভ্রমণ", 39 | "book-category.wiktionary": "উইকিঅভিধান", 40 | "book-category.other": "অন্যান্য" 41 | } 42 | -------------------------------------------------------------------------------- /src/kiwixserve.cpp: -------------------------------------------------------------------------------- 1 | #include "kiwixserve.h" 2 | #include "subprocess.h" 3 | 4 | #ifdef _WIN32 5 | # define KIWIXSERVE_CMD "kiwix-serve.exe" 6 | # include 7 | #else 8 | # define KIWIXSERVE_CMD "kiwix-serve" 9 | # include 10 | #endif 11 | 12 | #include "tools.h" 13 | #include "tools/pathTools.h" 14 | #include "tools/stringTools.h" 15 | 16 | namespace kiwix { 17 | 18 | KiwixServe::KiwixServe(const std::string& libraryPath, int port) 19 | : m_port(port), 20 | m_libraryPath(libraryPath) 21 | { 22 | } 23 | 24 | KiwixServe::~KiwixServe() 25 | { 26 | shutDown(); 27 | } 28 | 29 | void KiwixServe::run() 30 | { 31 | #ifdef _WIN32 32 | int pid = GetCurrentProcessId(); 33 | #else 34 | pid_t pid = getpid(); 35 | 36 | #endif 37 | 38 | std::vector callCmd; 39 | std::string kiwixServeCmd = appendToDirectory( 40 | removeLastPathElement(getExecutablePath(true)), 41 | KIWIXSERVE_CMD); 42 | if (fileExists(kiwixServeCmd)) { 43 | // A local kiwix-serve exe exists (packaged with kiwix-desktop), use it. 44 | callCmd.push_back(kiwixServeCmd.c_str()); 45 | } else { 46 | // Try to use a potential installed kiwix-serve. 47 | callCmd.push_back(KIWIXSERVE_CMD); 48 | } 49 | std::string attachProcessOpt = "-a" + to_string(pid); 50 | std::string portOpt = "-p" + to_string(m_port); 51 | callCmd.push_back(attachProcessOpt.c_str()); 52 | callCmd.push_back(portOpt.c_str()); 53 | callCmd.push_back("-l"); 54 | callCmd.push_back(m_libraryPath.c_str()); 55 | mp_kiwixServe = Subprocess::run(callCmd); 56 | } 57 | 58 | void KiwixServe::shutDown() 59 | { 60 | if (mp_kiwixServe) 61 | mp_kiwixServe->kill(); 62 | } 63 | 64 | bool KiwixServe::isRunning() 65 | { 66 | if (mp_kiwixServe) { 67 | return (mp_kiwixServe->isRunning()); 68 | } 69 | return false; 70 | } 71 | 72 | int KiwixServe::setPort(int port) 73 | { 74 | if (port >= 1 && port <= 65535) { 75 | m_port = port; 76 | } else { 77 | return -1; 78 | } 79 | return m_port; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /static/skin/i18n/br.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Adriendelucca", 5 | "Y-M D" 6 | ] 7 | }, 8 | "name": "brezhoneg", 9 | "suggest-full-text-search": "E lec'h emañ \"{{{SEARCH_TERMS}}}\"...", 10 | "no-such-book": "N’eus ket eus al levr-mañ: {{BOOK_NAME}}", 11 | "no-book-found": "N’eus levr ebet a glot gant an dezverkoù-se", 12 | "url-not-found": "N’eo ket bet kavet an URL \"{{url}}\" goulennet war ar servijer-mañ.", 13 | "random-article-failure": "Chaous! N’hon eus ket gellet dibab ur pennad dre ziouer evidoc’h :(", 14 | "400-page-title": "Reked amwiriek", 15 | "400-page-heading": "Reked amwiriek", 16 | "404-page-heading": "N'eo ket bet kavet", 17 | "500-page-title": "Fazi diabarzh ar servijer", 18 | "500-page-heading": "Fazi diabarzh ar servijer", 19 | "search-results-page-title": "Klask: {{SEARCH_PATTERN}}", 20 | "search-results-page-header": "Disoc’hoù {{START}}-{{END}} diwar {{COUNT}} evit \"{{{SEARCH_PATTERN}}}\"", 21 | "empty-search-results-page-header": "Disoc’h ebet kavet evit \"{{{SEARCH_PATTERN}}}\"", 22 | "search-result-book-info": "diouzh {{BOOK_TITLE}}", 23 | "word-count": "{{COUNT}} a c’herioù", 24 | "library-button-text": "Mont d’ar bajenn degemer", 25 | "home-button-text": "Mont da bajenn degemer \"{{BOOK_TITLE}}\"", 26 | "random-page-button-text": "Mont d’ur bajenn dre zegouezh", 27 | "searchbox-tooltip": "Klask '{{BOOK_TITLE}}'", 28 | "powered-by-kiwix-html": "Lusket gant Kiwix", 29 | "search": "Klask", 30 | "book-filtering-all-categories": "An holl rummadoù", 31 | "book-filtering-all-languages": "An holl yezhoù", 32 | "count-of-matching-books": "{{COUNT}} levr", 33 | "download": "Pellgargañ", 34 | "direct-download-link-text": "Eeun", 35 | "filter-by-tag": "Silañ gant an dikedenn \"{{TAG}}\"", 36 | "stop-filtering-by-tag": "Paouez da silañ gant an dikedenn \"{{TAG}}\"", 37 | "welcome-to-kiwix-server": "Degemer mat er servijer Kiwix", 38 | "download-links-heading": "Liammoù pellgargañ evit {{BOOK_TITLE}}", 39 | "download-links-title": "Pellgargañ al levr", 40 | "preview-book": "Rakwelet", 41 | "unknown-error": "Fazi dianav" 42 | } 43 | -------------------------------------------------------------------------------- /src/opds_catalog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #include "opds_catalog.h" 21 | #include "tools/stringTools.h" 22 | 23 | #include 24 | 25 | namespace kiwix 26 | { 27 | 28 | namespace 29 | { 30 | const char opdsSearchEndpoint[] = "/catalog/v2/entries"; 31 | 32 | enum Separator { AMP }; 33 | 34 | std::ostringstream& operator<<(std::ostringstream& oss, Separator sep) 35 | { 36 | if ( oss.tellp() > 0 ) 37 | oss << "&"; 38 | return oss; 39 | } 40 | 41 | std::string buildSearchString(const Filter& f) 42 | { 43 | std::ostringstream oss; 44 | if ( f.hasQuery() ) 45 | oss << AMP << "q=" << urlEncode(f.getQuery()); 46 | 47 | if ( f.hasCategory() ) 48 | oss << AMP << "category=" << urlEncode(f.getCategory()); 49 | 50 | if ( f.hasLang() ) 51 | oss << AMP << "lang=" << urlEncode(f.getLang()); 52 | 53 | if ( f.hasName() ) 54 | oss << AMP << "name=" << urlEncode(f.getName()); 55 | 56 | if ( !f.getAcceptTags().empty() ) 57 | oss << AMP << "tag=" << urlEncode(join(f.getAcceptTags(), ";")); 58 | 59 | return oss.str(); 60 | } 61 | 62 | } // unnamed namespace 63 | 64 | std::string getSearchUrl(const Filter& f) 65 | { 66 | const std::string searchString = buildSearchString(f); 67 | 68 | if ( searchString.empty() ) 69 | return opdsSearchEndpoint; 70 | else 71 | return opdsSearchEndpoint + ("?" + searchString); 72 | } 73 | 74 | } // namespace kiwix 75 | -------------------------------------------------------------------------------- /static/meson.build: -------------------------------------------------------------------------------- 1 | if meson.version().version_compare('>=0.47.0') 2 | resource_files = run_command( 3 | res_manager, 4 | '--list-all', 5 | files('resources_list.txt'), 6 | check: true 7 | ).stdout().strip().split('\n') 8 | else 9 | resource_files = run_command( 10 | res_manager, 11 | '--list-all', 12 | files('resources_list.txt') 13 | ).stdout().strip().split('\n') 14 | endif 15 | 16 | 17 | preprocessed_resources = custom_target('preprocessed_resource_files', 18 | input: 'resources_list.txt', 19 | output: ['resources_list.txt'], 20 | command:[res_manager, 21 | '--preprocess', 22 | '--outdir', '@OUTDIR@', 23 | '@INPUT@'], 24 | depend_files: resource_files 25 | ) 26 | 27 | lib_resources = custom_target('resources', 28 | input: [preprocessed_resources, 'i18n_resources_list.txt'], 29 | output: ['libkiwix-resources.cpp', 'libkiwix-resources.h'], 30 | command:[res_compiler, 31 | '--cxxfile', '@OUTPUT0@', 32 | '--hfile', '@OUTPUT1@', 33 | '--source_dir', '@OUTDIR@', 34 | '@INPUT@'], 35 | depends: preprocessed_resources 36 | ) 37 | 38 | # This could be replaced with 39 | # ``` 40 | # fs = import('fs') 41 | # i18n_resource_files = fs.read('i18n_resources_list.txt').strip().split('\n') 42 | # ``` 43 | # once we move to meson >= 0.57.0 44 | 45 | if meson.version().version_compare('>=0.47.0') 46 | i18n_resource_files = run_command( 47 | find_program('python3'), 48 | '-c', 49 | 'import sys; f=open(sys.argv[1]); print(f.read())', 50 | files('i18n_resources_list.txt'), 51 | check: true 52 | ).stdout().strip().split('\n') 53 | else 54 | i18n_resource_files = run_command( 55 | find_program('python3'), 56 | '-c', 57 | 'import sys; f=open(sys.argv[1]); print(f.read())', 58 | files('i18n_resources_list.txt'), 59 | ).stdout().strip().split('\n') 60 | endif 61 | 62 | 63 | i18n_resources = custom_target('i18n_resources', 64 | input: i18n_resource_files, 65 | output: ['libkiwix-i18n-resources.cpp'], 66 | command:[i18n_compiler, 67 | '--cxxfile', '@OUTPUT0@', 68 | '@INPUT@'], 69 | ) 70 | -------------------------------------------------------------------------------- /static/templates/catalog_v2_root.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | {{feed_id}} 5 | 8 | 11 | 14 | OPDS Catalog Root 15 | {{date}} 16 | 17 | 18 | All entries 19 | 22 | {{date}} 23 | {{all_entries_feed_id}} 24 | All entries from this catalog. 25 | 26 | 27 | All entries (partial) 28 | 31 | {{date}} 32 | {{partial_entries_feed_id}} 33 | All entries from this catalog in partial format. 34 | 35 | 36 | List of categories 37 | 40 | {{date}} 41 | {{category_list_feed_id}} 42 | List of all categories in this catalog. 43 | 44 | 45 | List of languages 46 | 49 | {{date}} 50 | {{language_list_feed_id}} 51 | List of all languages in this catalog. 52 | 53 | 54 | -------------------------------------------------------------------------------- /test/i18n.cpp: -------------------------------------------------------------------------------- 1 | #include "../src/server/i18n_utils.h" 2 | #include "gtest/gtest.h" 3 | 4 | using namespace kiwix; 5 | 6 | TEST(ParameterizedMessage, parameterlessMessages) 7 | { 8 | { 9 | const ParameterizedMessage msg("404-page-title", {}); 10 | 11 | EXPECT_EQ(msg.getText("en"), "Content not found"); 12 | EXPECT_EQ(msg.getText("test"), "[I18N TESTING] Not Found - Try Again"); 13 | } 14 | 15 | { 16 | // Make sure that msgId influences the result of getText() 17 | const ParameterizedMessage msg("random-page-button-text", {}); 18 | 19 | EXPECT_EQ(msg.getText("en"), "Go to a randomly selected page"); 20 | EXPECT_EQ(msg.getText("test"), "[I18N TESTING] I am tired of determinism"); 21 | } 22 | 23 | { 24 | // Demonstrate that unwanted parameters are silently ignored 25 | const ParameterizedMessage msg("404-page-title", {{"abc", "xyz"}}); 26 | 27 | EXPECT_EQ(msg.getText("en"), "Content not found"); 28 | EXPECT_EQ(msg.getText("test"), "[I18N TESTING] Not Found - Try Again"); 29 | } 30 | } 31 | 32 | TEST(ParameterizedMessage, messagesWithParameters) 33 | { 34 | { 35 | const ParameterizedMessage msg("filter-by-tag", 36 | {{"TAG", "scifi"}} 37 | ); 38 | 39 | EXPECT_EQ(msg.getText("en"), "Filter by tag \"scifi\""); 40 | EXPECT_EQ(msg.getText("test"), "Filter [I18N] by [TESTING] tag \"scifi\""); 41 | } 42 | 43 | { 44 | // Omitting expected parameters amounts to using empty values for them 45 | const ParameterizedMessage msg("filter-by-tag", {}); 46 | 47 | EXPECT_EQ(msg.getText("en"), "Filter by tag \"\""); 48 | EXPECT_EQ(msg.getText("test"), "Filter [I18N] by [TESTING] tag \"\""); 49 | } 50 | } 51 | 52 | TEST(I18n, translateBookCategory) 53 | { 54 | 55 | EXPECT_EQ(translateBookCategory("en", "ted"), "Ted"); 56 | EXPECT_EQ(translateBookCategory("test", "ted"), "[I18N] Ted [TESTING]"); 57 | 58 | EXPECT_EQ(translateBookCategory("en", "stack_exchange"), "Stack Exchange"); 59 | EXPECT_EQ(translateBookCategory("test", "stack_exchange"), "[I18N] Stack Exchange [TESTING]"); 60 | 61 | // unknown categories are simply not translated 62 | EXPECT_EQ(translateBookCategory("en", "Qwerty"), "Qwerty"); 63 | EXPECT_EQ(translateBookCategory("test", "Qwerty"), "Qwerty"); 64 | } 65 | -------------------------------------------------------------------------------- /src/libxml_dumper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_LIBXML_DUMPER_H 21 | #define KIWIX_LIBXML_DUMPER_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include "library.h" 29 | 30 | namespace kiwix 31 | { 32 | 33 | /** 34 | * A tool to dump a `Library` into a basic library.xml 35 | * 36 | */ 37 | class LibXMLDumper 38 | { 39 | public: 40 | LibXMLDumper() = default; 41 | LibXMLDumper(const Library* library); 42 | ~LibXMLDumper(); 43 | 44 | /** 45 | * Dump the library.xml 46 | * 47 | * @param id The id of the library. 48 | * @return The library.xml content. 49 | */ 50 | std::string dumpLibXMLContent(const std::vector& bookIds); 51 | 52 | 53 | /** 54 | * Dump the bookmark of the library. 55 | * 56 | * @return The bookmark.xml content. 57 | */ 58 | std::string dumpLibXMLBookmark(); 59 | 60 | /** 61 | * Set the base directory used. 62 | * 63 | * @param baseDir the base directory to use. 64 | */ 65 | void setBaseDir(const std::string& baseDir) { this->baseDir = baseDir; } 66 | 67 | /** 68 | * Set the library to dump. 69 | * 70 | * @param library The library to dump. 71 | */ 72 | void setLibrary(const Library* library) { this->library = library; } 73 | 74 | protected: 75 | const kiwix::Library* library; 76 | std::string baseDir; 77 | private: 78 | void handleBook(Book book, pugi::xml_node root_node); 79 | void handleBookmark(Bookmark bookmark, pugi::xml_node root_node); 80 | }; 81 | } 82 | 83 | #endif // KIWIX_OPDS_DUMPER_H 84 | -------------------------------------------------------------------------------- /src/tools/archiveTools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Maneesh P M 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_ARCHIVETOOLS_H 21 | #define KIWIX_ARCHIVETOOLS_H 22 | 23 | #include 24 | #include 25 | 26 | /** 27 | * This file contains all the functions that would make handling data related to 28 | * an archive easier. 29 | **/ 30 | 31 | namespace kiwix 32 | { 33 | std::string getMetadata(const zim::Archive& archive, const std::string& name); 34 | std::string getArchiveTitle(const zim::Archive& archive); 35 | std::string getMetaDescription(const zim::Archive& archive); 36 | std::string getMetaTags(const zim::Archive& archive, bool original = false); 37 | std::string getMetaLanguage(const zim::Archive& archive); 38 | std::string getMetaName(const zim::Archive& archive); 39 | std::string getMetaDate(const zim::Archive& archive); 40 | std::string getMetaCreator(const zim::Archive& archive); 41 | std::string getMetaPublisher(const zim::Archive& archive); 42 | std::string getMetaFlavour(const zim::Archive& archive); 43 | 44 | bool getArchiveFavicon(const zim::Archive& archive, unsigned size, 45 | std::string& content, std::string& mimeType); 46 | 47 | unsigned int getArchiveMediaCount(const zim::Archive& archive); 48 | unsigned int getArchiveArticleCount(const zim::Archive& archive); 49 | unsigned int getArchiveFileSize(const zim::Archive& archive); 50 | 51 | zim::Item getFinalItem(const zim::Archive& archive, const zim::Entry& entry); 52 | 53 | zim::Entry getEntryFromPath(const zim::Archive& archive, const std::string& path); 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'libkiwix' 21 | copyright = '2022, libkiwix-team' 22 | author = 'libkiwix-team' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = [ 31 | 'breathe', 32 | 'exhale' 33 | ] 34 | 35 | # Add any paths that contain templates here, relative to this directory. 36 | templates_path = ['_templates'] 37 | 38 | # List of patterns, relative to source directory, that match files and 39 | # directories to ignore when looking for source files. 40 | # This pattern also affects html_static_path and html_extra_path. 41 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 42 | 43 | html_theme = 'sphinx_rtd_theme' 44 | 45 | # Add any paths that contain custom static files (such as style sheets) here, 46 | # relative to this directory. They are copied after the builtin static files, 47 | # so a file named "default.css" will overwrite the builtin "default.css". 48 | html_static_path = ['_static'] 49 | 50 | breathe_projects = { 51 | "libkiwix": "./xml" 52 | } 53 | breathe_default_project = 'libkiwix' 54 | 55 | exhale_args = { 56 | "containmentFolder": "./api", 57 | "rootFileName": "ref_api.rst", 58 | "rootFileTitle": "Reference API", 59 | "doxygenStripFromPath":"..", 60 | "treeViewIsBootstrap": True, 61 | "createTreeView" : True, 62 | "exhaleExecutesDoxygen": True, 63 | "exhaleDoxygenStdin": "INPUT = ../include" 64 | } 65 | 66 | primary_domain = 'cpp' 67 | 68 | highlight_language = 'cpp' 69 | -------------------------------------------------------------------------------- /src/server/i18n_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_SERVER_I18N_UTILS 21 | #define KIWIX_SERVER_I18N_UTILS 22 | 23 | #include "i18n.h" 24 | #include 25 | 26 | namespace kiwix 27 | { 28 | 29 | struct I18nString { 30 | const char* const key; 31 | const char* const value; 32 | }; 33 | 34 | struct I18nStringTable { 35 | const char* const lang; 36 | const size_t entryCount; 37 | const I18nString* const entries; 38 | 39 | const char* get(const std::string& key) const; 40 | }; 41 | 42 | namespace i18n 43 | { 44 | 45 | class GetTranslatedStringWithMsgId 46 | { 47 | typedef kainjow::mustache::basic_data MustacheString; 48 | typedef std::pair MsgIdAndTranslation; 49 | 50 | public: 51 | explicit GetTranslatedStringWithMsgId(const std::string& lang) : m_lang(lang) {} 52 | 53 | MsgIdAndTranslation operator()(const std::string& key) const 54 | { 55 | return {key, getTranslatedString(m_lang, key)}; 56 | } 57 | 58 | MsgIdAndTranslation operator()(const std::string& key, const Parameters& params) const 59 | { 60 | return {key, expandParameterizedString(m_lang, key, params)}; 61 | } 62 | 63 | private: 64 | const std::string m_lang; 65 | }; 66 | 67 | } // namespace i18n 68 | 69 | struct LangPreference 70 | { 71 | const std::string lang; 72 | const float preference; 73 | }; 74 | 75 | typedef std::vector UserLangPreferences; 76 | 77 | UserLangPreferences parseUserLanguagePreferences(const std::string& s); 78 | 79 | std::string selectMostSuitableLanguage(const UserLangPreferences& prefs); 80 | 81 | } // namespace kiwix 82 | 83 | #endif // KIWIX_SERVER_I18N_UTILS 84 | -------------------------------------------------------------------------------- /test/data/library.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 37 | 54 | 55 | -------------------------------------------------------------------------------- /static/skin/i18n/fi.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "MITO", 5 | "Nike", 6 | "Pyscowicz", 7 | "Samoasambia" 8 | ] 9 | }, 10 | "name": "suomi", 11 | "suggest-full-text-search": "sisältää '{{{SEARCH_TERMS}}}'...", 12 | "no-such-book": "Kirjaa {{BOOK_NAME}} ei ole olemassa", 13 | "url-not-found": "Pyydettyä URL-osoitetta \"{{url}}\" ei löytynyt tältä palvelimelta.", 14 | "400-page-title": "Virheellinen pyyntö", 15 | "400-page-heading": "Virheellinen pyyntö", 16 | "404-page-title": "Sisältöä ei löytynyt", 17 | "404-page-heading": "Ei löytynyt", 18 | "new-404-page-title": "Sivua ei löytynyt", 19 | "new-404-page-heading": "Hupsista. Artikkelia ei löytynyt.", 20 | "404-img-text": "Ei löytynyt!", 21 | "path-was-not-found": "Pyydettyä polkua ei löytynyt:", 22 | "500-page-title": "Sisäinen palvelinvirhe", 23 | "500-page-heading": "Hupsista. Sivu ei toimi.", 24 | "500-img-text": "Sivu ei toimi", 25 | "external-link-detected": "Ulkoinen linkki havaittu", 26 | "caution-warning": "Huomio!", 27 | "external-link-intro": "Olet poistumassa Kiwixin ZIM-lukijasta siirtyäksesi verkkoon", 28 | "search-results-page-title": "Haku: {{SEARCH_PATTERN}}", 29 | "word-count": "{{COUNT}} sanaa", 30 | "library-button-text": "Siirry tervetulosivulle", 31 | "home-button-text": "Siirry kirjan '{{{BOOK_TITLE}}}' etusivulle", 32 | "random-page-button-text": "Siirry satunnaiselle sivulle", 33 | "searchbox-tooltip": "Hae kirjasta '{{{BOOK_TITLE}}}'", 34 | "search": "Hae", 35 | "book-filtering-all-categories": "Kaikki luokat", 36 | "book-filtering-all-languages": "Kaikki kielet", 37 | "count-of-matching-books": "{{COUNT}} kirja(a)", 38 | "download": "Lataa", 39 | "magnet-link-text": "Magnet-linkki", 40 | "magnet-alt-text": "lataa magnet", 41 | "torrent-download-link-text": "BitTorrent", 42 | "torrent-download-alt-text": "lataa torrent-tiedosto", 43 | "filter-by-tag": "Suodata tunnisteen ”{{TAG}}” mukaan", 44 | "download-links-title": "Lataa kirja", 45 | "preview-book": "Esikatsele", 46 | "unknown-error": "Tuntematon virhe", 47 | "book-category.wikibooks": "Wikikirjasto", 48 | "book-category.wikinews": "Wikiuutiset", 49 | "book-category.wikipedia": "Wikipedia", 50 | "book-category.wikiquote": "Wikisitaatit", 51 | "book-category.wikisource": "Wikiaineisto", 52 | "book-category.wikispecies": "Wikispecies", 53 | "book-category.wikiversity": "Wikiopisto", 54 | "book-category.wikivoyage": "Wikimatkat", 55 | "book-category.wiktionary": "Wikisanakirja", 56 | "book-category.other": "Muu", 57 | "text-loading-content": "Ladataan sisältöä" 58 | } 59 | -------------------------------------------------------------------------------- /src/tools/languageTools.cpp: -------------------------------------------------------------------------------- 1 | #include "tools.h" 2 | #include "stringTools.h" 3 | #include 4 | 5 | namespace kiwix 6 | { 7 | 8 | namespace 9 | { 10 | 11 | // These mappings are not provided by the ICU library, any such mappings can be manually added here 12 | std::map iso639_3 = { 13 | {"ami", "Amis"}, 14 | {"atj", "atikamekw"}, 15 | {"azb", "آذربایجان دیلی"}, 16 | {"bcl", "central bikol"}, 17 | {"bgs", "tagabawa"}, 18 | {"blk", "ပအိုဝ်ႏ"}, 19 | {"bxr", "буряад хэлэн"}, 20 | {"cbk", "chavacano"}, 21 | {"cdo", "閩東語"}, 22 | {"dag", "Dagbani"}, 23 | {"diq", "dimli"}, 24 | {"dty", "डोटेली"}, 25 | {"eml", "emiliân-rumagnōl"}, 26 | {"fbs", "српскохрватски"}, 27 | {"fon", "fɔ̀ngbè"}, 28 | {"gcr", "Kriyòl gwiyannen"}, 29 | {"guw", "Gungbe"}, 30 | {"hbs", "srpskohrvatski"}, 31 | {"hyw", "հայերէն/հայերեն"}, 32 | {"ido", "ido"}, 33 | {"kbp", "kabɩyɛ"}, 34 | {"kld", "Gamilaraay"}, 35 | {"lbe", "лакку маз"}, 36 | {"lbj", "ལ་དྭགས་སྐད་"}, 37 | {"lld", "ladin"}, 38 | {"map", "Austronesian"}, 39 | {"mhr", "марий йылме"}, 40 | {"mnw", "ဘာသာမန်"}, 41 | {"myn", "mayan"}, 42 | {"nah", "nahuatl"}, 43 | {"nai", "north American Indian"}, 44 | {"nds", "plattdütsch"}, 45 | {"nrm", "bhasa narom"}, 46 | {"olo", "livvi"}, 47 | {"pih", "Pitcairn-Norfolk"}, 48 | {"pnb", "Western Panjabi"}, 49 | {"pwn", "Pinayuanan"}, 50 | {"rmr", "Caló"}, 51 | {"rmy", "romani shib"}, 52 | {"roa", "romance languages"}, 53 | {"skr", "سرائیکی"}, 54 | {"szy", "Sakizaya"}, 55 | {"tay", "Tayal"}, 56 | {"tgl", "Wikang Tagalog"}, 57 | {"twi", "Akwapem Twi"}, 58 | // ICU for Ubuntu versions <= focal (20.04) returns "" for the language code "" 59 | // unlike the later versions - which returns "und". We map this value to "Undetermined" for a common ground. 60 | {"", "Undetermined"}, 61 | }; 62 | 63 | std::once_flag fillLanguagesFlag; 64 | 65 | void fillLanguagesMap() 66 | { 67 | for (auto icuLangPtr = icu::Locale::getISOLanguages(); *icuLangPtr != NULL; ++icuLangPtr) { 68 | const kiwix::ICULanguageInfo lang(*icuLangPtr); 69 | iso639_3.insert({lang.iso3Code(), lang.selfName()}); 70 | } 71 | iso639_3.erase("mul"); 72 | } 73 | 74 | } // unnamed namespace 75 | 76 | std::string getLanguageSelfName(const std::string& lang) 77 | { 78 | std::call_once(fillLanguagesFlag, fillLanguagesMap); 79 | const auto itr = iso639_3.find(lang); 80 | if (itr != iso639_3.end()) { 81 | return itr->second; 82 | } 83 | return lang; 84 | }; 85 | 86 | } // namespace kiwix 87 | -------------------------------------------------------------------------------- /static/generate_i18n_resources_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) 2020 Matthieu Gautier 3 | # 4 | # This file is part of libkiwix. 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | from pathlib import Path 20 | import json 21 | 22 | script_path = Path(__file__) 23 | 24 | resource_file = script_path.parent / "i18n_resources_list.txt" 25 | translation_dir = script_path.parent / "skin/i18n" 26 | language_list_relpath = "skin/languages.js" 27 | 28 | def get_translation_info(filepath): 29 | lang_code = Path(filepath).stem 30 | with open(filepath, 'r', encoding="utf-8") as f: 31 | content = json.load(f) 32 | lang_name = content.get("name") 33 | translation_count = len(content) 34 | return dict(iso_code=lang_code, 35 | self_name=lang_name, 36 | translation_count=translation_count) 37 | 38 | language_list = [] 39 | json_files = translation_dir.glob("*.json") 40 | with open(resource_file, 'w', encoding="utf-8") as f: 41 | for i18n_file in sorted(translation_dir.glob("*.json")): 42 | if i18n_file.name == "qqq.json": 43 | continue 44 | print("Processing", i18n_file.name) 45 | if i18n_file.name != "test.json": 46 | translation_info = get_translation_info(i18n_file) 47 | lang_name = translation_info["self_name"] 48 | if lang_name: 49 | language_list.append(translation_info) 50 | else: 51 | print(f"Warning: missing 'name' in {i18n_file.name}") 52 | f.write(str(i18n_file.relative_to(script_path.parent)) + '\n') 53 | 54 | language_list_jsobj_str = json.dumps(language_list, 55 | indent=2, 56 | ensure_ascii=False) 57 | print("Saving", language_list_relpath) 58 | fullpath = script_path.parent / language_list_relpath 59 | with open(fullpath, 'w', encoding="utf-8") as f: 60 | f.write("const uiLanguages = " + language_list_jsobj_str) 61 | -------------------------------------------------------------------------------- /static/skin/autoComplete/css/autoComplete.css: -------------------------------------------------------------------------------- 1 | /* Modified from https://github.com/TarekRaafat/autoComplete.js (version 10.2.6)*/ 2 | .autoComplete_wrapper { 3 | display: inline-block; 4 | position: relative; 5 | } 6 | 7 | .autoComplete_wrapper > input { 8 | width: 370px; 9 | height: 40px; 10 | padding-left: 20px; 11 | font-size: 1rem; 12 | color: rgba(123, 123, 123, 1); 13 | border-radius: 8px; 14 | border: 0; 15 | outline: none; 16 | background-color: #f1f3f4; 17 | } 18 | 19 | .autoComplete_wrapper > input::placeholder { 20 | color: rgba(123, 123, 123, 0.5); 21 | transition: all 0.3s ease; 22 | } 23 | 24 | .autoComplete_wrapper > ul { 25 | position: absolute; 26 | min-width: 100%; 27 | width: fit-content; 28 | max-width: 600px; 29 | max-height: 226px; 30 | overflow-y: scroll; 31 | top: 100%; 32 | left: 0; 33 | right: 0; 34 | padding: 0; 35 | margin: 0.5rem 0 0; 36 | border-radius: 0.6rem; 37 | background-color: #fff; 38 | box-shadow: 0 3px 6px rgba(149, 157, 165, 0.15); 39 | border: 1px solid rgba(33, 33, 33, 0.07); 40 | z-index: 1000; 41 | outline: none; 42 | } 43 | 44 | .autoComplete_wrapper > ul[hidden], 45 | .autoComplete_wrapper > ul:empty { 46 | display: block; 47 | opacity: 0; 48 | transform: scale(0); 49 | } 50 | 51 | .autoComplete_wrapper > ul > li { 52 | margin: 0.3rem; 53 | padding: 0.3rem 0.5rem; 54 | list-style: none; 55 | text-align: left; 56 | font-size: 1rem; 57 | color: #212121; 58 | border-radius: 0.35rem; 59 | background-color: rgba(255, 255, 255, 1); 60 | white-space: nowrap; 61 | overflow: hidden; 62 | text-overflow: ellipsis; 63 | transition: all 0.2s ease; 64 | } 65 | 66 | .autoComplete_wrapper > ul > li > a { 67 | overflow: hidden; 68 | text-overflow: ellipsis; 69 | } 70 | 71 | .autoComplete_wrapper > ul > li::selection { 72 | color: rgba(#ffffff, 0); 73 | background-color: rgba(#ffffff, 0); 74 | } 75 | 76 | .autoComplete_wrapper > ul > li:hover { 77 | cursor: pointer; 78 | background-color: rgba(123, 123, 123, 0.1); 79 | } 80 | 81 | .autoComplete_wrapper > ul > li mark { 82 | background-color: transparent; 83 | color: rgba(255, 122, 122, 1); 84 | font-weight: bold; 85 | } 86 | 87 | .autoComplete_wrapper > ul > li mark::selection { 88 | color: rgba(#ffffff, 0); 89 | background-color: rgba(#ffffff, 0); 90 | } 91 | 92 | .autoComplete_wrapper > ul > li[aria-selected="true"] { 93 | background-color: rgba(123, 123, 123, 0.1); 94 | } 95 | 96 | @media only screen and (max-width: 600px) { 97 | .autoComplete_wrapper > input { 98 | width: 18rem; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /static/skin/i18n/ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Asma", 5 | "Hamoudak", 6 | "Meno25", 7 | "Mohammed Qays", 8 | "Ravan", 9 | "محمد أحمد عبد الفتاح" 10 | ] 11 | }, 12 | "name": "الإنجليزية", 13 | "no-such-book": "لا يوجد مثل هذا الكتاب: {{BOOK_NAME}}", 14 | "too-many-books": "طلب العديد من الكتب {{NB_BOOKS}} حيث الحد {{LIMIT}}", 15 | "no-book-found": "لا يوجد كتاب يطابق معايير الاختيار", 16 | "url-not-found": "لم يتم العثور على عنوان URL المطلوب \"{{url}}\" على هذا الخادم.", 17 | "suggest-search": "قم بإجراء بحث عن النص الكامل لـ {{PATTERN}}", 18 | "random-article-failure": "للأسف ! فشل في اختيار مقال عشوائي :(", 19 | "invalid-raw-data-type": "{{DATATYPE}} ليس طلبًا صالحًا للمحتوى الأولي.", 20 | "no-value-for-arg": "لم يتم تقديم قيمة للوسيطة {{ARGUMENT}}", 21 | "no-query": "لم يتم تقديم ملخص.", 22 | "raw-entry-not-found": "لا يمكن العثور على إدخال {{DATATYPE}} {{ENTRY}}", 23 | "400-page-title": "طلب غير صالح", 24 | "400-page-heading": "طلب غير صالح", 25 | "404-page-title": "المحتوى غير موجود", 26 | "404-page-heading": "لم يتم العثور عليه", 27 | "500-page-title": "خطأ داخلي بالخادم", 28 | "500-page-heading": "عفواً، الصفحة لا تعمل.", 29 | "500-page-text": "لا يمكن إرسال المسار المطلوب بشكل صحيح:", 30 | "fulltext-search-unavailable": "البحث في كامل النص غير متاح", 31 | "no-search-results": "محرك البحث في كامل النص غير متوفر لهذا المحتوي.", 32 | "library-button-text": "توجه إلي صفحة الترحيب", 33 | "home-button-text": "انتقل إلى الصفحة الرئيسة لـ '{{{BOOK_TITLE}}}'", 34 | "random-page-button-text": "اذهب إلى صفحة عشوائية", 35 | "searchbox-tooltip": "ابحث عن '{{{BOOK_TITLE}}}'", 36 | "confusion-of-tongues": "قد يشارك في البحث كتابان أو أكثر بلغات مختلفة، مما قد يؤدي إلى نتائج محيرة.", 37 | "direct-download-alt-text": "التنزيل مباشرة عبر بروتوكول HTTP(S)", 38 | "hash-download-link-text": "المجموع الإختباري لخوارزمية SHA-256", 39 | "hash-download-alt-text": "عرض المجموع الإختباري لخوارزمية SHA-256 للملف", 40 | "magnet-link-text": "رابط جاذب", 41 | "magnet-alt-text": "التنزيل بواسطة الرابط الجاذب", 42 | "torrent-download-link-text": "بت تورنت", 43 | "torrent-download-alt-text": "التنزيل بواسطة بت تورنت", 44 | "unknown-error": "خطأ غير معروف", 45 | "book-category.wikibooks": "ويكي الكتب", 46 | "book-category.wikinews": "ويكي الأخبار", 47 | "book-category.wikipedia": "ويكيبيديا", 48 | "book-category.wikiquote": "ويكي الإقتباس", 49 | "book-category.wikisource": "ويكي مصدر", 50 | "book-category.wikispecies": "ويكي أنواع", 51 | "book-category.wikiversity": "ويكي الجامعة", 52 | "book-category.wikivoyage": "ويكي الرحلات", 53 | "book-category.wiktionary": "ويكي القاموس", 54 | "book-category.other": "أخرى {كتب أخري}" 55 | } 56 | -------------------------------------------------------------------------------- /test/opds_catalog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied 11 | * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and 12 | * NON-INFRINGEMENT. See the GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | */ 19 | 20 | #include "../include/opds_catalog.h" 21 | 22 | #include "gtest/gtest.h" 23 | 24 | using namespace kiwix; 25 | 26 | TEST(OpdsCatalog, getSearchUrl) 27 | { 28 | #define EXPECT_SEARCH_URL(url) EXPECT_EQ(url, getSearchUrl(f)) 29 | { 30 | Filter f; 31 | EXPECT_SEARCH_URL("/catalog/v2/entries"); 32 | } 33 | { 34 | Filter f; 35 | f.query("abc"); 36 | EXPECT_SEARCH_URL("/catalog/v2/entries?q=abc"); 37 | } 38 | { 39 | Filter f; 40 | f.query("abc def#xyz"); 41 | EXPECT_SEARCH_URL("/catalog/v2/entries?q=abc%20def%23xyz"); 42 | } 43 | { 44 | Filter f; 45 | f.category("ted&bob"); 46 | EXPECT_SEARCH_URL("/catalog/v2/entries?category=ted%26bob"); 47 | } 48 | { 49 | Filter f; 50 | f.lang("eng,fra"); 51 | EXPECT_SEARCH_URL("/catalog/v2/entries?lang=eng%2Cfra"); 52 | } 53 | { 54 | Filter f; 55 | f.name("second?"); 56 | EXPECT_SEARCH_URL("/catalog/v2/entries?name=second%3F"); 57 | } 58 | { 59 | Filter f; 60 | f.acceptTags({"#paper", "#plastic"}); 61 | EXPECT_SEARCH_URL("/catalog/v2/entries?tag=%23paper%3B%23plastic"); 62 | } 63 | { 64 | Filter f; 65 | f.query("abc=123"); 66 | f.category("@ted"); 67 | EXPECT_SEARCH_URL("/catalog/v2/entries?q=abc%3D123&category=%40ted"); 68 | } 69 | { 70 | Filter f; 71 | f.category("ted"); 72 | f.query("abc"); 73 | EXPECT_SEARCH_URL("/catalog/v2/entries?q=abc&category=ted"); 74 | } 75 | { 76 | Filter f; 77 | f.query("peru"); 78 | f.category("scifi"); 79 | f.lang("html"); 80 | f.name("edsonarantesdonascimento"); 81 | f.acceptTags({"body", "script"}); 82 | EXPECT_SEARCH_URL("/catalog/v2/entries?q=peru&category=scifi&lang=html&name=edsonarantesdonascimento&tag=body%3Bscript"); 83 | } 84 | #undef EXPECT_SEARCH_URL 85 | } 86 | -------------------------------------------------------------------------------- /static/skin/i18n/nqo.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Lancine.kounfantoh.fofana" 5 | ] 6 | }, 7 | "name": "ߒߞߏ", 8 | "suggest-full-text-search": "ߞߣߐߞߍߣߍ߲߫ ߦߋ߫ '{{{SEARCH_TERMS}}}'...", 9 | "no-such-book": "ߞߊ߬ߝߊ߫ ߛߎ߮ ߏ߬ ߕߴߦߋ߲߬: {{BOOK_NAME}}", 10 | "too-many-books": "ߞߝߊ߬ ߛߌߦߊߡߊ߲߫ ߡߊߢߌ߬ߣߌ߲߬ߞߊ߬ߣߍ߲߫ ߞߏߖߎ߰ {{NB_BOOKS}} ߡߍ߲ ߞߐߘߊ߲ ߦߋ߫ {{LIMIT}} ߘߌ߫", 11 | "no-book-found": "ߞߝߊ߬ ߛߌ߫ ߓߍ߬ߣߍ߲߬ ߕߍ߫ ߛߎߥߊ߲ߘߟߌ ߛߙߊߕߌ ߏ߬ ߡߊ߬", 12 | "url-not-found": "ߍ߲߬ߤߍ߲߫ ''URL ''{{url}} ߡߊߢߌ߬ߣߌ߲߬ߞߊ߬ߣߍ߲ ߡߊ߫ ߛߐ߬ߘߐ߲߫ ߡߊ߬ߟߐ߬ߟߊ߲ ߣߌ߲߬ ߠߊ߫.", 13 | "suggest-search": "ߛߓߍߟߌ߫ ߘߝߊߣߍ߲ ߢߌߣߌ߲ߠߌ߲ ߞߍ߫ {{PATTERN}}", 14 | "random-article-failure": "ߏ߯߹ ߞߢߊ߬ ߓߘߊ߫ ߞߍ߫ ߓߍ߲߬ߛߋ߲߬ߡߊ߬ ߞߎߡߘߊ ߛߐ߬ߘߐ߲߬ ߠߊ߫:(", 15 | "invalid-raw-data-type": "{{DATATYPE}} ߕߍ߫ ߡߞߊ߬ߣߌ߲߬ߣߍ߲߫ ߓߍ߲߬ߣߍ߲߫ ߘߌ߫ ߞߣߐߘߐ߫ ߘߝߊߣߍ߲ ߞߊ߲ߡߊ߬.", 16 | "no-value-for-arg": "ߡߐ߬ߟߐ߲߬ ߡߊ߫ ߡߊߛߐ߫ ߘߊߘߐߡߌߣߊߞߎ߲ߧߊ {{ARGUMENT}} ߞߊ߲ߡߊ߬", 17 | "no-query": "ߡߞߊ߬ߣߌ߲߬ߠߌ߲߫ ߛߌ߫ ߡߊ߫ ߡߊߛߐ߫.", 18 | "raw-entry-not-found": "ߟߊ߬ߘߏ߲߬ߣߍ߲ {{ENTRY}} {{DATATYPE}} ߕߍ߫ ߣߊ߬ ߡߊߛߐ߬ߘߐ߲߫ ߠߊ߫", 19 | "400-page-title": "ߡߞߊ߬ߣߌ߲߬ߠߌ߲߫ ߓߍ߲߬ߓߊߟߌ", 20 | "400-page-heading": "ߡߞߊ߬ߣߌ߲߬ߠߌ߲߫ ߓߍ߲߬ߓߊߟߌ", 21 | "404-page-title": "ߞߣߐߘߐ ߡߊ߫ ߛߐ߬ߘߐ߲߫", 22 | "404-page-heading": "ߡߊ߫ ߛߐ߬ߘߐ߲߫", 23 | "500-page-title": "ߞߣߐߟߊ ߡߊ߬ߛߐ߬ߟߊ߲ ߝߎ߬ߕߎ߲߬ߕߌ", 24 | "500-page-heading": "ߞߣߐߟߊ ߡߊ߬ߛߐ߬ߟߊ߲ ߝߎ߬ߕߎ߲߬ߕߌ", 25 | "fulltext-search-unavailable": "ߛߓߍߟߌ߫ ߘߝߊߣߍ߲ ߢߌߣߌ߲ߠߌ߲ ߕߍ߫ ߦߋ߲߬", 26 | "no-search-results": "ߛߓߍߟߌ߫ ߘߝߊߣߍ߲ ߢߌߣߌ߲ߠߌ߲߫ ߣߌߘߐ ߕߍ߫ ߦߋ߲߬ ߞߣߐߘߐ ߣߌ߲߬ ߢߍ߫.", 27 | "library-button-text": "ߕߊ߯ ߟߊ߬ߛߣߍ߬ߟߌ߫ ߞߐߜߍ ߞߊ߲߬", 28 | "home-button-text": "ߕߊ߯ {{BOOK_TITLE}} ߓߏ߬ߟߏ߲߬ߘߊ ߞߐߜߍ ߞߊ߲߬", 29 | "random-page-button-text": "ߕߊ߯ ߓߍ߲߬ߛߋ߲߬ߡߊ߬ ߞߐߜߍ߫ ߛߎߥߊ߲ߘߌߣߍ߲ ߠߎ߬ ߞߊ߲߬", 30 | "searchbox-tooltip": "ߕߌߙߌ߲ߠߌ߲ {{BOOK_TITLE}}", 31 | "confusion-of-tongues": "ߞߊ߬ߝߊ߫ ߝߌ߬ߟߊ߬ ߥߟߊ߫ ߦߙߌߞߊ ߞߊ߲߫ ߜߘߍ ߟߎ߬ ߘߐ߫߸ ߏ߬ ߟߎ߫ ߘߌߣߊ߬ ߕߘߍ߬ ߢߌߣߌ߲ߠߌ߲ ߘߐ߫߸ ߡߍ߲ ߠߎ߬ ߛߌ߫ ߞߣߐ߬ߝߟߌ ߟߊߘߏ߲߬ ߠߊ߫ ߞߐߝߟߌ ߘߐ߫.", 32 | "welcome-page-overzealous-filter": "ߞߐߝߟߌ߫ ߕߴߦߋ߲߬. ߊ߬ ߝߐ߫ ߌ ߦߴߊ߬ ߝߍ߬ ߞߊ߬ ߛߍ߲ߛߍ߲ߟߊ߲ ߘߐߛߌ߰ ߕߎ߲߯؟", 33 | "search": "ߢߌߣߌ߲ߠߌ߲", 34 | "book-filtering-all-categories": "ߦߌߟߡߊ ߟߎ߬ ߓߍ߯", 35 | "book-filtering-all-languages": "ߞߊ߲ ߠߎ߬ ߓߍ߯", 36 | "count-of-matching-books": "ߞߊ߬ߝߊ {{COUNT}}(ߟߎ߫)", 37 | "download": "ߟߊ߬ߖߌ߰ߒ߬ߞߎ߲߬ߠߌ߲", 38 | "direct-download-link-text": "ߒߕߋߟߋ߲ߡߊ߬", 39 | "direct-download-alt-text": "ߟߊ߬ߖߌ߰ߒ߬ߞߎ߲߬ߠߌ߲߫ ߝߊ߲ߞߢߊ", 40 | "hash-download-alt-text": "ߤߊߛ߭ ߟߊߖߌ߰ ߌ ߞߎ߲߬", 41 | "magnet-link-text": "ߡߊߢߍߕ ߛߘߌ߬ߜߋ߲", 42 | "magnet-alt-text": "ߡߊߢߍߕ ߟߊߖߌ߰ ߌ ߞߎ߲߬", 43 | "torrent-download-link-text": "ߕߏߙߍ߲ߕ ߞߐߕߐ߮", 44 | "torrent-download-alt-text": "ߕߏߙߍ߲ߕ ߟߊߖߌ߰ ߌ ߞߎ߲߬", 45 | "welcome-to-kiwix-server": "ߌ ߣߌ߫ ߛߣߍ߫ ߞߥߌߞߛ ߡߊߛߐߟߊ߲ ߞߣߐ߫", 46 | "download-links-heading": "{{BOOK_TITLE}} ߛߘߌ߬ߜߋ߲ ߠߊߖߌ߰ ߌ ߞߎ߲߬", 47 | "download-links-title": "ߞߊ߬ߝߊ ߟߊߖߌ߰ ߌ ߞߎ߲߬", 48 | "preview-book": "ߊ߬ ߘߐߜߍ߫ ߡߎߣߎ߲߬" 49 | } 50 | -------------------------------------------------------------------------------- /src/opds_dumper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_OPDS_DUMPER_H 21 | #define KIWIX_OPDS_DUMPER_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #include "library.h" 30 | #include "name_mapper.h" 31 | #include "library_dumper.h" 32 | 33 | using namespace std; 34 | 35 | namespace kiwix 36 | { 37 | 38 | /** 39 | * A tool to dump a `Library` into a opds stream. 40 | * 41 | */ 42 | class OPDSDumper : public LibraryDumper 43 | { 44 | public: 45 | OPDSDumper(const Library* library, const NameMapper* NameMapper); 46 | ~OPDSDumper(); 47 | 48 | /** 49 | * Dump the OPDS feed. 50 | * 51 | * @param bookIds the ids of the books to include in the feed 52 | * @param query the query used to obtain the list of book ids 53 | * @return The OPDS feed. 54 | */ 55 | std::string dumpOPDSFeed(const std::vector& bookIds, const std::string& query) const; 56 | 57 | /** 58 | * Dump the OPDS feed. 59 | * 60 | * @param bookIds the ids of the books to include in the feed 61 | * @param query the query used to obtain the list of book ids 62 | * @param partial whether the feed should include partial or complete entries 63 | * @return The OPDS feed. 64 | */ 65 | std::string dumpOPDSFeedV2(const std::vector& bookIds, const std::string& query, bool partial) const; 66 | 67 | /** 68 | * Dump the OPDS complete entry document. 69 | * 70 | * @param bookId the id of the book 71 | * @return The OPDS complete entry document. 72 | */ 73 | std::string dumpOPDSCompleteEntry(const std::string& bookId) const; 74 | 75 | /** 76 | * Dump the categories OPDS feed. 77 | * 78 | * @return The OPDS feed. 79 | */ 80 | std::string categoriesOPDSFeed() const; 81 | 82 | /** 83 | * Dump the languages OPDS feed. 84 | * 85 | * @return The OPDS feed. 86 | */ 87 | std::string languagesOPDSFeed() const; 88 | }; 89 | } 90 | 91 | #endif // KIWIX_OPDS_DUMPER_H 92 | -------------------------------------------------------------------------------- /include/name_mapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_NAMEMAPPER_H 21 | #define KIWIX_NAMEMAPPER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace kiwix 29 | { 30 | 31 | class Library; 32 | 33 | class NameMapper { 34 | public: 35 | virtual ~NameMapper() = default; 36 | virtual std::string getNameForId(const std::string& id) const = 0; 37 | virtual std::string getIdForName(const std::string& name) const = 0; 38 | }; 39 | 40 | 41 | class IdNameMapper : public NameMapper { 42 | public: 43 | virtual std::string getNameForId(const std::string& id) const { return id; }; 44 | virtual std::string getIdForName(const std::string& name) const { return name; }; 45 | }; 46 | 47 | class HumanReadableNameMapper : public NameMapper { 48 | private: 49 | std::map m_idToName; 50 | std::map m_nameToId; 51 | 52 | public: 53 | HumanReadableNameMapper(kiwix::Library& library, bool withAlias); 54 | virtual ~HumanReadableNameMapper() = default; 55 | virtual std::string getNameForId(const std::string& id) const; 56 | virtual std::string getIdForName(const std::string& name) const; 57 | 58 | private: 59 | void mapName(const kiwix::Library& lib, std::string name, std::string id); 60 | }; 61 | 62 | class UpdatableNameMapper : public NameMapper { 63 | typedef std::shared_ptr NameMapperHandle; 64 | public: 65 | UpdatableNameMapper(std::shared_ptr library, bool withAlias); 66 | 67 | virtual std::string getNameForId(const std::string& id) const; 68 | virtual std::string getIdForName(const std::string& name) const; 69 | 70 | void update(); 71 | 72 | private: 73 | NameMapperHandle currentNameMapper() const; 74 | 75 | private: 76 | mutable std::mutex mutex; 77 | std::shared_ptr library; 78 | NameMapperHandle nameMapper; 79 | const bool withAlias; 80 | }; 81 | 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /include/i18n.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_I18N 21 | #define KIWIX_I18N 22 | 23 | #include 24 | #include 25 | 26 | namespace kiwix 27 | { 28 | 29 | std::string getTranslatedString(const std::string& lang, const std::string& key); 30 | 31 | namespace i18n 32 | { 33 | 34 | typedef std::map Parameters; 35 | 36 | std::string expandParameterizedString(const std::string& lang, 37 | const std::string& key, 38 | const Parameters& params); 39 | 40 | class GetTranslatedString 41 | { 42 | public: 43 | explicit GetTranslatedString(const std::string& lang) : m_lang(lang) {} 44 | 45 | std::string operator()(const std::string& key) const 46 | { 47 | return getTranslatedString(m_lang, key); 48 | } 49 | 50 | std::string operator()(const std::string& key, const Parameters& params) const 51 | { 52 | return expandParameterizedString(m_lang, key, params); 53 | } 54 | 55 | private: 56 | const std::string m_lang; 57 | }; 58 | 59 | } // namespace i18n 60 | 61 | class ParameterizedMessage 62 | { 63 | public: // types 64 | typedef i18n::Parameters Parameters; 65 | 66 | public: // functions 67 | ParameterizedMessage(const std::string& msgId, const Parameters& params) 68 | : msgId(msgId) 69 | , params(params) 70 | {} 71 | 72 | std::string getText(const std::string& lang) const; 73 | 74 | const std::string& getMsgId() const { return msgId; } 75 | const Parameters& getParams() const { return params; } 76 | 77 | private: // data 78 | const std::string msgId; 79 | const Parameters params; 80 | }; 81 | 82 | inline ParameterizedMessage nonParameterizedMessage(const std::string& msgId) 83 | { 84 | const ParameterizedMessage::Parameters noParams; 85 | return ParameterizedMessage(msgId, noParams); 86 | } 87 | 88 | std::string translateBookCategory(const std::string& lang, const std::string& category); 89 | 90 | } // namespace kiwix 91 | 92 | #endif // KIWIX_I18N 93 | -------------------------------------------------------------------------------- /src/library_dumper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Nikhil Tanwar <2002nikhiltanwar@gmail.com> 3 | * Copyright 2017 Matthieu Gautier 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 3 of the License, or 8 | * any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 18 | * MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef KIWIX_LIBRARY_DUMPER_H 22 | #define KIWIX_LIBRARY_DUMPER_H 23 | 24 | #include 25 | 26 | 27 | #include "library.h" 28 | #include "name_mapper.h" 29 | #include 30 | 31 | namespace kiwix 32 | { 33 | 34 | /** 35 | * A base class to dump Library in various formats. 36 | * 37 | */ 38 | class LibraryDumper 39 | { 40 | public: 41 | LibraryDumper(const Library* library, const NameMapper* NameMapper); 42 | ~LibraryDumper(); 43 | 44 | void setLibraryId(const std::string& id) { this->libraryId = id;} 45 | 46 | /** 47 | * Set the root location used when generating url. 48 | * 49 | * @param rootLocation the root location to use. 50 | */ 51 | void setRootLocation(const std::string& rootLocation) { this->rootLocation = rootLocation; } 52 | 53 | /** 54 | * Set some informations about the search results. 55 | * 56 | * @param totalResult the total number of results of the search. 57 | * @param startIndex the start index of the result. 58 | * @param count the number of result of the current set (or page). 59 | */ 60 | void setOpenSearchInfo(int totalResult, int startIndex, int count); 61 | 62 | /** 63 | * Sets user default language 64 | * 65 | * @param userLang the user language to be set 66 | */ 67 | void setUserLanguage(std::string userLang) { this->m_userLang = userLang; } 68 | 69 | /** 70 | * Get the data of categories 71 | */ 72 | kainjow::mustache::list getCategoryData() const; 73 | 74 | /** 75 | * Get the data of languages 76 | */ 77 | kainjow::mustache::list getLanguageData() const; 78 | 79 | protected: 80 | const kiwix::Library* const library; 81 | const kiwix::NameMapper* const nameMapper; 82 | std::string libraryId; 83 | std::string rootLocation; 84 | std::string m_userLang; 85 | int m_totalResults; 86 | int m_startIndex; 87 | int m_count; 88 | }; 89 | } 90 | 91 | #endif // KIWIX_LIBRARY_DUMPER_H 92 | -------------------------------------------------------------------------------- /src/tools/otherTools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_OTHERTOOLS_H 21 | #define KIWIX_OTHERTOOLS_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "stringTools.h" 31 | 32 | namespace pugi { 33 | class xml_node; 34 | } 35 | 36 | namespace zim { 37 | class SuggestionItem; 38 | } 39 | 40 | namespace kiwix 41 | { 42 | std::string nodeToString(const pugi::xml_node& node); 43 | 44 | /* 45 | * Convert all format tag string to new format 46 | */ 47 | std::vector convertTags(const std::string& tags_str); 48 | std::string getTagValueFromTagList(const std::vector& tagList, 49 | const std::string& tagName); 50 | bool convertStrToBool(const std::string& value); 51 | 52 | std::string gen_date_str(); 53 | std::string gen_uuid(const std::string& s); 54 | 55 | // if s is empty then returns kainjow::mustache::data(false) 56 | // otherwise kainjow::mustache::data(value) 57 | kainjow::mustache::data onlyAsNonEmptyMustacheValue(const std::string& s); 58 | 59 | std::string render_template(const std::string& template_str, kainjow::mustache::data data); 60 | 61 | template 62 | T getEnvVar(const char* name, const T& defaultValue) 63 | { 64 | try { 65 | const char* envString = std::getenv(name); 66 | if (envString == nullptr) { 67 | throw std::runtime_error("Environment variable not set"); 68 | } 69 | return extractFromString(envString); 70 | } catch (...) {} 71 | 72 | return defaultValue; 73 | } 74 | 75 | class Suggestions 76 | { 77 | public: 78 | Suggestions(); 79 | 80 | void add(const zim::SuggestionItem& suggestion); 81 | 82 | void addFTSearchSuggestion(const std::string& uiLang, 83 | const std::string& query); 84 | 85 | std::string getJSON() const; 86 | 87 | private: 88 | kainjow::mustache::data m_data; 89 | }; 90 | } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /static/skin/i18n/lb.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Kelson", 5 | "Robby", 6 | "Volvox" 7 | ] 8 | }, 9 | "name": "Lëtzebuergesch", 10 | "suggest-full-text-search": "enthält '{{{SEARCH_TERMS}}}'...", 11 | "no-such-book": "Buch net fonnt: {{BOOK_NAME}}", 12 | "too-many-books": "Ze vill Bicher ugefrot ({{NB_BOOKS}}), d'Limitt läit bei {{LIMIT}}", 13 | "url-not-found": "Déi ugefroten URL „{{url}}“ gouf op dësem Server net fonnt.", 14 | "suggest-search": "Maacht eng Volltext-Sich fir {{PATTERN}}", 15 | "random-article-failure": "Ups! Et konnt keen zoufällegen Artikel ausgewielt ginn :(", 16 | "404-page-title": "Inhalt net fonnt", 17 | "404-page-heading": "Net fonnt", 18 | "new-404-page-title": "Säit net fonnt", 19 | "new-404-page-heading": "Ups. Säit net fonnt.", 20 | "404-img-text": "Net fonnt!", 21 | "500-page-title": "Interne Feeler um Server", 22 | "500-page-heading": "Ups. D'Säit funktionéiert net.", 23 | "500-page-text": "Et ass en interne Serverfeeler opgetrueden. Mir entschëllegen eis dofir :/", 24 | "500-img-text": "Säit funktionéiert net", 25 | "external-link-detected": "Externe Link entdeckt", 26 | "caution-warning": "Opgepasst!", 27 | "fulltext-search-unavailable": "Volltext-Sich net verfügbar", 28 | "search-results-page-title": "Sichen: {{SEARCH_PATTERN}}", 29 | "search-results-page-header": "Resultater {{START}}-{{END}} vu(n) {{COUNT}} fir „{{{SEARCH_PATTERN}}}“", 30 | "empty-search-results-page-header": "Keng Resultater fonnt fir „{{{SEARCH_PATTERN}}}“", 31 | "search-result-book-info": "aus {{BOOK_TITLE}}", 32 | "word-count": "{{COUNT}} Wierder", 33 | "home-button-text": "Op d'Haaptsäit vun '{{{BOOK_TITLE}}}' goen", 34 | "random-page-button-text": "Gitt op eng zoufälleg gewielte Säit", 35 | "searchbox-tooltip": "No '{{{BOOK_TITLE}}}' sichen", 36 | "welcome-page-overzealous-filter": "Kee Resultat. Wëllt Dir de Filter zrécksetzen?", 37 | "search": "Sichen", 38 | "book-filtering-all-categories": "All Kategorien", 39 | "book-filtering-all-languages": "All Sproochen", 40 | "count-of-matching-books": "{{COUNT}} Buch/Bicher", 41 | "download": "Eroflueden", 42 | "direct-download-link-text": "Direkt", 43 | "torrent-download-link-text": "BitTorrent", 44 | "download-links-title": "Buch eroflueden", 45 | "unknown-error": "Onbekannte Feeler", 46 | "book-category.stack_exchange": "Stack Exchange", 47 | "book-category.wikibooks": "Wikibooks", 48 | "book-category.wikinews": "Wikinews", 49 | "book-category.wikipedia": "Wikipedia", 50 | "book-category.wikiquote": "Wikiquote", 51 | "book-category.wikisource": "Wikisource", 52 | "book-category.wikispecies": "Wikispecies", 53 | "book-category.wikiversity": "Wikiversity", 54 | "book-category.wikivoyage": "Wikivoyage", 55 | "book-category.wiktionary": "Wiktionnaire", 56 | "book-category.other": "Anerer" 57 | } 58 | -------------------------------------------------------------------------------- /src/server.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #include "server.h" 21 | 22 | #include "library.h" 23 | #include "name_mapper.h" 24 | 25 | #include 26 | 27 | #include 28 | #include "server/internalServer.h" 29 | 30 | namespace kiwix { 31 | 32 | Server::Server(LibraryPtr library, std::shared_ptr nameMapper) : 33 | mp_library(library), 34 | mp_nameMapper(nameMapper), 35 | mp_server(nullptr) 36 | { 37 | } 38 | 39 | Server::~Server() = default; 40 | 41 | bool Server::start() { 42 | mp_server.reset(new InternalServer( 43 | mp_library, 44 | mp_nameMapper, 45 | m_addr, 46 | m_port, 47 | m_root, 48 | m_nbThreads, 49 | m_multizimSearchLimit, 50 | m_verbose, 51 | m_withTaskbar, 52 | m_withLibraryButton, 53 | m_blockExternalLinks, 54 | m_ipMode, 55 | m_indexTemplateString, 56 | m_ipConnectionLimit)); 57 | return mp_server->start(); 58 | } 59 | 60 | void Server::stop() { 61 | if (mp_server) { 62 | mp_server->stop(); 63 | mp_server.reset(nullptr); 64 | } 65 | } 66 | 67 | void Server::setRoot(const std::string& root) 68 | { 69 | m_root = root; 70 | if (m_root[0] != '/') { 71 | m_root = "/" + m_root; 72 | } 73 | if (m_root.back() == '/') { 74 | m_root.erase(m_root.size() - 1); 75 | } 76 | } 77 | 78 | void Server::setAddress(const std::string& addr) 79 | { 80 | m_addr.addr.clear(); 81 | m_addr.addr6.clear(); 82 | 83 | if (addr.empty()) return; 84 | 85 | if (addr.find(':') != std::string::npos) { // IPv6 86 | m_addr.addr6 = (addr[0] == '[') ? addr.substr(1, addr.length() - 2) : addr; // Remove brackets if any 87 | } else { 88 | m_addr.addr = addr; 89 | } 90 | } 91 | 92 | int Server::getPort() const 93 | { 94 | return mp_server->getPort(); 95 | } 96 | 97 | IpAddress Server::getAddress() const 98 | { 99 | return mp_server->getAddress(); 100 | } 101 | 102 | IpMode Server::getIpMode() const 103 | { 104 | return mp_server->getIpMode(); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/tools/regexTools.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | std::map> regexCache; 31 | static std::mutex regexLock; 32 | 33 | std::unique_ptr buildMatcher(const std::string& regex, icu::UnicodeString& content) 34 | { 35 | std::shared_ptr pattern; 36 | /* Regex is in cache */ 37 | try { 38 | pattern = regexCache.at(regex); 39 | } catch (std::out_of_range&) { 40 | // Redo the search with a lock to avoid race condition. 41 | std::lock_guard l(regexLock); 42 | try { 43 | pattern = regexCache.at(regex); 44 | } catch (std::out_of_range&) { 45 | UErrorCode status = U_ZERO_ERROR; 46 | UParseError pe; 47 | icu::UnicodeString uregex(regex.c_str()); 48 | pattern.reset(icu::RegexPattern::compile(uregex, UREGEX_CASE_INSENSITIVE, pe, status)); 49 | regexCache[regex] = pattern; 50 | } 51 | } 52 | UErrorCode status = U_ZERO_ERROR; 53 | return std::unique_ptr(pattern->matcher(content, status)); 54 | } 55 | 56 | bool matchRegex(const std::string& content, const std::string& regex) 57 | { 58 | ucnv_setDefaultName("UTF-8"); 59 | icu::UnicodeString ucontent(content.c_str()); 60 | auto matcher = buildMatcher(regex, ucontent); 61 | return matcher->find(); 62 | } 63 | 64 | std::string replaceRegex(const std::string& content, 65 | const std::string& replacement, 66 | const std::string& regex) 67 | { 68 | ucnv_setDefaultName("UTF-8"); 69 | icu::UnicodeString ureplacement(replacement.c_str()); 70 | icu::UnicodeString ucontent(content.c_str()); 71 | auto matcher = buildMatcher(regex, ucontent); 72 | UErrorCode status = U_ZERO_ERROR; 73 | auto uresult = matcher->replaceAll(ureplacement, status); 74 | std::string tmp; 75 | uresult.toUTF8String(tmp); 76 | return tmp; 77 | } 78 | -------------------------------------------------------------------------------- /test/meson.build: -------------------------------------------------------------------------------- 1 | tests = [ 2 | 'library', 3 | 'regex', 4 | 'tagParsing', 5 | 'stringTools', 6 | 'pathTools', 7 | 'otherTools', 8 | 'opdsParsingTools', 9 | 'languageTools', 10 | 'kiwixserve', 11 | 'book', 12 | 'manager', 13 | 'name_mapper', 14 | 'opds_catalog', 15 | 'server_helper', 16 | 'lrucache', 17 | 'i18n', 18 | 'response' 19 | ] 20 | 21 | if build_machine.system() != 'windows' 22 | tests += [ 23 | 'server', 24 | 'library_server', 25 | 'server_search' 26 | ] 27 | endif 28 | 29 | 30 | 31 | gtest_dep = dependency('gtest', 32 | main:true, 33 | fallback: ['gtest', 'gtest_main_dep'], 34 | required:false) 35 | 36 | if gtest_dep.found() and not meson.is_cross_build() 37 | data_files = [ 38 | 'example.zim', 39 | 'zimfile.zim', 40 | 'zimfile&other.zim', 41 | 'zimfile_raycharles.zim', 42 | 'zimfile_raycharles_uncategorized.zim', 43 | 'corner_cases#&.zim', 44 | 'poor.zim', 45 | 'library.xml', 46 | 'lib_for_server_search_test.xml', 47 | 'customized_resources.txt', 48 | 'helloworld.txt', 49 | 'welcome.html', 50 | ] 51 | foreach file : data_files 52 | # configure_file(input : 'data/' + file, 53 | # output : file, 54 | # copy: true ) 55 | # 56 | # Above (commented) command doesn't work with Meson versions below 0.47 57 | # (in which the 'copy' keyword was first introduced). We want to keep 58 | # compatibility with Ubuntu 18.04 Bionic (which has Meson version 0.45) 59 | # until its EOL. 60 | # 61 | # Below is a python based workaround. 62 | configure_file(input : 'data/' + file, 63 | output : file, 64 | command: [ 65 | find_program('python3'), 66 | '-c', 67 | 'import sys; import shutil; shutil.copy(sys.argv[1], sys.argv[2])', 68 | '@INPUT@', 69 | '@OUTPUT@' 70 | ]) 71 | endforeach 72 | 73 | foreach test_name : tests 74 | # XXX: implicit_include_directories must be set to false, otherwise 75 | # XXX: '#include ' includes the regex unit test binary 76 | test_exe = executable(test_name, [test_name+'.cpp'], 77 | implicit_include_directories: false, 78 | include_directories : inc, 79 | link_with : libkiwix, 80 | link_args: extra_libs, 81 | dependencies : all_deps + [gtest_dep], 82 | build_rpath : '$ORIGIN') 83 | test(test_name, test_exe, timeout : 160) 84 | endforeach 85 | endif 86 | -------------------------------------------------------------------------------- /src/subprocess_windows.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "subprocess_windows.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | WinImpl::WinImpl(): 12 | m_pid(0), 13 | m_running(false), 14 | m_subprocessHandle(INVALID_HANDLE_VALUE), 15 | m_waitingThreadHandle(INVALID_HANDLE_VALUE) 16 | { 17 | InitializeCriticalSection(&m_criticalSection); 18 | } 19 | 20 | WinImpl::~WinImpl() 21 | { 22 | kill(); 23 | WaitForSingleObject(m_waitingThreadHandle, INFINITE); 24 | CloseHandle(m_subprocessHandle); 25 | DeleteCriticalSection(&m_criticalSection); 26 | } 27 | 28 | DWORD WINAPI WinImpl::waitForPID(void* _self) 29 | { 30 | WinImpl* self = static_cast(_self); 31 | WaitForSingleObject(self->m_subprocessHandle, INFINITE); 32 | 33 | EnterCriticalSection(&self->m_criticalSection); 34 | self->m_running = false; 35 | LeaveCriticalSection(&self->m_criticalSection); 36 | 37 | return 0; 38 | } 39 | 40 | std::unique_ptr toWideChar(const std::string& value, size_t min_size = 0) 41 | { 42 | size_t size = MultiByteToWideChar(CP_UTF8, 0, 43 | value.c_str(), -1, nullptr, 0); 44 | auto wdata = std::unique_ptr(new wchar_t[size>min_size?size:min_size]); 45 | auto ret = MultiByteToWideChar(CP_UTF8, 0, 46 | value.c_str(), -1, wdata.get(), size); 47 | if (0 == ret) { 48 | std::ostringstream oss; 49 | oss << "Cannot convert to wchar : " << GetLastError(); 50 | throw std::runtime_error(oss.str()); 51 | } 52 | if (size < min_size) { 53 | memset(wdata.get() + size, 0, min_size-size); 54 | } 55 | return wdata; 56 | } 57 | 58 | 59 | void WinImpl::run(commandLine_t& commandLine) 60 | { 61 | STARTUPINFOW startInfo = {0}; 62 | PROCESS_INFORMATION procInfo; 63 | startInfo.cb = sizeof(startInfo); 64 | std::wostringstream oss; 65 | for(auto& item: commandLine) { 66 | auto witem = toWideChar(item, MAX_PATH); 67 | PathQuoteSpacesW(witem.get()); 68 | oss << witem.get() << " "; 69 | } 70 | auto wCommandLine = oss.str(); 71 | if (CreateProcessW( 72 | NULL, 73 | const_cast(wCommandLine.c_str()), 74 | NULL, 75 | NULL, 76 | false, 77 | CREATE_NO_WINDOW, 78 | NULL, 79 | NULL, 80 | &startInfo, 81 | &procInfo)) 82 | { 83 | m_pid = procInfo.dwProcessId; 84 | m_subprocessHandle = procInfo.hProcess; 85 | CloseHandle(procInfo.hThread); 86 | m_running = true; 87 | m_waitingThreadHandle = CreateThread(NULL, 0, &waitForPID, this, 0, NULL); 88 | } 89 | } 90 | 91 | bool WinImpl::kill() 92 | { 93 | return TerminateProcess(m_subprocessHandle, 0); 94 | } 95 | 96 | bool WinImpl::isRunning() 97 | { 98 | EnterCriticalSection(&m_criticalSection); 99 | bool ret = m_running; 100 | LeaveCriticalSection(&m_criticalSection); 101 | return ret; 102 | } 103 | -------------------------------------------------------------------------------- /src/server/etag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | 21 | #ifndef KIWIXLIB_SERVER_ETAG_H 22 | #define KIWIXLIB_SERVER_ETAG_H 23 | 24 | #include 25 | 26 | namespace kiwix { 27 | 28 | // The ETag string used by Kiwix server (more precisely, its value inside the 29 | // double quotes) consists of two parts: 30 | // 31 | // 1. Body - A string uniquely identifying the object or state from which 32 | // the resource has been obtained. 33 | // 34 | // 2. Options - Zero or more characters encoding the type of the ETag and/or 35 | // the values of some of the headers of the response 36 | // 37 | // The two parts are separated with a slash (/) symbol (which is always present, 38 | // even when the the options part is empty). Neither portion of a Kiwix ETag 39 | // may contain the slash symbol. 40 | // Examples of valid Kiwix server ETags (including the double quotes): 41 | // 42 | // "abcdefghijklmn/" 43 | // "1234567890/z" 44 | // "6f1d19d0-633f-087b-fb55-7ac324ff9baf/Zz" 45 | // 46 | // The options part of the Kiwix ETag allows to correctly set the required 47 | // headers when responding to a conditional If-None-Match request with a 304 48 | // (Not Modified) response without following the full code path that would 49 | // discover the necessary options. 50 | 51 | class ETag 52 | { 53 | public: // types 54 | enum Option { 55 | ZIM_CONTENT, 56 | COMPRESSED_CONTENT, 57 | OPTION_COUNT 58 | }; 59 | 60 | public: // functions 61 | ETag() {} 62 | 63 | void set_body(const std::string& s) { m_body = s; } 64 | void set_option(Option opt); 65 | 66 | explicit operator bool() const { return !m_body.empty(); } 67 | 68 | bool get_option(Option opt) const; 69 | std::string get_etag() const; 70 | 71 | 72 | static ETag match(const std::string& etags, const std::string& server_id); 73 | 74 | private: // functions 75 | ETag(const std::string& serverId, const std::string& options); 76 | 77 | static ETag parse(std::string s); 78 | 79 | private: // data 80 | std::string m_body; 81 | std::string m_options; 82 | }; 83 | 84 | } // namespace kiwix 85 | 86 | #endif // KIWIXLIB_SERVER_ETAG_H 87 | -------------------------------------------------------------------------------- /include/bookmark.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_BOOKMARK_H 21 | #define KIWIX_BOOKMARK_H 22 | 23 | #include 24 | 25 | namespace pugi { 26 | class xml_node; 27 | } 28 | 29 | namespace kiwix 30 | { 31 | 32 | class Book; 33 | /** 34 | * A class to store information about a bookmark (an article in a book) 35 | */ 36 | class Bookmark 37 | { 38 | public: 39 | /** 40 | * Create an empty bookmark. 41 | * 42 | * Bookmark must be populated with `set*` methods 43 | */ 44 | Bookmark(); 45 | 46 | /** 47 | * Create a bookmark given a Book, a path and a title. 48 | */ 49 | Bookmark(const Book& book, const std::string& path, const std::string& title); 50 | 51 | ~Bookmark(); 52 | 53 | void updateFromXml(const pugi::xml_node& node); 54 | 55 | const std::string& getBookId() const { return m_bookId; } 56 | const std::string& getBookTitle() const { return m_bookTitle; } 57 | const std::string& getBookName() const { return m_bookName; } 58 | const std::string& getBookFlavour() const { return m_bookFlavour; } 59 | const std::string& getUrl() const { return m_url; } 60 | const std::string& getTitle() const { return m_title; } 61 | const std::string& getLanguage() const { return m_language; } 62 | const std::string& getDate() const { return m_date; } 63 | 64 | void setBookId(const std::string& bookId) { m_bookId = bookId; } 65 | void setBookTitle(const std::string& bookTitle) { m_bookTitle = bookTitle; } 66 | void setBookName(const std::string& bookName) { m_bookName = bookName; } 67 | void setBookFlavour(const std::string& bookFlavour) { m_bookFlavour = bookFlavour; } 68 | void setUrl(const std::string& url) { m_url = url; } 69 | void setTitle(const std::string& title) { m_title = title; } 70 | void setLanguage(const std::string& language) { m_language = language; } 71 | void setDate(const std::string& date) { m_date = date; } 72 | 73 | protected: 74 | std::string m_bookId; 75 | std::string m_bookTitle; 76 | std::string m_bookName; 77 | std::string m_bookFlavour; 78 | std::string m_url; 79 | std::string m_title; 80 | std::string m_language; 81 | std::string m_date; 82 | }; 83 | 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/server/byte_range.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Veloman Yunkan 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | 21 | #ifndef KIWIXLIB_SERVER_BYTE_RANGE_H 22 | #define KIWIXLIB_SERVER_BYTE_RANGE_H 23 | 24 | #include 25 | #include 26 | 27 | namespace kiwix { 28 | 29 | class ByteRange 30 | { 31 | public: // types 32 | // ByteRange is parsed in a request, then it must be resolved (taking 33 | // into account the actual size of the requested resource) before 34 | // being applied in the response. 35 | // The Kind enum represents possible states in such a lifecycle. 36 | enum Kind { 37 | // The request is not a range request (no Range header) 38 | NONE, 39 | 40 | // The value of the Range header is not a valid continuous 41 | // range. Note that a valid (according to RFC7233) sequence of multiple 42 | // byte ranges is considered invalid in the current implementation 43 | // (i.e. only single-range partial requests are supported). 44 | INVALID, 45 | 46 | // This byte-range has been successfully parsed from the request 47 | PARSED, 48 | 49 | // This is a response to a regular (non-range) request 50 | RESOLVED_FULL_CONTENT, 51 | 52 | // The range request is invalid or unsatisfiable 53 | RESOLVED_UNSATISFIABLE, 54 | 55 | // This is a response to a (satisfiable) range request 56 | RESOLVED_PARTIAL_CONTENT, 57 | }; 58 | 59 | public: // functions 60 | // Constructs a ByteRange object of NONE kind 61 | ByteRange(); 62 | 63 | // Constructs a ByteRange object of the given kind (except NONE) 64 | ByteRange(Kind kind, int64_t first, int64_t last); 65 | 66 | // Constructs a ByteRange object of PARSED kind corresponding to a 67 | // range request of the form "Range: bytes=-suffix_length" 68 | explicit ByteRange(int64_t suffix_length); 69 | 70 | Kind kind() const { return kind_; } 71 | int64_t first() const; 72 | int64_t last() const; 73 | int64_t length() const; 74 | 75 | static ByteRange parse(const std::string& rangeStr); 76 | ByteRange resolve(int64_t contentSize) const; 77 | 78 | private: // data 79 | Kind kind_; 80 | int64_t first_; 81 | int64_t last_; 82 | }; 83 | 84 | } // namespace kiwix 85 | 86 | #endif //KIWIXLIB_SERVER_BYTE_RANGE_H 87 | -------------------------------------------------------------------------------- /static/skin/i18n/dag.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Kalakpagh", 5 | "Ruky Wunpini" 6 | ] 7 | }, 8 | "name": "Silimiinsili", 9 | "suggest-full-text-search": "Gbubi la '{{{SEARCH_TERMS}}}'...", 10 | "no-such-book": "Lala buku kani:{{BOOK_NAME}}", 11 | "too-many-books": "Buku nima pam ka bɛ daa suhi ({{NB_BOOKS}}) din ni ka tariga nyɛ {{LIMIT}}", 12 | "no-book-found": "Buku kani lu zahim a ni piigi yaɣa shɛli", 13 | "url-not-found": "URL \"{{url}}\" shɛli bɛ ni daa suhi daa kani n-ti tum tumda ŋɔ.", 14 | "suggest-search": "Niŋmi lahabali pali vihigu zaŋ n-ti {{PATTERN}}", 15 | "random-article-failure": "Oops! Zaɣisiya ni di gahim piigi lahabali :(", 16 | "invalid-raw-data-type": "{{DATATYPE}} nyɛla din suhibu bi niŋ viɛnyɛla zaŋ n-ti lahabali kahili.", 17 | "invalid-request": "URL \"{{{url}}}\" shɛli bɛ ni daa suhi ŋɔ nyɛla din bi suhi viɛnyɛla.", 18 | "no-value-for-arg": "Dariza shɛli bi ti zaŋ n-ti nangban'kpeeni {{ARGUMENT}}", 19 | "no-query": "Yɛlshɛli bi yiina", 20 | "raw-entry-not-found": "Ku tooi nya {{DATATYPE}} kpɛbu {{ENTRY}}", 21 | "400-page-title": "Suhigu din bi niŋ viɛnyɛla", 22 | "400-page-heading": "Suhigu din bi niŋ viɛnyɛla", 23 | "404-page-title": "Lahabali kani", 24 | "404-page-heading": "Kani", 25 | "500-page-title": "Puuni tum tumda chiriŋ", 26 | "500-page-heading": "Puuni tum tumda chiriŋ", 27 | "500-page-text": "Puuni tum tumda chiriŋ niŋya. Ti niŋ yolitem zaŋ jɛndi li :/", 28 | "fulltext-search-unavailable": "Lahabali pali vihigu kani", 29 | "search-results-page-title": "Vihima:{{SEARCH_PATTERN}}", 30 | "search-results-page-header": "Chaɣili nima {{START}}-{{END}} of {{COUNT}} for \"{{{SEARCH_PATTERN}}}\"", 31 | "empty-search-results-page-header": "Chaɣili daa kani zaŋ n-ti\n \"{{{SEARCH_PATTERN}}}\"", 32 | "search-result-book-info": "yina {{BOOK_TITLE}}", 33 | "word-count": "{{COUNT}} bachi nima", 34 | "library-button-text": "Cham solɔɣu", 35 | "home-button-text": "Cham yaɣili maŋmaŋ zaŋ n-ti\n'{{BOOK_TITLE}}'", 36 | "random-page-button-text": "Cham gahim piigi yaɣili", 37 | "searchbox-tooltip": "Vihima '{{BOOK_TITLE}}'", 38 | "confusion-of-tongues": "Buku nima ayi bee gari balli koŋkoba nyɛ din yɛn be vihigu ŋɔ ni ka di ni tooi chɛ ka di laasabu wali.", 39 | "welcome-page-overzealous-filter": "Labisibu kani. A ni yu ni a\nreset filter?", 40 | "powered-by-kiwix-html": "Din niŋ li nyɛ  Kiwix", 41 | "search": "Vihima", 42 | "book-filtering-all-categories": "Pubu zaa", 43 | "book-filtering-all-languages": "Bala zaa", 44 | "count-of-matching-books": "{{COUNT}} Buku(nima)", 45 | "download": "Deebu", 46 | "direct-download-link-text": "Tibi", 47 | "direct-download-alt-text": "Tibi deebu", 48 | "hash-download-link-text": "Sha256 hash", 49 | "hash-download-alt-text": "Deebu daliŋ", 50 | "welcome-to-kiwix-server": "Maraba Kiwix tum tumda", 51 | "download-links-heading": "Deemi soli zaŋ n-ti {{BOOK_TITLE}}", 52 | "download-links-title": "Deemi buku", 53 | "preview-book": "Daŋyuli", 54 | "unknown-error": "Chiriŋ din bi tooi baŋ" 55 | } 56 | -------------------------------------------------------------------------------- /static/skin/error.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family:"DM Sans"; 3 | font-style: normal; 4 | font-weight: 400; 5 | src : url('../skin/fonts/DMSans-Regular.ttf?KIWIXCACHEID'); 6 | } 7 | @font-face { 8 | font-family:"DM Sans Bold"; 9 | font-style: normal; 10 | font-weight: 700; 11 | src : url('../skin/fonts/DMSans-Regular.ttf?KIWIXCACHEID'); 12 | } 13 | 14 | body { 15 | background: linear-gradient(to bottom right, #ffffff, #e6e6e6); 16 | background-repeat: no-repeat; 17 | background-attachment: fixed; 18 | } 19 | 20 | header { 21 | width: 100%; 22 | margin: auto; 23 | text-align: center; 24 | 25 | margin-top: 15%; 26 | margin-bottom: 15%; 27 | } 28 | 29 | header img { 30 | width: 60%; 31 | min-width: 200px; 32 | max-width: 500px; 33 | max-height: 300px; 34 | } 35 | 36 | section { 37 | display: flex; 38 | flex-direction: column; 39 | align-items: center; 40 | } 41 | 42 | header, .intro { 43 | font-family: "DM Sans"; 44 | } 45 | 46 | .intro { 47 | font-size: 1em; 48 | padding: 0 10%; 49 | line-height: 1.2em; 50 | text-align: center; 51 | } 52 | 53 | .intro h1 { 54 | line-height: 1.1em; 55 | font-family: "DM Sans Bold"; 56 | font-size: 1.2em; 57 | } 58 | 59 | .intro code { 60 | font-family: monospace; 61 | font-size: 1.1em; 62 | word-break: break-all; 63 | } 64 | 65 | .intro a, .intro a:active, .intro a:visited { 66 | color: #00b4e4; 67 | text-decoration: none; 68 | word-break: break-all; 69 | } 70 | 71 | .advice { 72 | width: 80%; 73 | margin: auto; 74 | margin-bottom: 15%; 75 | margin-top: 5em; 76 | 77 | background-color: #ffffff; 78 | border-radius: 1rem; 79 | border: 1px solid #b7b7b7; 80 | 81 | padding: 2em; 82 | 83 | font-family: "DM Sans"; 84 | font-size: .9em; 85 | box-sizing: border-box; 86 | 87 | align-items: normal; 88 | } 89 | 90 | .advice p { 91 | margin-bottom: 1em; 92 | } 93 | 94 | .advice p:first-child { 95 | margin-top: 0; 96 | } 97 | 98 | .advice p.list-intro { 99 | margin: 0; 100 | } 101 | 102 | .advice ul { 103 | list-style-type: square; 104 | margin: 0; 105 | padding: 0 1em; 106 | } 107 | 108 | .advice ul li { 109 | line-height: 2em; 110 | } 111 | 112 | .advice p:last-child { 113 | margin-bottom: 0; 114 | } 115 | 116 | 117 | /* sm: 640px+ */ 118 | @media (width >= 40rem) { 119 | header { 120 | margin-bottom: 1em; 121 | margin-top: 5em; 122 | } 123 | 124 | header img { 125 | width: 50%; 126 | } 127 | 128 | .intro h1 { 129 | font-size: 2em; 130 | } 131 | 132 | .advice { 133 | width: 50%; 134 | } 135 | } 136 | 137 | /* xl: 1280px+ */ 138 | @media (width >= 80rem) { 139 | .intro h1 { 140 | font-size: 3.4em; 141 | } 142 | } 143 | 144 | /* 2xl: 1536px+ */ 145 | @media (width >= 96rem) { 146 | header img { 147 | width: 25%; 148 | min-width: 200px; 149 | max-width: 500px; 150 | max-height: 300px; 151 | } 152 | 153 | .advice { 154 | width: 25%; 155 | min-width: 200px; 156 | min-width: 300px; 157 | max-width: 500px; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/version.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Emmanuel Engelhart 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | namespace kiwix 35 | { 36 | LibVersions getVersions() { 37 | LibVersions versions = { 38 | { "libkiwix", LIBKIWIX_VERSION }, 39 | { "libzim", LIBZIM_VERSION }, 40 | { "libxapian", XAPIAN_VERSION }, 41 | { "libcurl", LIBCURL_VERSION }, 42 | { "libmicrohttpd", MHD_get_version() }, 43 | { "libz", ZLIB_VERSION } 44 | }; 45 | 46 | // U_ICU_VERSION does not include the patch level if 0 47 | std::ostringstream libicu_version; 48 | libicu_version << U_ICU_VERSION_MAJOR_NUM << "." << U_ICU_VERSION_MINOR_NUM << "." << U_ICU_VERSION_PATCHLEVEL_NUM; 49 | versions.push_back({ "libicu", libicu_version.str() }); 50 | 51 | // No human readable version string for pugixml 52 | const unsigned pugixml_major = (PUGIXML_VERSION - PUGIXML_VERSION % 1000) / 1000; 53 | const unsigned pugixml_minor = (PUGIXML_VERSION - pugixml_major * 1000 - PUGIXML_VERSION % 10) / 10; 54 | const unsigned pugixml_patch = PUGIXML_VERSION - pugixml_major * 1000 - pugixml_minor * 10; 55 | std::ostringstream libpugixml_version; 56 | libpugixml_version << pugixml_major << "." << pugixml_minor << "." << pugixml_patch; 57 | versions.push_back({ "libpugixml", libpugixml_version.str() }); 58 | 59 | // Needs version 5.0 of Mustache 60 | #if defined(KAINJOW_MUSTACHE_VERSION_MAJOR) 61 | std::ostringstream libmustache_version; 62 | libmustache_version << KAINJOW_MUSTACHE_VERSION_MAJOR << "." << 63 | KAINJOW_MUSTACHE_VERSION_MINOR << "." << KAINJOW_MUSTACHE_VERSION_PATCH; 64 | versions.push_back({ "libmustache", libmustache_version.str() }); 65 | #endif 66 | 67 | return versions; 68 | } 69 | 70 | void printVersions(std::ostream& out) { 71 | LibVersions versions = getVersions(); 72 | for (const auto& iter : versions) { 73 | out << (iter != versions.front() ? "+ " : "") 74 | << iter.first << " " << iter.second << std::endl; 75 | } 76 | } 77 | } //namespace kiwix 78 | -------------------------------------------------------------------------------- /static/skin/favicon/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/regex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of the 7 | * License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but 10 | * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied 11 | * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and 12 | * NON-INFRINGEMENT. See the GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | */ 19 | 20 | #include "gtest/gtest.h" 21 | #include 22 | 23 | 24 | #include "../src/tools/regexTools.h" 25 | 26 | namespace 27 | { 28 | 29 | TEST(MatchRegex, match) 30 | { 31 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "f")); 32 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "ef")); 33 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "efg")); 34 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "mno")); 35 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "m*o")); 36 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "m*v")); 37 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "M")); 38 | EXPECT_TRUE(matchRegex("abcdefghijklmnopqrstuvwxyz", "STU")); 39 | EXPECT_TRUE(matchRegex("Mythology & Folklore Stack Exchange", "folklore")); 40 | EXPECT_TRUE(matchRegex("Mythology & Folklore Stack Exchange", "Folklore")); 41 | EXPECT_TRUE(matchRegex("Mythology & Folklore Stack Exchange", "folklore")); 42 | } 43 | 44 | TEST(MatchRegex, nomatch) 45 | { 46 | EXPECT_FALSE(matchRegex("abcdefghijklmnopqrstuvwxyz", "vu")); 47 | } 48 | 49 | TEST(ReplaceRegex, beginning) 50 | { 51 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "abcd"), "----efghij"); 52 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "abcde"), "----fghij"); 53 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "a.*i"), "----j"); 54 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "AbCd"), "----efghij"); 55 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "A"), "----bcdefghij"); 56 | } 57 | 58 | TEST(ReplaceRegex, end) 59 | { 60 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "ghij"), "abcdef----"); 61 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "fghij"), "abcde----"); 62 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "c.*j"), "ab----"); 63 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "GhIj"), "abcdef----"); 64 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "J"), "abcdefghi----"); 65 | } 66 | 67 | TEST(ReplaceRegex, middle) 68 | { 69 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "cdef"), "ab----ghij"); 70 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "cdefgh"), "ab----ij"); 71 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "c.*f"), "ab----ghij"); 72 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "DeFg"), "abc----hij"); 73 | EXPECT_EQ(replaceRegex("abcdefghij", "----", "F"), "abcde----ghij"); 74 | } 75 | 76 | }; 77 | -------------------------------------------------------------------------------- /static/skin/kiwix.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: inherit; 7 | } 8 | 9 | html { 10 | font-size: 62.5%; 11 | } 12 | 13 | body { 14 | position: relative; 15 | box-sizing: border-box; 16 | background: #ffffff; 17 | } 18 | 19 | .loader { 20 | position: absolute; 21 | top: 50%; 22 | left: 50%; 23 | transform: translate(-50%, -50%); 24 | font-size: 24px; 25 | background: rgba(255, 255, 255, 0.8); 26 | padding: 10px 20px; 27 | border-radius: 5px; 28 | display: flex; 29 | align-items: center; 30 | gap: 10px; 31 | white-space: nowrap; /* Prevents text from wrapping */ 32 | min-width: fit-content; /* Ensures the container doesn’t shrink */ 33 | } 34 | 35 | .spinner { 36 | width: 20px; 37 | height: 20px; 38 | border: 3px solid #ccc; 39 | border-top: 3px solid #007bff; 40 | border-radius: 50%; 41 | animation: spin 1s linear infinite; 42 | } 43 | 44 | .hidden { 45 | visibility: hidden; 46 | } 47 | 48 | ::selection { 49 | background-color: #00b4e4; 50 | color: white; 51 | } 52 | 53 | .modal-wrapper { 54 | position: fixed; 55 | z-index: 100; 56 | top: 0; 57 | left: 0; 58 | width: 100vw; 59 | height: 100vh; 60 | display: flex; 61 | justify-content: center; 62 | align-items: center; 63 | align-content: center; 64 | background-color: rgba(0, 0, 0, 30%); 65 | } 66 | 67 | .modal { 68 | color: #444343; 69 | height: 280px; 70 | width: 250px; 71 | margin: 15px; 72 | background-color: #f7f7f7; 73 | border: 1px solid #ececec; 74 | border-radius: 3px; 75 | } 76 | 77 | .modal-heading { 78 | background-color: #f0f0f0; 79 | height: 20%; 80 | width: 100%; 81 | border-bottom: 1px solid #ececec; 82 | display: grid; 83 | grid-template-columns: 3fr 1fr; 84 | } 85 | 86 | .modal-title { 87 | display: flex; 88 | font-size: 15px; 89 | align-items: center; 90 | padding-left: 20px; 91 | font-family: poppins; 92 | } 93 | 94 | .modal-close-button { 95 | cursor: pointer; 96 | display: flex; 97 | justify-content: center; 98 | align-items: center; 99 | } 100 | 101 | .modal-content { 102 | padding: 20px; 103 | } 104 | 105 | #content_iframe { 106 | background: #ffffff; 107 | } 108 | 109 | #uiLanguageSelector { 110 | display: none; 111 | } 112 | 113 | #uiLanguageSelector .modal { 114 | height: 140px; 115 | } 116 | 117 | #uiLanguageSelector .modal-heading { 118 | height: 40%; 119 | } 120 | 121 | #uiLanguageSelector .modal-content #ui_language { 122 | font-size: 1.6rem; 123 | width: 100%; 124 | } 125 | 126 | #uiLanguageSelectorButton { 127 | margin: 0px 12px; 128 | float: right; 129 | cursor: pointer; 130 | height: 30px; 131 | } 132 | 133 | @keyframes spin { 134 | 0% { transform: rotate(0deg); } 135 | 100% { transform: rotate(360deg); } 136 | } 137 | 138 | @font-face { 139 | font-family: "poppins"; 140 | src: url("../skin/fonts/Poppins.ttf?KIWIXCACHEID") format("truetype"); 141 | } 142 | 143 | @font-face { 144 | font-family: "roboto"; 145 | src: url("../skin/fonts/Roboto.ttf?KIWIXCACHEID") format("truetype"); 146 | } 147 | -------------------------------------------------------------------------------- /include/server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Matthieu Gautier 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License, or 7 | * any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef KIWIX_SERVER_H 21 | #define KIWIX_SERVER_H 22 | 23 | #include 24 | #include 25 | #include "tools.h" 26 | 27 | namespace kiwix 28 | { 29 | class Library; 30 | class NameMapper; 31 | class InternalServer; 32 | 33 | class Server { 34 | public: 35 | /** 36 | * The default constructor. 37 | * 38 | * @param library The library to serve. 39 | */ 40 | Server(std::shared_ptr library, std::shared_ptr nameMapper=nullptr); 41 | 42 | virtual ~Server(); 43 | 44 | /** 45 | * Serve the content. 46 | */ 47 | bool start(); 48 | 49 | /** 50 | * Stop the daemon. 51 | */ 52 | void stop(); 53 | 54 | void setRoot(const std::string& root); 55 | void setAddress(const std::string& addr); 56 | void setPort(int port) { m_port = port; } 57 | void setNbThreads(int threads) { m_nbThreads = threads; } 58 | void setMultiZimSearchLimit(unsigned int limit) { m_multizimSearchLimit = limit; } 59 | void setIpConnectionLimit(int limit) { m_ipConnectionLimit = limit; } 60 | void setVerbose(bool verbose) { m_verbose = verbose; } 61 | void setIndexTemplateString(const std::string& indexTemplateString) { m_indexTemplateString = indexTemplateString; } 62 | void setTaskbar(bool withTaskbar, bool withLibraryButton) 63 | { m_withTaskbar = withTaskbar; m_withLibraryButton = withLibraryButton; } 64 | void setBlockExternalLinks(bool blockExternalLinks) 65 | { m_blockExternalLinks = blockExternalLinks; } 66 | void setIpMode(IpMode mode) { m_ipMode = mode; } 67 | int getPort() const; 68 | IpAddress getAddress() const; 69 | IpMode getIpMode() const; 70 | 71 | protected: 72 | std::shared_ptr mp_library; 73 | std::shared_ptr mp_nameMapper; 74 | std::string m_root = ""; 75 | IpAddress m_addr; 76 | std::string m_indexTemplateString = ""; 77 | int m_port = 80; 78 | int m_nbThreads = 1; 79 | unsigned int m_multizimSearchLimit = 0; 80 | bool m_verbose = false; 81 | bool m_withTaskbar = true; 82 | bool m_withLibraryButton = true; 83 | bool m_blockExternalLinks = false; 84 | IpMode m_ipMode = IpMode::AUTO; 85 | int m_ipConnectionLimit = 0; 86 | std::unique_ptr mp_server; 87 | }; 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /static/skin/i18n/or.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Gouri", 5 | "Psubhashish" 6 | ] 7 | }, 8 | "name": "ଓଡ଼ିଆ", 9 | "suggest-full-text-search": "${{{SEARCH_TERMS}}} ଧାରଣ କରିଛି ...", 10 | "no-such-book": "ଏପରି କୌଣସି ପୁସ୍ତକ ନାହିଁଃ ${{BOOK_NAME}}", 11 | "too-many-books": "ଅତ୍ୟଧିକ ବହି ଅନୁରୋଧ (${{NB_BOOKS}}) ଯେଉଁଠାରେ ସୀମା ${{LIMIT}} |", 12 | "no-book-found": "କୌଣସି ପୁସ୍ତକ ଚଯ଼ନ ମାନଦଣ୍ଡ ସହ ମେଳ ଖାଉନାହିଁ ।", 13 | "url-not-found": "ଅନୁରୋଧ କରାଯାଇଥିବା URL \"{{url}}\" ଏହି ସର୍ଭରରେ ମିଳିଲା ନାହିଁ |", 14 | "suggest-search": "{{PATTERN}} ପାଇଁ ପୂରା ପାଠ ଖୋଜନ୍ତୁ |", 15 | "random-article-failure": "ଓହୋ! ଏକ ଅନିୟମିତ ପ୍ରବନ୍ଧ ବାଛିବାରେ ବିଫଳ :(", 16 | "invalid-raw-data-type": "{{DATATYPE}} କଞ୍ଚା ବିଷୟବସ୍ତୁ ପାଇଁ ଏକ ବ valid ଧ ଅନୁରୋଧ ନୁହେଁ |", 17 | "no-value-for-arg": "ଯୁକ୍ତି ପାଇଁ କୌଣସି ମୂଲ୍ଯ଼ ପ୍ରଦାନ କରାଯାଇନାହିଁ ${{ARGUMENT}}", 18 | "no-query": "କୌଣସି ପ୍ରଶ୍ନ ପ୍ରଦାନ କରାଯାଇନାହିଁ ।", 19 | "raw-entry-not-found": "${{DATATYPE}} ${{ENTRY}} କୁ ଖୋଜି ପାରୁନାହିଁ|", 20 | "400-page-title": "ଅବୈଧ ଅନୁରୋଧ", 21 | "400-page-heading": "ଅବୈଧ ଅନୁରୋଧ", 22 | "404-page-title": "ବିଷଯ଼ବସ୍ତୁ ମିଳୁନାହିଁ", 23 | "404-page-heading": "ମିଳିଲାନାହିଁ", 24 | "500-page-title": "ଆନ୍ତରିକ ସର୍ଭର ତୃଟି", 25 | "500-page-heading": "ଆନ୍ତରିକ ସର୍ଭର ତୃଟି", 26 | "fulltext-search-unavailable": "ପୂର୍ଣ୍ଣ ପାଠ ସନ୍ଧାନ ଉପଲବ୍ଧ ନାହିଁ |", 27 | "no-search-results": "ଏହି ବିଷୟବସ୍ତୁ ପାଇଁ ଫୁଲ୍ ଟେକ୍ସଟ୍ ସର୍ଚ୍ଚ ଇଞ୍ଜିନ୍ ଉପଲବ୍ଧ ନାହିଁ |", 28 | "library-button-text": "ସ୍ୱାଗତ ପୃଷ୍ଠାକୁ ଯାଆନ୍ତୁ |", 29 | "home-button-text": "'{{BOOK_TITLE}}' ର ମୁଖ୍ୟ ପୃଷ୍ଠାକୁ ଯାଆନ୍ତୁ |", 30 | "random-page-button-text": "ଏକ ଅନିୟମିତ ଭାବରେ ମନୋନୀତ ପୃଷ୍ଠାକୁ ଯାଆନ୍ତୁ |", 31 | "searchbox-tooltip": "'{{BOOK_TITLE}}' ସନ୍ଧାନ କରନ୍ତୁ |", 32 | "confusion-of-tongues": "ବିଭିନ୍ନ ଭାଷାରେ ଦୁଇ କିମ୍ବା ଅଧିକ ପୁସ୍ତକ ସର୍ଚ୍ଚରେ ଅଂଶଗ୍ରହଣ କରିବେ ଯାହା ବିଭ୍ରାନ୍ତିକର ଫଳାଫଳ ଆଣିପାରେ |", 33 | "welcome-page-overzealous-filter": "କୌଣସି ଫଳାଫଳ ନାହିଁ | ଆପଣ ଫିଲ୍ଟର ପୁନ res ସେଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି?", 34 | "powered-by-kiwix-html": "କିୱିକ୍ସ ଦ୍ୱାରା ଚାଳିତ |", 35 | "search": "ଖୋଜନ୍ତୁ", 36 | "book-filtering-all-categories": "ସମସ୍ତ ବର୍ଗ |", 37 | "book-filtering-all-languages": "ସମସ୍ତ ଭାଷା", 38 | "count-of-matching-books": "{{COUNT}} ପୁସ୍ତକ (ଗୁଡିକ)", 39 | "download": "ଡାଉନଲୋଡ଼", 40 | "direct-download-link-text": "ସିଧାସଳଖ |", 41 | "direct-download-alt-text": "ସିଧାସଳଖ ଡାଉନଲୋଡ୍ |", 42 | "hash-download-link-text": "Sha256 ହ୍ୟାସ୍ |", 43 | "hash-download-alt-text": "ହ୍ୟାସ୍ ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", 44 | "magnet-link-text": "ଚୁମ୍ବକୀୟ ଲିଙ୍କ୍", 45 | "magnet-alt-text": "ଚୁମ୍ବକ ଡାଉନଲୋଡ୍ କରନ୍ତୁ", 46 | "torrent-download-link-text": "ଟୋରେଣ୍ଟ ଫାଇଲ୍ |", 47 | "torrent-download-alt-text": "torrent ଡାଉନଲୋଡ୍ କରନ୍ତୁ", 48 | "library-opds-feed-all-entries": "ଲାଇବ୍ରେରୀ OPDS ଫିଡ୍ - ସମସ୍ତ ଏଣ୍ଟ୍ରିଗୁଡିକ |", 49 | "filter-by-tag": "ଟ୍ୟାଗ୍ ଦ୍ୱାରା ଫିଲ୍ଟର୍ \"{{TAG}}\"", 50 | "stop-filtering-by-tag": "\"${{TAG}}\" ଟ୍ୟାଗ୍ ଦ୍ୱାରା ଫିଲ୍ଟର କରିବା ବନ୍ଦ କରନ୍ତୁ |", 51 | "library-opds-feed-parameterised": "ଲାଇବ୍ରେରୀ OPDS ଫିଡ୍ - ଏଣ୍ଟ୍ରିଗୁଡିକ {{#LANG}}! N! ଭାଷା! ${{LANG}} ! {#TAG}} Category: ${{CATEGORY}} ଟ୍ୟାଗ୍: ${{TAG}} {{/ TAG}} {{# Q}}! ପ୍ରଶ୍ନ: {{Q}} {{/ Q}}", 52 | "welcome-to-kiwix-server": "Kiwix ସର୍ଭରକୁ ସ୍ୱାଗତ |", 53 | "download-links-heading": "${{BOOK_TITLE}} for ପାଇଁ ଲିଙ୍କ୍ ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", 54 | "download-links-title": "ବହି ଡାଉନଲୋଡ୍ କରନ୍ତୁ |", 55 | "preview-book": "ପୂର୍ବରୂପ" 56 | } 57 | -------------------------------------------------------------------------------- /static/skin/i18n/te.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Chaduvari", 5 | "Rishitha 1238", 6 | "V Bhavya" 7 | ] 8 | }, 9 | "name": "ఇంగ్లీషు", 10 | "suggest-full-text-search": "'{{{SEARCH_TERMS}}}'ని కలిగి ఉంది...", 11 | "no-such-book": "అలాంటి పుస్తకం లేదు: {{BOOK_NAME}}", 12 | "too-many-books": "పరిమితి {{LIMIT}} ఉన్న చాలా పుస్తకాలు అభ్యర్థించబడ్డాయి ({{NB_BOOKS}})", 13 | "no-book-found": "ఎంపిక ప్రమాణాలకు ఏ పుస్తకం సరిపోలలేదు", 14 | "url-not-found": "అభ్యర్థించిన URL \"{{url}}\" ఈ సర్వర్‌లో కనుగొనబడలేదు.", 15 | "suggest-search": "{{PATTERN}} కోసం పూర్తి వచన శోధన చేయండి", 16 | "random-article-failure": "అయ్యో! యాదృచ్ఛిక కథనాన్ని ఎంచుకోవడంలో విఫలమైంది :(", 17 | "invalid-raw-data-type": "ముడి కంటెంట్ కోసం {{DATATYPE}} చెల్లుబాటు అయ్యే అభ్యర్థన కాదు.", 18 | "no-value-for-arg": "ఆర్గ్యుమెంట్ {{ARGUMENT}}కి విలువ అందించబడలేదు", 19 | "no-query": "ప్రశ్న ఏదీ అందించబడలేదు.", 20 | "raw-entry-not-found": "{{DATATYPE}} ఎంట్రీ {{ENTRY}} కనుగొనబడలేదు", 21 | "400-page-title": "చెల్లని అభ్యర్థన", 22 | "400-page-heading": "చెల్లని అభ్యర్థన", 23 | "404-page-title": "కంటెంట్ కనుగొనబడలేదు", 24 | "404-page-heading": "దొరకలేదు", 25 | "500-page-title": "అంతర్గత సర్వర్ లోపం", 26 | "500-page-heading": "అంతర్గత సర్వర్ లోపం", 27 | "fulltext-search-unavailable": "పూర్తి వచన శోధన అందుబాటులో లేదు", 28 | "no-search-results": "ఈ కంటెంట్ కోసం ఫుల్‌టెక్స్ట్ శోధన ఇంజిన్ అందుబాటులో లేదు.", 29 | "library-button-text": "స్వాగత పేజీకి వెళ్లండి", 30 | "home-button-text": "'{{BOOK_TITLE}}' యొక్క ప్రధాన పేజీకి వెళ్లండి", 31 | "random-page-button-text": "యాదృచ్ఛికంగా ఎంచుకున్న పేజీకి వెళ్లండి", 32 | "searchbox-tooltip": "'{{BOOK_TITLE}}'ని శోధించండి", 33 | "confusion-of-tongues": "వివిధ భాషల్లోని రెండు లేదా అంతకంటే ఎక్కువ పుస్తకాలు శోధనలో పాల్గొంటాయి, ఇది గందరగోళ ఫలితాలకు దారితీయవచ్చు.", 34 | "welcome-page-overzealous-filter": "ఫలితం లేదు. వడపోతను రీసెట్ చేస్తారా?", 35 | "powered-by-kiwix-html": "Kiwix ద్వారా ఆధారితం", 36 | "search": "వెతుకు", 37 | "book-filtering-all-categories": "వర్గాలన్నీ", 38 | "book-filtering-all-languages": "అన్ని భాషలు", 39 | "count-of-matching-books": "{{COUNT}} పుస్తకం(లు)", 40 | "download": "డౌన్‌లోడ్", 41 | "direct-download-link-text": "డైరెక్ట్", 42 | "direct-download-alt-text": "నేరుగా డౌన్లోడ్", 43 | "hash-download-link-text": "షా256 హాష్", 44 | "hash-download-alt-text": "హాష్‌ని డౌన్‌లోడ్ చేయండి", 45 | "magnet-link-text": "మాగ్నెట్ లింక్", 46 | "magnet-alt-text": "అయస్కాంతాన్ని డౌన్‌లోడ్ చేయండి", 47 | "torrent-download-link-text": "టోరెంట్ ఫైల్", 48 | "torrent-download-alt-text": "టొరెంట్‌ని డౌన్‌లోడ్ చేయండి", 49 | "library-opds-feed-all-entries": "లైబ్రరీ OPDS ఫీడ్ - అన్ని ఎంట్రీలు", 50 | "filter-by-tag": "\"{{TAG}}\" ట్యాగ్ ద్వారా ఫిల్టర్ చేయండి", 51 | "stop-filtering-by-tag": "\"{{TAG}}\" ట్యాగ్ ద్వారా ఫిల్టర్ చేయడాన్ని ఆపివేయి", 52 | "library-opds-feed-parameterised": "లైబ్రరీ OPDS ఫీడ్ - ఎంట్రీలు సరిపోలే {{#LANG}}\nభాష: {{LANG}} {{/LANG}}{{#CATEGORY}}\nCategory: {{CATEGORY}} {{/CATEGORY}} {{#TAG}}\nట్యాగ్: {{TAG}} {{/TAG}}{{#Q}}\nప్రశ్న: {{Q}} {{/Q}}", 53 | "welcome-to-kiwix-server": "Kiwix సర్వర్‌కి స్వాగతం", 54 | "download-links-heading": "{{BOOK_TITLE}} కోసం లింక్‌లను డౌన్‌లోడ్ చేయండి", 55 | "download-links-title": "పుస్తకాన్ని డౌన్‌లోడ్ చేయండి", 56 | "preview-book": "ప్రివ్యూ" 57 | } 58 | -------------------------------------------------------------------------------- /static/skin/i18n/zh-hans.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "GuoPC", 5 | "IceButBin", 6 | "Kichin", 7 | "Peterxy12", 8 | "Prmsh", 9 | "StarrySky", 10 | "Sunai", 11 | "XtexChooser", 12 | "沈澄心" 13 | ] 14 | }, 15 | "name": "简体中文", 16 | "suggest-full-text-search": "正在查找「{{{SEARCH_TERMS}}}」…", 17 | "no-such-book": "没有名为“{{BOOK_NAME}}”的图书", 18 | "too-many-books": "请求的图书过多 ({{NB_BOOKS}}),上限为 {{LIMIT}}", 19 | "no-book-found": "没有符合搜索要求的图书", 20 | "url-not-found": "在此服务器上找不到请求的 URL:{{url}}", 21 | "suggest-search": "对{{PATTERN}}进行全文搜索", 22 | "random-article-failure": "抱歉! 随机条目失败了 (⁠〒⁠﹏⁠〒⁠)", 23 | "invalid-raw-data-type": "{{DATATYPE}} 对原请求无效。", 24 | "invalid-request": "请求的URL无效:{{{url}}}", 25 | "no-value-for-arg": "参数{{ARGUMENT}}无值", 26 | "no-query": "未提供查询。", 27 | "raw-entry-not-found": "找不到 {{DATATYPE}} 条目 {{ENTRY}}", 28 | "400-page-title": "无效请求", 29 | "400-page-heading": "无效请求", 30 | "404-page-title": "未找到内容", 31 | "404-page-heading": "未找到", 32 | "500-page-title": "内部服务器错误", 33 | "500-page-heading": "内部服务器错误", 34 | "500-page-text": "内部服务器出现错误。真的十分抱歉 (⁠;⁠ŏ⁠﹏⁠ŏ~⁠)", 35 | "fulltext-search-unavailable": "全文搜索不可用", 36 | "no-search-results": "全文搜索引擎不适用于该内容。", 37 | "search-results-page-title": "搜索:{{SEARCH_PATTERN}}", 38 | "search-results-page-header": "“{{{SEARCH_PATTERN}}}”第 {{START}}-{{END}}个结果(共{{COUNT}}个)", 39 | "empty-search-results-page-header": "未找到“{{{SEARCH_PATTERN}}}”的结果", 40 | "search-result-book-info": "来自{{BOOK_TITLE}}", 41 | "word-count": "{{COUNT}} 个字", 42 | "library-button-text": "转到欢迎页面", 43 | "home-button-text": "转到“{{{BOOK_TITLE}}}”的主页", 44 | "random-page-button-text": "前往随机选择的页面", 45 | "searchbox-tooltip": "搜索“{{{BOOK_TITLE}}}”", 46 | "confusion-of-tongues": "两本或多本不同语言的图书将同时被搜索,这可能会导致搜索结果混乱。", 47 | "welcome-page-overzealous-filter": "没有结果。您想重置过滤器吗?", 48 | "powered-by-kiwix-html": "由Kiwix提供技术支持", 49 | "search": "搜索", 50 | "book-filtering-all-categories": "所有分类", 51 | "book-filtering-all-languages": "所有语言", 52 | "count-of-matching-books": "{{COUNT}} 本书", 53 | "download": "下载", 54 | "direct-download-link-text": "直接", 55 | "direct-download-alt-text": "通过 HTTP(S) 直接下載", 56 | "hash-download-link-text": "SHA-256 校验和", 57 | "hash-download-alt-text": "显示 SHA-256 文件校验和", 58 | "magnet-link-text": "磁力链接", 59 | "magnet-alt-text": "通过磁力链接下载", 60 | "torrent-download-link-text": "BitTorrent", 61 | "torrent-download-alt-text": "通过 BitTorrent 下载", 62 | "library-opds-feed-all-entries": "图书馆 OPDS Feed - 所有条目", 63 | "filter-by-tag": "按标签“{{{TAG}}}”过滤", 64 | "stop-filtering-by-tag": "停止按标签“{{{TAG}}}”过滤", 65 | "library-opds-feed-parameterised": "图书馆 OPDS Feed - 匹配的项目 {{#LANG}}\n语言:{{LANG}} {{/LANG}}{{#CATEGORY}}\n分类:{{CATEGORY}} {{/CATEGORY}}{{#TAG}}\n标签:{{TAG}} {{/TAG}}{{#Q}}\n查询:{{Q}} {{/Q}}", 66 | "welcome-to-kiwix-server": "欢迎来到 Kiwix 服务器", 67 | "download-links-heading": "下载{{BOOK_TITLE}}的链接", 68 | "download-links-title": "下载书籍", 69 | "preview-book": "预览", 70 | "unknown-error": "未知错误", 71 | "book-category.wikibooks": "维基教科书", 72 | "book-category.wikinews": "维基新闻", 73 | "book-category.wikipedia": "维基百科", 74 | "book-category.wikiquote": "维基语录", 75 | "book-category.wikisource": "维基文库", 76 | "book-category.wikispecies": "维基物种", 77 | "book-category.wikiversity": "维基学院", 78 | "book-category.wikivoyage": "维基导游", 79 | "book-category.wiktionary": "维基词典", 80 | "book-category.other": "其他", 81 | "text-loading-content": "内容加载中" 82 | } 83 | -------------------------------------------------------------------------------- /static/skin/i18n/sc.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Kelson", 5 | "L2212" 6 | ] 7 | }, 8 | "name": "Sardu", 9 | "suggest-full-text-search": "chi cuntenet '{{{SEARCH_TERMS}}}'...", 10 | "no-such-book": "Perunu libru cun custu nùmene: {{BOOK_NAME}}", 11 | "too-many-books": "Tropu libros pedidos, {{NB_BOOKS}} cando su lìmite est de {{LIMIT}}", 12 | "no-book-found": "Perunu libru currispondet a sos critèrios de seletzione", 13 | "url-not-found": "S'URL pedidu \"{{url}}\" non s'est atzapadu in custu serbidore.", 14 | "suggest-search": "Faghe una chirca de testu intreu pro {{PATTERN}}", 15 | "random-article-failure": "Oops! Sa seletzione de un'artìculu a casu est fallida :(", 16 | "invalid-raw-data-type": "{{DATATYPE}} no est una rechesta vàlida pro cuntenutu puru.", 17 | "no-value-for-arg": "Perunu valore frunidu pro s'argumentu {{ARGUMENT}}", 18 | "no-query": "Peruna chirca frunida.", 19 | "raw-entry-not-found": "Non faghet a atzapare s'elementu {{ENTRY}} de genia {{DATATYPE}}", 20 | "400-page-title": "Rechesta non vàlida", 21 | "400-page-heading": "Rechesta non vàlida", 22 | "404-page-title": "Cuntentu no agatadu", 23 | "404-page-heading": "No agatadu", 24 | "500-page-title": "Errore internu de su serbidore", 25 | "500-page-heading": "Errore internu de su serbidore", 26 | "fulltext-search-unavailable": "Chirca de testu integrale no a disponimentu", 27 | "no-search-results": "Su motore de chirca de testu integrale no est a disponimentu pro custu cuntenutu.", 28 | "library-button-text": "Bae a sa pàgina de bene bènnidu", 29 | "home-button-text": "Bae a sa pàgina printzipale de '{{BOOK_TITLE}}'", 30 | "random-page-button-text": "Bae a una pàgina seletzionada a manera casuale", 31 | "searchbox-tooltip": "Chirca '{{BOOK_TITLE}}'", 32 | "confusion-of-tongues": "Duos o prus libros in limbas diferentes diant pigare parte a sa chirca, cosa chi diat pòdere causare resurtados confusionosos.", 33 | "welcome-page-overzealous-filter": "Perunu resurtadu. Boles resetare su filtru?", 34 | "powered-by-kiwix-html": "Alimentadu dae Kiwix", 35 | "search": "Chirca", 36 | "book-filtering-all-categories": "Totu sas categorias", 37 | "book-filtering-all-languages": "Totu sas limbas", 38 | "count-of-matching-books": "{{COUNT}} libru/os", 39 | "download": "Iscàrriga", 40 | "direct-download-link-text": "Diretu", 41 | "direct-download-alt-text": "Iscàrriga in manera direta tràmite HTTP(S)", 42 | "hash-download-link-text": "Summa de controllu SHA-256", 43 | "hash-download-alt-text": "Mustra sa summa de controllu SHA-256", 44 | "magnet-link-text": "Ligàmene Magnet", 45 | "magnet-alt-text": "Iscàrriga impreende su ligàmene Magnet", 46 | "torrent-download-link-text": "BitTorrent", 47 | "torrent-download-alt-text": "Iscàrriga impreende BitTorrent", 48 | "library-opds-feed-all-entries": "Flussu OPDS de sa biblioteca – Totu sos elementos", 49 | "filter-by-tag": "Filtra pro eticheta \"{{{TAG}}}\"", 50 | "stop-filtering-by-tag": "Non filtres prus pro eticheta \"{{{TAG}}}\"", 51 | "library-opds-feed-parameterised": "Flussu OPDS de sa biblioteca - elementos chi currispondet cun {{#LANG}}\nLimba: {{LANG}} {{/LANG}}{{#CATEGORY}}\nCategoria: {{CATEGORY}} {{/CATEGORY}}{{#TAG}}\nEticheta: {{TAG}} {{/TAG}}{{#Q}}\nChirca: {{Q}} {{/Q}}", 52 | "welcome-to-kiwix-server": "Bene bènnidu a su serbidore de Kiwix", 53 | "download-links-heading": "Ligàmenes de iscarrigamentu pro {{BOOK_TITLE}}", 54 | "download-links-title": "Iscàrriga su libru", 55 | "preview-book": "Antiprima" 56 | } 57 | --------------------------------------------------------------------------------