From: Josef Schlehofer Date: Mon, 29 Dec 2025 09:04:15 +0000 (+0100) Subject: radicale3: new package X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=16b5a43e39b99de7c70e67e1ec71cda45909b6c0;p=openwrt-packages.git radicale3: new package Radicale is a small but powerful CalDAV (calendars, to-do lists) and CardDAV (contacts) server. This package provides the latest 3.x series, which succeeds radicale2. This is replacament for recently dropped radicale2 and radicale1. Signed-off-by: Josef Schlehofer --- diff --git a/net/radicale3/Makefile b/net/radicale3/Makefile new file mode 100644 index 000000000..1db52b126 --- /dev/null +++ b/net/radicale3/Makefile @@ -0,0 +1,54 @@ +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=radicale3 +PKG_VERSION:=3.5.10 +PKG_RELEASE:=1 + +PKG_LICENSE:=GPL-3.0-or-later +PKG_LICENSE_FILES:=COPYING.md +PKG_CPE_ID:=cpe:/a:radicale:radicale + +PYPI_NAME:=Radicale +PYPI_SOURCE_NAME:=radicale +PKG_HASH:=569f2a8cf990faf9bb25b7442f36ddd439526b95db81d8878952d77836ab3d4c + +include ../../lang/python/pypi.mk +include $(INCLUDE_DIR)/package.mk +include ../../lang/python/python3-package.mk + +define Package/radicale3 + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + URL:=https://radicale.org/ + TITLE:=Radicale 3.x CalDAV/CardDAV server + USERID:=radicale3=226:radicale3=226 + DEPENDS:=+python3 +python3-dateutil +python3-vobject +python3-setuptools +python3-defusedxml +python3-passlib +python3-requests +python3-pika + PROVIDES:=radicale radicale2 +endef + +define Package/radicale3/description + The Radicale Project is a CalDAV (calendar) and CardDAV (contact) server. It aims to be a light solution, easy to use, easy to install, easy to configure. As a consequence, it requires few software dependencies and is pre-configured to work out-of-the-box. + The Radicale Project runs on most of the UNIX-like platforms (Linux, BSD, MacOS X) and Windows. It is known to work with Evolution, Lightning, iPhone and Android clients. It is free and open-source software, released under GPL version 3. + + This package contains the python files. +endef + +define Package/radicale3/conffiles +/etc/config/radicale3 +endef + +define Py3Package/radicale3/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/radicale $(1)/usr/bin/radicale3 + $(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d + $(INSTALL_CONF) ./files/radicale3.config $(1)/etc/config/radicale3 + $(INSTALL_BIN) ./files/radicale3.init $(1)/etc/init.d/radicale3 +endef + +$(eval $(call Py3Package,radicale3)) +$(eval $(call BuildPackage,radicale3)) +$(eval $(call BuildPackage,radicale3-src)) diff --git a/net/radicale3/files/radicale3.config b/net/radicale3/files/radicale3.config new file mode 100644 index 000000000..5107219df --- /dev/null +++ b/net/radicale3/files/radicale3.config @@ -0,0 +1,7 @@ +#config section server + # list host 127.0.0.1:5232 + # list host ::1:5232 + +#config user + #option name user1 + #option password password1 diff --git a/net/radicale3/files/radicale3.init b/net/radicale3/files/radicale3.init new file mode 100755 index 000000000..1afc25f26 --- /dev/null +++ b/net/radicale3/files/radicale3.init @@ -0,0 +1,221 @@ +#!/bin/sh /etc/rc.common + +START=99 +USE_PROCD=1 + +PROG=/usr/bin/radicale3 +CFGDIR=/var/etc/radicale3 +SYSCFG=$CFGDIR/config +USRCFG=$CFGDIR/users +DATADIR="/srv/radicale3/data" + +conf_line() { + local cfgfile="$1" + local option="$2" + local value="$3" + + if [ -n "$value" ]; then + echo "$option = $value" >> "$cfgfile" + fi +} + +conf_getline() { + local cfg="$1" + local cfgfile="$2" + local option="$3" + local defval="$4" + local boolean="$5" + # Note: $value is used by the caller, so we do not declare it local here. + unset value + + if [ "$boolean" != "1" ]; then + config_get value "$cfg" "$option" "$defval" + conf_line "$cfgfile" "$option" "$value" + else + config_get_bool value "$cfg" "$option" "$defval" + # config_get_bool returns 0/1 in value + if [ -n "$value" ]; then + if [ "$value" -eq 1 ]; then + conf_line "$cfgfile" "$option" "True" + else + conf_line "$cfgfile" "$option" "False" + fi + fi + fi +} + +build_hosts_line() { + local val="$1" + append hostlist "$val" ", " +} + +conf_section() { + local cfg="$1" + local cfgfile="$2" + local hostlist="" + local value + + echo "[$cfg]" >> "$cfgfile" + + case $cfg in + server) + config_list_foreach "$cfg" host build_hosts_line + conf_line "$cfgfile" hosts "$hostlist" + conf_getline "$cfg" "$cfgfile" max_connections + conf_getline "$cfg" "$cfgfile" max_content_length + conf_getline "$cfg" "$cfgfile" timeout + + conf_getline "$cfg" "$cfgfile" ssl 0 1 + if [ "$value" -eq 1 ]; then + conf_getline "$cfg" "$cfgfile" certificate + conf_getline "$cfg" "$cfgfile" key + conf_getline "$cfg" "$cfgfile" certificate_authority + conf_getline "$cfg" "$cfgfile" protocol + conf_getline "$cfg" "$cfgfile" ciphers + fi + + conf_getline "$cfg" "$cfgfile" dns_lookup 1 1 + conf_getline "$cfg" "$cfgfile" realm + ;; + encoding) + conf_getline "$cfg" "$cfgfile" request + conf_getline "$cfg" "$cfgfile" stock + ;; + auth) + conf_getline "$cfg" "$cfgfile" "type" htpasswd + if [ "$value" = "htpasswd" ]; then + conf_getline "$cfg" "$cfgfile" htpasswd_filename "$USRCFG" + conf_getline "$cfg" "$cfgfile" htpasswd_encryption plain + fi + + conf_getline "$cfg" "$cfgfile" delay + ;; + rights) + conf_getline "$cfg" "$cfgfile" "type" + if [ "$value" = "from_file" ]; then + conf_getline "$cfg" "$cfgfile" "file" + fi + ;; + storage) + conf_getline "$cfg" "$cfgfile" filesystem_folder "$DATADIR" + # Update global DATADIR if user specified a custom one, so we can mkdir it later + if [ -n "$value" ]; then + DATADIR="$value" + fi + conf_getline "$cfg" "$cfgfile" filesystem_locking 1 1 + conf_getline "$cfg" "$cfgfile" max_sync_token_age + conf_getline "$cfg" "$cfgfile" filesystem_close_lock_file 0 1 + conf_getline "$cfg" "$cfgfile" hook + ;; + web) + conf_getline "$cfg" "$cfgfile" "type" + ;; + logging) + conf_getline "$cfg" "$cfgfile" config + conf_getline "$cfg" "$cfgfile" debug 0 1 + conf_getline "$cfg" "$cfgfile" full_environment 0 1 + conf_getline "$cfg" "$cfgfile" mask_passwords 1 1 + ;; + headers) + config_get cors "$cfg" cors + if [ -n "$cors" ]; then + echo "Access-Control-Allow-Origin = $cors" >> "$cfgfile" + fi + ;; + esac + + echo "" >> "$cfgfile" +} + +add_missing_sections() { + local cfgfile="$1" + + for section in server encoding auth rights storage web logging headers; do + if ! grep -q "\[$section\]" "$cfgfile"; then + echo "[$section]" >> "$cfgfile" + case $section in + server) + echo "hosts = 0.0.0.0:5232, [::]:5232" >> "$cfgfile" + ;; + auth) + echo "type = htpasswd" >> "$cfgfile" + echo "htpasswd_filename = $USRCFG" >> "$cfgfile" + echo "htpasswd_encryption = plain" >> "$cfgfile" + ;; + storage) + echo "filesystem_folder = $DATADIR" >> "$cfgfile" + ;; + esac + echo "" >> "$cfgfile" + fi + done +} + +add_user() { + local cfg="$1" + local tmpfile="$2" + local name password + + config_get name "$cfg" name + config_get password "$cfg" password + + [ -n "$name" ] && echo "$name:$password" >> "$tmpfile" +} + +build_users() { + local tmpfile="$1" + config_foreach add_user user "$tmpfile" +} + +build_config() { + local tmpconf=$(mktemp) + local tmpusers=$(mktemp) + + chmod 0640 "$tmpconf" "$tmpusers" + + config_load radicale3 + config_foreach conf_section section "$tmpconf" + add_missing_sections "$tmpconf" + + build_users "$tmpusers" + + # Apply permissions + mkdir -p "$CFGDIR" + chmod 0750 "$CFGDIR" + chgrp radicale3 "$CFGDIR" + + cat "$tmpconf" > "$SYSCFG" + cat "$tmpusers" > "$USRCFG" + chmod 0640 "$SYSCFG" "$USRCFG" + chgrp radicale3 "$SYSCFG" "$USRCFG" + + rm -f "$tmpconf" "$tmpusers" +} + +start_service() { + # If custom config (/etc/radicale3/config) absent, build it from UCI + if [ ! -f /etc/radicale3/config ]; then + build_config + CFG_FILE="$SYSCFG" + + # Ensure data dir exists (DATADIR might have been updated by build_config) + mkdir -p "$DATADIR" + chown radicale3:radicale3 "$DATADIR" + else + CFG_FILE="/etc/radicale3/config" + # We assume user handles directory creation if using manual config, + # but we could attempt it if we parsed it. simpler to leave it for now. + fi + + procd_open_instance + procd_set_param command "$PROG" --config "$CFG_FILE" + procd_set_param user radicale3 + procd_set_param respawn + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_close_instance +} + +service_triggers() { + procd_add_reload_trigger "radicale3" +}