mirror of
https://github.com/kiwix/kiwix-tools.git
synced 2026-01-09 22:47:59 -05:00
Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2bc6cead2 | ||
|
|
b7a6f78150 | ||
|
|
9e3d4c9615 | ||
|
|
472ff19861 | ||
|
|
97aa28c74d | ||
|
|
2c40d23991 | ||
|
|
ca8d6e570c | ||
|
|
78887d6815 | ||
|
|
643a07f653 | ||
|
|
9a07dd8314 | ||
|
|
bdd36f0379 | ||
|
|
62195c788e | ||
|
|
fa7948abbe | ||
|
|
2c701cb260 | ||
|
|
8b36e94d50 | ||
|
|
f9ce353ad1 | ||
|
|
2bb080ee3b | ||
|
|
dd5aa33775 | ||
|
|
0ed608f5c2 | ||
|
|
8f4758a6a9 | ||
|
|
b10f2ed1a1 | ||
|
|
94549828cb | ||
|
|
f342bd5e24 | ||
|
|
f316bb14a2 | ||
|
|
ea44dc76f6 | ||
|
|
6dfdcea5ce | ||
|
|
0ef85944b8 | ||
|
|
04ac15508f | ||
|
|
eeb41d8047 | ||
|
|
85a3093df3 | ||
|
|
2c435926ca | ||
|
|
b8c4791dd0 | ||
|
|
701541aa2f | ||
|
|
527981ba66 | ||
|
|
d8ed915c80 | ||
|
|
74d3bffde0 | ||
|
|
b974e121b4 | ||
|
|
d2bb9d123e | ||
|
|
9b158360a6 | ||
|
|
7d2c67f43d | ||
|
|
a080a3137e | ||
|
|
dedcae83cd | ||
|
|
c0fa06c931 | ||
|
|
dbe6126496 | ||
|
|
94bf71eb82 | ||
|
|
25e9941f6a | ||
|
|
81d8ad964a | ||
|
|
9a49623879 | ||
|
|
f7f10597eb | ||
|
|
c8be7c47ca | ||
|
|
f356587b23 | ||
|
|
32432a7113 | ||
|
|
7985ba1b0c | ||
|
|
933aa0cd63 | ||
|
|
098e1cfe51 | ||
|
|
43b5be179a | ||
|
|
88213b3f3b | ||
|
|
7659efa97c | ||
|
|
4faaa978f7 | ||
|
|
d73fcb357f | ||
|
|
61e82228a4 | ||
|
|
01430603b6 | ||
|
|
6c31d0d7b0 | ||
|
|
c1731c9697 | ||
|
|
929c36c930 | ||
|
|
3df4a94863 | ||
|
|
2cd190e965 | ||
|
|
6a7c737d48 | ||
|
|
b20e83bd0b | ||
|
|
7a3f77dbf2 | ||
|
|
71e065312f | ||
|
|
9f207a61f9 | ||
|
|
43656554f1 | ||
|
|
7d55c0f6ac | ||
|
|
c3721970c5 | ||
|
|
81ac333cc9 | ||
|
|
d1edbc11d3 | ||
|
|
47929008cf | ||
|
|
4ba79d9776 | ||
|
|
c1e2913f24 | ||
|
|
ac3e889388 | ||
|
|
6d9fa0cb45 | ||
|
|
c76bbabd10 | ||
|
|
a5cf735ffe | ||
|
|
b064796c2d | ||
|
|
6f2316bc8a | ||
|
|
b2aeb08051 | ||
|
|
17b7fb2145 | ||
|
|
36c7bf4d6f | ||
|
|
a3ed7ad3e1 | ||
|
|
b7d884ceb2 | ||
|
|
19322958b3 | ||
|
|
ccb8d11dce | ||
|
|
7bdbe901db | ||
|
|
7e6e74330a | ||
|
|
9efd18a9a4 | ||
|
|
0e9f406180 | ||
|
|
0160f356a6 | ||
|
|
8cc34782bc | ||
|
|
b2c68d7f22 | ||
|
|
977cfb9887 | ||
|
|
1671effaf4 | ||
|
|
8d00e45d2a | ||
|
|
730f20e86f | ||
|
|
ff5f1d96d2 | ||
|
|
d1d72218b3 | ||
|
|
88269c1ff2 | ||
|
|
4ee202514e | ||
|
|
98b372ee17 | ||
|
|
8e5df188b3 | ||
|
|
ed709454bd | ||
|
|
f5762c72d3 | ||
|
|
1744b152ac | ||
|
|
7f09e55077 | ||
|
|
fdec897bc7 | ||
|
|
764dd8848b | ||
|
|
4a944cc901 | ||
|
|
4120e7fd25 | ||
|
|
8736a2f4ea | ||
|
|
00b810d649 | ||
|
|
5d21baa759 | ||
|
|
6ba6046850 | ||
|
|
d24f474dda | ||
|
|
07de2d29c4 | ||
|
|
d99e5cd975 | ||
|
|
f82d5aa7e5 | ||
|
|
824aef9189 | ||
|
|
d6914eb34f | ||
|
|
b65212fab7 | ||
|
|
83427af3d2 | ||
|
|
d572bf875d | ||
|
|
833c997782 | ||
|
|
44613aae5d |
@@ -1,6 +1,6 @@
|
||||
name: CI
|
||||
|
||||
on: [pull_request]
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
@@ -14,42 +14,37 @@ jobs:
|
||||
- win32_dyn
|
||||
include:
|
||||
- target: native_static
|
||||
image_variant: xenial
|
||||
image_variant: bionic
|
||||
lib_postfix: '/x86_64-linux-gnu'
|
||||
- target: native_dyn
|
||||
image_variant: xenial
|
||||
image_variant: bionic
|
||||
lib_postfix: '/x86_64-linux-gnu'
|
||||
- target: win32_static
|
||||
image_variant: f31
|
||||
image_variant: f35
|
||||
lib_postfix: '64'
|
||||
- target: win32_dyn
|
||||
image_variant: f31
|
||||
image_variant: f35
|
||||
lib_postfix: '64'
|
||||
env:
|
||||
HOME: /home/runner
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: "kiwix/kiwix-build_ci:${{matrix.image_variant}}-26"
|
||||
image: "kiwix/kiwix-build_ci:${{matrix.image_variant}}-31"
|
||||
steps:
|
||||
- name: Extract branch name
|
||||
shell: bash
|
||||
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
|
||||
id: extract_branch
|
||||
- name: Checkout code
|
||||
shell: python
|
||||
run: |
|
||||
import json
|
||||
from subprocess import check_call
|
||||
from os import environ
|
||||
with open(environ['GITHUB_EVENT_PATH'], 'r') as f:
|
||||
content = f.read()
|
||||
event_data = json.loads(content)
|
||||
try:
|
||||
branch_ref = event_data['ref'].split('/')[-1]
|
||||
except KeyError:
|
||||
branch_ref = event_data['pull_request']['head']['ref']
|
||||
print("Cloning branch", branch_ref)
|
||||
command = [
|
||||
'git', 'clone',
|
||||
'https://github.com/${{github.repository}}',
|
||||
'--depth=1',
|
||||
'--branch', branch_ref
|
||||
'--branch', '${{steps.extract_branch.outputs.branch}}'
|
||||
]
|
||||
check_call(command, cwd=environ['HOME'])
|
||||
- name: Install deps
|
||||
61
.github/workflows/docker.yml
vendored
Normal file
61
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Specific version to build (overrides on-master and tag-pattern)
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
build-and-push-kiwix-tools:
|
||||
name: Deploy kiwix-tools Docker Image
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build and publish kiwix-tools
|
||||
uses: openzim/docker-publish-action@v5
|
||||
with:
|
||||
image-name: kiwix/kiwix-tools
|
||||
credentials: |
|
||||
DOCKERIO_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERIO_TOKEN=${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
GHCRIO_USERNAME=${{ secrets.GHCR_USERNAME }}
|
||||
GHCRIO_TOKEN=${{ secrets.GHCR_TOKEN }}
|
||||
context: docker
|
||||
latest-on-tag: true
|
||||
build-args:
|
||||
VERSION={tag}
|
||||
platforms: |
|
||||
linux/amd64
|
||||
linux/arm/v7
|
||||
linux/arm64
|
||||
restrict-to: kiwix/kiwix-tools
|
||||
manual-tag: ${{ github.event.inputs.version }}
|
||||
|
||||
build-and-push-kiwix-serve:
|
||||
name: Deploy kiwix-serve Docker Image
|
||||
runs-on: ubuntu-20.04
|
||||
needs: build-and-push-kiwix-tools
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build and publish kiwix-serve
|
||||
uses: openzim/docker-publish-action@v5
|
||||
with:
|
||||
image-name: kiwix/kiwix-serve
|
||||
credentials: |
|
||||
DOCKERIO_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERIO_TOKEN=${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
GHCRIO_USERNAME=${{ secrets.GHCR_USERNAME }}
|
||||
GHCRIO_TOKEN=${{ secrets.GHCR_TOKEN }}
|
||||
context: docker/server
|
||||
latest-on-tag: true
|
||||
build-args:
|
||||
VERSION={tag}
|
||||
platforms: |
|
||||
linux/amd64
|
||||
linux/arm/v7
|
||||
linux/arm64
|
||||
restrict-to: kiwix/kiwix-tools
|
||||
manual-tag: ${{ github.event.inputs.version }}
|
||||
82
.github/workflows/package.yml
vendored
Normal file
82
.github/workflows/package.yml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
name: Packages
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-deb:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
distro:
|
||||
- ubuntu-jammy
|
||||
- ubuntu-impish
|
||||
- ubuntu-focal
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Determine which PPA we should upload to
|
||||
- name: PPA
|
||||
id: ppa
|
||||
run: |
|
||||
if [[ $REF == refs/tags* ]]
|
||||
then
|
||||
echo "::set-output name=ppa::kiwixteam/release"
|
||||
else
|
||||
echo "::set-output name=ppa::kiwixteam/dev"
|
||||
fi
|
||||
env:
|
||||
REF: ${{ github.ref }}
|
||||
|
||||
- uses: legoktm/gh-action-auto-dch@master
|
||||
with:
|
||||
fullname: Kiwix builder
|
||||
email: release+launchpad@kiwix.org
|
||||
distro: ${{ matrix.distro }}
|
||||
|
||||
- uses: legoktm/gh-action-build-deb@ubuntu-jammy
|
||||
if: matrix.distro == 'ubuntu-jammy'
|
||||
name: Build package for ubuntu-jammy
|
||||
id: build-ubuntu-jammy
|
||||
with:
|
||||
args: --no-sign
|
||||
ppa: ${{ steps.ppa.outputs.ppa }}
|
||||
|
||||
- uses: legoktm/gh-action-build-deb@ubuntu-impish
|
||||
if: matrix.distro == 'ubuntu-impish'
|
||||
name: Build package for ubuntu-impish
|
||||
id: build-ubuntu-impish
|
||||
with:
|
||||
args: --no-sign
|
||||
ppa: ${{ steps.ppa.outputs.ppa }}
|
||||
|
||||
- uses: legoktm/gh-action-build-deb@ubuntu-focal
|
||||
if: matrix.distro == 'ubuntu-focal'
|
||||
name: Build package for ubuntu-focal
|
||||
id: build-ubuntu-focal
|
||||
with:
|
||||
args: --no-sign
|
||||
ppa: ${{ steps.ppa.outputs.ppa }}
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Packages for ${{ matrix.distro }}
|
||||
path: output
|
||||
|
||||
- uses: legoktm/gh-action-dput@master
|
||||
name: Upload dev package
|
||||
# Only upload on pushes to master
|
||||
if: github.event_name == 'push' && github.event.ref == 'refs/heads/master' && startswith(matrix.distro, 'ubuntu-')
|
||||
with:
|
||||
gpg_key: ${{ secrets.LAUNCHPAD_GPG }}
|
||||
repository: ppa:kiwixteam/dev
|
||||
packages: output/*_source.changes
|
||||
|
||||
- uses: legoktm/gh-action-dput@master
|
||||
name: Upload release package
|
||||
# Only upload on pushes to master or tag
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') && startswith(matrix.distro, 'ubuntu-')
|
||||
with:
|
||||
gpg_key: ${{ secrets.LAUNCHPAD_GPG }}
|
||||
repository: ppa:kiwixteam/release
|
||||
packages: output/*_source.changes
|
||||
|
||||
65
Changelog
65
Changelog
@@ -1,3 +1,68 @@
|
||||
kiwix-tools 3.3.0
|
||||
=================
|
||||
|
||||
* Remove kiwix-read tool (@veloman-yunkan #535)
|
||||
|
||||
kiwix-serve
|
||||
-----------
|
||||
|
||||
* Add an option to limit the number of connections for a same IP (@nikhil #534)
|
||||
* Add an option to limit the number of zim in a multizim fulltext search (@mgautierfr #558)
|
||||
|
||||
kiwix-search
|
||||
------------
|
||||
|
||||
* Remove usage of libkiwix's deprecated api (@veloman-yunkan #535)
|
||||
|
||||
kiwix-manage
|
||||
------------
|
||||
|
||||
* Correctly return a value !0 if something went wrong (@mgautierfr #553)
|
||||
|
||||
|
||||
kiwix-tools 3.2.0
|
||||
=================
|
||||
|
||||
* Print the version of all dependencies (@kelson42 #516)
|
||||
* Better Docker images (@kelson42 @rgaudin)
|
||||
* Update Readme (@kelson42)
|
||||
* Build debian packages on CI (@legoktm #394)
|
||||
* Add man pages for kiwix-read and kiwix-search (@legoktm #392)
|
||||
* Various fixes (@legoktm @hashworks @mgautierfr)
|
||||
|
||||
|
||||
kiwix-serve
|
||||
-----------
|
||||
|
||||
* Print the url on which a user can connect to on startup (@nikhil #499 #522)
|
||||
* Reload library on SIGHUP signal (@veloman-yunkan #497)
|
||||
* Add a option `--monitorLibrary` to monitor and automically reload the library
|
||||
(@veloman-yunkan #503)
|
||||
* Correct handling of SIGTERM and SIGINT (@veloman-yunkan #488)
|
||||
* Add `--customIndexTemplate` option (@manan #477)
|
||||
* Add `--help` option (@kelson42 #511)
|
||||
|
||||
|
||||
kiwix-tools 3.1.2
|
||||
=================
|
||||
|
||||
* Use new threadsafe API of kiwix-lib to do suggestions search.
|
||||
|
||||
kiwix-tools 3.1.1
|
||||
=================
|
||||
|
||||
* Fix compilation on Windows' CI
|
||||
|
||||
kiwix-tools 3.1.0
|
||||
=================
|
||||
|
||||
* [SERVER] Add option to block external links
|
||||
|
||||
kiwix-tools 3.0.3
|
||||
=================
|
||||
|
||||
* [MANAGER] Fix broken --version argument parsing
|
||||
|
||||
kiwix-tools 3.0.2
|
||||
=================
|
||||
|
||||
|
||||
35
README.md
35
README.md
@@ -8,23 +8,15 @@ command line tools:
|
||||
* kiwix-search: Fulltext search in ZIM files
|
||||
* kiwix-serve: HTTP daemon serving ZIM files
|
||||
|
||||
[](https://travis-ci.com/kiwix/kiwix-tools)
|
||||
[](https://download.kiwix.org/release/kiwix-tools/)
|
||||
[](https://github.com/kiwix/kiwix-tools/wiki/Repology)
|
||||
[](https://hub.docker.com/r/kiwix/kiwix-tools)
|
||||
[&sort=date)](https://hub.docker.com/r/kiwix/kiwix-serve)
|
||||
[](https://apps.sandstorm.io/app/5uh349d0kky2zp5whrh2znahn27gwha876xze3864n0fu9e5220h)
|
||||
[](https://github.com/kiwix/kiwix-tools/actions?query=branch%3Amaster)
|
||||
[](https://www.codefactor.io/repository/github/kiwix/kiwix-tools)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
|
||||
Distribution
|
||||
------------
|
||||
|
||||
#### Official
|
||||
|
||||
[](https://download.kiwix.org/release/kiwix-tools/)
|
||||
[](https://hub.docker.com/r/kiwix/kiwix-serve)
|
||||
|
||||
#### Contribution
|
||||
|
||||
[](https://aur.archlinux.org/packages/kiwix-tools/)
|
||||
[](https://apps.sandstorm.io/app/5uh349d0kky2zp5whrh2znahn27gwha876xze3864n0fu9e5220h)
|
||||
|
||||
Disclaimer
|
||||
----------
|
||||
|
||||
@@ -49,10 +41,8 @@ Dependencies
|
||||
The Kiwix tools rely on a few third party software libraries. They are
|
||||
prerequisites to the Kiwix tools compilation. Therefore, following
|
||||
libraries need to be available:
|
||||
* [Kiwix lib](https://github.com/kiwix/kiwix-lib) (no package so far)
|
||||
* [Libmicrohttpd](https://www.gnu.org/software/libmicrohttpd/)
|
||||
(package `libmicrohttpd-dev` on Debian/Ubuntu)
|
||||
* [Zlib](https://www.zlib.net/) (package `zlib1g-dev` on Debian/Ubuntu)
|
||||
* [libkiwix](https://github.com/kiwix/libkiwix) (package `libkiwix` on Debian/Ubuntu)
|
||||
* [libzim](https://github.com/openzim/libzim) (package `libzim` on Debian/Ubuntu)
|
||||
|
||||
These dependencies may or may not be packaged by your operating
|
||||
system. They may also be packaged but only in an older version. They
|
||||
@@ -68,10 +58,6 @@ If you want to compile Kiwix tools statically, the dependencies should
|
||||
be compiled statically (provide a `lib...a` library), for example by
|
||||
using `--enable-static` with `./configure`.
|
||||
|
||||
If you compile manually Libmicrohttpd, you might need to compile it
|
||||
without GNU TLS, a bug here will empeach further compilation of Kiwix
|
||||
tools otherwise.
|
||||
|
||||
Environment
|
||||
-------------
|
||||
|
||||
@@ -127,7 +113,10 @@ Like for the installation, you might need to run the command as `root`
|
||||
Docker
|
||||
------
|
||||
|
||||
An official Docker image of `kiwix-serve` can be found in the [Docker Hub](https://hub.docker.com/r/kiwix/kiwix-serve).
|
||||
An official Docker image of the Kiwix tools can be found in the
|
||||
[Docker Hub](https://hub.docker.com/r/kiwix/kiwix-tools). A
|
||||
`kiwix-serve` dedicated Docker image [exists
|
||||
too](https://hub.docker.com/r/kiwix/kiwix-serve).
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
kiwix-tools (0.0.0) unstable; urgency=medium
|
||||
|
||||
* Initial release
|
||||
|
||||
-- Kunal Mehta <legoktm@debian.org> Mon, 13 Jul 2020 17:21:11 -0700
|
||||
26
debian/control
vendored
Normal file
26
debian/control
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Source: kiwix-tools
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Maintainer: Kiwix team <kiwix@kiwix.org>
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
libkiwix-dev (>= 10.0.0~),
|
||||
libzim-dev (>= 7.2.0~),
|
||||
meson,
|
||||
pkg-config,
|
||||
Standards-Version: 4.5.0
|
||||
Homepage: https://github.com/kiwix/kiwix-tools
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: kiwix-tools
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: collection of Kiwix tools
|
||||
kiwix-tools is a collection of various command-line tools used to help
|
||||
users interact with and manage ZIM files. It includes:
|
||||
* kiwix-serve is a standalone HTTP server for serving ZIM files
|
||||
over the network.
|
||||
* kiwix-manage allows one to manage the content of the Kiwix library (an
|
||||
XML file listing available ZIM files).
|
||||
* kiwix-read allows for reading ZIM files from the command-line.
|
||||
* kiwix-search allows one to find articles in a ZIM file using fulltext
|
||||
search patterns.
|
||||
1
debian/copyright
vendored
Normal file
1
debian/copyright
vendored
Normal file
@@ -0,0 +1 @@
|
||||
See COPYING in the repository root.
|
||||
5
debian/rules
vendored
Executable file
5
debian/rules
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/make -f
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
%:
|
||||
dh $@
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (native)
|
||||
49
docker/Dockerfile
Normal file
49
docker/Dockerfile
Normal file
@@ -0,0 +1,49 @@
|
||||
# dumb-init to use as entrypoint so it can forward signals to our CMD
|
||||
FROM debian:bullseye-slim as builder
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential ca-certificates musl-tools wget unzip make \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
# compile dumb-init
|
||||
RUN wget -nv https://github.com/Yelp/dumb-init/archive/refs/tags/v1.2.5.zip && \
|
||||
unzip v1.2.5.zip && cd dumb-init-1.2.5 && CC=musl-gcc make
|
||||
|
||||
# declare build option ARCH if not using buildx
|
||||
ARG ARCH=
|
||||
# declare version to build image for
|
||||
ARG VERSION=
|
||||
|
||||
# alpine is a multi-arch image
|
||||
FROM alpine:3
|
||||
LABEL org.opencontainers.image.source https://github.com/openzim/kiwix-tools
|
||||
|
||||
# TARGETARCH is injected by buildx
|
||||
ARG TARGETARCH
|
||||
ARG VERSION
|
||||
ARG ARCH
|
||||
|
||||
# copy built dumb-init
|
||||
COPY --from=builder /dumb-init-1.2.5/dumb-init /usr/bin/dumb-init
|
||||
|
||||
# find and store arch in image, using (in this order):
|
||||
# $TARGETARCH || --build-arg ARCH (not using buildx) || amd64
|
||||
RUN echo "amd64" > /etc/docker_arch && \
|
||||
if [ ! -z "$ARCH" ] ; then echo "$ARCH" > /etc/docker_arch ; fi && \
|
||||
if [ ! -z "$TARGETARCH" ] ; then echo "$TARGETARCH" > /etc/docker_arch ; fi
|
||||
|
||||
# decide which kiwix arch to download later (`armhf` for all arm* and x86_64 otherwise)
|
||||
RUN if [ $(cut -c 1-3 /etc/docker_arch) = "arm" ] ; then echo "armhf" > /etc/kiwix_arch ; else echo "x86_64" > /etc/kiwix_arch ; fi
|
||||
|
||||
# Install kiwix-tools
|
||||
RUN url="http://mirror.download.kiwix.org/release/kiwix-tools/kiwix-tools_linux-$(cat /etc/kiwix_arch)-$VERSION.tar.gz" && \
|
||||
echo "URL: $url" && \
|
||||
wget -q -O - $url | tar -xz && \
|
||||
mv kiwix-tools*/kiwix-* /usr/local/bin && \
|
||||
rm -r kiwix-tools*
|
||||
|
||||
# expose kiwix-serve default port
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||
CMD ["/bin/sh", "-c", "echo 'Welcome to kiwix-tools! The following binaries are available:' && ls /usr/local/bin/"]
|
||||
32
docker/README.md
Normal file
32
docker/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
Kiwix-tools Docker image
|
||||
===
|
||||
|
||||
- Available on [docker.io](https://hub.docker.com/r/kiwix/kiwix-tools) and [ghcr.io](https://ghcr.io/kiwix/kiwix-tools).
|
||||
- multi-arch (`linux/amd64`, `linux/arm64`, `linux/arm/v7`)
|
||||
- based on official `kiwix-tools` binaries.
|
||||
|
||||
## Usage
|
||||
|
||||
``` sh
|
||||
$ docker run -it kiwix/kiwix-tools:3.1.2
|
||||
|
||||
Welcome to kiwix-tools! The following binaries are available:
|
||||
kiwix-manage kiwix-read kiwix-search kiwix-serve
|
||||
```
|
||||
|
||||
`kiwix-tools` operates on zim files. You shall mount a volume to access the files.
|
||||
|
||||
```sh
|
||||
docker run -v $(pwd):/data -it kiwix/kiwix-tools kiwix-read --suggest="Mali" /data/wikipedia_fr_test.zim
|
||||
```
|
||||
|
||||
## Building and reusing
|
||||
|
||||
- `kiwix/kiwix-tools` is multi-arch and is ideally built using `buildx`.
|
||||
- requires a `--build-arg VERSION=` with the kiwix-tools release.
|
||||
- can be built using `docker build` in which case it expects an additionnal `--build-arg ARCH=arm` for arm. Otherwise defaults to `amd64`.
|
||||
|
||||
**Notes:**
|
||||
|
||||
- `wget` in `alpine:3` on `arm/v7` (__inside github action only__) crashes when downloading from HTTPs locations. Keep http-only in Dockerfile.
|
||||
- Was also unhappy when using the mirrors so it's using `mirror.download` on purpose.
|
||||
@@ -1,18 +1,14 @@
|
||||
FROM alpine:latest
|
||||
LABEL maintainer Emmanuel Engelhart <kelson@kiwix.org>
|
||||
ARG VERSION=latest
|
||||
|
||||
# Install kiwix-serve
|
||||
WORKDIR /
|
||||
RUN apk add --no-cache curl bzip2
|
||||
RUN curl -kL https://download.kiwix.org/release/kiwix-tools/kiwix-tools_linux-x86_64.tar.gz | tar -xz && \
|
||||
mv kiwix-tools*/kiwix-serve /usr/local/bin && \
|
||||
rm -r kiwix-tools*
|
||||
# kiwix-tools is multi-arch
|
||||
FROM kiwix/kiwix-tools:$VERSION
|
||||
LABEL org.opencontainers.image.source https://github.com/openzim/kiwix-tools
|
||||
|
||||
# Run kiwix-serve
|
||||
# expose kiwix-serve default port and workdir
|
||||
EXPOSE 80
|
||||
VOLUME /data
|
||||
WORKDIR /data
|
||||
|
||||
COPY ./start.sh /usr/local/bin/
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/start.sh"]
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/start.sh"]
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Kiwix serve Docker image
|
||||
========================
|
||||
|
||||
With local ZIM file
|
||||
-------------------
|
||||
With local ZIM file(s)
|
||||
----------------------
|
||||
|
||||
* Download a ZIM file from <https://wiki.kiwix.org/wiki/Content>
|
||||
|
||||
* Given `wikipedia.zim` resides in `/tmp/zim/`, execute the following:
|
||||
* Given `wikipedia.zim` and `wiktionary.zim` reside in `/tmp/zim/`, execute the following:
|
||||
|
||||
```bash
|
||||
docker run -v /tmp/zim:/data -p 8080:80 kiwix/kiwix-serve wikipedia.zim
|
||||
docker run -v /tmp/zim:/data -p 8080:80 kiwix/kiwix-serve wikipedia.zim wiktionary.zim
|
||||
```
|
||||
|
||||
With remote ZIM file
|
||||
@@ -19,6 +19,16 @@ With remote ZIM file
|
||||
docker run -e "DOWNLOAD=https://download.kiwix.org/zim/wikipedia_bm_all.zim" -p 8080:80 kiwix/kiwix-serve
|
||||
```
|
||||
|
||||
ARM
|
||||
---
|
||||
|
||||
Build an image for an ARM based GNU/Linux:
|
||||
```bash
|
||||
docker build . -t kiwix/kiwix-serve:latest --build-arg ARCH="arm32v7/"
|
||||
```
|
||||
|
||||
You can also deploy kiwix with [`docker-compose`](https://docs.docker.com/compose/). Check out a sample at [docker-compose.yml.example](docker-compose.yml.example)
|
||||
|
||||
Screenshots
|
||||
-----------
|
||||
|
||||
|
||||
14
docker/server/docker-compose.yml.example
Normal file
14
docker/server/docker-compose.yml.example
Normal file
@@ -0,0 +1,14 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
kiwix-serve:
|
||||
ports:
|
||||
- 8080:80
|
||||
image: kiwix/kiwix-serve
|
||||
# uncomment next 4 lines to use it with local zim file in /tmp/zim
|
||||
# volumes:
|
||||
# - /tmp/zim:/data
|
||||
# command:
|
||||
# - *.zim
|
||||
# uncomment next 2 lines to use it with remote zim file
|
||||
# environment:
|
||||
# - 'DOWNLOAD=https://download.kiwix.org/zim/wikipedia_bm_all.zim'
|
||||
@@ -16,3 +16,10 @@ fi
|
||||
CMD="/usr/local/bin/kiwix-serve --port=80 $@"
|
||||
echo $CMD
|
||||
$CMD
|
||||
|
||||
# If error, print the content of /data
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Here is the content of /data:"
|
||||
find /data -type f
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
project('kiwix-tools', 'cpp',
|
||||
version : '3.0.2',
|
||||
version : '3.3.0',
|
||||
license : 'GPL',
|
||||
default_options: ['c_std=c11', 'cpp_std=c++11', 'werror=true'])
|
||||
|
||||
@@ -13,11 +13,10 @@ if static_linkage
|
||||
endif
|
||||
|
||||
thread_dep = dependency('threads')
|
||||
kiwixlib_dep = dependency('kiwix', version:'>=9.0.0', static:static_linkage)
|
||||
microhttpd_dep = dependency('libmicrohttpd', static:static_linkage)
|
||||
z_dep = dependency('zlib', static:static_linkage)
|
||||
kiwixlib_dep = dependency('kiwix', version:'>=11.0.0', static:static_linkage)
|
||||
libzim_dep = dependency('libzim', version:'>=7.2.0', static:static_linkage)
|
||||
|
||||
all_deps = [thread_dep, kiwixlib_dep, microhttpd_dep, z_dep]
|
||||
all_deps = [thread_dep, kiwixlib_dep, libzim_dep]
|
||||
|
||||
if static_linkage
|
||||
librt = compiler.find_library('rt', required:false)
|
||||
|
||||
18
src/man/kiwix-read.1
Normal file
18
src/man/kiwix-read.1
Normal file
@@ -0,0 +1,18 @@
|
||||
.TH KIWIX-READ "1" "July 2020" "kiwix-tools" "User Commands"
|
||||
.SH NAME
|
||||
kiwix-read \- Read ZIM file content
|
||||
.SH SYNOPSIS
|
||||
\fBkiwix-read\fR [\-\-verbose] [\-\-version] \-\-suggest=PATTERN ZIM\fR
|
||||
.SH DESCRIPTION
|
||||
.TP
|
||||
ZIM
|
||||
ZIM file to search
|
||||
.TP
|
||||
\fB\-\-verbose\fR
|
||||
Enable extra output
|
||||
.TP
|
||||
\fB\-\-version\fR
|
||||
print software version
|
||||
.TP
|
||||
\fB\-\-suggest=PATTERN\fR
|
||||
Get search suggestions for the provided pattern
|
||||
21
src/man/kiwix-search.1
Normal file
21
src/man/kiwix-search.1
Normal file
@@ -0,0 +1,21 @@
|
||||
.TH KIWIX-SEARCH "1" "July 2020" "kiwix-tools" "User Commands"
|
||||
.SH NAME
|
||||
kiwix-search \- find articles using a fulltext search pattern
|
||||
.SH SYNOPSIS
|
||||
\fBkiwix-search\fR [OPTIONS] ZIM PATTERN\fR
|
||||
.SH DESCRIPTION
|
||||
.TP
|
||||
ZIM
|
||||
ZIM file to search
|
||||
.TP
|
||||
PATTERN
|
||||
Words or parts of words to search for in the ZIM file
|
||||
.TP
|
||||
\fB\-s\fR, \fB\-\-suggestion\fR
|
||||
Suggest article titles based on the PATTERN instead of a fulltext search
|
||||
.TP
|
||||
\fB\-V\fR, \fB\-\-version\fR
|
||||
print software version
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-verbose\fR
|
||||
Give details about the search process
|
||||
@@ -1,3 +1,5 @@
|
||||
install_man('kiwix-manage.1',
|
||||
'kiwix-read.1',
|
||||
'kiwix-search.1',
|
||||
'kiwix-serve.1')
|
||||
subdir('fr')
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <kiwix/tools/stringTools.h>
|
||||
#include <kiwix/manager.h>
|
||||
#include <kiwix/tools.h>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
@@ -119,7 +119,6 @@ int handle_add(kiwix::Library* library, const std::string& libraryPath,
|
||||
string zimPath;
|
||||
string zimPathToSave = ".";
|
||||
string url;
|
||||
string origID = "";
|
||||
int option_index = 0;
|
||||
int c = 0;
|
||||
int resultCode = 0;
|
||||
@@ -133,7 +132,6 @@ int handle_add(kiwix::Library* library, const std::string& libraryPath,
|
||||
optind = 3;
|
||||
static struct option long_options[] = {
|
||||
{"url", required_argument, 0, 'u'},
|
||||
{"origId", required_argument, 0, 'o'},
|
||||
{"zimPathToSave", required_argument, 0, 'z'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
@@ -149,9 +147,6 @@ int handle_add(kiwix::Library* library, const std::string& libraryPath,
|
||||
case 'u':
|
||||
url = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
origID = optarg;
|
||||
break;
|
||||
case 'z':
|
||||
zimPathToSave = optarg;
|
||||
break;
|
||||
@@ -174,7 +169,10 @@ int handle_add(kiwix::Library* library, const std::string& libraryPath,
|
||||
std::string zimPath = argv[i];
|
||||
if (!zimPath.empty()) {
|
||||
auto _zimPathToSave = zimPathToSave == "." ? zimPath : zimPathToSave;
|
||||
manager.addBookFromPathAndGetId(zimPath, _zimPathToSave, url, false);
|
||||
if (manager.addBookFromPathAndGetId(zimPath, _zimPathToSave, url, false).empty()) {
|
||||
std::cerr << "Cannot add zim " << zimPath << " to the library." << std::endl;
|
||||
resultCode = 1;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Invalid zim file path" << std::endl;
|
||||
resultCode = 1;
|
||||
@@ -228,7 +226,7 @@ int main(int argc, char** argv)
|
||||
|
||||
int option_index = 0;
|
||||
int c;
|
||||
while (true) {
|
||||
while (true && argc == 2) {
|
||||
c = getopt_long(argc, argv, "v", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
@@ -256,15 +254,20 @@ int main(int argc, char** argv)
|
||||
/* Print usage)) if necessary */
|
||||
if (libraryPath == "" || action == NONE) {
|
||||
usage();
|
||||
exit(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try to read the file */
|
||||
libraryPath = isRelativePath(libraryPath)
|
||||
? computeAbsolutePath(getCurrentDirectory(), libraryPath)
|
||||
libraryPath = kiwix::isRelativePath(libraryPath)
|
||||
? kiwix::computeAbsolutePath(kiwix::getCurrentDirectory(), libraryPath)
|
||||
: libraryPath;
|
||||
kiwix::Manager manager(&library);
|
||||
manager.readFile(libraryPath, false);
|
||||
if (!manager.readFile(libraryPath, false)) {
|
||||
if (kiwix::fileExists(libraryPath) || action!=ADD) {
|
||||
std::cerr << "Cannot read the library " << libraryPath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* SHOW */
|
||||
int exitCode = 0;
|
||||
@@ -282,10 +285,18 @@ int main(int argc, char** argv)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Rewrite the library file */
|
||||
if (action == REMOVE || action == ADD) {
|
||||
library.writeToFile(libraryPath);
|
||||
if (exitCode) {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
exit(exitCode);
|
||||
/* Rewrite the library file */
|
||||
if (action == REMOVE || action == ADD) {
|
||||
// writeToFile return true (1) if everything is ok => exitCode is 0
|
||||
if (!library.writeToFile(libraryPath)) {
|
||||
std::cerr << "Cannot write the library " << libraryPath << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
|
||||
subdir('manager')
|
||||
subdir('reader')
|
||||
subdir('searcher')
|
||||
subdir('server')
|
||||
subdir('man')
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 Emmanuel Engelhart <kelson@kiwix.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <kiwix/reader.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
void usage()
|
||||
{
|
||||
cout << "Usage: kiwix-read [--verbose] [--version] --suggest=<PATTERN> ZIM_FILE_PATH" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
/* Init the variables */
|
||||
const char* filePath = NULL;
|
||||
const char* pattern = NULL;
|
||||
int option_index = 0;
|
||||
int c = 0;
|
||||
|
||||
kiwix::Reader* reader = NULL;
|
||||
|
||||
/* Argument parsing */
|
||||
while (42) {
|
||||
static struct option long_options[]
|
||||
= {{"verbose", no_argument, 0, 'v'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"suggest", required_argument, 0, 's'},
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
if (c != -1) {
|
||||
c = getopt_long(argc, argv, "Vvs:", long_options, &option_index);
|
||||
|
||||
switch (c) {
|
||||
case 'v':
|
||||
break;
|
||||
case 'V':
|
||||
version();
|
||||
return 0;
|
||||
case 's':
|
||||
pattern = optarg;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (optind < argc) {
|
||||
if (filePath == NULL) {
|
||||
filePath = argv[optind++];
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have enough arguments */
|
||||
if (filePath == NULL) {
|
||||
usage();
|
||||
}
|
||||
|
||||
/* Instanciate the reader */
|
||||
reader = new kiwix::Reader(filePath);
|
||||
|
||||
/* Start to read an article */
|
||||
if (reader != NULL) {
|
||||
string content;
|
||||
string contentType;
|
||||
string suggestion;
|
||||
|
||||
if (pattern != NULL) {
|
||||
std::cout << "Searching suggestions for: " << pattern << std::endl;
|
||||
|
||||
reader->searchSuggestionsSmart(pattern, 10);
|
||||
while (reader->getNextSuggestion(suggestion)) {
|
||||
std::cout << suggestion << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
delete reader;
|
||||
} else {
|
||||
cerr << "Unable instanciate the Kiwix reader." << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
executable('kiwix-read', ['kiwix-read.cpp'],
|
||||
dependencies:all_deps,
|
||||
install:true)
|
||||
@@ -18,15 +18,20 @@
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <kiwix/reader.h>
|
||||
#include <kiwix/searcher.h>
|
||||
|
||||
#include <zim/search.h>
|
||||
#include <zim/suggestion.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void usage()
|
||||
{
|
||||
cout << "Usage: kiwix-search [OPTIONS] ZIM PATTERN" << endl << endl
|
||||
<< " kiwix-search allows to find articles based on the a fulltext search pattern." << endl << endl
|
||||
<< " kiwix-search allows one to find articles based on the a fulltext search pattern." << endl << endl
|
||||
<< " ZIM is the full path of the ZIM file." << endl
|
||||
<< " PATTERN is/are word(s) - or part of - to search in the ZIM." << endl << endl
|
||||
<< " -s, --suggestion\tSuggest article titles based on the few letters of the PATTERN instead of making a fulltext search. Work a bit like a completion solution." << endl
|
||||
@@ -48,9 +53,6 @@ int main(int argc, char** argv)
|
||||
int option_index = 0;
|
||||
int c = 0;
|
||||
|
||||
kiwix::Searcher* searcher = NULL;
|
||||
kiwix::Reader* reader = NULL;
|
||||
|
||||
/* Argument parsing */
|
||||
while (42) {
|
||||
static struct option long_options[]
|
||||
@@ -96,40 +98,24 @@ int main(int argc, char** argv)
|
||||
|
||||
/* Try to prepare the indexing */
|
||||
try {
|
||||
reader = new kiwix::Reader(zimPath);
|
||||
} catch (...) {
|
||||
/* Cannot open the zimPath, maybe it is a plain old xapian database
|
||||
* directory */
|
||||
}
|
||||
zim::Archive archive(zimPath);
|
||||
|
||||
if (reader) {
|
||||
searcher = new kiwix::Searcher();
|
||||
searcher->add_reader(reader);
|
||||
} else {
|
||||
cerr << "Unable to search through zim '" << zimPath << "'." << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Start the indexing */
|
||||
if (searcher != NULL) {
|
||||
string searchString(search);
|
||||
if (suggestionFlag) {
|
||||
searcher->suggestions(searchString, verboseFlag);
|
||||
} else {
|
||||
searcher->search(searchString, 0, 10, verboseFlag);
|
||||
zim::SuggestionSearcher searcher(archive);
|
||||
searcher.setVerbose(verboseFlag);
|
||||
for (const auto& r : searcher.suggest(search).getResults(0, 10) ) {
|
||||
cout << r.getTitle() << endl;
|
||||
}
|
||||
} else {
|
||||
zim::Searcher searcher(archive);
|
||||
searcher.setVerbose(verboseFlag);
|
||||
const zim::Query query(search);
|
||||
for (const auto& r : searcher.search(query).getResults(0, 10) ) {
|
||||
cout << r.getTitle() << endl;
|
||||
}
|
||||
}
|
||||
kiwix::Result* p_result;
|
||||
while ((p_result = searcher->getNextResult())) {
|
||||
cout << p_result->get_title() << endl;
|
||||
delete p_result;
|
||||
}
|
||||
|
||||
delete searcher;
|
||||
delete reader;
|
||||
|
||||
// kiwix::XapianSearcher::terminate();
|
||||
} else {
|
||||
cerr << "Unable instanciate the Kiwix searcher." << endl;
|
||||
} catch ( const std::runtime_error& err) {
|
||||
cerr << err.what() << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
#include <kiwix/manager.h>
|
||||
#include <kiwix/server.h>
|
||||
#include <kiwix/name_mapper.h>
|
||||
#include <kiwix/tools/otherTools.h>
|
||||
#include <kiwix/tools.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# import <sys/sysctl.h>
|
||||
@@ -45,28 +49,33 @@ void usage()
|
||||
<< std::endl
|
||||
|
||||
<< "Purpose:" << std::endl
|
||||
<< "\tDeliver ZIM file articles via HTTP"
|
||||
<< "\tDeliver ZIM file(s) articles via HTTP"
|
||||
<< std::endl << std::endl
|
||||
|
||||
<< "Mandatory arguments:" << std::endl
|
||||
<< "\tLIBRARY_PATH\t\tis the XML library file path listing ZIM file to serve. To be used only with the --library argument."
|
||||
<< "\tLIBRARY_PATH\t\tXML library file path listing ZIM file to serve. To be used only with the --library argument."
|
||||
<< std::endl
|
||||
<< "\tZIM_PATH\t\tis the path of a ZIM file."
|
||||
<< "\tZIM_PATH\t\tZIM file path(s)"
|
||||
<< std::endl << std::endl
|
||||
|
||||
<< "Optional arguments:" << std::endl
|
||||
<< "\t-a, --attachToProcess\texit if given process id is not running anymore" << std::endl
|
||||
<< "\t-d, --daemon\t\tdetach the HTTP server daemon from the main process" << std::endl
|
||||
<< "\t-i, --address\t\tlisten only on this ip address, all available ones otherwise" << std::endl
|
||||
<< "\t-m, --nolibrarybutton\tdo not print the builtin home button in the builtin top bar overlay" << std::endl
|
||||
<< "\t-n, --nosearchbar\tdo not print the builtin bar overlay on the top of each served page" << std::endl
|
||||
<< "Optional arguments:" << std::endl << std::endl
|
||||
<< "\t-h, --help\t\tPrint this help" << std::endl << std::endl
|
||||
<< "\t-a, --attachToProcess\tWxit if given process id is not running anymore" << std::endl
|
||||
<< "\t-d, --daemon\t\tDetach the HTTP server daemon from the main process" << std::endl
|
||||
<< "\t-i, --address\t\tListen only on this ip address, all available ones otherwise" << std::endl
|
||||
<< "\t-M, --monitorLibrary\tMonitor the XML library file and reload it automatically" << std::endl
|
||||
<< "\t-m, --nolibrarybutton\tDon't print the builtin home button in the builtin top bar overlay" << std::endl
|
||||
<< "\t-n, --nosearchbar\tDon't print the builtin bar overlay on the top of each served page" << std::endl
|
||||
<< "\t-b, --blockexternal\tPrevent users from directly accessing external links" << std::endl
|
||||
<< "\t-p, --port\t\tTCP port on which to listen to HTTP requests (default: 80)" << std::endl
|
||||
<< "\t-r, --urlRootLocation\tURL prefix on which the content should be made available (default: /)" << std::endl
|
||||
<< "\t-t, --threads\t\tnumber of threads to run in parallel (default: " << DEFAULT_THREADS << ")" << std::endl
|
||||
<< "\t-v, --verbose\t\tprint debug log to STDOUT" << std::endl
|
||||
<< "\t-V, --version\t\tprint software version" << std::endl
|
||||
<< "\t-z, --nodatealiases\tcreate URL aliases for each content by removing the date" << std::endl
|
||||
<< "\t--donottrustlibrary\tRead the metadata from the zim file instead of trusting the library." << std::endl
|
||||
<< "\t-s, --searchLimit\t\tMaximun number of zim in a fulltext multizim search (default: No limit)" << std::endl
|
||||
<< "\t-t, --threads\t\tNumber of threads to run in parallel (default: " << DEFAULT_THREADS << ")" << std::endl
|
||||
<< "\t-v, --verbose\t\tPrint debug log to STDOUT" << std::endl
|
||||
<< "\t-V, --version\t\tPrint software version" << std::endl
|
||||
<< "\t-z, --nodatealiases\tCreate URL aliases for each content by removing the date" << std::endl
|
||||
<< "\t-c, --customIndex\tAdd path to custom index.html for welcome page" << std::endl
|
||||
<< "\t-L, --ipConnectionLimit\tMax number of (concurrent) connections per IP (default: infinite, recommended: >= 6)" << std::endl
|
||||
<< std::endl
|
||||
|
||||
<< "Documentation:" << std::endl
|
||||
@@ -75,8 +84,107 @@ void usage()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
string loadCustomTemplate (string customIndexPath) {
|
||||
customIndexPath = kiwix::isRelativePath(customIndexPath) ?
|
||||
kiwix::computeAbsolutePath(kiwix::getCurrentDirectory(), customIndexPath) :
|
||||
customIndexPath;
|
||||
if (!kiwix::fileReadable(customIndexPath)) {
|
||||
throw runtime_error("No such file exist (or file is not readable) " + customIndexPath);
|
||||
}
|
||||
if (kiwix::getMimeTypeForFile(customIndexPath) != "text/html") {
|
||||
throw runtime_error("Invalid File Mime Type " + kiwix::getMimeTypeForFile(customIndexPath));
|
||||
}
|
||||
string indexTemplateString = kiwix::getFileContent(customIndexPath);
|
||||
|
||||
if (indexTemplateString.empty()) {
|
||||
throw runtime_error("Unreadable or empty file " + customIndexPath);
|
||||
}
|
||||
return indexTemplateString;
|
||||
}
|
||||
|
||||
volatile sig_atomic_t waiting = false;
|
||||
volatile sig_atomic_t libraryMustBeReloaded = false;
|
||||
|
||||
#ifndef _WIN32
|
||||
void handle_sigterm(int signum)
|
||||
{
|
||||
if ( waiting == false ) {
|
||||
_exit(signum);
|
||||
}
|
||||
waiting = false;
|
||||
}
|
||||
|
||||
void handle_sighup(int signum)
|
||||
{
|
||||
libraryMustBeReloaded = true;
|
||||
}
|
||||
|
||||
typedef void (*SignalHandler)(int);
|
||||
|
||||
void set_signal_handler(int sig, SignalHandler handler)
|
||||
{
|
||||
struct sigaction sa;
|
||||
sigaction(sig, NULL, &sa);
|
||||
sa.sa_handler = handler;
|
||||
sigaction(sig, &sa, NULL);
|
||||
}
|
||||
|
||||
void setup_sighandlers()
|
||||
{
|
||||
set_signal_handler(SIGTERM, &handle_sigterm);
|
||||
set_signal_handler(SIGINT, &handle_sigterm);
|
||||
set_signal_handler(SIGHUP, &handle_sighup);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t fileModificationTime(const std::string& path)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(stat)
|
||||
#define stat _stat
|
||||
#endif
|
||||
struct stat fileStatData;
|
||||
if ( stat(path.c_str(), &fileStatData) == 0 ) {
|
||||
return fileStatData.st_mtime;
|
||||
}
|
||||
return 0;
|
||||
#ifdef _WIN32
|
||||
#undef stat
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t newestFileTimestamp(const std::vector<std::string>& paths)
|
||||
{
|
||||
uint64_t t = 0;
|
||||
for ( const auto& p : paths ) {
|
||||
t = std::max(t, fileModificationTime(p));
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
bool reloadLibrary(kiwix::Manager& mgr, const std::vector<std::string>& paths)
|
||||
{
|
||||
try {
|
||||
std::cout << "Loading the library from the following files:\n";
|
||||
for ( const auto& p : paths ) {
|
||||
std::cout << "\t" << p << std::endl;
|
||||
}
|
||||
mgr.reload(paths);
|
||||
std::cout << "The library was successfully loaded." << std::endl;
|
||||
return true;
|
||||
} catch ( const std::runtime_error& err ) {
|
||||
std::cerr << "ERROR: " << err.what() << std::endl;
|
||||
std::cerr << "Errors encountered while loading the library." << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
setup_sighandlers();
|
||||
#endif
|
||||
|
||||
std::string rootLocation = "";
|
||||
kiwix::Library library;
|
||||
unsigned int nb_threads = DEFAULT_THREADS;
|
||||
@@ -84,41 +192,53 @@ int main(int argc, char** argv)
|
||||
string libraryPath;
|
||||
string rootPath;
|
||||
string address;
|
||||
string customIndexPath="";
|
||||
string indexTemplateString="";
|
||||
int serverPort = 80;
|
||||
int daemonFlag [[gnu::unused]] = false;
|
||||
int libraryFlag = false;
|
||||
bool noLibraryButtonFlag = false;
|
||||
bool noSearchBarFlag = false;
|
||||
bool noDateAliasesFlag = false;
|
||||
bool blockExternalLinks = false;
|
||||
bool isVerboseFlag = false;
|
||||
bool trustlibrary = true;
|
||||
string PPIDString;
|
||||
bool monitorLibrary = false;
|
||||
unsigned int PPID = 0;
|
||||
int ipConnectionLimit = 0;
|
||||
int searchLimit = 0;
|
||||
|
||||
static struct option long_options[]
|
||||
= {{"daemon", no_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"library", no_argument, 0, 'l'},
|
||||
{"nolibrarybutton", no_argument, 0, 'm'},
|
||||
{"nodatealiases", no_argument, 0, 'z'},
|
||||
{"nosearchbar", no_argument, 0, 'n'},
|
||||
{"blockexternallinks", no_argument, 0, 'b'},
|
||||
{"attachToProcess", required_argument, 0, 'a'},
|
||||
{"port", required_argument, 0, 'p'},
|
||||
{"address", required_argument, 0, 'i'},
|
||||
{"threads", required_argument, 0, 't'},
|
||||
{"urlRootLocation", required_argument, 0, 'r'},
|
||||
{"donottrustlibrary", no_argument, 0, 'T'},
|
||||
{"customIndex", required_argument, 0, 'c'},
|
||||
{"monitorLibrary", no_argument, 0, 'M'},
|
||||
{"ipConnectionLimit", required_argument, 0, 'L'},
|
||||
{"searchLimit", required_argument, 0, 's'},
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
/* Argument parsing */
|
||||
while (true) {
|
||||
int option_index = 0;
|
||||
int c
|
||||
= getopt_long(argc, argv, "zmndvVla:p:f:t:r:i:", long_options, &option_index);
|
||||
= getopt_long(argc, argv, "hzmnbdvVla:p:f:t:r:i:c:ML:s:", long_options, &option_index);
|
||||
|
||||
if (c != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
case 'd':
|
||||
daemonFlag = true;
|
||||
break;
|
||||
@@ -134,19 +254,19 @@ int main(int argc, char** argv)
|
||||
case 'n':
|
||||
noSearchBarFlag = true;
|
||||
break;
|
||||
case 'b':
|
||||
blockExternalLinks = true;
|
||||
break;
|
||||
case 'z':
|
||||
noDateAliasesFlag = true;
|
||||
break;
|
||||
case 'm':
|
||||
noLibraryButtonFlag = true;
|
||||
break;
|
||||
case 'T':
|
||||
trustlibrary = false;
|
||||
case 'p':
|
||||
serverPort = atoi(optarg);
|
||||
break;
|
||||
case 'a':
|
||||
PPIDString = string(optarg);
|
||||
PPID = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
@@ -158,6 +278,18 @@ int main(int argc, char** argv)
|
||||
case 'r':
|
||||
rootLocation = string(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
customIndexPath = string(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
monitorLibrary = true;
|
||||
break;
|
||||
case 'L':
|
||||
ipConnectionLimit = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
searchLimit = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (optind < argc) {
|
||||
@@ -180,30 +312,11 @@ int main(int argc, char** argv)
|
||||
|
||||
/* Setup the library manager and get the list of books */
|
||||
kiwix::Manager manager(&library);
|
||||
vector<string> libraryPaths;
|
||||
if (libraryFlag) {
|
||||
vector<string> libraryPaths = kiwix::split(libraryPath, ";");
|
||||
vector<string>::iterator itr;
|
||||
|
||||
for (itr = libraryPaths.begin(); itr != libraryPaths.end(); ++itr) {
|
||||
if (!itr->empty()) {
|
||||
bool retVal = false;
|
||||
|
||||
try {
|
||||
string libraryPath
|
||||
= isRelativePath(*itr)
|
||||
? computeAbsolutePath(getCurrentDirectory(), *itr)
|
||||
: *itr;
|
||||
retVal = manager.readFile(libraryPath, true, trustlibrary);
|
||||
} catch (...) {
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
if (!retVal) {
|
||||
cerr << "Unable to open the XML library file '" << *itr << "'."
|
||||
<< endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
libraryPaths = kiwix::split(libraryPath, ";");
|
||||
if ( !reloadLibrary(manager, libraryPaths) ) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check if the library is not empty (or only remote books)*/
|
||||
@@ -221,6 +334,8 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
auto libraryFileTimestamp = newestFileTimestamp(libraryPaths);
|
||||
auto curLibraryFileTimestamp = libraryFileTimestamp;
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Fork if necessary */
|
||||
@@ -241,25 +356,39 @@ int main(int argc, char** argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
kiwix::HumanReadableNameMapper nameMapper(library, noDateAliasesFlag);
|
||||
kiwix::UpdatableNameMapper nameMapper(library, noDateAliasesFlag);
|
||||
kiwix::Server server(&library, &nameMapper);
|
||||
|
||||
if (!customIndexPath.empty()) {
|
||||
try {
|
||||
indexTemplateString = loadCustomTemplate(customIndexPath);
|
||||
} catch (std::runtime_error& e) {
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
server.setAddress(address);
|
||||
server.setRoot(rootLocation);
|
||||
server.setPort(serverPort);
|
||||
server.setNbThreads(nb_threads);
|
||||
server.setVerbose(isVerboseFlag);
|
||||
server.setTaskbar(!noSearchBarFlag, !noLibraryButtonFlag);
|
||||
server.setBlockExternalLinks(blockExternalLinks);
|
||||
server.setIndexTemplateString(indexTemplateString);
|
||||
server.setIpConnectionLimit(ipConnectionLimit);
|
||||
server.setMultiZimSearchLimit(searchLimit);
|
||||
|
||||
if (! server.start()) {
|
||||
cerr << "Unable to instantiate the HTTP daemon. The port " << serverPort
|
||||
<< " is maybe already occupied or need more permissions to be open. "
|
||||
"Please try as root or with a port number higher or equal to 1024."
|
||||
<< endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string url = "http://" + server.getAddress() + ":" + std::to_string(server.getPort()) + "/" + rootLocation;
|
||||
std::cout << "The Kiwix server is running and can be accessed in the local network at: "
|
||||
<< url << std::endl;
|
||||
|
||||
/* Run endless (until PPID dies) */
|
||||
bool waiting = true;
|
||||
waiting = true;
|
||||
do {
|
||||
if (PPID > 0) {
|
||||
#ifdef _WIN32
|
||||
@@ -280,7 +409,7 @@ int main(int argc, char** argv)
|
||||
int ret = sysctl(mib, MIBSIZE, &kp, &len, NULL, 0);
|
||||
if (ret != -1 && len > 0) {
|
||||
#else /* Linux & co */
|
||||
string procPath = "/proc/" + string(PPIDString);
|
||||
string procPath = "/proc/" + std::to_string(PPID);
|
||||
if (access(procPath.c_str(), F_OK) != -1) {
|
||||
#endif
|
||||
} else {
|
||||
@@ -289,6 +418,18 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
kiwix::sleep(1000);
|
||||
|
||||
if ( monitorLibrary ) {
|
||||
curLibraryFileTimestamp = newestFileTimestamp(libraryPaths);
|
||||
libraryMustBeReloaded += curLibraryFileTimestamp > libraryFileTimestamp;
|
||||
}
|
||||
|
||||
if ( libraryMustBeReloaded && !libraryPaths.empty() ) {
|
||||
libraryFileTimestamp = curLibraryFileTimestamp;
|
||||
reloadLibrary(manager, libraryPaths);
|
||||
nameMapper.update();
|
||||
libraryMustBeReloaded = false;
|
||||
}
|
||||
} while (waiting);
|
||||
|
||||
/* Stop the daemon */
|
||||
|
||||
@@ -24,9 +24,15 @@
|
||||
#define KIWIX_TOOLS_VERSION "undefined"
|
||||
#endif
|
||||
|
||||
#include <kiwix/version.h>
|
||||
#include <zim/version.h>
|
||||
|
||||
void version()
|
||||
{
|
||||
std::cout << KIWIX_TOOLS_VERSION << std::endl;
|
||||
std::cout << "kiwix-tools " << KIWIX_TOOLS_VERSION << std::endl << std::endl;
|
||||
kiwix::printVersions();
|
||||
std::cout << std::endl;
|
||||
zim::printVersions();
|
||||
}
|
||||
|
||||
#endif //_KIWIX_TOOLs_VERSION_H_
|
||||
|
||||
Reference in New Issue
Block a user