├── .clang-format ├── .github ├── FUNDING.yml ├── move.yml └── workflows │ ├── ci.yml │ ├── docker.yml │ └── package.yml ├── .readthedocs.yaml ├── .well-known └── funding-manifest-urls ├── AUTHORS ├── COPYING ├── Changelog ├── README.md ├── debian ├── changelog ├── control ├── copyright ├── rules └── source │ └── format ├── docker ├── Dockerfile ├── README.md └── server │ ├── Dockerfile │ ├── README.md │ ├── docker-compose.yml.example │ ├── pictures │ ├── screenshot_1.png │ └── screenshot_2.png │ └── start.sh ├── docs ├── conf.py ├── index.rst ├── kiwix-serve.rst ├── meson.build └── requirements.txt ├── format_code.sh ├── meson.build ├── meson_options.txt └── src ├── man ├── fr │ ├── kiwix-manage.1 │ ├── kiwix-serve.1 │ └── meson.build ├── kiwix-manage.1 ├── kiwix-search.1 ├── kiwix-serve.1 └── meson.build ├── manager ├── kiwix-manage.cpp └── meson.build ├── meson.build ├── searcher ├── kiwix-search.cpp └── meson.build ├── server ├── kiwix-serve.cpp └── meson.build └── version.h /.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 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: kiwix # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 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 | -------------------------------------------------------------------------------- /.github/move.yml: -------------------------------------------------------------------------------- 1 | # Configuration for Move Issues - https://github.com/dessant/move-issues 2 | 3 | # Delete the command comment when it contains no other content 4 | deleteCommand: true 5 | 6 | # Close the source issue after moving 7 | closeSourceIssue: true 8 | 9 | # Lock the source issue after moving 10 | lockSourceIssue: false 11 | 12 | # Mention issue and comment authors 13 | mentionAuthors: true 14 | 15 | # Preserve mentions in the issue content 16 | keepContentMentions: true 17 | 18 | # Move labels that also exist on the target repository 19 | moveLabels: true 20 | 21 | # Set custom aliases for targets 22 | # aliases: 23 | # r: repo 24 | # or: owner/repo 25 | 26 | # Repository to extend settings from 27 | # _extends: repo -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | Windows: 11 | runs-on: windows-2022 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v4 16 | 17 | - name: Setup Python 3.10 18 | uses: actions/setup-python@v5 19 | with: 20 | python-version: '3.10' 21 | 22 | - name: Install packages 23 | run: 24 | choco install pkgconfiglite ninja 25 | 26 | - name: Install python modules 27 | run: pip3 install meson 28 | 29 | - name: Setup MSVC compiler 30 | uses: bus1/cabuild/action/msdevshell@v1 31 | with: 32 | architecture: x64 33 | 34 | - name: Install dependencies 35 | uses: kiwix/kiwix-build/actions/dl_deps_archive@main 36 | with: 37 | target_platform: win-x86_64-static 38 | 39 | - name: Compile 40 | shell: cmd 41 | run: | 42 | set PKG_CONFIG_PATH=%cd%\BUILD_win-amd64\INSTALL\lib\pkgconfig 43 | set CPPFLAGS=-I%cd%\BUILD_win-amd64\INSTALL\include 44 | meson.exe setup . build -Dstatic-linkage=true --buildtype=release 45 | cd build 46 | ninja.exe 47 | 48 | - name: Test 49 | shell: cmd 50 | run: | 51 | cd build 52 | meson.exe test --verbose 53 | env: 54 | WAIT_TIME_FACTOR_TEST: 10 55 | 56 | Linux: 57 | runs-on: ubuntu-22.04 58 | 59 | strategy: 60 | fail-fast: false 61 | matrix: 62 | target: 63 | - linux-x86_64-static 64 | - linux-x86_64-dyn 65 | include: 66 | - target: linux-x86_64-static 67 | image_variant: focal 68 | lib_postfix: '/x86_64-linux-gnu' 69 | arch_name: linux-x86_64 70 | - target: linux-x86_64-dyn 71 | image_variant: focal 72 | lib_postfix: '/x86_64-linux-gnu' 73 | arch_name: linux-x86_64 74 | 75 | env: 76 | HOME: /home/runner 77 | 78 | container: 79 | image: "ghcr.io/kiwix/kiwix-build_ci_${{matrix.image_variant}}:36" 80 | 81 | steps: 82 | - name: Checkout code 83 | uses: actions/checkout@v4 84 | 85 | - name: Install dependencies 86 | uses: kiwix/kiwix-build/actions/dl_deps_archive@main 87 | with: 88 | target_platform: ${{ matrix.target }} 89 | 90 | - name: Compile 91 | shell: bash 92 | run: | 93 | if [[ "${{matrix.target}}" =~ .*-static ]]; then 94 | MESON_OPTION="-Dstatic-linkage=true" 95 | else 96 | MESON_OPTION="" 97 | fi 98 | if [ -e "$HOME/BUILD_${{matrix.arch_name}}/meson_cross_file.txt" ]; then 99 | MESON_OPTION="$MESON_OPTION --cross-file $HOME/BUILD_${{matrix.arch_name}}/meson_cross_file.txt" 100 | fi 101 | meson . build ${MESON_OPTION} 102 | cd build 103 | ninja 104 | env: 105 | PKG_CONFIG_PATH: "${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/lib/pkgconfig:${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/lib${{matrix.lib_postfix}}/pkgconfig" 106 | CPPFLAGS: "-I${{env.HOME}}/BUILD_${{matrix.arch_name}}/INSTALL/include" 107 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: Specific version to build (overrides on-master and tag-pattern) 8 | required: false 9 | default: '' 10 | 11 | jobs: 12 | build-and-push-kiwix-tools: 13 | name: Deploy kiwix-tools Docker Image 14 | runs-on: ubuntu-22.04 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: build and publish kiwix-tools 18 | uses: openzim/docker-publish-action@v10 19 | with: 20 | image-name: kiwix/kiwix-tools 21 | registries: ghcr.io 22 | credentials: | 23 | GHCRIO_USERNAME=${{ secrets.GHCR_USERNAME }} 24 | GHCRIO_TOKEN=${{ secrets.GHCR_TOKEN }} 25 | context: docker 26 | latest-on-tag: true 27 | build-args: 28 | VERSION={tag} 29 | platforms: | 30 | linux/amd64 31 | linux/arm64 32 | linux/arm/v7 33 | linux/arm/v6 34 | linux/386 35 | restrict-to: kiwix/kiwix-tools 36 | manual-tag: ${{ github.event.inputs.version }} 37 | repo_description: auto 38 | repo_overview: Kiwix command line tools 39 | 40 | build-and-push-kiwix-serve: 41 | name: Deploy kiwix-serve Docker Image 42 | runs-on: ubuntu-22.04 43 | needs: build-and-push-kiwix-tools 44 | steps: 45 | - uses: actions/checkout@v4 46 | - name: build and publish kiwix-serve 47 | uses: openzim/docker-publish-action@v10 48 | with: 49 | image-name: kiwix/kiwix-serve 50 | registries: ghcr.io 51 | credentials: | 52 | GHCRIO_USERNAME=${{ secrets.GHCR_USERNAME }} 53 | GHCRIO_TOKEN=${{ secrets.GHCR_TOKEN }} 54 | context: docker/server 55 | latest-on-tag: true 56 | build-args: 57 | VERSION={tag} 58 | platforms: | 59 | linux/amd64 60 | linux/arm64 61 | linux/arm/v7 62 | linux/arm/v6 63 | linux/386 64 | restrict-to: kiwix/kiwix-tools 65 | manual-tag: ${{ github.event.inputs.version }} 66 | repo_description: auto 67 | repo_overview: Kiwix web-server 68 | -------------------------------------------------------------------------------- /.github/workflows/package.yml: -------------------------------------------------------------------------------- 1 | name: Packages 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | release: 8 | types: [published] 9 | 10 | jobs: 11 | build-deb: 12 | runs-on: ubuntu-22.04 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | distro: 17 | # - debian-unstable 18 | # - debian-trixie 19 | # - debian-bookworm 20 | # - debian-bullseye 21 | - ubuntu-noble 22 | - ubuntu-jammy 23 | - ubuntu-focal 24 | 25 | steps: 26 | - uses: actions/checkout@v4 27 | 28 | # Determine which PPA we should upload to 29 | - name: PPA 30 | id: ppa 31 | run: | 32 | if [[ $REF == refs/tags* ]] 33 | then 34 | echo "ppa=kiwixteam/release" >> $GITHUB_OUTPUT 35 | else 36 | echo "ppa=kiwixteam/dev" >> $GITHUB_OUTPUT 37 | fi 38 | env: 39 | REF: ${{ github.ref }} 40 | 41 | - uses: legoktm/gh-action-auto-dch@main 42 | with: 43 | fullname: Kiwix builder 44 | email: release+launchpad@kiwix.org 45 | distro: ${{ matrix.distro }} 46 | 47 | # - uses: legoktm/gh-action-build-deb@debian-unstable 48 | # if: matrix.distro == 'debian-unstable' 49 | # name: Build package for debian-unstable 50 | # id: build-debian-unstable 51 | # with: 52 | # args: --no-sign 53 | # 54 | # - uses: legoktm/gh-action-build-deb@b47978ba8498dc8b8153cc3b5f99a5fc1afa5de1 # pin@debian-trixie 55 | # if: matrix.distro == 'debian-trixie' 56 | # name: Build package for debian-trixie 57 | # id: build-debian-trixie 58 | # with: 59 | # args: --no-sign 60 | # 61 | # - uses: legoktm/gh-action-build-deb@1f4e86a6bb34aaad388167eaf5eb85d553935336 # pin@debian-bookworm 62 | # if: matrix.distro == 'debian-bookworm' 63 | # name: Build package for debian-bookworm 64 | # id: build-debian-bookworm 65 | # with: 66 | # args: --no-sign 67 | # 68 | # - uses: legoktm/gh-action-build-deb@084b4263209252ec80a75d2c78a586192c17f18d # pin@debian-bullseye 69 | # if: matrix.distro == 'debian-bullseye' 70 | # name: Build package for debian-bullseye 71 | # id: build-debian-bullseye 72 | # with: 73 | # args: --no-sign 74 | 75 | - uses: legoktm/gh-action-build-deb@9114a536498b65c40b932209b9833aa942bf108d # pin@ubuntu-noble 76 | if: matrix.distro == 'ubuntu-noble' 77 | name: Build package for ubuntu-noble 78 | id: build-ubuntu-noble 79 | with: 80 | args: --no-sign 81 | ppa: ${{ steps.ppa.outputs.ppa }} 82 | 83 | - uses: legoktm/gh-action-build-deb@ubuntu-jammy 84 | if: matrix.distro == 'ubuntu-jammy' 85 | name: Build package for ubuntu-jammy 86 | id: build-ubuntu-jammy 87 | with: 88 | args: --no-sign 89 | ppa: ${{ steps.ppa.outputs.ppa }} 90 | 91 | - uses: legoktm/gh-action-build-deb@ubuntu-focal 92 | if: matrix.distro == 'ubuntu-focal' 93 | name: Build package for ubuntu-focal 94 | id: build-ubuntu-focal 95 | with: 96 | args: --no-sign 97 | ppa: ${{ steps.ppa.outputs.ppa }} 98 | 99 | - uses: actions/upload-artifact@v4 100 | with: 101 | name: Packages for ${{ matrix.distro }} 102 | path: output 103 | 104 | - uses: legoktm/gh-action-dput@main 105 | name: Upload dev package 106 | # Only upload on pushes to git default branch 107 | if: github.event_name == 'push' && github.event.ref == 'refs/heads/main' && startswith(matrix.distro, 'ubuntu-') 108 | with: 109 | gpg_key: ${{ secrets.LAUNCHPAD_GPG }} 110 | repository: ppa:kiwixteam/dev 111 | packages: output/*_source.changes 112 | 113 | - uses: legoktm/gh-action-dput@main 114 | name: Upload release package 115 | # Only upload on pushes to main or tag 116 | if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') && startswith(matrix.distro, 'ubuntu-') 117 | with: 118 | gpg_key: ${{ secrets.LAUNCHPAD_GPG }} 119 | repository: ppa:kiwixteam/release 120 | packages: output/*_source.changes 121 | 122 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.well-known/funding-manifest-urls: -------------------------------------------------------------------------------- 1 | https://kiwix.org/funding.json 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Emmanuel Engelhart 2 | Renaud Gaudin 3 | Christian Pühringer 4 | Fabien Coullon 5 | Guillaume Duhamel 6 | Wilfredo Rodriguez 7 | Jorge Gonzalez 8 | Richzendy 9 | Ayoub Dardory 10 | Rashiq Ahmad 11 | Isaac Hutt 12 | Elad Keyshawn 13 | Matthieu Gautier 14 | Translatewiki comunity https://translatewiki.net/wiki/Translating:Kiwix 15 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | GNU GENERAL PUBLIC LICENSE 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The GNU General Public License is a free, copyleft license for 12 | software and other kinds of works. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | the GNU General Public License is intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. We, the Free Software Foundation, use the 19 | GNU General Public License for most of our software; it applies also to 20 | any other work released this way by its authors. You can apply it to 21 | your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not 24 | price. Our General Public Licenses are designed to make sure that you 25 | have the freedom to distribute copies of free software (and charge for 26 | them if you wish), that you receive source code or can get it if you 27 | want it, that you can change the software or use pieces of it in new 28 | free programs, and that you know you can do these things. 29 | 30 | To protect your rights, we need to prevent others from denying you 31 | these rights or asking you to surrender the rights. Therefore, you have 32 | certain responsibilities if you distribute copies of the software, or if 33 | you modify it: responsibilities to respect the freedom of others. 34 | 35 | For example, if you distribute copies of such a program, whether 36 | gratis or for a fee, you must pass on to the recipients the same 37 | freedoms that you received. You must make sure that they, too, receive 38 | or can get the source code. And you must show them these terms so they 39 | know their rights. 40 | 41 | Developers that use the GNU GPL protect your rights with two steps: 42 | (1) assert copyright on the software, and (2) offer you this License 43 | giving you legal permission to copy, distribute and/or modify it. 44 | 45 | For the developers' and authors' protection, the GPL clearly explains 46 | that there is no warranty for this free software. For both users' and 47 | authors' sake, the GPL requires that modified versions be marked as 48 | changed, so that their problems will not be attributed erroneously to 49 | authors of previous versions. 50 | 51 | Some devices are designed to deny users access to install or run 52 | modified versions of the software inside them, although the manufacturer 53 | can do so. This is fundamentally incompatible with the aim of 54 | protecting users' freedom to change the software. The systematic 55 | pattern of such abuse occurs in the area of products for individuals to 56 | use, which is precisely where it is most unacceptable. Therefore, we 57 | have designed this version of the GPL to prohibit the practice for those 58 | products. If such problems arise substantially in other domains, we 59 | stand ready to extend this provision to those domains in future versions 60 | of the GPL, as needed to protect the freedom of users. 61 | 62 | Finally, every program is threatened constantly by software patents. 63 | States should not allow patents to restrict development and use of 64 | software on general-purpose computers, but in those that do, we wish to 65 | avoid the special danger that patents applied to a free program could 66 | make it effectively proprietary. To prevent this, the GPL assures that 67 | patents cannot be used to render the program non-free. 68 | 69 | The precise terms and conditions for copying, distribution and 70 | modification follow. 71 | 72 | TERMS AND CONDITIONS 73 | 74 | 0. Definitions. 75 | 76 | "This License" refers to version 3 of the GNU General Public License. 77 | 78 | "Copyright" also means copyright-like laws that apply to other kinds of 79 | works, such as semiconductor masks. 80 | 81 | "The Program" refers to any copyrightable work licensed under this 82 | License. Each licensee is addressed as "you". "Licensees" and 83 | "recipients" may be individuals or organizations. 84 | 85 | To "modify" a work means to copy from or adapt all or part of the work 86 | in a fashion requiring copyright permission, other than the making of an 87 | exact copy. The resulting work is called a "modified version" of the 88 | earlier work or a work "based on" the earlier work. 89 | 90 | A "covered work" means either the unmodified Program or a work based 91 | on the Program. 92 | 93 | To "propagate" a work means to do anything with it that, without 94 | permission, would make you directly or secondarily liable for 95 | infringement under applicable copyright law, except executing it on a 96 | computer or modifying a private copy. Propagation includes copying, 97 | distribution (with or without modification), making available to the 98 | public, and in some countries other activities as well. 99 | 100 | To "convey" a work means any kind of propagation that enables other 101 | parties to make or receive copies. Mere interaction with a user through 102 | a computer network, with no transfer of a copy, is not conveying. 103 | 104 | An interactive user interface displays "Appropriate Legal Notices" 105 | to the extent that it includes a convenient and prominently visible 106 | feature that (1) displays an appropriate copyright notice, and (2) 107 | tells the user that there is no warranty for the work (except to the 108 | extent that warranties are provided), that licensees may convey the 109 | work under this License, and how to view a copy of this License. If 110 | the interface presents a list of user commands or options, such as a 111 | menu, a prominent item in the list meets this criterion. 112 | 113 | 1. Source Code. 114 | 115 | The "source code" for a work means the preferred form of the work 116 | for making modifications to it. "Object code" means any non-source 117 | form of a work. 118 | 119 | A "Standard Interface" means an interface that either is an official 120 | standard defined by a recognized standards body, or, in the case of 121 | interfaces specified for a particular programming language, one that 122 | is widely used among developers working in that language. 123 | 124 | The "System Libraries" of an executable work include anything, other 125 | than the work as a whole, that (a) is included in the normal form of 126 | packaging a Major Component, but which is not part of that Major 127 | Component, and (b) serves only to enable use of the work with that 128 | Major Component, or to implement a Standard Interface for which an 129 | implementation is available to the public in source code form. A 130 | "Major Component", in this context, means a major essential component 131 | (kernel, window system, and so on) of the specific operating system 132 | (if any) on which the executable work runs, or a compiler used to 133 | produce the work, or an object code interpreter used to run it. 134 | 135 | The "Corresponding Source" for a work in object code form means all 136 | the source code needed to generate, install, and (for an executable 137 | work) run the object code and to modify the work, including scripts to 138 | control those activities. However, it does not include the work's 139 | System Libraries, or general-purpose tools or generally available free 140 | programs which are used unmodified in performing those activities but 141 | which are not part of the work. For example, Corresponding Source 142 | includes interface definition files associated with source files for 143 | the work, and the source code for shared libraries and dynamically 144 | linked subprograms that the work is specifically designed to require, 145 | such as by intimate data communication or control flow between those 146 | subprograms and other parts of the work. 147 | 148 | The Corresponding Source need not include anything that users 149 | can regenerate automatically from other parts of the Corresponding 150 | Source. 151 | 152 | The Corresponding Source for a work in source code form is that 153 | same work. 154 | 155 | 2. Basic Permissions. 156 | 157 | All rights granted under this License are granted for the term of 158 | copyright on the Program, and are irrevocable provided the stated 159 | conditions are met. This License explicitly affirms your unlimited 160 | permission to run the unmodified Program. The output from running a 161 | covered work is covered by this License only if the output, given its 162 | content, constitutes a covered work. This License acknowledges your 163 | rights of fair use or other equivalent, as provided by copyright law. 164 | 165 | You may make, run and propagate covered works that you do not 166 | convey, without conditions so long as your license otherwise remains 167 | in force. You may convey covered works to others for the sole purpose 168 | of having them make modifications exclusively for you, or provide you 169 | with facilities for running those works, provided that you comply with 170 | the terms of this License in conveying all material for which you do 171 | not control copyright. Those thus making or running the covered works 172 | for you must do so exclusively on your behalf, under your direction 173 | and control, on terms that prohibit them from making any copies of 174 | your copyrighted material outside their relationship with you. 175 | 176 | Conveying under any other circumstances is permitted solely under 177 | the conditions stated below. Sublicensing is not allowed; section 10 178 | makes it unnecessary. 179 | 180 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 181 | 182 | No covered work shall be deemed part of an effective technological 183 | measure under any applicable law fulfilling obligations under article 184 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 185 | similar laws prohibiting or restricting circumvention of such 186 | measures. 187 | 188 | When you convey a covered work, you waive any legal power to forbid 189 | circumvention of technological measures to the extent such circumvention 190 | is effected by exercising rights under this License with respect to 191 | the covered work, and you disclaim any intention to limit operation or 192 | modification of the work as a means of enforcing, against the work's 193 | users, your or third parties' legal rights to forbid circumvention of 194 | technological measures. 195 | 196 | 4. Conveying Verbatim Copies. 197 | 198 | You may convey verbatim copies of the Program's source code as you 199 | receive it, in any medium, provided that you conspicuously and 200 | appropriately publish on each copy an appropriate copyright notice; 201 | keep intact all notices stating that this License and any 202 | non-permissive terms added in accord with section 7 apply to the code; 203 | keep intact all notices of the absence of any warranty; and give all 204 | recipients a copy of this License along with the Program. 205 | 206 | You may charge any price or no price for each copy that you convey, 207 | and you may offer support or warranty protection for a fee. 208 | 209 | 5. Conveying Modified Source Versions. 210 | 211 | You may convey a work based on the Program, or the modifications to 212 | produce it from the Program, in the form of source code under the 213 | terms of section 4, provided that you also meet all of these conditions: 214 | 215 | a) The work must carry prominent notices stating that you modified 216 | it, and giving a relevant date. 217 | 218 | b) The work must carry prominent notices stating that it is 219 | released under this License and any conditions added under section 220 | 7. This requirement modifies the requirement in section 4 to 221 | "keep intact all notices". 222 | 223 | c) You must license the entire work, as a whole, under this 224 | License to anyone who comes into possession of a copy. This 225 | License will therefore apply, along with any applicable section 7 226 | additional terms, to the whole of the work, and all its parts, 227 | regardless of how they are packaged. This License gives no 228 | permission to license the work in any other way, but it does not 229 | invalidate such permission if you have separately received it. 230 | 231 | d) If the work has interactive user interfaces, each must display 232 | Appropriate Legal Notices; however, if the Program has interactive 233 | interfaces that do not display Appropriate Legal Notices, your 234 | work need not make them do so. 235 | 236 | A compilation of a covered work with other separate and independent 237 | works, which are not by their nature extensions of the covered work, 238 | and which are not combined with it such as to form a larger program, 239 | in or on a volume of a storage or distribution medium, is called an 240 | "aggregate" if the compilation and its resulting copyright are not 241 | used to limit the access or legal rights of the compilation's users 242 | beyond what the individual works permit. Inclusion of a covered work 243 | in an aggregate does not cause this License to apply to the other 244 | parts of the aggregate. 245 | 246 | 6. Conveying Non-Source Forms. 247 | 248 | You may convey a covered work in object code form under the terms 249 | of sections 4 and 5, provided that you also convey the 250 | machine-readable Corresponding Source under the terms of this License, 251 | in one of these ways: 252 | 253 | a) Convey the object code in, or embodied in, a physical product 254 | (including a physical distribution medium), accompanied by the 255 | Corresponding Source fixed on a durable physical medium 256 | customarily used for software interchange. 257 | 258 | b) Convey the object code in, or embodied in, a physical product 259 | (including a physical distribution medium), accompanied by a 260 | written offer, valid for at least three years and valid for as 261 | long as you offer spare parts or customer support for that product 262 | model, to give anyone who possesses the object code either (1) a 263 | copy of the Corresponding Source for all the software in the 264 | product that is covered by this License, on a durable physical 265 | medium customarily used for software interchange, for a price no 266 | more than your reasonable cost of physically performing this 267 | conveying of source, or (2) access to copy the 268 | Corresponding Source from a network server at no charge. 269 | 270 | c) Convey individual copies of the object code with a copy of the 271 | written offer to provide the Corresponding Source. This 272 | alternative is allowed only occasionally and noncommercially, and 273 | only if you received the object code with such an offer, in accord 274 | with subsection 6b. 275 | 276 | d) Convey the object code by offering access from a designated 277 | place (gratis or for a charge), and offer equivalent access to the 278 | Corresponding Source in the same way through the same place at no 279 | further charge. You need not require recipients to copy the 280 | Corresponding Source along with the object code. If the place to 281 | copy the object code is a network server, the Corresponding Source 282 | may be on a different server (operated by you or a third party) 283 | that supports equivalent copying facilities, provided you maintain 284 | clear directions next to the object code saying where to find the 285 | Corresponding Source. Regardless of what server hosts the 286 | Corresponding Source, you remain obligated to ensure that it is 287 | available for as long as needed to satisfy these requirements. 288 | 289 | e) Convey the object code using peer-to-peer transmission, provided 290 | you inform other peers where the object code and Corresponding 291 | Source of the work are being offered to the general public at no 292 | charge under subsection 6d. 293 | 294 | A separable portion of the object code, whose source code is excluded 295 | from the Corresponding Source as a System Library, need not be 296 | included in conveying the object code work. 297 | 298 | A "User Product" is either (1) a "consumer product", which means any 299 | tangible personal property which is normally used for personal, family, 300 | or household purposes, or (2) anything designed or sold for incorporation 301 | into a dwelling. In determining whether a product is a consumer product, 302 | doubtful cases shall be resolved in favor of coverage. For a particular 303 | product received by a particular user, "normally used" refers to a 304 | typical or common use of that class of product, regardless of the status 305 | of the particular user or of the way in which the particular user 306 | actually uses, or expects or is expected to use, the product. A product 307 | is a consumer product regardless of whether the product has substantial 308 | commercial, industrial or non-consumer uses, unless such uses represent 309 | the only significant mode of use of the product. 310 | 311 | "Installation Information" for a User Product means any methods, 312 | procedures, authorization keys, or other information required to install 313 | and execute modified versions of a covered work in that User Product from 314 | a modified version of its Corresponding Source. The information must 315 | suffice to ensure that the continued functioning of the modified object 316 | code is in no case prevented or interfered with solely because 317 | modification has been made. 318 | 319 | If you convey an object code work under this section in, or with, or 320 | specifically for use in, a User Product, and the conveying occurs as 321 | part of a transaction in which the right of possession and use of the 322 | User Product is transferred to the recipient in perpetuity or for a 323 | fixed term (regardless of how the transaction is characterized), the 324 | Corresponding Source conveyed under this section must be accompanied 325 | by the Installation Information. But this requirement does not apply 326 | if neither you nor any third party retains the ability to install 327 | modified object code on the User Product (for example, the work has 328 | been installed in ROM). 329 | 330 | The requirement to provide Installation Information does not include a 331 | requirement to continue to provide support service, warranty, or updates 332 | for a work that has been modified or installed by the recipient, or for 333 | the User Product in which it has been modified or installed. Access to a 334 | network may be denied when the modification itself materially and 335 | adversely affects the operation of the network or violates the rules and 336 | protocols for communication across the network. 337 | 338 | Corresponding Source conveyed, and Installation Information provided, 339 | in accord with this section must be in a format that is publicly 340 | documented (and with an implementation available to the public in 341 | source code form), and must require no special password or key for 342 | unpacking, reading or copying. 343 | 344 | 7. Additional Terms. 345 | 346 | "Additional permissions" are terms that supplement the terms of this 347 | License by making exceptions from one or more of its conditions. 348 | Additional permissions that are applicable to the entire Program shall 349 | be treated as though they were included in this License, to the extent 350 | that they are valid under applicable law. If additional permissions 351 | apply only to part of the Program, that part may be used separately 352 | under those permissions, but the entire Program remains governed by 353 | this License without regard to the additional permissions. 354 | 355 | When you convey a copy of a covered work, you may at your option 356 | remove any additional permissions from that copy, or from any part of 357 | it. (Additional permissions may be written to require their own 358 | removal in certain cases when you modify the work.) You may place 359 | additional permissions on material, added by you to a covered work, 360 | for which you have or can give appropriate copyright permission. 361 | 362 | Notwithstanding any other provision of this License, for material you 363 | add to a covered work, you may (if authorized by the copyright holders of 364 | that material) supplement the terms of this License with terms: 365 | 366 | a) Disclaiming warranty or limiting liability differently from the 367 | terms of sections 15 and 16 of this License; or 368 | 369 | b) Requiring preservation of specified reasonable legal notices or 370 | author attributions in that material or in the Appropriate Legal 371 | Notices displayed by works containing it; or 372 | 373 | c) Prohibiting misrepresentation of the origin of that material, or 374 | requiring that modified versions of such material be marked in 375 | reasonable ways as different from the original version; or 376 | 377 | d) Limiting the use for publicity purposes of names of licensors or 378 | authors of the material; or 379 | 380 | e) Declining to grant rights under trademark law for use of some 381 | trade names, trademarks, or service marks; or 382 | 383 | f) Requiring indemnification of licensors and authors of that 384 | material by anyone who conveys the material (or modified versions of 385 | it) with contractual assumptions of liability to the recipient, for 386 | any liability that these contractual assumptions directly impose on 387 | those licensors and authors. 388 | 389 | All other non-permissive additional terms are considered "further 390 | restrictions" within the meaning of section 10. If the Program as you 391 | received it, or any part of it, contains a notice stating that it is 392 | governed by this License along with a term that is a further 393 | restriction, you may remove that term. If a license document contains 394 | a further restriction but permits relicensing or conveying under this 395 | License, you may add to a covered work material governed by the terms 396 | of that license document, provided that the further restriction does 397 | not survive such relicensing or conveying. 398 | 399 | If you add terms to a covered work in accord with this section, you 400 | must place, in the relevant source files, a statement of the 401 | additional terms that apply to those files, or a notice indicating 402 | where to find the applicable terms. 403 | 404 | Additional terms, permissive or non-permissive, may be stated in the 405 | form of a separately written license, or stated as exceptions; 406 | the above requirements apply either way. 407 | 408 | 8. Termination. 409 | 410 | You may not propagate or modify a covered work except as expressly 411 | provided under this License. Any attempt otherwise to propagate or 412 | modify it is void, and will automatically terminate your rights under 413 | this License (including any patent licenses granted under the third 414 | paragraph of section 11). 415 | 416 | However, if you cease all violation of this License, then your 417 | license from a particular copyright holder is reinstated (a) 418 | provisionally, unless and until the copyright holder explicitly and 419 | finally terminates your license, and (b) permanently, if the copyright 420 | holder fails to notify you of the violation by some reasonable means 421 | prior to 60 days after the cessation. 422 | 423 | Moreover, your license from a particular copyright holder is 424 | reinstated permanently if the copyright holder notifies you of the 425 | violation by some reasonable means, this is the first time you have 426 | received notice of violation of this License (for any work) from that 427 | copyright holder, and you cure the violation prior to 30 days after 428 | your receipt of the notice. 429 | 430 | Termination of your rights under this section does not terminate the 431 | licenses of parties who have received copies or rights from you under 432 | this License. If your rights have been terminated and not permanently 433 | reinstated, you do not qualify to receive new licenses for the same 434 | material under section 10. 435 | 436 | 9. Acceptance Not Required for Having Copies. 437 | 438 | You are not required to accept this License in order to receive or 439 | run a copy of the Program. Ancillary propagation of a covered work 440 | occurring solely as a consequence of using peer-to-peer transmission 441 | to receive a copy likewise does not require acceptance. However, 442 | nothing other than this License grants you permission to propagate or 443 | modify any covered work. These actions infringe copyright if you do 444 | not accept this License. Therefore, by modifying or propagating a 445 | covered work, you indicate your acceptance of this License to do so. 446 | 447 | 10. Automatic Licensing of Downstream Recipients. 448 | 449 | Each time you convey a covered work, the recipient automatically 450 | receives a license from the original licensors, to run, modify and 451 | propagate that work, subject to this License. You are not responsible 452 | for enforcing compliance by third parties with this License. 453 | 454 | An "entity transaction" is a transaction transferring control of an 455 | organization, or substantially all assets of one, or subdividing an 456 | organization, or merging organizations. If propagation of a covered 457 | work results from an entity transaction, each party to that 458 | transaction who receives a copy of the work also receives whatever 459 | licenses to the work the party's predecessor in interest had or could 460 | give under the previous paragraph, plus a right to possession of the 461 | Corresponding Source of the work from the predecessor in interest, if 462 | the predecessor has it or can get it with reasonable efforts. 463 | 464 | You may not impose any further restrictions on the exercise of the 465 | rights granted or affirmed under this License. For example, you may 466 | not impose a license fee, royalty, or other charge for exercise of 467 | rights granted under this License, and you may not initiate litigation 468 | (including a cross-claim or counterclaim in a lawsuit) alleging that 469 | any patent claim is infringed by making, using, selling, offering for 470 | sale, or importing the Program or any portion of it. 471 | 472 | 11. Patents. 473 | 474 | A "contributor" is a copyright holder who authorizes use under this 475 | License of the Program or a work on which the Program is based. The 476 | work thus licensed is called the contributor's "contributor version". 477 | 478 | A contributor's "essential patent claims" are all patent claims 479 | owned or controlled by the contributor, whether already acquired or 480 | hereafter acquired, that would be infringed by some manner, permitted 481 | by this License, of making, using, or selling its contributor version, 482 | but do not include claims that would be infringed only as a 483 | consequence of further modification of the contributor version. For 484 | purposes of this definition, "control" includes the right to grant 485 | patent sublicenses in a manner consistent with the requirements of 486 | this License. 487 | 488 | Each contributor grants you a non-exclusive, worldwide, royalty-free 489 | patent license under the contributor's essential patent claims, to 490 | make, use, sell, offer for sale, import and otherwise run, modify and 491 | propagate the contents of its contributor version. 492 | 493 | In the following three paragraphs, a "patent license" is any express 494 | agreement or commitment, however denominated, not to enforce a patent 495 | (such as an express permission to practice a patent or covenant not to 496 | sue for patent infringement). To "grant" such a patent license to a 497 | party means to make such an agreement or commitment not to enforce a 498 | patent against the party. 499 | 500 | If you convey a covered work, knowingly relying on a patent license, 501 | and the Corresponding Source of the work is not available for anyone 502 | to copy, free of charge and under the terms of this License, through a 503 | publicly available network server or other readily accessible means, 504 | then you must either (1) cause the Corresponding Source to be so 505 | available, or (2) arrange to deprive yourself of the benefit of the 506 | patent license for this particular work, or (3) arrange, in a manner 507 | consistent with the requirements of this License, to extend the patent 508 | license to downstream recipients. "Knowingly relying" means you have 509 | actual knowledge that, but for the patent license, your conveying the 510 | covered work in a country, or your recipient's use of the covered work 511 | in a country, would infringe one or more identifiable patents in that 512 | country that you have reason to believe are valid. 513 | 514 | If, pursuant to or in connection with a single transaction or 515 | arrangement, you convey, or propagate by procuring conveyance of, a 516 | covered work, and grant a patent license to some of the parties 517 | receiving the covered work authorizing them to use, propagate, modify 518 | or convey a specific copy of the covered work, then the patent license 519 | you grant is automatically extended to all recipients of the covered 520 | work and works based on it. 521 | 522 | A patent license is "discriminatory" if it does not include within 523 | the scope of its coverage, prohibits the exercise of, or is 524 | conditioned on the non-exercise of one or more of the rights that are 525 | specifically granted under this License. You may not convey a covered 526 | work if you are a party to an arrangement with a third party that is 527 | in the business of distributing software, under which you make payment 528 | to the third party based on the extent of your activity of conveying 529 | the work, and under which the third party grants, to any of the 530 | parties who would receive the covered work from you, a discriminatory 531 | patent license (a) in connection with copies of the covered work 532 | conveyed by you (or copies made from those copies), or (b) primarily 533 | for and in connection with specific products or compilations that 534 | contain the covered work, unless you entered into that arrangement, 535 | or that patent license was granted, prior to 28 March 2007. 536 | 537 | Nothing in this License shall be construed as excluding or limiting 538 | any implied license or other defenses to infringement that may 539 | otherwise be available to you under applicable patent law. 540 | 541 | 12. No Surrender of Others' Freedom. 542 | 543 | If conditions are imposed on you (whether by court order, agreement or 544 | otherwise) that contradict the conditions of this License, they do not 545 | excuse you from the conditions of this License. If you cannot convey a 546 | covered work so as to satisfy simultaneously your obligations under this 547 | License and any other pertinent obligations, then as a consequence you may 548 | not convey it at all. For example, if you agree to terms that obligate you 549 | to collect a royalty for further conveying from those to whom you convey 550 | the Program, the only way you could satisfy both those terms and this 551 | License would be to refrain entirely from conveying the Program. 552 | 553 | 13. Use with the GNU Affero General Public License. 554 | 555 | Notwithstanding any other provision of this License, you have 556 | permission to link or combine any covered work with a work licensed 557 | under version 3 of the GNU Affero General Public License into a single 558 | combined work, and to convey the resulting work. The terms of this 559 | License will continue to apply to the part which is the covered work, 560 | but the special requirements of the GNU Affero General Public License, 561 | section 13, concerning interaction through a network will apply to the 562 | combination as such. 563 | 564 | 14. Revised Versions of this License. 565 | 566 | The Free Software Foundation may publish revised and/or new versions of 567 | the GNU General Public License from time to time. Such new versions will 568 | be similar in spirit to the present version, but may differ in detail to 569 | address new problems or concerns. 570 | 571 | Each version is given a distinguishing version number. If the 572 | Program specifies that a certain numbered version of the GNU General 573 | Public License "or any later version" applies to it, you have the 574 | option of following the terms and conditions either of that numbered 575 | version or of any later version published by the Free Software 576 | Foundation. If the Program does not specify a version number of the 577 | GNU General Public License, you may choose any version ever published 578 | by the Free Software Foundation. 579 | 580 | If the Program specifies that a proxy can decide which future 581 | versions of the GNU General Public License can be used, that proxy's 582 | public statement of acceptance of a version permanently authorizes you 583 | to choose that version for the Program. 584 | 585 | Later license versions may give you additional or different 586 | permissions. However, no additional obligations are imposed on any 587 | author or copyright holder as a result of your choosing to follow a 588 | later version. 589 | 590 | 15. Disclaimer of Warranty. 591 | 592 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 593 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 594 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 595 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 596 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 597 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 598 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 599 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 600 | 601 | 16. Limitation of Liability. 602 | 603 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 604 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 605 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 606 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 607 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 608 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 609 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 610 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 611 | SUCH DAMAGES. 612 | 613 | 17. Interpretation of Sections 15 and 16. 614 | 615 | If the disclaimer of warranty and limitation of liability provided 616 | above cannot be given local legal effect according to their terms, 617 | reviewing courts shall apply local law that most closely approximates 618 | an absolute waiver of all civil liability in connection with the 619 | Program, unless a warranty or assumption of liability accompanies a 620 | copy of the Program in return for a fee. 621 | 622 | END OF TERMS AND CONDITIONS 623 | 624 | How to Apply These Terms to Your New Programs 625 | 626 | If you develop a new program, and you want it to be of the greatest 627 | possible use to the public, the best way to achieve this is to make it 628 | free software which everyone can redistribute and change under these terms. 629 | 630 | To do so, attach the following notices to the program. It is safest 631 | to attach them to the start of each source file to most effectively 632 | state the exclusion of warranty; and each file should have at least 633 | the "copyright" line and a pointer to where the full notice is found. 634 | 635 | 636 | Copyright (C) 637 | 638 | This program is free software: you can redistribute it and/or modify 639 | it under the terms of the GNU General Public License as published by 640 | the Free Software Foundation, either version 3 of the License, or 641 | (at your option) any later version. 642 | 643 | This program is distributed in the hope that it will be useful, 644 | but WITHOUT ANY WARRANTY; without even the implied warranty of 645 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 646 | GNU General Public License for more details. 647 | 648 | You should have received a copy of the GNU General Public License 649 | along with this program. If not, see . 650 | 651 | Also add information on how to contact you by electronic and paper mail. 652 | 653 | If the program does terminal interaction, make it output a short 654 | notice like this when it starts in an interactive mode: 655 | 656 | Copyright (C) 657 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 658 | This is free software, and you are welcome to redistribute it 659 | under certain conditions; type `show c' for details. 660 | 661 | The hypothetical commands `show w' and `show c' should show the appropriate 662 | parts of the General Public License. Of course, your program's commands 663 | might be different; for a GUI interface, you would use an "about box". 664 | 665 | You should also get your employer (if you work as a programmer) or school, 666 | if any, to sign a "copyright disclaimer" for the program, if necessary. 667 | For more information on this, and how to apply and follow the GNU GPL, see 668 | . 669 | 670 | The GNU General Public License does not permit incorporating your program 671 | into proprietary programs. If your program is a subroutine library, you 672 | may consider it more useful to permit linking proprietary applications with 673 | the library. If this is what you want to do, use the GNU Lesser General 674 | Public License instead of this License. But first, please read 675 | . 676 | 677 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | kiwix-tools 3.7.0 2 | ================= 3 | 4 | * Fixed ZIM name vs Book name confusion in documentation (@veloman-yunkan #663) 5 | * Fixes compilation dependencies to rely on appropriate version (@kelson42 #667) 6 | * New --skipInvalid Kiwix Server command line option (@schuellerf @kelson42 #666) 7 | 8 | kiwix-tools 3.6.0 9 | ================= 10 | 11 | * Improved kiwix-serve man page (@iArchitSharma #626) 12 | * C++17 compliant code base (@mgautierfr #636) 13 | * Support of libkiwix13 (@mgautierfr #633) 14 | * Additional docker images archs for armv6 and i386 (@rgaudin #622) 15 | 16 | kiwix-tools 3.5.0 17 | ================= 18 | 19 | * Do not use `--static` option when compiling on MacOs (@mgautierfr #615) 20 | * Move main branch from `master` to `main`. 21 | * Fix docker image (@jacroe #597) 22 | * Various CI improvements (@kelson42) 23 | 24 | kiwix-serve 25 | ----------- 26 | 27 | * Add documentation about the kiwix-serve API (@veloman-yunkan #586) 28 | https://kiwix-tools.readthedocs.io/en/latest/kiwix-serve.html#http-api 29 | 30 | kiwix-tools 3.4.0 31 | ================= 32 | 33 | * Remove last reference to kiwix-read tool (@legoktm #569) 34 | 35 | kiwix-serve 36 | ----------- 37 | 38 | * Fix broken indentation in usage (@kelson42 #560) 39 | * Exit if wrong arguments are passed (@kelson42 #567) 40 | * Do not allow multiple values for same option (@juuz0 #564) 41 | * Fix default location of "rootLocation" (@rgaudin #571) 42 | * [DOCKER] Change default port to 8080 (@neyder #581) 43 | * [DOCKER] Simplify dockerfile (@rgaudin #582) 44 | 45 | kiwix-manage 46 | ------------ 47 | 48 | * Fix man page (@kelson42 #576) 49 | 50 | kiwix-tools 3.3.0 51 | ================= 52 | 53 | * Remove kiwix-read tool (@veloman-yunkan #535) 54 | 55 | kiwix-serve 56 | ----------- 57 | 58 | * Add an option to limit the number of connections for a same IP (@juuz0 #534) 59 | * Add an option to limit the number of zim in a multizim fulltext search (@mgautierfr #558) 60 | 61 | kiwix-search 62 | ------------ 63 | 64 | * Remove usage of libkiwix's deprecated api (@veloman-yunkan #535) 65 | 66 | kiwix-manage 67 | ------------ 68 | 69 | * Correctly return a value !0 if something went wrong (@mgautierfr #553) 70 | 71 | 72 | kiwix-tools 3.2.0 73 | ================= 74 | 75 | * Print the version of all dependencies (@kelson42 #516) 76 | * Better Docker images (@kelson42 @rgaudin) 77 | * Update Readme (@kelson42) 78 | * Build debian packages on CI (@legoktm #394) 79 | * Add man pages for kiwix-read and kiwix-search (@legoktm #392) 80 | * Various fixes (@legoktm @hashworks @mgautierfr) 81 | 82 | 83 | kiwix-serve 84 | ----------- 85 | 86 | * Print the url on which a user can connect to on startup (@juuz0 #499 #522) 87 | * Reload library on SIGHUP signal (@veloman-yunkan #497) 88 | * Add a option `--monitorLibrary` to monitor and automically reload the library 89 | (@veloman-yunkan #503) 90 | * Correct handling of SIGTERM and SIGINT (@veloman-yunkan #488) 91 | * Add `--customIndexTemplate` option (@manan #477) 92 | * Add `--help` option (@kelson42 #511) 93 | 94 | 95 | kiwix-tools 3.1.2 96 | ================= 97 | 98 | * Use new threadsafe API of kiwix-lib to do suggestions search. 99 | 100 | kiwix-tools 3.1.1 101 | ================= 102 | 103 | * Fix compilation on Windows' CI 104 | 105 | kiwix-tools 3.1.0 106 | ================= 107 | 108 | * [SERVER] Add option to block external links 109 | 110 | kiwix-tools 3.0.3 111 | ================= 112 | 113 | * [MANAGER] Fix broken --version argument parsing 114 | 115 | kiwix-tools 3.0.2 116 | ================= 117 | 118 | * New option --version for all tools 119 | * Remove benchmark.sh file. 120 | * [DOCKER] Add ability to download a file at container start. 121 | * [CI] Move to github actions instead of travis. 122 | * [SERVER] Trust the given library by default. 123 | * [SERVER] Add shortcut alias for option `--address` and `--nodatealias` 124 | 125 | kiwix-tools 3.0.1 126 | ================= 127 | 128 | * Fix --nodatealiases inverted logic regression 129 | 130 | kiwix-tools 3.0.0 131 | ================= 132 | 133 | * Move kiwix-serve implementation in kiwix-lib. 134 | 135 | kiwix-tools 2.1.0 136 | ================= 137 | 138 | * Fix few compilation errors. 139 | 140 | kiwix-serve 141 | ----------- 142 | 143 | * Use new api to filter the library. 144 | * Mobile friendly top bar. 145 | * Add notag parameter to be able to exclude tags from the zim search. 146 | 147 | 148 | kiwix-tools 2.0.0 149 | ================= 150 | 151 | kiwix-manage 152 | ----------- 153 | 154 | * Better usage() 155 | * Adding multiple files bug fix 156 | * Remove download command. 157 | 158 | kiwix-serve 159 | ----------- 160 | 161 | * Better usage() 162 | * Display properly welcome page on 3 columns 163 | * New welcome page footer "Powered by Kiwix" 164 | 165 | kiwix-tools 1.2.1 166 | ================= 167 | 168 | kiwix-serve 169 | ----------- 170 | 171 | * Always use POLL when avaible. 172 | 173 | kiwix-tools 1.2.0 174 | ================= 175 | 176 | * Remove rpath for installed binaries. 177 | 178 | kiwix-serve 179 | ----------- 180 | 181 | * New Dockerfile of kiwix-serve 182 | * New --nodatealiases option 183 | * Do not use POLL on windows 184 | 185 | kiwix-manage 186 | ------------ 187 | 188 | * Do not show all books if book ids has been provided. 189 | * Be able to add several zim files in the same time in a library. 190 | 191 | kiwix-tools 1.1.0 192 | ================= 193 | 194 | kiwix-serve 195 | ----------- 196 | 197 | * Fix bug about handling of absolute url in old zim file. 198 | * All the catalog to be searched by tags. 199 | 200 | kiwix-tools 1.0.0 201 | ================= 202 | 203 | * [CI] Use the new deps archive xz 204 | * Move version 1.0.0. There is no need to stay in pre 1.0 version. 205 | 206 | kiwix-serve 207 | ----------- 208 | 209 | * Correctly implement redirection. 210 | kiwix-serve now return a 302 http status code instead of resolving the 211 | redirection internally and return the content. 212 | 213 | 214 | kiwix-tools 0.9.0 215 | ================= 216 | 217 | * Update README 218 | * Update man pages 219 | * Remove support of external indexes (manage, search, serve) 220 | * Update build system as we don't use ctpp2 anymore 221 | * Update to last kiwix-lib API. 222 | 223 | kiwix-manage 224 | ------------ 225 | 226 | * Update usage. 227 | 228 | 229 | kiwix-tools 0.8.0 230 | ================= 231 | 232 | kiwix-manage 233 | ------------ 234 | 235 | * Be able to remove several books from the library in one command. 236 | 237 | kiwix-tools 0.7.0 238 | ================= 239 | 240 | * Adapt to kiwix-lib new API 241 | 242 | kiwix-serve 243 | ----------- 244 | 245 | * Dumps only valid books in the opdsfeed. 246 | * Allow the opds feed to be filtered by lang and paginated. 247 | 248 | kiwix-manage 249 | ------------ 250 | 251 | * Add a download command to download a remote book locally 252 | * Book are referenced by bookId not index. 253 | * No more indexType option as it is always XAPIAN. 254 | 255 | kiwix-tools 0.6.1 256 | ================= 257 | 258 | kiwix-serve 259 | ----------- 260 | 261 | * Update README. 262 | * Fix crash when `--library` flag is provided without value. 263 | * Correctly handle mimetype of file without extension on 64bits. 264 | * Minor fixes 265 | 266 | kiwix-tools 0.6.0 267 | ================= 268 | 269 | * remove kiwix-install tool. 270 | 271 | kiwix-serve 272 | ----------- 273 | 274 | * Improved taskbar #160 275 | * Fix global page when using the option `--nosearchbar` 276 | * Return 404 for missing resources 277 | * Fix compilation for gcc 4.8. 278 | 279 | kiwix-manage 280 | ------------ 281 | 282 | * Returns proper exit code (not always 0) 283 | 284 | 285 | kiwix-tools 0.5.0 286 | ================= 287 | 288 | * Build kiwix-tools setting the RPATH 289 | * Compile without warning. 290 | 291 | 292 | kiwix-serve 293 | ------------ 294 | 295 | * Serve metadata information using the "/meta" url. 296 | * Serve an OPDS stream of all zim handled by kiwix-serve 297 | All informations cannot be infer from the zim file itself, 298 | you should use a library.xml to provide needed information (url, ...) 299 | * Update kiwix-serve to use the new API of kiwix-lib 300 | 301 | kiwix-tools 0.4.0 302 | ================= 303 | 304 | * Use gcc-5 on travis. 305 | 306 | kiwix-serve 307 | ----------- 308 | 309 | * Accept zim file with `&` in the name 310 | * Do not cache (on client side) global search (as it can depends on the zim 311 | files handled) 312 | * Fix HTTP byte range handling. (#91) 313 | * Fix opening of relative path (#70) 314 | * Add a small (and hidden) API to do geo search. 315 | * Better request parsing. (#91) 316 | * Better handling of invalid request (#116) 317 | * Various bug fixes (#146, #150, #153, #165, #168, #165) 318 | 319 | kiwix-search 320 | ------------ 321 | 322 | * Add an option `--suggestion` to do suggestion search with 323 | kiwix-search.(#132) 324 | 325 | kiwix-tools 0.3.0 326 | ================= 327 | 328 | * Move to C++11 329 | 330 | kiwix-serve 331 | ----------- 332 | 333 | * Add a global taskbar in the welcome page to search in all zims (#49) 334 | * Serve the taskbar as css file instead of including it in the html (#68): 335 | * Better client caching 336 | * The html encoding is now in the first 1024 bytes and firefox correctly 337 | detect the encoding 338 | * Make kiwix-server multi-threaded (#82) 339 | * Correctly return 404 instead of crashing when request inexistant skin file 340 | (#83) 341 | * Correctly respond to bytes-range requests.(#84) 342 | * Directly respond to first request for a url instead of refusing the first 343 | connexion 344 | * Add support to relative url location. (#86) 345 | * Remove caching (on client side) for the welcome page. (#86) 346 | 347 | 348 | kiwix-tools 0.2.0 349 | ================= 350 | 351 | * Remove indexer tools 352 | 353 | kiwix-serve 354 | ----------- 355 | 356 | * Correctly fix the deflate data we send over http. (#15) 357 | * Update in the taskbar (or topbar): 358 | * Taskbar is responsive (github.com/kiwix/kiwix/issues/336) 359 | * Force css rules for the taskbar (and not be impacted by content's css) 360 | * Add `--nolibrarybutton` to hide the library button from the taskbar. 361 | * Rewrite of the welcome page. 362 | 363 | 364 | kiwix-installer 365 | --------------- 366 | 367 | * Remove indexing functionnality 368 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Kiwix tools 2 | =========== 3 | 4 | The Kiwix tools is a collection of [Kiwix](https://kiwix.org) related 5 | command line tools: 6 | * kiwix-manage: Manage XML based library of ZIM files 7 | * kiwix-search: Full text search in ZIM files 8 | * kiwix-serve: HTTP daemon serving ZIM files 9 | 10 | [![latest release](https://img.shields.io/github/v/tag/kiwix/kiwix-tools?label=latest%20release&sort=semver)](https://download.kiwix.org/release/kiwix-tools/) 11 | [![Repositories](https://img.shields.io/repology/repositories/kiwix-tools?label=repositories)](https://github.com/kiwix/kiwix-tools/wiki/Repology) 12 | [![Docker](https://ghcr-badge.deta.dev/kiwix/kiwix-tools/latest_tag?label=docker)](https://ghcr.io/kiwix/kiwix-tools) 13 | [![Docker](https://ghcr-badge.deta.dev/kiwix/kiwix-tools/latest_tag?label=docker%20(kiwix-serve))](https://ghcr.io/kiwix/kiwix-tools) 14 | [![Build Status](https://github.com/kiwix/kiwix-tools/workflows/CI/badge.svg?query=branch%3Amain)](https://github.com/kiwix/kiwix-tools/actions?query=branch%3Amain) 15 | [![Doc](https://readthedocs.org/projects/kiwix-tools/badge/?style=flat)](https://kiwix-tools.readthedocs.org/en/latest/?badge=latest) 16 | [![CodeFactor](https://www.codefactor.io/repository/github/kiwix/kiwix-tools/badge)](https://www.codefactor.io/repository/github/kiwix/kiwix-tools) 17 | [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) 18 | 19 | Disclaimer 20 | ---------- 21 | 22 | This document assumes you have a little knowledge about software 23 | compilation. If you experience difficulties with the dependencies or 24 | with the Kiwix tools compilation itself, we recommend to have a look 25 | to [kiwix-build](https://github.com/kiwix/kiwix-build). 26 | 27 | Preamble 28 | -------- 29 | 30 | Although the Kiwix tools can be compiled/cross-compiled on/for many 31 | systems, the following documentation explains how to do it on POSIX 32 | ones. It is primarily thought for GNU/Linux systems and has been tested 33 | on recent releases of 34 | [Debian](https://debian.org)/[Ubuntu](https://ubuntu.com) and 35 | [Fedora](https://getfedora.org). 36 | 37 | Dependencies 38 | ------------ 39 | 40 | The Kiwix tools rely on a few third party software libraries. They are 41 | prerequisites to the Kiwix tools compilation. Therefore, following 42 | libraries need to be available: 43 | * [libkiwix](https://github.com/kiwix/libkiwix) (package `libkiwix` on Debian/Ubuntu) 44 | * [libzim](https://github.com/openzim/libzim) (package `libzim` on Debian/Ubuntu) 45 | 46 | These dependencies may or may not be packaged by your operating 47 | system. They may also be packaged but only in an older version. They 48 | may be also packaged but without providing a static version. The 49 | compilation script will tell you if one of them is missing or too old. 50 | In the worse case, you will have to download and compile bleeding edge 51 | version by hand. 52 | 53 | If you want to install these dependencies locally, then use the 54 | kiwix-tools directory as install prefix. 55 | 56 | If you want to compile Kiwix tools statically, the dependencies should 57 | be compiled statically (provide a `lib...a` library), for example by 58 | using `--enable-static` with `./configure`. 59 | 60 | Environment 61 | ------------- 62 | 63 | The Kiwix tools build using [Meson](http://mesonbuild.com/) version 64 | 0.43 or higher. Meson relies itself on Ninja, pkg-config and a few other 65 | compilation tools. Install them first: 66 | * [Meson](http://mesonbuild.com/) 67 | * [Ninja](https://ninja-build.org/) 68 | * [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) 69 | 70 | These tools should be packaged if you use a cutting edge operating 71 | system. If not, have a look to the [Troubleshooting](#Troubleshooting) 72 | section. 73 | 74 | Compilation 75 | ----------- 76 | 77 | Once all dependencies are installed, you can compile Kiwix tools with: 78 | ```bash 79 | meson . build 80 | ninja -C build 81 | ``` 82 | 83 | By default, it will compile dynamic linked libraries. If you want 84 | statically linked libraries, you can add `-Dstatic-linkage=true` 85 | option to the Meson command. 86 | 87 | Depending of you system, `ninja` may be called `ninja-build`. 88 | 89 | Installation 90 | ------------ 91 | 92 | If you want to install the Kiwix tools, here we go: 93 | ```bash 94 | ninja -C build install 95 | ``` 96 | 97 | You might need to run the command as `root` (or using `sudo`), 98 | depending on where you want to install the Kiwix tools. After the 99 | installation succeeded, you may need to run ldconfig (as `root`). 100 | 101 | Uninstallation 102 | ------------ 103 | 104 | If you want to uninstall the Kiwix tools: 105 | ```bash 106 | ninja -C build uninstall 107 | ``` 108 | 109 | Like for the installation, you might need to run the command as `root` 110 | (or using `sudo`). 111 | 112 | Docker 113 | ------ 114 | 115 | An official Docker image of the Kiwix tools can be found on 116 | [GHCR](https://ghcr.io/kiwix/kiwix-tools). A 117 | `kiwix-serve` dedicated Docker image [exists 118 | too](https://ghcr.io/kiwix/kiwix-serve). 119 | 120 | Troubleshooting 121 | --------------- 122 | 123 | If you need to install Meson "manually": 124 | ```bash 125 | virtualenv -p python3 ./ # Create virtualenv 126 | source bin/activate # Activate the virtualenv 127 | pip3 install meson # Install Meson 128 | hash -r # Refresh bash paths 129 | ``` 130 | 131 | If you need to install Ninja "manually": 132 | ```bash 133 | git clone git://github.com/ninja-build/ninja.git 134 | cd ninja 135 | git checkout release 136 | ./configure.py --bootstrap 137 | mkdir ../bin 138 | cp ninja ../bin 139 | cd .. 140 | ``` 141 | 142 | If the compilation still fails, you might need to get a more recent 143 | version of a dependency than the one packaged by your Linux 144 | distribution. Try then with a source tarball distributed by the 145 | problematic upstream project or even directly from the source code 146 | repository. 147 | 148 | License 149 | ------- 150 | 151 | [GPLv3](https://www.gnu.org/licenses/gpl-3.0) or later, see 152 | [COPYING](COPYING) for more details. 153 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | kiwix-tools (0.0.0) unstable; urgency=medium 2 | 3 | * Initial release 4 | 5 | -- Kunal Mehta Mon, 13 Jul 2020 17:21:11 -0700 6 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: kiwix-tools 2 | Section: utils 3 | Priority: optional 4 | Maintainer: Kiwix team 5 | Build-Depends: debhelper-compat (= 13), 6 | libzim-dev (>= 9.0), libzim-dev (<< 10.0), 7 | libkiwix-dev (>= 14.0), libkiwix-dev (<< 15.0), 8 | cmake, 9 | libdocopt-dev, 10 | meson, 11 | pkgconf, 12 | Standards-Version: 4.6.2 13 | Homepage: https://github.com/kiwix/kiwix-tools 14 | Rules-Requires-Root: no 15 | 16 | Package: kiwix-tools 17 | Architecture: any 18 | Depends: ${misc:Depends}, ${shlibs:Depends} 19 | Description: collection of Kiwix tools 20 | kiwix-tools is a collection of various command-line tools used to help 21 | users interact with and manage ZIM files. It includes: 22 | * kiwix-serve is a standalone HTTP server for serving ZIM files 23 | over the network. 24 | * kiwix-manage allows one to manage the content of the Kiwix library (an 25 | XML file listing available ZIM files). 26 | * kiwix-search allows one to find articles in a ZIM file using fulltext 27 | search patterns. 28 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | See COPYING in the repository root. 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all 3 | 4 | %: 5 | dh $@ 6 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.18 2 | LABEL org.opencontainers.image.source https://github.com/openzim/kiwix-tools 3 | 4 | # TARGETPLATFORM is injected by docker build 5 | ARG TARGETPLATFORM 6 | ARG VERSION 7 | 8 | RUN set -e && \ 9 | apk --no-cache add dumb-init curl && \ 10 | echo "TARGETPLATFORM: $TARGETPLATFORM" && \ 11 | if [ "$TARGETPLATFORM" = "linux/386" ]; then ARCH="i586"; \ 12 | # linux/arm64/v8 points to linux/arm64 13 | elif [ "$TARGETPLATFORM" = "linux/arm64/v8" \ 14 | -o "$TARGETPLATFORM" = "linux/arm64" ]; then ARCH="aarch64"; \ 15 | # linux/arm translates to linux/arm/v7 16 | elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then ARCH="armv8"; \ 17 | elif [ "$TARGETPLATFORM" = "linux/arm/v6" ]; then ARCH="armv6"; \ 18 | elif [ "$TARGETPLATFORM" = "linux/amd64/v3" \ 19 | -o "$TARGETPLATFORM" = "linux/amd64/v2" \ 20 | -o "$TARGETPLATFORM" = "linux/amd64" ]; then ARCH="x86_64"; \ 21 | # we dont suppot any other arch so let it fail 22 | else ARCH="unknown"; fi && \ 23 | # download requested kiwix-tools version 24 | url="http://mirror.download.kiwix.org/release/kiwix-tools/kiwix-tools_linux-$ARCH-$VERSION.tar.gz" && \ 25 | echo "URL: $url" && \ 26 | curl -k -L $url | tar -xz -C /usr/local/bin/ --strip-components 1 && \ 27 | # only needed in dockerfile 28 | apk del curl 29 | 30 | # expose kiwix-serve default port 31 | EXPOSE 80 32 | 33 | ENTRYPOINT ["/usr/bin/dumb-init", "--"] 34 | CMD ["/bin/sh", "-c", "echo 'Welcome to kiwix-tools! The following binaries are available:' && ls /usr/local/bin/"] 35 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | Kiwix-tools Docker image 2 | === 3 | 4 | - Available on [ghcr.io](https://ghcr.io/kiwix/kiwix-tools). 5 | - multi-arch (`linux/amd64`, `linux/arm64`, `linux/arm/v7`) 6 | - based on official `kiwix-tools` binaries. 7 | 8 | ## Usage 9 | 10 | ``` sh 11 | $ docker run -it ghcr.io/kiwix/kiwix-tools:3.1.2 12 | 13 | Welcome to kiwix-tools! The following binaries are available: 14 | kiwix-manage kiwix-search kiwix-serve 15 | ``` 16 | 17 | `kiwix-tools` operates on zim files. You shall mount a volume to access the files. 18 | 19 | ```sh 20 | docker run -v $(pwd):/data -it ghcr.io/kiwix/kiwix-tools kiwix-search /data/wikipedia_fr_test.zim "Mali" 21 | ``` 22 | 23 | ## Building and reusing 24 | 25 | - `kiwix/kiwix-tools` is multi-arch and is ideally built using `buildx`. 26 | - requires a `--build-arg VERSION=` with the kiwix-tools release. 27 | - can be built using `docker build` in which case it expects an additionnal `--build-arg ARCH=arm` for arm. Otherwise defaults to `amd64`. 28 | 29 | **Notes:** 30 | 31 | - `wget` in `alpine:3` on `arm/v7` (__inside github action only__) crashes when downloading from HTTPs locations. Keep http-only in Dockerfile. 32 | - Was also unhappy when using the mirrors so it's using `mirror.download` on purpose. 33 | 34 | ## See also 35 | 36 | If you are interested by a Kiwix server only container image, [here it is](server/README.md). -------------------------------------------------------------------------------- /docker/server/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VERSION=latest 2 | 3 | # kiwix-tools is multi-arch 4 | FROM ghcr.io/kiwix/kiwix-tools:$VERSION 5 | LABEL org.opencontainers.image.source https://github.com/openzim/kiwix-tools 6 | 7 | # expose kiwix-serve default port and workdir 8 | EXPOSE 8080 9 | VOLUME /data 10 | WORKDIR /data 11 | 12 | COPY ./start.sh /usr/local/bin/ 13 | 14 | ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/start.sh"] 15 | -------------------------------------------------------------------------------- /docker/server/README.md: -------------------------------------------------------------------------------- 1 | Kiwix serve Docker image 2 | ======================== 3 | 4 | With local ZIM file(s) 5 | ---------------------- 6 | 7 | * Download a ZIM file from 8 | 9 | * Given `wikipedia.zim` and `wiktionary.zim` reside in `/tmp/zim/`, execute the following: 10 | 11 | ```bash 12 | docker run -v /tmp/zim:/data -p 8080:8080 ghcr.io/kiwix/kiwix-serve wikipedia.zim wiktionary.zim 13 | ``` 14 | 15 | or, if you want to load all ZIM files within a directory, then use globbing: 16 | 17 | ```bash 18 | docker run -v /tmp/zim:/data -p 8080:8080 ghcr.io/kiwix/kiwix-serve '*.zim' 19 | ``` 20 | 21 | With remote ZIM file 22 | -------------------- 23 | 24 | ```bash 25 | docker run -e "DOWNLOAD=https://download.kiwix.org/zim/wikipedia_bm_all.zim" -p 8080:8080 ghcr.io/kiwix/kiwix-serve 26 | ``` 27 | 28 | Change default port 29 | ------------------- 30 | 31 | You can change port to expose with environment variable PORT, useful if running on Podman, K8s or OpenShift 32 | 33 | ```bash 34 | podman run -e "DOWNLOAD=https://download.kiwix.org/zim/wikipedia_bm_all.zim" -e PORT=8888 -p 8080:8888 ghcr.io/kiwix/kiwix-serve 35 | ``` 36 | 37 | ARM 38 | --- 39 | 40 | Build an image for an ARM based GNU/Linux: 41 | ```bash 42 | docker build . -t ghcr.io/kiwix/kiwix-serve:latest --build-arg ARCH="arm32v7/" 43 | ``` 44 | 45 | Docker Compose 46 | -------------- 47 | 48 | You can also deploy kiwix with 49 | [`docker-compose`](https://docs.docker.com/compose/). Check out a 50 | sample at [docker-compose.yml.example](docker-compose.yml.example). 51 | 52 | Screenshots 53 | ----------- 54 | 55 | ![screenshot_1.png](https://github.com/kiwix/kiwix-tools/raw/master/docker/server/pictures/screenshot_1.png) 56 | ![screenshot_2.png](https://github.com/kiwix/kiwix-tools/raw/master/docker/server/pictures/screenshot_2.png) 57 | -------------------------------------------------------------------------------- /docker/server/docker-compose.yml.example: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | services: 3 | kiwix-serve: 4 | ports: 5 | - 8080:8080 6 | image: ghcr.io/kiwix/kiwix-serve:latest 7 | # uncomment next 4 lines to use it with local zim file in /tmp/zim 8 | # volumes: 9 | # - /tmp/zim:/data 10 | # command: 11 | # - '*.zim' 12 | # uncomment next 2 lines to use it with remote zim file 13 | # environment: 14 | # - 'DOWNLOAD=https://download.kiwix.org/zim/wikipedia_bm_all.zim' 15 | -------------------------------------------------------------------------------- /docker/server/pictures/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiwix/kiwix-tools/0d38d071a8b584c8b62917383f6706aa9639c6ba/docker/server/pictures/screenshot_1.png -------------------------------------------------------------------------------- /docker/server/pictures/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kiwix/kiwix-tools/0d38d071a8b584c8b62917383f6706aa9639c6ba/docker/server/pictures/screenshot_2.png -------------------------------------------------------------------------------- /docker/server/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Download if necessary a file 4 | if [ ! -z "$DOWNLOAD" ] 5 | then 6 | ZIM=`basename $DOWNLOAD` 7 | wget $DOWNLOAD -O "$ZIM" 8 | 9 | # Set arguments 10 | if [ "$#" -eq "0" ] 11 | then 12 | set -- "$@" $ZIM 13 | fi 14 | fi 15 | 16 | if [ -z "$PORT" ] 17 | then 18 | PORT=8080 19 | fi 20 | CMD="/usr/local/bin/kiwix-serve --port=$PORT $@" 21 | echo $CMD 22 | $CMD 23 | 24 | # If error, print the content of /data 25 | if [ $? -ne 0 ] 26 | then 27 | echo "Here is the content of /data:" 28 | find /data -type f 29 | fi 30 | -------------------------------------------------------------------------------- /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 = 'kiwix-tools' 21 | copyright = '2024, kiwix-team' 22 | author = 'kiwix-team' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 28 | 29 | # Add any Sphinx extension module names here, as strings. They can be 30 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 31 | # ones. 32 | extensions = [ 33 | "sphinx_rtd_theme" 34 | ] 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ['_templates'] 38 | 39 | # List of patterns, relative to source directory, that match files and 40 | # directories to ignore when looking for source files. 41 | # This pattern also affects html_static_path and html_extra_path. 42 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 43 | 44 | 45 | html_theme = 'sphinx_rtd_theme' 46 | 47 | # Add any paths that contain custom static files (such as style sheets) here, 48 | # relative to this directory. They are copied after the builtin static files, 49 | # so a file named "default.css" will overwrite the builtin "default.css". 50 | html_static_path = [] 51 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to kiwix-tools' documentation! 2 | ====================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | kiwix-serve 9 | -------------------------------------------------------------------------------- /docs/kiwix-serve.rst: -------------------------------------------------------------------------------- 1 | *********** 2 | kiwix-serve 3 | *********** 4 | 5 | Introduction 6 | ============ 7 | 8 | ``kiwix-serve`` is a tool for serving ZIM file content over HTTP. It supports 9 | serving a library containing multiple ZIM files. In a large library served by a 10 | ``kiwix-serve`` instance clients can look up/filter ZIM files of interest by 11 | words in their :term:`titles ` and/or descriptions, language, tags, etc. 12 | 13 | ``kiwix-serve`` provides a ZIM file viewer for displaying inidividual pages 14 | from a ZIM file inside the user's web browser (without downloading the full ZIM 15 | file). 16 | 17 | Clients can also remotely search inside those ZIM files that contain a full-text 18 | search database. 19 | 20 | ``kiwix-serve`` supports Web browsers `Firefox >= 70, Chrome >= 80, Edge >= 80, ChromeAndroid >= 80, Safari >= 14, iOS >= 14 `_. 21 | 22 | Usage 23 | ===== 24 | 25 | .. code-block:: sh 26 | 27 | kiwix-serve --library [OPTIONS] LIBRARY_FILE_PATH 28 | kiwix-serve [OPTIONS] ZIM_FILE_PATH ... 29 | 30 | 31 | Arguments 32 | --------- 33 | 34 | .. _cli-arg-library-file-path: 35 | 36 | ``LIBRARY_FILE_PATH``: path of an XML library file listing ZIM files to serve. 37 | To be used only with the :option:`--library` option. Multiple library files can 38 | be provided as a semicolon (``;``) separated list. 39 | 40 | ``ZIM_FILE_PATH``: ZIM file path (multiple arguments are allowed). 41 | 42 | Options 43 | ------- 44 | 45 | .. option:: --library 46 | 47 | By default, ``kiwix-serve`` expects a list of ZIM files as command line 48 | arguments. Providing the :option:`--library` option tells ``kiwix-serve`` 49 | that the command line argument is rather a :ref:`library XML file 50 | `. 51 | 52 | .. option:: -i ADDR, --address=ADDR 53 | 54 | Listen only on this IP address. By default the server listens on all 55 | available IP addresses. Alternatively, you can use special values to define which types of connections to accept: 56 | 57 | - all : Listen for connections on all IP addresses (IPv4 and IPv6). 58 | - ipv4 : Listen for connections on all IPv4 addresses. 59 | - ipv6 : Listen for connections on all IPv6 addresses. 60 | 61 | 62 | .. option:: -p PORT, --port=PORT 63 | 64 | TCP port on which to listen for HTTP requests (default: 80). 65 | 66 | 67 | .. option:: -r ROOT, --urlRootLocation=ROOT 68 | 69 | URL prefix on which the content should be made available (default: empty). 70 | 71 | 72 | .. option:: -d, --daemon 73 | 74 | Detach the HTTP server daemon from the main process. 75 | 76 | 77 | .. option:: -a PID, --attachToProcess=PID 78 | 79 | Exit when the process with id PID stops running. 80 | 81 | 82 | .. option:: -M, --monitorLibrary 83 | 84 | Monitor the XML library file and reload it automatically when it changes. 85 | 86 | Library reloading can be forced anytime by sending a SIGHUP signal to the 87 | ``kiwix-serve`` process (this works regardless of the presence of the 88 | :option:`--monitorLibrary`/:option:`-M` option). 89 | 90 | 91 | .. option:: -m, --nolibrarybutton 92 | 93 | Disable the library home button in the ZIM viewer toolbar. 94 | 95 | 96 | .. option:: -n, --nosearchbar 97 | 98 | Disable the searchbox in the ZIM viewer toolbar. 99 | 100 | 101 | .. option:: -b, --blockexternal 102 | 103 | Prevent the users from directly navigating to external resources via such 104 | links in ZIM content. 105 | 106 | 107 | .. option:: -t N, --threads=N 108 | 109 | Number of threads to run in parallel (default: 4). 110 | 111 | 112 | .. option:: -s N, --searchLimit=N 113 | 114 | Maximum number of ZIM files in a fulltext multizim search (default: No limit). 115 | 116 | 117 | .. option:: -z, --nodatealiases 118 | 119 | Create URL aliases for each content by removing the date embedded in the file 120 | name. The expected format of the date in the filename is ``_YYYY-MM``. For 121 | example, ZIM file ``wikipedia_en_all_2020-08.zim`` will be accessible both as 122 | ``wikipedia_en_all_2020-08`` and ``wikipedia_en_all``. 123 | 124 | 125 | .. option:: -c PATH, --customIndex=PATH 126 | 127 | Override the welcome page with a custom HTML file. 128 | 129 | 130 | .. option:: -L N, --ipConnectionLimit=N 131 | 132 | Max number of (concurrent) connections per IP (default: infinite, 133 | recommended: >= 6). 134 | 135 | 136 | .. option:: -v, --verbose 137 | 138 | Print debug log to STDOUT. 139 | 140 | 141 | .. option:: -V, --version 142 | 143 | Print the software version. 144 | 145 | 146 | .. option:: -h, --help 147 | 148 | Print the help text. 149 | 150 | 151 | HTTP API 152 | ======== 153 | 154 | ``kiwix-serve`` serves content at/under ``http://ADDR:PORT/ROOT`` where 155 | ``ADDR``, ``PORT`` and ``ROOT`` are the values supplied to the 156 | :option:`--address`/:option:`-i`, :option:`--port`/:option:`-p` and 157 | :option:`--urlRootLocation`/:option:`-r` options, respectively. 158 | 159 | HTTP API endpoints presented below are relative to that location, i.e. 160 | ``/foo/bar`` must be actually accessed as ``http://ADDR:PORT/ROOT/foo/bar``. 161 | 162 | .. note:: 163 | 164 | The HTTP API is documented in its entirety in order to facilitate the work of 165 | the Kiwix development team. Note, however, that only a subset of the HTTP API 166 | constitutes ``kiwix-serves``'s public interface. 167 | 168 | .. _public-api-endpoint: 169 | 170 | **Public API endpoint** 171 | 172 | A public HTTP API endpoint is intended to serve the outside world (in 173 | addition to ``kiwix-serve``'s front-end and other Kiwix products). The 174 | Kiwix development team will do its best to ensure gratifying experience for 175 | clients of public API endpoints at all stages of the endpoint lifecycle. 176 | 177 | .. _private-api-endpoint: 178 | 179 | **Private API endpoint** 180 | 181 | A private API endpoint is intended to be used only by ``kiwix-serve``'s 182 | frontend or by other products maintained solely by the Kiwix team. Private 183 | API comes without any guaranees. It may change as frequently and as 184 | drasticaly as the Kiwix development team sees fit. 185 | 186 | .. _deprecation: 187 | 188 | **Deprecation** 189 | 190 | Public API doesn't stay frozen once and forever. As the API evolves, Kiwix 191 | team reserves the right to drop support for certain old functionality. In 192 | such events, an advance notice will be issued and the users will be given 193 | enough time to prepare for the change. 194 | 195 | Currently, public endpoints are limited to the following list: 196 | 197 | - :ref:`OPDS API ` 198 | - ``/raw`` 199 | - ``/search`` (with ``/search/searchdescription.xml``) 200 | 201 | .. _welcome-page: 202 | 203 | ``/`` 204 | ----- 205 | 206 | ===== =========== 207 | Type: :ref:`private ` 208 | ===== =========== 209 | 210 | Welcome page is served under ``/``. By default this is the library page, where 211 | books are listed and can be looked up/filtered interactively. However, the 212 | welcome page can be overriden through the :option:`--customIndex`/:option:`-c` 213 | command line option of ``kiwix-serve``. 214 | 215 | 216 | .. _new-opds-api: 217 | 218 | ``/catalog/v2`` (OPDS API) 219 | ------------------------------ 220 | 221 | ===== =========== 222 | Type: :ref:`public ` 223 | ===== =========== 224 | 225 | The new OPDS API of ``kiwix-serve`` is based on the `OPDS Catalog specification 226 | v1.2 `_. All of its endpoints are grouped under 227 | ``/catalog/v2``. 228 | 229 | :ref:`Legacy OPDS API ` is preserved for backward 230 | compatibility. 231 | 232 | 233 | ``/catalog/v2/root.xml`` 234 | ^^^^^^^^^^^^^^^^^^^^^^^^ 235 | 236 | ===== =========== 237 | Type: member of a :ref:`public API ` 238 | ===== =========== 239 | 240 | The OPDS Catalog Root links to the OPDS acquisition and navigation feeds 241 | accessible through the other endpoints of the OPDS API. 242 | 243 | 244 | ``/catalog/v2/searchdescription.xml`` 245 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 246 | 247 | ===== =========== 248 | Type: member of a :ref:`public API ` 249 | ===== =========== 250 | 251 | Describes the `/catalog/v2/entries`_ endpoint in `OpenSearch description format 252 | `_. 253 | 254 | 255 | 256 | ``/catalog/v2/categories`` 257 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 258 | 259 | ===== =========== 260 | Type: member of a :ref:`public API ` 261 | ===== =========== 262 | 263 | Returns the full list of ZIM file categories as an `OPDS Navigation Feed 264 | `_. 265 | 266 | 267 | ``/catalog/v2/entries`` 268 | ^^^^^^^^^^^^^^^^^^^^^^^ 269 | 270 | ===== =========== 271 | Type: member of a :ref:`public API ` 272 | ===== =========== 273 | 274 | Returns a full or filtered list of ZIM files as a paginated `OPDS acquisition 275 | feed `_ with `complete 276 | entries 277 | `_. 278 | 279 | **Pagination:** 280 | 281 | By default, no more than 10 first entries are returned from the library. To 282 | obtain the remaining entries the URL query parameters ``start`` and/or 283 | ``count`` must be used. The output of ``/catalog/v2/entries?start=s&count=n`` 284 | will contain at most ``n`` (default value: 10) results starting from entry # 285 | ``s`` (default value: 0). ``count`` with a negative value (e.g. ``count=-1``) 286 | removes the limit on the number of results in the output. 287 | 288 | 289 | .. note:: 290 | 291 | Previously ``count=0`` also designated an unbounded query (i.e. worked 292 | similarly to ``count=-1``). The response to a ``count=0`` query was changed 293 | to consist of 0 results, as such a query/response combination is a good way 294 | to find out the total number of results (when only that information is 295 | needed) with minimal consumption of resources. 296 | 297 | Examples: 298 | 299 | .. code:: sh 300 | 301 | # Returns the first 10 entries (internally numbered 0 through 9) 302 | $ curl 'http://localhost:8080/catalog/v2/entries' 303 | 304 | # Returns the next 10 entries (internally numbered 10 through 19) 305 | $ curl 'http://localhost:8080/catalog/v2/entries?start=10' 306 | 307 | # Returns the first 50 entries 308 | $ curl 'http://localhost:8080/catalog/v2/entries?count=50' 309 | 310 | # Returns 50 entries starting from entry # 100 (i.e. entries ## 100-149) 311 | $ curl 'http://localhost:8080/catalog/v2/entries?start=100&count=50' 312 | 313 | # Returns all entries 314 | $ curl 'http://localhost:8080/catalog/v2/entries?count=-1' 315 | 316 | # Returns all entries starting from entry # 100 317 | $ curl 'http://localhost:8080/catalog/v2/entries?start=100&count=-1' 318 | 319 | 320 | .. _library-filtering: 321 | 322 | **Filtering:** 323 | 324 | A filtered subset of the library can be requested by providing one or more 325 | filtering criteria, whereupon only entries matching *all* of the criteria are 326 | included in the response. Pagination is applied to the filtered list. The 327 | filtering criteria must be specified via the following URL parameters: 328 | 329 | * ``lang`` - filter by language (specified as a 3-letter language code). 330 | 331 | * ``category`` - filter by categories associated with the library entries. 332 | 333 | * ``tag`` - filter by tags associated with the library entries. Multiple tags 334 | can be provided as a semicolon separated list (e.g 335 | ``tag=wikipedia;_videos:no``). The result will contain only those entries 336 | that contain *all* of the requested tags. 337 | 338 | * ``notag`` - filter out (exclude) entries with *any* of the specified tags 339 | (example - ``notag=ted;youtube``). 340 | 341 | * ``maxsize`` - include in the results only entries whose size (in bytes) 342 | doesn't exceed the provided value. 343 | 344 | * ``q`` - include in the results only entries that contain the specified text 345 | in the title or description. 346 | 347 | * ``name`` - include in the results only entries with a matching 348 | :term:`book name `. 349 | 350 | 351 | Examples: 352 | 353 | .. code:: sh 354 | 355 | # List only books in Italian (lang=ita) but 356 | # return only results ## 100-149 (start=100&count=50) 357 | $ curl 'http://localhost:8080/catalog/v2/entries?lang=ita&start=100&count=50' 358 | 359 | # List only books with category of 'wikipedia' AND containing the word 360 | # 'science' in the title or description. Return only the first 10 results. 361 | $ curl 'http://localhost:8080/catalog/v2/entries?q=science&category=wikipedia' 362 | 363 | 364 | ``/catalog/v2/entry/ZIMID`` 365 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 366 | 367 | ===== =========== 368 | Type: member of a :ref:`public API ` 369 | ===== =========== 370 | 371 | Returns full info about the library entry with :term:`UUID ` 372 | ``ZIMID``. 373 | 374 | 375 | ``/catalog/v2/illustration/ZIMID`` 376 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 377 | 378 | ===== =========== 379 | Type: member of a :ref:`public API ` 380 | ===== =========== 381 | 382 | **Usage:** 383 | 384 | ``/catalog/v2/illustration/ZIMID?size=N`` 385 | 386 | Returns the illustration of size ``NxN`` pixels for the library entry with 387 | :term:`UUID ` ``ZIMID``. 388 | 389 | If no illustration of requested size is found a HTTP 404 error is returned. 390 | 391 | 392 | ``/catalog/v2/languages`` 393 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 394 | 395 | ===== =========== 396 | Type: member of a :ref:`public API ` 397 | ===== =========== 398 | 399 | Returns the full list of ZIM file languages as an `OPDS Navigation Feed 400 | `_. 401 | 402 | 403 | ``/catalog/v2/partial_entries`` 404 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 405 | 406 | ===== =========== 407 | Type: member of a :ref:`public API ` 408 | ===== =========== 409 | 410 | Returns the full or filtered list of ZIM files as an `OPDS acquisition feed 411 | `_ with `partial entries 412 | `_. 413 | 414 | Supported filters are the same as for the `/catalog/v2/entries`_ endpoint. 415 | 416 | 417 | .. _legacy-opds-api: 418 | 419 | ``/catalog`` (Legacy OPDS API) 420 | ------------------------------ 421 | 422 | ===== =========== 423 | Type: :ref:`deprecated ` 424 | ===== =========== 425 | 426 | The legacy OPDS API is preserved for backward compatibility and is deprecated. 427 | :ref:`New OPDS API ` should be used instead. 428 | 429 | 430 | ``/catalog/root.xml`` 431 | ^^^^^^^^^^^^^^^^^^^^^ 432 | 433 | ===== =========== 434 | Type: member of a :ref:`deprecated API ` 435 | ===== =========== 436 | 437 | Full library OPDS catalog (list of all ZIM files). 438 | 439 | 440 | ``/catalog/searchdescription.xml`` 441 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 442 | 443 | ===== =========== 444 | Type: member of a :ref:`deprecated API ` 445 | ===== =========== 446 | 447 | Describes the `/catalog/search`_ endpoint in `OpenSearch description format 448 | `_. 449 | 450 | 451 | ``/catalog/search`` 452 | ^^^^^^^^^^^^^^^^^^^ 453 | 454 | ===== =========== 455 | Type: member of a :ref:`deprecated API ` 456 | ===== =========== 457 | 458 | Returns the list of ZIM files (in OPDS catalog format) matching the 459 | search/filtering criteria. Supported filters are the same as for the 460 | `/catalog/v2/entries`_ endpoint. 461 | 462 | 463 | ``/catch/external`` 464 | ------------------- 465 | 466 | ===== =========== 467 | Type: :ref:`private ` 468 | ===== =========== 469 | 470 | **Usage:** 471 | 472 | ``/catch/external?source=URL`` 473 | 474 | Generates a HTML page with a link leading to (the decoded version of) ``URL`` 475 | and a warning that following that link will load an external (out of ZIM) 476 | resource. 477 | 478 | **Parameters:** 479 | 480 | ``source``: URL of the external resource (must be URL-encoded). 481 | 482 | **Example:** 483 | 484 | .. code:: sh 485 | 486 | # Intercept an external link to https://example.com?query=abcd 487 | $ curl 'http://localhost:8080/catch/external?source=https%3A%2F%2Fexample.com%3Fquery%3Dabcd' 488 | 489 | 490 | 491 | ``/content`` 492 | ------------ 493 | 494 | ===== =========== 495 | Type: :ref:`private ` 496 | ===== =========== 497 | 498 | ZIM file content is served under the ``/content`` endpoint as described below. 499 | 500 | 501 | ``/content/ZIMNAME/PATH/IN/ZIMFILE`` 502 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 503 | 504 | ===== =========== 505 | Type: :ref:`private ` 506 | ===== =========== 507 | 508 | Returns the entry with path ``PATH/IN/ZIMFILE`` from ZIM file with :term:`name 509 | ` ``ZIMNAME``. 510 | 511 | 512 | ``/content/ZIMNAME`` 513 | ^^^^^^^^^^^^^^^^^^^^ 514 | 515 | ===== =========== 516 | Type: :ref:`private ` 517 | ===== =========== 518 | 519 | ``/content/ZIMNAME`` redirects to the main page of the ZIM file with :term:`name 520 | ` ``ZIMNAME`` (unless that ZIM file contains an entry with an empty 521 | path or path equal to ``/``, in which case that entry is returned). 522 | 523 | 524 | ``/random`` 525 | ----------- 526 | 527 | ===== =========== 528 | Type: :ref:`private ` 529 | ===== =========== 530 | 531 | **Usage:** 532 | 533 | ``/random?content=ZIMNAME`` 534 | 535 | Generates a HTTP redirect to a randomly selected article/page from the 536 | specified ZIM file. 537 | 538 | **Parameters:** 539 | 540 | ``content``: :term:`name of the ZIM file `. 541 | 542 | 543 | .. _raw: 544 | 545 | ``/raw`` 546 | -------- 547 | 548 | ===== =========== 549 | Type: :ref:`public ` 550 | ===== =========== 551 | 552 | The ``/raw`` API provides access to ZIM file data. It consists of two separate 553 | endpoints for accessing data and metadata. 554 | 555 | 556 | ``/raw/ZIMNAME/content/PATH/IN/ZIMFILE`` 557 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 558 | 559 | ===== =========== 560 | Type: member of a :ref:`public API ` 561 | ===== =========== 562 | 563 | Returns the entry with path ``PATH/IN/ZIMFILE`` from the ZIM file with 564 | :term:`name ` ``ZIMNAME``. Currently, this endpoint almost duplicates 565 | (with some subtle technical differences) the newer endpoint 566 | `/content/ZIMNAME/PATH/IN/ZIMFILE`_. The important difference is that the 567 | ``/raw`` endpoint guarantees that no server-side processing will be applied to 568 | the returned content, whereas content obtained via the ``/content`` endpoint 569 | may in the future undergo some processing intended to improve the operation of 570 | the viewer (e.g. compensating for certain bugs in ZIM creation). Also note that 571 | ``/raw`` is :ref:`public `, whereas ``/content`` is 572 | :ref:`private `. 573 | 574 | 575 | ``/raw/ZIMNAME/meta/METADATAID`` 576 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 577 | 578 | ===== =========== 579 | Type: member of a :ref:`public API ` 580 | ===== =========== 581 | 582 | Returns the metadata item ``METADATAID`` from the ZIM file with :term:`name 583 | ` ``ZIMNAME``. 584 | 585 | 586 | ``/search`` 587 | ----------- 588 | 589 | ===== =========== 590 | Type: :ref:`public ` 591 | ===== =========== 592 | 593 | Performs a full text search on one or more ZIM files and returns an HTML page 594 | with a list of links to matching pages along with snippets of the matching 595 | portions of those pages. 596 | 597 | .. _multi-zim-search-constraints: 598 | 599 | A multi-ZIM search request must comply with the following constraints: 600 | 601 | * the number of ZIM files participating in the search operation must not exceed 602 | the limit imposed by the :option:`--searchLimit` option of ``kiwix-serve``. 603 | 604 | * all of the ZIM files participating in the same search operation must be in 605 | the same language. 606 | 607 | **Parameters:** 608 | 609 | 610 | ZIM file selection parameters: 611 | 612 | At least one of the following parameters must be provided in order to 613 | specify in which ZIM file(s) to search. Parameters appearing earlier in 614 | below list take precedence over subsequent ones (the later ones, even if 615 | present in the request, are simply ignored). 616 | 617 | ``content``: :term:`name of the ZIM file ` (for a single-ZIM 618 | search). This is a :ref:`legacy parameter `. ``books.name`` 619 | should be used instead. 620 | 621 | ``books.id``: :term:`UUID ` of the ZIM file. Can be repeated for 622 | a multi-ZIM search, however must respect the :ref:`multi-ZIM search 623 | constraints `. 624 | 625 | .. note:: 626 | 627 | If any of the provided ``books.id`` values refers to a book missing 628 | from the library then an error is returned instead of running the 629 | search on the remaining (valid) entries. 630 | 631 | ``books.name``: :term:`name of the ZIM file ` (not to be confused 632 | with ``books.filter.name`` which selects/filters based on the :term:`book 633 | name `). Can be repeated for a multi-ZIM search, however must 634 | respect the :ref:`multi-ZIM search constraints 635 | `. 636 | 637 | .. note:: 638 | 639 | If any of the provided ``books.name`` values refers to a book missing 640 | from the library then an error is returned instead of running the 641 | search on the remaining (valid) entries. 642 | 643 | ``books.filter.{criteria}``: allows to take full advantage of :ref:`library 644 | filtering ` functionality of the `/catalog/v2/entries`_ 645 | endpoint (``{criteria}`` must be replaced with an attribute/filtering 646 | criteria name supported by :ref:`library filtering `). 647 | 648 | Query parameters: 649 | 650 | ``pattern`` (optional; defaults to an empty string): text to search for. 651 | 652 | ``latitude``, ``longitude`` & ``distance`` (optional): geospatial query 653 | parameters. If all of these are provided, then the results will be 654 | restricted to geotagged pages that are within ``distance`` metres from the 655 | location on Earth with coordinates ``latitude`` and ``longitude``. 656 | 657 | Pagination parameters: 658 | 659 | ``pageLength`` (optional, default: 25): maximum number of search results in 660 | the response. Capped at 140. 661 | 662 | ``start`` (optional, default: 1): this parameter enables pagination of 663 | results. The response will include up to ``pageLength`` results starting 664 | with entry # ``start`` from the full list of search results (the first 665 | result is assumed to have index 1). 666 | 667 | Other parameters: 668 | 669 | ``format`` (optional, default: html): format of the search results. Allowed 670 | values are: html, xml. 671 | 672 | Examples: 673 | 674 | .. code:: sh 675 | 676 | # Search for 'android' in the book with name 'scifi-library' 677 | # Return results ## 51-60. 678 | $ curl 'http://localhost:8080/search?pattern=android&books.name=scifi-library&start=51&pageLength=10' 679 | 680 | # Search for 'napoli' in books in Italian 681 | $ curl 'http://localhost:8080/search?books.filter.lang=ita&pattern=napoli' 682 | 683 | # Search for 'chateau' in books in French that have a category of 'wikipedia'. 684 | # Return the results as XML. 685 | $ curl 'http://localhost:8080/search?pattern=chateau&books.filter.lang=fra&books.filter.category=wikipedia&format=xml' 686 | 687 | 688 | ``/search/searchdescription.xml`` 689 | --------------------------------- 690 | 691 | ===== =========== 692 | Type: :ref:`public ` 693 | ===== =========== 694 | 695 | Describes the `/search`_ endpoint in `OpenSearch description format 696 | `_. 697 | 698 | 699 | 700 | ``/skin`` 701 | ----------- 702 | 703 | ===== =========== 704 | Type: :ref:`private ` 705 | ===== =========== 706 | 707 | Static front-end resources (such as CSS, javascript and images) are all grouped 708 | under ``/skin``. 709 | 710 | **Usage:** 711 | ``/skin/PATH/TO/RESOURCE[?cacheid=CACHEID]`` 712 | 713 | `Cache busting 714 | `_ of 715 | static resources is supported via the optional param ``cacheid``. By default, 716 | i.e. when the ``cacheid`` parameter is not specified while accessing the 717 | ``/skin`` endpoint, static resources are served as if they were dynamic (i.e. 718 | could be different for an immediately repeated request). Specifying the 719 | ``cacheid`` parameter with a correct value (matching the value embedded in the 720 | ``kiwix-serve`` instance), makes the returned resource to be presented as 721 | immutable. However, if the value of the ``cacheid`` parameter mismatches then 722 | ``kiwix-serve`` responds with a 404 HTTP error. 723 | 724 | ``kiwix-serve``'s default front-end (the :ref:`welcome page ` and 725 | the :ref:`ZIM file viewer `) access all underlying static 726 | resources by using explicit ``cacheid`` s. 727 | 728 | 729 | ``/suggest`` 730 | ------------ 731 | 732 | ===== =========== 733 | Type: :ref:`private ` 734 | ===== =========== 735 | 736 | **Usage:** 737 | 738 | ``/suggest?content=ZIMNAME[&term=QUERY][&count=N][&start=S]`` 739 | 740 | Returns suggestions (in JSON format) for a text string that is assumed to be a 741 | partially typed search for a page inside a particular ZIM file. 742 | 743 | Suggestions are obtained as matches of the query text against the page titles 744 | in the ZIM file using the title index database generated during the creation of 745 | the ZIM file. 746 | 747 | In case of a multi-word query the order of the words matters in two ways: 748 | 749 | 1. the last word is considered as partially typed, unless followed by a space; 750 | 2. ranking of the matches. 751 | 752 | If the ZIM file doesn't contain a title index then suggestions are generated by 753 | listing page titles starting *exactly* (in a case sensitive manner) with the 754 | query text. Otherwise, suggestions are case-insensitive. 755 | 756 | If the ZIM file contains a full text search index, then an extra suggestion is 757 | added as an option to perform a full text search in the said ZIM file. 758 | 759 | **Parameters:** 760 | 761 | ``content`` (mandatory): :term:`name of the ZIM file `. 762 | 763 | ``term`` (optional; defaults to an empty string): query text. 764 | 765 | ``count`` (optional, default: 10): maximum number of page suggestions in the 766 | response (i.e. the extra option to perform a full text search is not included 767 | in this count). 768 | 769 | ``start`` (optional, default: 0): this parameter enables pagination of 770 | results. The response will include up to ``count`` entries starting with 771 | entry # ``start`` from the full list of page suggestions (the first result is 772 | assumed to have index 0). 773 | 774 | **Example:** 775 | 776 | .. code:: sh 777 | 778 | $ curl 'http://localhost/suggest?content=stackoverflow_en&term=pyth&count=50' 779 | 780 | 781 | .. _zim-file-viewer: 782 | 783 | ``/viewer`` 784 | ----------- 785 | 786 | ===== =========== 787 | Type: :ref:`private ` 788 | ===== =========== 789 | 790 | ZIM file viewer. The ZIM file and entry therein must be specified via the hash 791 | component of the URL as ``/viewer#ZIMNAME/PATH/IN/ZIMFILE``. 792 | 793 | 794 | ``/viewer_settings.js`` 795 | ----------------------- 796 | 797 | ===== =========== 798 | Type: :ref:`private ` 799 | ===== =========== 800 | 801 | Settings of the ZIM file viewer that are configurable via certain command line 802 | options of ``kiwix-serve`` (e.g. ``--nolibrarybutton``). 803 | 804 | 805 | /ANYTHING/ELSE 806 | -------------- 807 | 808 | ===== =========== 809 | Type: :ref:`private ` 810 | ===== =========== 811 | 812 | Any other URL is considered as an attempt to access ZIM file content using the 813 | legacy URL scheme and is redirected to ``/content/ANYTHING/ELSE``. 814 | 815 | 816 | Glossary 817 | ======== 818 | 819 | .. glossary:: 820 | 821 | Book name 822 | 823 | Name of the book as specified in the ZIM file metadata (for a 824 | ``kiwix-serve`` started *WITHOUT* the :option:`--library` option) or the 825 | library XML file (for a ``kiwix-serve`` started with the 826 | :option:`--library` option). 827 | 828 | .. note:: 829 | 830 | Two or more books may have the same name in the library. That's not 831 | considered a conflict, because there may be multiple versions of the 832 | "same" book (differing by the settings of the scraper, date, etc). 833 | :ref:`Library filtering ` by name will return all 834 | matching books. 835 | 836 | ZIM filename 837 | 838 | Name of a ZIM file on the server filesystem. 839 | 840 | ZIM name 841 | 842 | Identifier of a ZIM file in the server's library (used for referring to a 843 | particular ZIM file in requests). 844 | 845 | ZIM names are derived from the filenames as follows: 846 | 847 | - file extension is removed, 848 | - all characters are converted to lowercase, 849 | - diacritics are removed, 850 | - spaces are replaced with underscores, 851 | - ``+`` symbols are replaced with the text ``plus``. 852 | 853 | Presence of the :option:`-z`/:option:`--nodatealiases` option will create 854 | additional names (aliases) for filenames with dates. 855 | 856 | ZIM names are expected to be unique across the library. Any name conflicts 857 | (including those caused by the usage of the 858 | :option:`-z`/:option:`--nodatealiases` option) are reported on STDERR but, 859 | otherwise, are ignored (i.e. only one of the entries can be accessed via 860 | the conflicting name). 861 | 862 | ZIM title 863 | 864 | Title of a ZIM file. This can be any text (with whitespace). It is never 865 | used as a way of referring to a ZIM file. 866 | 867 | ZIM UUID 868 | 869 | This is a unique identifier of a ZIM file designated at its creation time 870 | and embedded in the ZIM file. Certain ``kiwix-serve`` operations may 871 | require that a ZIM file be referenced through its UUID rather than name. 872 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx==5.3.0 2 | sphinx-rtd-theme==1.1.1 3 | -------------------------------------------------------------------------------- /format_code.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | files=( 4 | "src/installer/kiwix-install.cpp" 5 | "src/searcher/kiwix-search.cpp" 6 | "src/manager/kiwix-manage.cpp" 7 | "src/server/kiwix-serve.cpp" 8 | ) 9 | 10 | for i in "${files[@]}" 11 | do 12 | echo $i 13 | clang-format -i -style=file $i 14 | done 15 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('kiwix-tools', 'cpp', 2 | version : '3.8.0', 3 | license : 'GPL', 4 | default_options: ['c_std=c11', 'cpp_std=c++17', 'werror=true']) 5 | 6 | compiler = meson.get_compiler('cpp') 7 | 8 | add_global_arguments('-DKIWIX_TOOLS_VERSION="@0@"'.format(meson.project_version()), language : 'cpp') 9 | 10 | if host_machine.system() == 'windows' 11 | add_project_arguments('-DNOMINMAX', language: 'cpp') 12 | endif 13 | 14 | static_linkage = get_option('static-linkage') 15 | if static_linkage 16 | # Static build is not supported on MacOS 17 | if host_machine.system() != 'darwin' 18 | add_global_link_arguments('-static-libstdc++', '--static', language:'cpp') 19 | endif 20 | endif 21 | 22 | thread_dep = dependency('threads') 23 | libzim_dep = dependency('libzim', version:['>=9.0.0', '<10.0.0'], static:static_linkage) 24 | libkiwix_dep = dependency('libkiwix', version:['>=14.0.0', '<15.0.0'], static:static_linkage) 25 | libdocopt_dep = dependency('docopt', static:static_linkage) 26 | 27 | all_deps = [thread_dep, libkiwix_dep, libzim_dep, libdocopt_dep] 28 | 29 | if static_linkage 30 | librt = compiler.find_library('rt', required:false) 31 | if librt.found() 32 | all_deps += librt 33 | endif 34 | endif 35 | 36 | subdir('src') 37 | if get_option('doc') 38 | subdir('docs') 39 | endif 40 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('static-linkage', type : 'boolean', value : false, 2 | description : 'Create statically linked binaries.') 3 | option('doc', type : 'boolean', value : false, 4 | description : 'Build the documentations.') 5 | -------------------------------------------------------------------------------- /src/man/fr/kiwix-manage.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX 1 "21 May 2012" 2 | .SH NAME 3 | kiwix\-manage \- Gestionnaire de bibliothèque Kiwix 4 | .SH SYNOPSIS 5 | .IX Header SYNOPSIS 6 | .B kiwix\-manage 7 | .br 8 | kiwix\-manage LIBRARY_PATH add ZIM_PATH ... 9 | .br 10 | kiwix-manage LIBRARY_PATH show [CONTENTID1] [CONTENTID2] ... 11 | .br 12 | kiwix\-manage LIBRARY_PATH remove CONTENTID1 [CONTENTID2] 13 | .SH DESCRIPTION 14 | .SS kiwix\-manage 15 | 16 | .PP 17 | Permet de gérer les contenus de la bibliothèque Kiwix. La bibliothèque est un fichier 18 | XML référencant les contenus ZIM et leurs méta-donnnées: Index, icone, date, etc. 19 | 20 | . 21 | .PP 22 | Un fichier d'exemple est disponible à http://www.kiwix.org/library\.xml 23 | 24 | .TP 25 | \fBadd\fR 26 | Ajoute le fichier \fBZIM_FILE\fP à la bibliothèque \fBLIBRARY_FILE\fP. 27 | 28 | .TP 29 | \fBshow\fR 30 | Show given \fBCONTENT_ID\fP from \fBLIBRARY_FILE\fR. If no \fBCONTENT_ID\fP is given then all contents from \fBLIBRARY_FILE\fR are shown. 31 | Affiche les détails de \fBCONTENT_ID\fP dans la bibliothèque \fBLIBRARY_FILE\fR. 32 | .br 33 | Sans \fBCONTENT_ID\fP, tous les contenus sont affichés. 34 | 35 | .TP 36 | \fBremove\fR 37 | Supprime le contenu \fBCONTENT_ID\fR de la bibliothèque. Au moins un \fBCONTENT_ID\fR doit être spécifié. 38 | 39 | .TP 40 | \fB\-\-zimPathToSave=\fR 41 | Change le chemin de référence du fichier ZIM dans la bibliothèque. 42 | 43 | .TP 44 | \fB\-\-current\fR 45 | Marque ce contenu comme celui courant (contenu par défaut) dans la biliothèque. 46 | 47 | .TP 48 | \fB\-\-backend=xapian|clucene\fR 49 | Séléctionne un moteur d'indexation. 50 | 51 | .TP 52 | \fB\-\-indexPath=FULLTEXT_IDX_PATH\fR 53 | Chemin vers l'index plein texte correspondant au fichier ZIM. 54 | 55 | .TP 56 | \fBurl\fR 57 | Définit l'adresse URL corresponsant au fichier ZIM pour pouvoir être téléchargé depuis Kiwix. 58 | 59 | .SH SEE ALSO 60 | kiwix(1) kiwix\-install(1) kiwix\-serve(1) 61 | .SH AUTHOR 62 | Emmanuel Engelhart 63 | .br 64 | Vasudev Kamath (Manual) 65 | -------------------------------------------------------------------------------- /src/man/fr/kiwix-serve.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX 1 "21 May 2012" 2 | .SH NAME 3 | kiwix\-serve \- Serveur Web Kiwix 4 | .SH SYNOPSIS 5 | .IX Header "SYNOPSIS" 6 | .br 7 | kiwix\-serve [\-\-index=INDEX_PATH] [\-\-port=PORT] [\-\-verbose] [\-\-daemon] [\-\-attachToProcess=PID] ZIM_PATH 8 | .br 9 | kiwix\-serve \-\-library [\-\-port=PORT] [\-\-verbose] [\-\-daemon] [\-\-attachToProcess=PID] LIBRARY_PATH 10 | .SH DESCRIPTION 11 | .PP 12 | Serveur Web (HTTP) autonome pour diffuser des contenus ZIM sur le réseau. 13 | 14 | .TP 15 | \fB\-\-index=INDEX_PATH\fR 16 | Chemin vers l'index plein text du fichier ZIM. 17 | 18 | .TP 19 | \fB\-\-port=PORT\fR 20 | Port sur lequel le serveur doit écouter. 21 | .br 22 | Par défaut, le serveur écoute sur le port 80. 23 | 24 | .TP 25 | \fB\-\-verbose\fR 26 | Active le mode verbeux de la sortie. 27 | 28 | .TP 29 | \fB\-\-daemon\fR 30 | Execute le serveur en mode démon. 31 | 32 | .TP 33 | \fB\-\-attachToProcess=PID\fR 34 | Arrêter le serveur lorsque que le processus PID meurt. 35 | 36 | .TP 37 | \fBZIM_PATH\fR 38 | Chemin vers le fichier ZIM à diffuser. 39 | .br 40 | Obligatoire en dehors du mode bibliothèque. 41 | 42 | .TP 43 | \fB\-\-library\fR 44 | Active le mode bibliothèque. 45 | .br 46 | Sert les contenus d'une bibliothèque Kiwix au lieu d'un seul fichier ZIM. 47 | 48 | .TP 49 | \fBLIBRARY_PATH\fR 50 | Chemin vers le fichier bibliothèque de Kiwix. 51 | .br 52 | Le fichier bibliothèque est un fichier XML créé avec \fBkiwix-manage\fB. 53 | 54 | .SH SEE ALSO 55 | kiwix(1) kiwix\-manage(1) 56 | .br 57 | kiwix\-install(1) 58 | .SH AUTHOR 59 | Emmanuel Engelhart 60 | .br 61 | Vasudev Kamath (Manual) 62 | -------------------------------------------------------------------------------- /src/man/fr/meson.build: -------------------------------------------------------------------------------- 1 | install_man('kiwix-manage.1', 2 | 'kiwix-serve.1', 3 | install_dir:get_option('mandir')+'/fr/man1') 4 | -------------------------------------------------------------------------------- /src/man/kiwix-manage.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX-MANAGE 1 "21 May 2012" 2 | 3 | .SH NAME 4 | kiwix\-manage \- Kiwix Library Manager 5 | 6 | .SH SYNOPSIS 7 | .IX Header SYNOPSIS 8 | .TP 9 | \fBkiwix\-manage\fR LIBRARY_PATH \fBadd\fR ZIM_PATH ... 10 | .TP 11 | \fBkiwix\-manage\fR LIBRARY_PATH \fBshow\fR [ZIM_ID_1] [ZIM_ID_2] ... 12 | .TP 13 | \fBkiwix\-manage\fR LIBRARY_PATH \fBremove\fR ZIM_ID_1 [ZIM_ID_2] ... 14 | .TP 15 | \fBkiwix\-manage\fR --version 16 | .TP 17 | \fBkiwix\-manage\fR --help 18 | 19 | .SH DESCRIPTION 20 | .PP 21 | \fBkiwix\-manage\fP is a command line tool for manipulating a Kiwix XML library. 22 | .PP 23 | \fBkiwix\-manage\fP allows to manage the entries of the Kiwix 24 | library. The library file is a flat XML file listing ZIM files with 25 | all necessary information like id, favicon, date, creator, 26 | description, filepath, title, url, etc. 27 | 28 | .SH ACTIONS 29 | 30 | .TP 31 | \fBadd\fR 32 | Add \fBZIM_FILE\fP to \fBLIBRARY_FILE\fP. Create the library file if necessary. 33 | 34 | .TP 35 | \fBremove\fR 36 | Remove the given \fBZIM_ID\fR from \fBLIBRARY_FILE\fR. At least one \fBZIM_ID\fR should be specified. 37 | 38 | .TP 39 | \fBshow\fR 40 | Show given \fBZIM_ID\fP from \fBLIBRARY_FILE\fR. If no \fBZIM_ID\fP is given then all contents from \fBLIBRARY_FILE\fR are shown. 41 | 42 | .SH OPTIONS 43 | .TP 44 | Options to be used with the action \fBadd\fR: 45 | 46 | .TP 47 | \fB\-\-url=HTTP_URL\fR 48 | Set the ZIM online HTTP(S) URL 49 | 50 | .TP 51 | \fB\-\-zimPathToSave=OTHER_FS_PATH\fR 52 | Set an arbitrary ZIM filesystem path (instead of the ZIM_PATH) 53 | 54 | .TP 55 | Other options (to be used alone): 56 | 57 | .TP 58 | \fB\-\-help | \-h\fR 59 | Display the kiwix-manage help 60 | 61 | .TP 62 | \fB\-\-version | \-v\fR 63 | Display the version of kiwix-manage and all dependences 64 | 65 | .SH SEE ALSO 66 | kiwix\-serve(1) 67 | 68 | .SH AUTHORS 69 | Kiwix team 70 | -------------------------------------------------------------------------------- /src/man/kiwix-search.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX-SEARCH "1" "July 2020" "kiwix-tools" "User Commands" 2 | .SH NAME 3 | kiwix-search \- find articles using a fulltext search pattern 4 | .SH SYNOPSIS 5 | \fBkiwix-search\fR [OPTIONS] ZIM PATTERN\fR 6 | .SH DESCRIPTION 7 | .TP 8 | ZIM 9 | ZIM file to search 10 | .TP 11 | PATTERN 12 | Words or parts of words to search for in the ZIM file 13 | .TP 14 | \fB\-s\fR, \fB\-\-suggestion\fR 15 | Suggest article titles based on the PATTERN instead of a fulltext search 16 | .TP 17 | \fB\-V\fR, \fB\-\-version\fR 18 | print software version 19 | .TP 20 | \fB\-v\fR, \fB\-\-verbose\fR 21 | Give details about the search process 22 | -------------------------------------------------------------------------------- /src/man/kiwix-serve.1: -------------------------------------------------------------------------------- 1 | .TH KIWIX 1 "10 July 2023" 2 | 3 | .SH NAME 4 | kiwix-serve \- Kiwix HTTP Server 5 | 6 | .SH SYNOPSIS 7 | 8 | .B kiwix-serve --library [OPTIONS] LIBRARY_FILE_PATH 9 | .br 10 | .B kiwix-serve [OPTIONS] ZIM_FILE_PATH ... 11 | 12 | .SH DESCRIPTION 13 | The \fBkiwix-serve\fR command is used to run a stand-alone HTTP server for serving ZIM contents over the network. 14 | 15 | .SH ARGUMENTS 16 | .TP 17 | \fBLIBRARY_FILE_PATH\fR 18 | Path of an XML library file listing ZIM files to serve. To be used only with the --library option. Multiple library files can be provided as a semicolon (;) separated list. 19 | 20 | .TP 21 | \fBZIM_FILE_PATH ...\fR 22 | ZIM file path(s). Multiple arguments are allowed. 23 | 24 | .SH OPTIONS 25 | .TP 26 | \fB--library\fR 27 | By default, kiwix-serve expects a list of ZIM files as command line arguments. Providing the --library option tells kiwix-serve that the command line argument is rather a library XML file. 28 | 29 | .TP 30 | \fB-i ADDR, --address=ADDR\fR 31 | Listen only on this IP address. By default, the server listens on all available IP addresses. Alternatively, you can use special values to define which types of connections to accept: 32 | 33 | all : Listen for connections on all IP addresses (IPv4 and IPv6). 34 | .br 35 | ipv4 : Listen for connections on all IPv4 addresses. 36 | .br 37 | ipv6 : Listen for connections on all IPv6 addresses. 38 | 39 | .TP 40 | \fB-p PORT, --port=PORT\fR 41 | TCP port on which to listen for HTTP requests (default: 80). 42 | 43 | .TP 44 | \fB-r ROOT, --urlRootLocation=ROOT\fR 45 | URL prefix on which the content should be made available (default: empty). 46 | 47 | .TP 48 | \fB-d, --daemon\fR 49 | Detach the HTTP server daemon from the main process. 50 | 51 | .TP 52 | \fB-a PID, --attachToProcess=PID\fR 53 | Exit when the process with id PID stops running. 54 | 55 | .TP 56 | \fB-M, --monitorLibrary\fR 57 | Monitor the XML library file and reload it automatically when it changes. 58 | 59 | Library reloading can be forced anytime by sending a SIGHUP signal to the 60 | \*(lqkiwix-serve\*(rq process (this works regardless of the presence of the 61 | \*(lq--monitorLibrary\*(rq/\*(lq-M\*(rq option). 62 | 63 | .TP 64 | \fB-m, --nolibrarybutton\fR 65 | Disable the library home button in the ZIM viewer toolbar. 66 | 67 | .TP 68 | \fB-n, --nosearchbar\fR 69 | Disable the search box in the ZIM viewer toolbar. 70 | 71 | .TP 72 | \fB-b, --blockexternal\fR 73 | Prevent users from directly navigating to external resources via links in ZIM content. 74 | 75 | .TP 76 | \fB-t N, --threads=N\fR 77 | Number of threads to run in parallel (default: 4). 78 | 79 | .TP 80 | \fB-s N, --searchLimit=N\fR 81 | Maximum number of ZIM files in a fulltext multizim search (default: No limit). 82 | 83 | .TP 84 | \fB-z, --nodatealiases\fR 85 | Create URL aliases for each content by removing the date embedded in the file name. 86 | 87 | The expected format of the date in the filename is \*(lq_YYYY-MM\*(rq. For example, a ZIM file named \*(lqwikipedia_en_all_2020-08.zim\*(rq will be accessible both as \*(lqwikipedia_en_all_2020-08\*(rq and \*(lqwikipedia_en_all\*(rq. 88 | 89 | .TP 90 | \fB-c PATH, --customIndex=PATH\fR 91 | Override the welcome page with a custom HTML file. 92 | 93 | .TP 94 | \fB-L N, --ipConnectionLimit=N\fR 95 | Max number of (concurrent) connections per IP (default: infinite, recommended: >= 6). 96 | 97 | .TP 98 | \fB-k, --skipInvalid\fR 99 | Startup even when ZIM files are invalid (those will be skipped) 100 | 101 | .TP 102 | \fB-v, --verbose\fR 103 | Print debug log to STDOUT. 104 | 105 | .TP 106 | \fB-V, --version\fR 107 | Print the software version. 108 | 109 | .TP 110 | \fB-h, --help\fR 111 | Print a help message. 112 | 113 | .SH EXAMPLES 114 | Serve a single ZIM file: 115 | .sp 116 | .nf 117 | .B kiwix-serve myzim.zim 118 | .fi 119 | 120 | Serve multiple ZIM files: 121 | .sp 122 | .nf 123 | .B kiwix-serve zim1.zim zim2.zim zim3.zim 124 | .fi 125 | 126 | Serve ZIM files from a library: 127 | .sp 128 | .nf 129 | .B kiwix-serve --library library.xml 130 | .fi 131 | 132 | .SH DOCUMENTATION 133 | Online documentation: https://kiwix-tools.readthedocs.io/en/latest/kiwix-serve.html 134 | .br 135 | Source code: https://github.com/kiwix/kiwix-tools 136 | .br 137 | More info: https://wiki.kiwix.org/wiki/Kiwix-serve 138 | 139 | .SH AUTHORS 140 | Emmanuel Engelhart 141 | .br 142 | Vasudev Kamath 143 | -------------------------------------------------------------------------------- /src/man/meson.build: -------------------------------------------------------------------------------- 1 | install_man('kiwix-manage.1', 2 | 'kiwix-search.1', 3 | 'kiwix-serve.1') 4 | subdir('fr') 5 | -------------------------------------------------------------------------------- /src/manager/kiwix-manage.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2019 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 | #include 23 | #include 24 | #include 25 | 26 | #include "../version.h" 27 | 28 | using namespace std; 29 | 30 | enum supportedAction { NONE, ADD, SHOW, REMOVE }; 31 | 32 | void show(const kiwix::Library& library, const std::string& bookId) 33 | { 34 | try { 35 | auto& book = library.getBookById(bookId); 36 | std::cout << "id:\t\t" << book.getId() << std::endl 37 | << "path:\t\t" << book.getPath() << std::endl 38 | << "url:\t\t" << book.getUrl() << std::endl 39 | << "title:\t\t" << book.getTitle() << std::endl 40 | << "name:\t\t" << book.getName() << std::endl 41 | << "tags:\t\t" << book.getTags() << std::endl 42 | << "description:\t" << book.getDescription() << std::endl 43 | << "creator:\t" << book.getCreator() << std::endl 44 | << "date:\t\t" << book.getDate() << std::endl 45 | << "articleCount:\t" << book.getArticleCount() << std::endl 46 | << "mediaCount:\t" << book.getMediaCount() << std::endl 47 | << "size:\t\t" << book.getSize() << " KB" << std::endl; 48 | } catch (std::out_of_range&) { 49 | std::cout << "No book " << bookId << " in the library" << std::endl; 50 | } 51 | std::cout << std::endl; 52 | } 53 | 54 | // Older version of docopt doesn't declare Options. Let's declare it ourself. 55 | using Options = std::map; 56 | 57 | 58 | /* Print correct console usage options */ 59 | static const char USAGE[] = 60 | R"(Manipulates the Kiwix library XML file 61 | 62 | Usage: 63 | kiwix-manage LIBRARYPATH add [--zimPathToSave=] [--url=] ZIMPATH 64 | kiwix-manage LIBRARYPATH remove|delete ZIMID ... 65 | kiwix-manage LIBRARYPATH show [ZIMID ...] 66 | kiwix-manage -v | --version 67 | kiwix-manage -h | --help 68 | 69 | Arguments: 70 | LIBRARYPATH The XML library file path. 71 | ZIMID ZIM file unique ID. 72 | ZIMPATH A path to a zim to add. 73 | 74 | Options: 75 | Custom options for "add" action: 76 | --zimPathToSave= Replace the current ZIM file path 77 | --url= Create an "url" attribute for the online version of the ZIM file 78 | 79 | Other options: 80 | -h --help Print this help 81 | -v --version Print the software version 82 | 83 | Examples: 84 | Add ZIM files to library: kiwix-manage my_library.xml add first.zim second.zim 85 | Remove ZIM files from library: kiwix-manage my_library.xml remove e5c2c003-b49e-2756-5176-5d9c86393dd9 86 | Show all library ZIM files: kiwix-manage my_library.xml show 87 | 88 | Documentation: 89 | Source code https://github.com/kiwix/kiwix-tools 90 | More info https://wiki.kiwix.org/wiki/Kiwix-manage 91 | )"; 92 | 93 | int handle_show(const kiwix::Library& library, const std::string& libraryPath, 94 | const Options& options) 95 | { 96 | if (options.at("ZIMID").isStringList()) { 97 | auto bookIds = options.at("ZIMID").asStringList(); 98 | for(auto& bookId: bookIds) { 99 | show(library, bookId); 100 | } 101 | } else { 102 | auto booksIds = library.getBooksIds(); 103 | for(auto& bookId: booksIds) { 104 | show(library, bookId); 105 | } 106 | } 107 | return(0); 108 | } 109 | 110 | int handle_add(kiwix::LibraryPtr library, const std::string& libraryPath, 111 | const Options& options) 112 | { 113 | string zimPathToSave; 114 | string url; 115 | 116 | kiwix::Manager manager(library); 117 | 118 | std::string zimPath = options.at("ZIMPATH").asString(); 119 | if (options.at("--zimPathToSave").isString()) { 120 | zimPathToSave = options.at("--zimPathToSave").asString(); 121 | } else { 122 | zimPathToSave = zimPath; 123 | } 124 | if (options.at("--url").isString()) { 125 | url = options.at("--url").asString(); 126 | } 127 | 128 | if (manager.addBookFromPathAndGetId(zimPath, zimPathToSave, url, false).empty()) { 129 | std::cerr << "Cannot add zim " << zimPath << " to the library." << std::endl; 130 | return 1; 131 | } 132 | 133 | return 0; 134 | } 135 | 136 | int handle_remove(kiwix::Library& library, const std::string& libraryPath, 137 | const Options& options) 138 | { 139 | const unsigned int totalBookCount = library.getBookCount(true, true); 140 | int exitCode = 0; 141 | 142 | if (!totalBookCount) { 143 | std::cerr << "Library is empty, no book to delete." 144 | << std::endl; 145 | return 1; 146 | } 147 | 148 | auto bookIds = options.at("ZIMID").asStringList(); 149 | for (auto& bookId: bookIds) { 150 | if (!library.removeBookById(bookId)) { 151 | std::cerr << "Invalid book id '" << bookId << "'." << std::endl; 152 | exitCode = 1; 153 | } 154 | } 155 | 156 | return(exitCode); 157 | } 158 | 159 | int main(int argc, char** argv) 160 | { 161 | supportedAction action = NONE; 162 | auto library = kiwix::Library::create(); 163 | 164 | Options args; 165 | try { 166 | args = docopt::docopt_parse(USAGE, {argv+1, argv+argc}, false, false); 167 | } catch (docopt::DocoptArgumentError const & error ) { 168 | std::cerr << error.what() << std::endl; 169 | std::cerr << USAGE << std::endl; 170 | return -1; 171 | } 172 | 173 | if (args["--help"].asBool()) { 174 | std::cout << USAGE << std::endl; 175 | return 0; 176 | } 177 | 178 | if (args["--version"].asBool()) { 179 | version(); 180 | return 0; 181 | } 182 | 183 | std::string libraryPath = args.at("LIBRARYPATH").asString(); 184 | 185 | if (args.at("add").asBool()) 186 | action = ADD; 187 | else if (args.at("show").asBool()) 188 | action = SHOW; 189 | else if (args.at("remove").asBool() || args.at("delete").asBool()) 190 | action = REMOVE; 191 | 192 | /* Try to read the file */ 193 | libraryPath = kiwix::isRelativePath(libraryPath) 194 | ? kiwix::computeAbsolutePath(kiwix::getCurrentDirectory(), libraryPath) 195 | : libraryPath; 196 | kiwix::Manager manager(library); 197 | if (!manager.readFile(libraryPath, false)) { 198 | if (kiwix::fileExists(libraryPath) || action!=ADD) { 199 | std::cerr << "Cannot read the library " << libraryPath << std::endl; 200 | return 1; 201 | } 202 | } 203 | 204 | /* SHOW */ 205 | int exitCode = 0; 206 | switch (action) { 207 | case SHOW: 208 | exitCode = handle_show(*library, libraryPath, args); 209 | break; 210 | case ADD: 211 | exitCode = handle_add(library, libraryPath, args); 212 | break; 213 | case REMOVE: 214 | exitCode = handle_remove(*library, libraryPath, args); 215 | break; 216 | case NONE: 217 | break; 218 | } 219 | 220 | if (exitCode) { 221 | return exitCode; 222 | } 223 | 224 | /* Rewrite the library file */ 225 | if (action == REMOVE || action == ADD) { 226 | // writeToFile return true (1) if everything is ok => exitCode is 0 227 | if (!library->writeToFile(libraryPath)) { 228 | std::cerr << "Cannot write the library " << libraryPath << std::endl; 229 | return 1; 230 | } 231 | } 232 | 233 | return 0; 234 | } 235 | -------------------------------------------------------------------------------- /src/manager/meson.build: -------------------------------------------------------------------------------- 1 | executable('kiwix-manage', ['kiwix-manage.cpp'], 2 | dependencies:all_deps, 3 | install:true) 4 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | subdir('manager') 2 | subdir('searcher') 3 | subdir('server') 4 | subdir('man') 5 | -------------------------------------------------------------------------------- /src/searcher/kiwix-search.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 | 27 | #include "../version.h" 28 | 29 | using namespace std; 30 | 31 | 32 | // Older version of docopt doesn't declare Options. Let's declare it ourself. 33 | using Options = std::map; 34 | 35 | static const char USAGE[] = 36 | R"(Find articles based on a fulltext search pattern. 37 | 38 | Usage: 39 | kiwix-search [options] ZIM PATTERN 40 | kiwix-search -h | --help 41 | kiwix-search -V | --version 42 | 43 | Arguments: 44 | ZIM The full path of the ZIM file 45 | PATTERN Word(s) - or part of - to search in the ZIM. 46 | 47 | Options: 48 | -s --suggestion Suggest article titles based on the few letters of the PATTERN instead of making a fulltext search. Work a bit like a completion solution 49 | -v --verbose Give details about the search process 50 | -V --version Print software version 51 | -h --help Print this help 52 | )"; 53 | 54 | 55 | int main(int argc, char** argv) 56 | { 57 | Options args; 58 | try { 59 | args = docopt::docopt_parse(USAGE, {argv+1, argv+argc}, false, false); 60 | } catch (docopt::DocoptArgumentError const & error ) { 61 | std::cerr << error.what() << std::endl; 62 | std::cerr << USAGE << std::endl; 63 | return -1; 64 | } 65 | 66 | if (args.at("--help").asBool()) { 67 | std::cout << USAGE << std::endl; 68 | return 0; 69 | } 70 | 71 | if (args.at("--version").asBool()) { 72 | version(); 73 | return 0; 74 | } 75 | 76 | auto zimPath = args.at("ZIM").asString(); 77 | auto pattern = args.at("PATTERN").asString(); 78 | auto verboseFlag = args.at("--verbose").asBool(); 79 | 80 | /* Try to prepare the indexing */ 81 | try { 82 | zim::Archive archive(zimPath); 83 | 84 | if (args.at("--suggestion").asBool()) { 85 | zim::SuggestionSearcher searcher(archive); 86 | searcher.setVerbose(verboseFlag); 87 | for (const auto& r:searcher.suggest(pattern).getResults(0, 10)) { 88 | cout << r.getTitle() << endl; 89 | } 90 | } else { 91 | zim::Searcher searcher(archive); 92 | searcher.setVerbose(verboseFlag); 93 | const zim::Query query(pattern); 94 | for (const auto& r : searcher.search(query).getResults(0, 10) ) { 95 | cout << r.getTitle() << endl; 96 | } 97 | } 98 | } catch ( const std::runtime_error& err) { 99 | cerr << err.what() << endl; 100 | exit(1); 101 | } 102 | 103 | exit(0); 104 | } 105 | -------------------------------------------------------------------------------- /src/searcher/meson.build: -------------------------------------------------------------------------------- 1 | executable('kiwix-search', ['kiwix-search.cpp'], 2 | dependencies:all_deps, 3 | install:true) 4 | -------------------------------------------------------------------------------- /src/server/kiwix-serve.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright 2009-2019 Emmanuel Engelhart 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 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef _WIN32 28 | # include 29 | #else 30 | # include 31 | # include 32 | #endif 33 | #include 34 | 35 | #ifdef __APPLE__ 36 | # import 37 | # import 38 | # define MIBSIZE 4 39 | #endif 40 | 41 | #include "../version.h" 42 | 43 | #define DEFAULT_THREADS 4 44 | #define LITERAL_AS_STR(A) #A 45 | #define AS_STR(A) LITERAL_AS_STR(A) 46 | 47 | 48 | static const char USAGE[] = 49 | R"(Deliver ZIM file(s) articles via HTTP 50 | 51 | Usage: 52 | kiwix-serve [options] ZIMPATH ... 53 | kiwix-serve [options] (-l | --library) LIBRARYPATH 54 | kiwix-serve -h | --help 55 | kiwix-serve -V | --version 56 | 57 | Mandatory arguments: 58 | LIBRARYPATH XML library file path listing ZIM file to serve. To be used only with the --library argument." 59 | ZIMPATH ZIM file path(s) 60 | 61 | Options: 62 | -h --help Print this help 63 | -a --attachToProcess= Exit if given process id is not running anymore [default: 0] 64 | -d --daemon Detach the HTTP server daemon from the main process 65 | -i
--address=
Listen only on the specified IP address. Specify 'ipv4', 'ipv6' or 'all' to listen on all IPv4, IPv6 or both types of addresses, respectively [default: all] 66 | -M --monitorLibrary Monitor the XML library file and reload it automatically 67 | -m --nolibrarybutton Don't print the builtin home button in the builtin top bar overlay 68 | -n --nosearchbar Don't print the builtin bar overlay on the top of each served page 69 | -b --blockexternal Prevent users from directly accessing external links 70 | -p --port= Port on which to listen to HTTP requests [default: 80] 71 | -r --urlRootLocation= URL prefix on which the content should be made available [default: /] 72 | -s --searchLimit= Maximun number of zim in a fulltext multizim search [default: 0] 73 | -t --threads= Number of threads to run in parallel [default: )" AS_STR(DEFAULT_THREADS) R"(] 74 | -v --verbose Print debug log to STDOUT 75 | -V --version Print software version 76 | -z --nodatealiases Create URL aliases for each content by removing the date 77 | -c --customIndex= Add path to custom index.html for welcome page 78 | -L --ipConnectionLimit= Max number of (concurrent) connections per IP [default: 0] (recommended: >= 6) 79 | -k --skipInvalid Startup even when ZIM files are invalid (those will be skipped) 80 | 81 | Documentation: 82 | Source code https://github.com/kiwix/kiwix-tools 83 | More info https://wiki.kiwix.org/wiki/Kiwix-serve 84 | https://kiwix-tools.readthedocs.io/en/latest/kiwix-serve.html 85 | )"; 86 | 87 | std::string loadCustomTemplate (std::string customIndexPath) { 88 | customIndexPath = kiwix::isRelativePath(customIndexPath) ? 89 | kiwix::computeAbsolutePath(kiwix::getCurrentDirectory(), customIndexPath) : 90 | customIndexPath; 91 | if (!kiwix::fileReadable(customIndexPath)) { 92 | throw std::runtime_error("No such file exist (or file is not readable) " + customIndexPath); 93 | } 94 | if (kiwix::getMimeTypeForFile(customIndexPath) != "text/html") { 95 | throw std::runtime_error("Invalid File Mime Type " + kiwix::getMimeTypeForFile(customIndexPath)); 96 | } 97 | std::string indexTemplateString = kiwix::getFileContent(customIndexPath); 98 | 99 | if (indexTemplateString.empty()) { 100 | throw std::runtime_error("Unreadable or empty file " + customIndexPath); 101 | } 102 | return indexTemplateString; 103 | } 104 | 105 | inline std::string normalizeRootUrl(std::string rootUrl) 106 | { 107 | while ( !rootUrl.empty() && rootUrl.back() == '/' ) 108 | rootUrl.pop_back(); 109 | 110 | while ( !rootUrl.empty() && rootUrl.front() == '/' ) 111 | rootUrl = rootUrl.substr(1); 112 | return rootUrl.empty() ? rootUrl : "/" + rootUrl; 113 | } 114 | 115 | #ifndef _WIN32 116 | volatile sig_atomic_t waiting = false; 117 | volatile sig_atomic_t libraryMustBeReloaded = false; 118 | void handle_sigterm(int signum) 119 | { 120 | if ( waiting == false ) { 121 | _exit(signum); 122 | } 123 | waiting = false; 124 | } 125 | 126 | void handle_sighup(int signum) 127 | { 128 | libraryMustBeReloaded = true; 129 | } 130 | 131 | typedef void (*SignalHandler)(int); 132 | 133 | void set_signal_handler(int sig, SignalHandler handler) 134 | { 135 | struct sigaction sa; 136 | sigaction(sig, NULL, &sa); 137 | sa.sa_handler = handler; 138 | sigaction(sig, &sa, NULL); 139 | } 140 | 141 | void setup_sighandlers() 142 | { 143 | set_signal_handler(SIGTERM, &handle_sigterm); 144 | set_signal_handler(SIGINT, &handle_sigterm); 145 | set_signal_handler(SIGHUP, &handle_sighup); 146 | } 147 | #else 148 | bool waiting = false; 149 | bool libraryMustBeReloaded = false; 150 | #endif 151 | 152 | uint64_t fileModificationTime(const std::string& path) 153 | { 154 | #if defined(_WIN32) && !defined(stat) 155 | #define stat _stat 156 | #endif 157 | struct stat fileStatData; 158 | if ( stat(path.c_str(), &fileStatData) == 0 ) { 159 | return fileStatData.st_mtime; 160 | } 161 | return 0; 162 | #ifdef _WIN32 163 | #undef stat 164 | #endif 165 | } 166 | 167 | uint64_t newestFileTimestamp(const std::vector& paths) 168 | { 169 | uint64_t t = 0; 170 | for ( const auto& p : paths ) { 171 | t = std::max(t, fileModificationTime(p)); 172 | } 173 | 174 | return t; 175 | } 176 | 177 | bool reloadLibrary(kiwix::Manager& mgr, const std::vector& paths) 178 | { 179 | try { 180 | std::cout << "Loading the library from the following files:\n"; 181 | for ( const auto& p : paths ) { 182 | std::cout << "\t" << p << std::endl; 183 | } 184 | mgr.reload(paths); 185 | std::cout << "The library was successfully loaded." << std::endl; 186 | return true; 187 | } catch ( const std::runtime_error& err ) { 188 | std::cerr << "ERROR: " << err.what() << std::endl; 189 | std::cerr << "Errors encountered while loading the library." << std::endl; 190 | return false; 191 | } 192 | } 193 | 194 | // docopt::value::isLong() is counting repeated values. 195 | // It doesn't check if the string can be parsed as long. 196 | // (Contrarly to `asLong` which will try to convert string to long) 197 | // See https://github.com/docopt/docopt.cpp/issues/62 198 | // `isLong` is a small helper to get if the value can be parsed as long. 199 | inline bool isLong(const docopt::value& v) { 200 | try { 201 | v.asLong(); 202 | return true; 203 | } catch (...) { 204 | return false; 205 | } 206 | } 207 | 208 | #define FLAG(NAME, VAR) if (arg.first == NAME) { VAR = arg.second.asBool(); continue; } 209 | #define STRING(NAME, VAR) if (arg.first == NAME && arg.second.isString() ) { VAR = arg.second.asString(); continue; } 210 | #define STRING_LIST(NAME, VAR, ERRORSTR) if (arg.first == NAME) { if (arg.second.isStringList()) { VAR = arg.second.asStringList(); continue; } else { errorString = ERRORSTR; break; } } 211 | #define INT(NAME, VAR, ERRORSTR) if (arg.first == NAME ) { if (isLong(arg.second)) { VAR = arg.second.asLong(); continue; } else { errorString = ERRORSTR; break; } } 212 | 213 | // Older version of docopt doesn't declare Options. Let's declare it ourself. 214 | using Options = std::map; 215 | 216 | int main(int argc, char** argv) 217 | { 218 | #ifndef _WIN32 219 | setup_sighandlers(); 220 | #endif 221 | 222 | std::string rootLocation = "/"; 223 | auto library = kiwix::Library::create(); 224 | unsigned int nb_threads = DEFAULT_THREADS; 225 | std::vector zimPathes; 226 | std::string libraryPath; 227 | std::string rootPath; 228 | std::string address; 229 | std::string customIndexPath=""; 230 | std::string indexTemplateString=""; 231 | int serverPort = 80; 232 | bool daemonFlag [[gnu::unused]] = false; 233 | bool helpFlag = false; 234 | bool noLibraryButtonFlag = false; 235 | bool noSearchBarFlag = false; 236 | bool noDateAliasesFlag = false; 237 | bool blockExternalLinks = false; 238 | bool isVerboseFlag = false; 239 | bool monitorLibrary = false; 240 | bool versionFlag = false; 241 | unsigned int PPID = 0; 242 | int ipConnectionLimit = 0; 243 | int searchLimit = 0; 244 | bool skipInvalid = false; 245 | 246 | std::string errorString; 247 | 248 | Options args; 249 | try { 250 | args = docopt::docopt_parse(USAGE, {argv+1, argv+argc}, false, false); 251 | } catch (docopt::DocoptArgumentError const & error) { 252 | std::cerr << error.what() << std::endl; 253 | std::cerr << USAGE << std::endl; 254 | return -1; 255 | } 256 | 257 | for (auto const& arg: args) { 258 | FLAG("--help", helpFlag) 259 | FLAG("--daemon", daemonFlag) 260 | FLAG("--verbose", isVerboseFlag) 261 | FLAG("--nosearchbar", noSearchBarFlag) 262 | FLAG("--blockexternal", blockExternalLinks) 263 | FLAG("--nodatealiases", noDateAliasesFlag) 264 | FLAG("--nolibrarybutton",noLibraryButtonFlag) 265 | FLAG("--monitorLibrary", monitorLibrary) 266 | FLAG("--skipInvalid", skipInvalid) 267 | FLAG("--version", versionFlag) 268 | STRING("LIBRARYPATH", libraryPath) 269 | INT("--port", serverPort, "Port must be an integer") 270 | INT("--attachToProcess", PPID, "Process to attach must be an integer") 271 | STRING("--address", address) 272 | INT("--threads", nb_threads, "Number of threads must be an integer") 273 | STRING("--urlRootLocation", rootLocation) 274 | STRING("--customIndex", customIndexPath) 275 | INT("--ipConnectionLimit", ipConnectionLimit, "IP connection limit must be an integer") 276 | INT("--searchLimit", searchLimit, "Search limit must be an integer") 277 | STRING_LIST("ZIMPATH", zimPathes, "ZIMPATH must be a string list") 278 | } 279 | 280 | if (!errorString.empty()) { 281 | std::cerr << errorString << std::endl; 282 | std::cerr << USAGE << std::endl; 283 | return -1; 284 | } 285 | 286 | if (helpFlag) { 287 | std::cout << USAGE << std::endl; 288 | return 0; 289 | } 290 | 291 | if (versionFlag) { 292 | version(); 293 | return 0; 294 | } 295 | 296 | /* Setup the library manager and get the list of books */ 297 | kiwix::Manager manager(library); 298 | std::vector libraryPaths; 299 | if (!libraryPath.empty()) { 300 | libraryPaths = kiwix::split(libraryPath, ";"); 301 | if ( !reloadLibrary(manager, libraryPaths) ) { 302 | exit(1); 303 | } 304 | 305 | /* Check if the library is not empty (or only remote books)*/ 306 | if (library->getBookCount(true, false) == 0) { 307 | std::cerr << "The XML library file '" << libraryPath 308 | << "' is empty (or has only remote books)." << std::endl; 309 | } 310 | } else { 311 | std::vector::iterator it; 312 | for (it = zimPathes.begin(); it != zimPathes.end(); it++) { 313 | if (!manager.addBookFromPath(*it, *it, "", false)) { 314 | if (skipInvalid) { 315 | std::cerr << "Skipping invalid '" << *it << "' ...continuing" << std::endl; 316 | } else { 317 | std::cerr << "Unable to add the ZIM file '" << *it 318 | << "' to the internal library." << std::endl; 319 | exit(1); 320 | } 321 | } 322 | } 323 | } 324 | auto libraryFileTimestamp = newestFileTimestamp(libraryPaths); 325 | auto curLibraryFileTimestamp = libraryFileTimestamp; 326 | 327 | kiwix::IpMode ipMode = kiwix::IpMode::AUTO; 328 | 329 | if (address == "all") { 330 | address.clear(); 331 | ipMode = kiwix::IpMode::ALL; 332 | } else if (address == "ipv4") { 333 | address.clear(); 334 | ipMode = kiwix::IpMode::IPV4; 335 | } else if (address == "ipv6") { 336 | address.clear(); 337 | ipMode = kiwix::IpMode::IPV6; 338 | } 339 | 340 | #ifndef _WIN32 341 | /* Fork if necessary */ 342 | if (daemonFlag) { 343 | pid_t pid; 344 | 345 | /* Fork off the parent process */ 346 | pid = fork(); 347 | if (pid < 0) { 348 | exit(1); 349 | } 350 | 351 | /* If we got a good PID, then 352 | we can exit the parent process. */ 353 | if (pid > 0) { 354 | exit(0); 355 | } 356 | } 357 | #endif 358 | 359 | auto nameMapper = std::make_shared(library, noDateAliasesFlag); 360 | kiwix::Server server(library, nameMapper); 361 | 362 | if (!customIndexPath.empty()) { 363 | try { 364 | indexTemplateString = loadCustomTemplate(customIndexPath); 365 | } catch (std::runtime_error& e) { 366 | std::cerr << "ERROR: " << e.what() << std::endl; 367 | exit(1); 368 | } 369 | } 370 | 371 | server.setAddress(address); 372 | server.setRoot(rootLocation); 373 | server.setPort(serverPort); 374 | server.setNbThreads(nb_threads); 375 | server.setVerbose(isVerboseFlag); 376 | server.setTaskbar(!noSearchBarFlag, !noLibraryButtonFlag); 377 | server.setBlockExternalLinks(blockExternalLinks); 378 | server.setIndexTemplateString(indexTemplateString); 379 | server.setIpConnectionLimit(ipConnectionLimit); 380 | server.setMultiZimSearchLimit(searchLimit); 381 | server.setIpMode(ipMode); 382 | 383 | if (! server.start()) { 384 | exit(1); 385 | } 386 | 387 | std::string prefix = "http://"; 388 | kiwix::IpAddress addresses = server.getAddress(); 389 | std::string suffix = ":" + std::to_string(server.getPort()) + normalizeRootUrl(rootLocation); 390 | std::cout << "The Kiwix server is running and can be accessed in the local network at: " << std::endl; 391 | if(!addresses.addr.empty()) std::cout << " - " << prefix << addresses.addr << suffix << std::endl; 392 | if(!addresses.addr6.empty()) std::cout << " - " << prefix << "[" << addresses.addr6 << "]" << suffix << std::endl; 393 | 394 | /* Run endless (until PPID dies) */ 395 | waiting = true; 396 | do { 397 | if (PPID > 0) { 398 | #ifdef _WIN32 399 | HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, PPID); 400 | DWORD ret = WaitForSingleObject(process, 0); 401 | CloseHandle(process); 402 | if (ret == WAIT_TIMEOUT) { 403 | #elif __APPLE__ 404 | int mib[MIBSIZE]; 405 | struct kinfo_proc kp; 406 | size_t len = sizeof(kp); 407 | 408 | mib[0] = CTL_KERN; 409 | mib[1] = KERN_PROC; 410 | mib[2] = KERN_PROC_PID; 411 | mib[3] = PPID; 412 | 413 | int ret = sysctl(mib, MIBSIZE, &kp, &len, NULL, 0); 414 | if (ret != -1 && len > 0) { 415 | #else /* Linux & co */ 416 | std::string procPath = "/proc/" + std::to_string(PPID); 417 | if (access(procPath.c_str(), F_OK) != -1) { 418 | #endif 419 | } else { 420 | waiting = false; 421 | } 422 | } 423 | 424 | kiwix::sleep(1000); 425 | 426 | if ( monitorLibrary ) { 427 | curLibraryFileTimestamp = newestFileTimestamp(libraryPaths); 428 | if ( !libraryMustBeReloaded ) { 429 | libraryMustBeReloaded = curLibraryFileTimestamp > libraryFileTimestamp; 430 | } 431 | } 432 | 433 | if ( libraryMustBeReloaded && !libraryPaths.empty() ) { 434 | libraryFileTimestamp = curLibraryFileTimestamp; 435 | reloadLibrary(manager, libraryPaths); 436 | nameMapper->update(); 437 | libraryMustBeReloaded = false; 438 | } 439 | } while (waiting); 440 | 441 | /* Stop the daemon */ 442 | server.stop(); 443 | } 444 | -------------------------------------------------------------------------------- /src/server/meson.build: -------------------------------------------------------------------------------- 1 | 2 | sources = ['kiwix-serve.cpp'] 3 | 4 | executable('kiwix-serve', sources, 5 | dependencies:all_deps, 6 | install:true) 7 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2016 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_TOOLS_VERSION_H_ 21 | #define _KIWIX_TOOLS_VERSION_H_ 22 | 23 | #ifndef KIWIX_TOOLS_VERSION 24 | #define KIWIX_TOOLS_VERSION "undefined" 25 | #endif 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | void version() 32 | { 33 | std::cout << "kiwix-tools " << KIWIX_TOOLS_VERSION << std::endl << std::endl; 34 | kiwix::printVersions(); 35 | std::cout << std::endl; 36 | zim::printVersions(); 37 | } 38 | 39 | #endif //_KIWIX_TOOLs_VERSION_H_ 40 | --------------------------------------------------------------------------------