mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-02-04 08:13:38 +00:00
Tests: - Without patch, upload an invalid zim file, 'Failed to add content'... message is shown. The library's content directory contains that invalid file. Try to add the file again and the message shown is 'File already exists'. - With patch, upload an invalid zim file, 'Failed to add content'... message is shown. The library's content directory does not contain that file. Try to add the file again and the same message is shown. - Functional tests for kiwix pass. Repeating just the test test_add_invalid_zim_file works. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Veiko Aasa <veiko17@disroot.org>
107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Privileged actions for Kiwix content server.
|
|
"""
|
|
|
|
import pathlib
|
|
import shutil
|
|
import subprocess
|
|
from xml.etree import ElementTree
|
|
|
|
from plinth import action_utils
|
|
from plinth.actions import privileged
|
|
from plinth.modules import kiwix
|
|
|
|
# Only one central library is supported.
|
|
KIWIX_HOME = pathlib.Path('/var/lib/kiwix-server-freedombox')
|
|
LIBRARY_FILE = KIWIX_HOME / 'library_zim.xml'
|
|
CONTENT_DIR = KIWIX_HOME / 'content'
|
|
|
|
|
|
@privileged
|
|
def add_package(file_name: str, temporary_file_path: str):
|
|
"""Adds a content package to Kiwix.
|
|
|
|
Adding packages is idempotent.
|
|
|
|
Users can add content to Kiwix in multiple ways:
|
|
- Upload a ZIM file
|
|
- Provide a link to the ZIM file
|
|
- Provide a magnet link to the ZIM file
|
|
|
|
The commandline download manager aria2c is a dependency of kiwix-tools.
|
|
aria2c is used for both HTTP and Magnet downloads.
|
|
"""
|
|
kiwix.validate_file_name(file_name)
|
|
# file_name is verified further by move_uploaded_file()
|
|
|
|
# Moving files to the Kiwix library path ensures that
|
|
# they can't be removed by other apps or users.
|
|
CONTENT_DIR.mkdir(exist_ok=True)
|
|
action_utils.move_uploaded_file(temporary_file_path, CONTENT_DIR,
|
|
file_name, allow_overwrite=False,
|
|
user='root', group='root',
|
|
permissions=0o644)
|
|
|
|
content_file = CONTENT_DIR / file_name
|
|
try:
|
|
_kiwix_manage_add(str(CONTENT_DIR / file_name))
|
|
except subprocess.CalledProcessError:
|
|
# Remove the uploaded file if we could not added it to library
|
|
content_file.unlink()
|
|
raise
|
|
|
|
|
|
def _kiwix_manage_add(zim_file: str):
|
|
subprocess.check_call(['kiwix-manage', LIBRARY_FILE, 'add', zim_file])
|
|
|
|
# kiwix-serve doesn't read the library file unless it is restarted.
|
|
action_utils.service_try_restart('kiwix-server-freedombox')
|
|
|
|
|
|
@privileged
|
|
def uninstall() -> None:
|
|
"""Remove all content during uninstall."""
|
|
shutil.rmtree(str(CONTENT_DIR), ignore_errors=True)
|
|
LIBRARY_FILE.unlink(missing_ok=True)
|
|
|
|
|
|
@privileged
|
|
def list_packages() -> dict[str, dict[str, str]]:
|
|
"""Return the list of content packages configured in library file."""
|
|
library = ElementTree.parse(LIBRARY_FILE).getroot()
|
|
|
|
books = {}
|
|
for book in library:
|
|
path = book.attrib['path'].split('/')[-1]
|
|
path = path.removesuffix('.zim').lower() # Strip '.zim' from the path
|
|
try:
|
|
books[book.attrib['id']] = {
|
|
'title': book.attrib['title'],
|
|
'description': book.attrib['description'],
|
|
'path': path
|
|
}
|
|
except KeyError:
|
|
pass # Ignore entries that don't have expected properties
|
|
|
|
return books
|
|
|
|
|
|
@privileged
|
|
def delete_package(zim_id: str):
|
|
"""Remove a content package from the library file."""
|
|
library = ElementTree.parse(LIBRARY_FILE).getroot()
|
|
|
|
for book in library:
|
|
try:
|
|
if book.attrib['id'] != zim_id:
|
|
continue
|
|
|
|
subprocess.check_call(
|
|
['kiwix-manage', LIBRARY_FILE, 'remove', zim_id])
|
|
(KIWIX_HOME / book.attrib['path']).unlink()
|
|
action_utils.service_try_restart('kiwix-server-freedombox')
|
|
return
|
|
except KeyError: # Expected properties not found on elements
|
|
pass
|