From unknown Sun Aug 17 01:51:36 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#61122] [PATCH] services: Add mympd-service-type. Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 28 Jan 2023 13:55:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 61122 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 61122@debbugs.gnu.org Cc: Bruno Victal X-Debbugs-Original-To: guix-patches@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.167491405530618 (code B ref -1); Sat, 28 Jan 2023 13:55:01 +0000 Received: (at submit) by debbugs.gnu.org; 28 Jan 2023 13:54:15 +0000 Received: from localhost ([127.0.0.1]:39904 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pLleo-0007xl-5G for submit@debbugs.gnu.org; Sat, 28 Jan 2023 08:54:15 -0500 Received: from lists.gnu.org ([209.51.188.17]:60914) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pLlel-0007xd-TD for submit@debbugs.gnu.org; Sat, 28 Jan 2023 08:54:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLlel-0000PV-Lt for guix-patches@gnu.org; Sat, 28 Jan 2023 08:54:11 -0500 Received: from smtpm1.myservices.hosting ([185.26.105.232]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLlei-0007Ap-VG for guix-patches@gnu.org; Sat, 28 Jan 2023 08:54:11 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpm1.myservices.hosting (Postfix) with ESMTP id 31CC720865 for ; Sat, 28 Jan 2023 14:53:57 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id CAEA380098; Sat, 28 Jan 2023 14:53:57 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 1UlGWltVrFiE; Sat, 28 Jan 2023 14:53:53 +0100 (CET) Received: from guix-nuc.home.arpa (bl9-118-236.dsl.telepac.pt [85.242.118.236]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id ED0A380097; Sat, 28 Jan 2023 14:53:52 +0100 (CET) From: Bruno Victal Date: Sat, 28 Jan 2023 13:53:43 +0000 Message-Id: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=185.26.105.232; envelope-from=mirai@makinata.eu; helo=smtpm1.myservices.hosting X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) * gnu/services/audio.scm (mympd-service-type): New variable. * gnu/tests/audio.scm (%test-mympd): New variable. * doc/guix.texi: Document it. --- doc/guix.texi | 115 +++++++++++++++++ gnu/services/audio.scm | 273 ++++++++++++++++++++++++++++++++++++++++- gnu/tests/audio.scm | 54 +++++++- 3 files changed, 440 insertions(+), 2 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 2b1ad77ba5..790696783c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -112,6 +112,7 @@ Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@* Copyright @copyright{} 2023 Giacomo Leidi@* Copyright @copyright{} 2022 Antero Mejr@* +Copyright @copyright{} 2022 Bruno Victal@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -33272,6 +33273,120 @@ Audio Services (port . "8080")))))))) @end lisp +@subsubheading myMPD + +@cindex MPD, web interface +@cindex myMPD service + +@uref{https://jcorporation.github.io/myMPD/, myMPD} is a web server +frontend for MPD that provides a mobile friendly web client for MPD. + +The following example shows a myMPD instance listening on port 80, +with album cover caching disabled. + +@lisp +(service mympd-service-type + (mympd-configuration + (port 80) + (covercache-ttl 0))) +@end lisp + +@defvar mympd-service-type +The service type for @command{mympd}. +@end defvar + +@c %start of fragment +@deftp {Data Type} mympd-configuration +Available @code{mympd-configuration} fields are: + +@table @asis +@item @code{package} (default: @code{mympd}) (type: file-like) +The package object of the myMPD server. + +@item @code{shepherd-requirement} (default: @code{()}) (type: list-of-symbol) +This is a list of symbols naming Shepherd services that this service +will depend on. + +@item @code{user} (default: @code{"mympd"}) (type: string) +Owner of the @command{mympd} process. + +@item @code{group} (default: @code{"nogroup"}) (type: string) +Owner group of the @command{mympd} process. + +@item @code{work-directory} (default: @code{"/var/lib/mympd"}) (type: string) +Where myMPD will store its data. + +@item @code{cache-directory} (default: @code{"/var/cache/mympd"}) (type: string) +Where myMPD will store its cache. + +@item @code{acl} (type: maybe-ip-acl) +ACL to access the myMPD webserver. See +@uref{https://jcorporation.github.io/myMPD/configuration/acl,myMPD ACL} +for syntax. + +@item @code{covercache-ttl} (default: @code{31}) (type: maybe-integer) +How long to keep cached covers, @code{0} disables cover caching. + +@item @code{http?} (default: @code{#t}) (type: boolean) +HTTP support. + +@item @code{host} (default: @code{"[::]"}) (type: string) +Host name to listen on. + +@item @code{port} (default: @code{80}) (type: maybe-port) +HTTP port to listen on. + +@item @code{log-level} (default: @code{5}) (type: integer) +How much detail to include in logs, possible values: @code{0} to +@code{7}. + +@item @code{log-to} (default: @code{"/var/log/mympd/log"}) (type: string-or-symbol) +Where to send logs. By default, the service logs to +@file{/var/log/mympd.log}. The alternative is @code{'syslog}, which +sends output to the running syslog service under the @samp{daemon} +facility. + +@item @code{lualibs} (default: @code{"all"}) (type: maybe-string) +See +@uref{https://jcorporation.github.io/myMPD/scripting/#lua-standard-libraries}. + +@item @code{script-acl} (default: @code{(ip-acl (allow '("127.0.0.1")))}) (type: maybe-ip-acl) +ACL to access the myMPD script backend. + +@item @code{ssl?} (default: @code{#f}) (type: boolean) +SSL/TLS support. + +@item @code{ssl-port} (default: @code{443}) (type: maybe-port) +Port to listen for HTTPS. + +@item @code{ssl-cert} (type: maybe-string) +Path to PEM encoded X.509 SSL/TLS certificate (public key). + +@item @code{ssl-key} (type: maybe-string) +Path to PEM encoded SSL/TLS private key. + +@item @code{pin-hash} (type: maybe-string) +SHA-256 hashed pin used by myMPD to control settings access by prompting +a pin from the user. + +@end table +@end deftp +@c %end of fragment + +@c %start of fragment +@deftp {Data Type} ip-acl +Available @code{ip-acl} fields are: + +@table @asis +@item @code{allow} (default: @code{()}) (type: list-of-string) +Allowed IP addresses. + +@item @code{deny} (default: @code{()}) (type: list-of-string) +Disallowed IP addresses. + +@end table +@end deftp +@c %end of fragment @node Virtualization Services @subsection Virtualization Services diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm index c60053f33c..c384d3d2b8 100644 --- a/gnu/services/audio.scm +++ b/gnu/services/audio.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017 Peter Mikkelsen ;;; Copyright © 2019 Ricardo Wurmus ;;; Copyright © 2020 Ludovic Courtès +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -21,6 +22,8 @@ (define-module (gnu services audio) #:use-module (guix gexp) #:use-module (gnu services) + #:use-module (gnu services admin) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) @@ -28,11 +31,41 @@ (define-module (gnu services audio) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (ice-9 format) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (mpd-output mpd-output? mpd-configuration mpd-configuration? - mpd-service-type)) + mpd-service-type + + mympd-service-type + mympd-configuration + mympd-configuration? + mympd-configuration-package + mympd-configuration-shepherd-requirement + mympd-configuration-user + mympd-configuration-group + mympd-configuration-work-directory + mympd-configuration-cache-directory + mympd-configuration-acl + mympd-configuration-covercache-ttl + mympd-configuration-http? + mympd-configuration-host + mympd-configuration-port + mympd-configuration-log-level + mympd-configuration-log-to + mympd-configuration-lualibs + mympd-configuration-script-acl + mympd-configuration-ssl? + mympd-configuration-ssl-port + mympd-configuration-ssl-cert + mympd-configuration-ssl-key + mympd-configuration-pin-hash + ip-acl + ip-acl? + ip-acl-allow + ip-acl-deny)) ;;; Commentary: ;;; @@ -197,3 +230,241 @@ (define mpd-service-type (service-extension activation-service-type mpd-service-activation))) (default-value (mpd-configuration)))) + + +;;; +;;; myMPD +;;; + +(define list-of-symbol? + (list-of symbol?)) + +(define list-of-string? + (list-of string?)) + +(define (port? n) + (and (integer? n) + (<= 0 n 65535))) + +(define (string-or-symbol? x) + (or (symbol? x) (string? x))) + +(define-configuration/no-serialization ip-acl + (allow + (list-of-string '()) + "Allowed IP addresses.") + + (deny + (list-of-string '()) + "Disallowed IP addresses.")) + +(define-maybe/no-serialization port) +(define-maybe/no-serialization integer) +(define-maybe/no-serialization string) +(define-maybe/no-serialization ip-acl) + +;; XXX: The serialization procedures are insufficient since we require +;; access to multiple fields at once. +;; Fields marked with empty-serializer are never serialized and are +;; used for command-line arguments or by the service definition. +(define-configuration/no-serialization mympd-configuration + (package + (file-like mympd) + "The package object of the myMPD server." + empty-serializer) + + (shepherd-requirement + (list-of-symbol '()) + "This is a list of symbols naming Shepherd services that this service +will depend on." + empty-serializer) + + (user + (string "mympd") + "Owner of the @command{mympd} process." + empty-serializer) + + (group + (string "nogroup") + "Owner group of the @command{mympd} process." + empty-serializer) + + (work-directory + (string "/var/lib/mympd") + "Where myMPD will store its data." + empty-serializer) + + (cache-directory + (string "/var/cache/mympd") + "Where myMPD will store its cache." + empty-serializer) + + (acl + maybe-ip-acl + "ACL to access the myMPD webserver. See +@uref{https://jcorporation.github.io/myMPD/configuration/acl,myMPD ACL} +for syntax.") + + (covercache-ttl + (maybe-integer 31) + "How long to keep cached covers, @code{0} disables cover caching.") + + (http? + (boolean #t) + "HTTP support.") + + (host + (string "[::]") + "Host name to listen on.") + + (port + (maybe-port 80) + "HTTP port to listen on.") + + (log-level + (integer 5) + "How much detail to include in logs, possible values: @code{0} to @code{7}.") + + (log-to + (string-or-symbol "/var/log/mympd/log") + "Where to send logs. By default, the service logs to +@file{/var/log/mympd.log}. The alternative is @code{'syslog}, which +sends output to the running syslog service under the @samp{daemon} facility." + empty-serializer) + + (lualibs + (maybe-string "all") + "See +@url{https://jcorporation.github.io/myMPD/scripting/#lua-standard-libraries}.") + + (script-acl + (maybe-ip-acl (ip-acl + (allow '("127.0.0.1")))) + "ACL to access the myMPD script backend.") + + (ssl? + (boolean #f) + "SSL/TLS support.") + + (ssl-port + (maybe-port 443) + "Port to listen for HTTPS.") + + (ssl-cert + maybe-string + "Path to PEM encoded X.509 SSL/TLS certificate (public key).") + + (ssl-key + maybe-string + "Path to PEM encoded SSL/TLS private key.") + + (pin-hash + maybe-string + "SHA-256 hashed pin used by myMPD to control settings access by +prompting a pin from the user.")) + +(define (mympd-serialize-configuration config) + (define serialize-value + (match-lambda + ((? boolean? val) (if val "true" "false")) + ((or (? port? val) (? integer? val)) (number->string val)) + ((? ip-acl? val) (ip-acl-serialize-configuration val)) + ((? string? val) val))) + + (define (ip-acl-serialize-configuration config) + (define (serialize-list-of-string prefix lst) + (map (cut format #f "~a~a" prefix <>) lst)) + (string-join + (append + (serialize-list-of-string "+" (ip-acl-allow config)) + (serialize-list-of-string "-" (ip-acl-deny config))) ",")) + + ;; myMPD configuration fields are serialized as individual files under + ;; /config/. + (match-record config (work-directory acl + covercache-ttl http? host port + log-level lualibs script-acl + ssl? ssl-port ssl-cert ssl-key + pin-hash) + (define (serialize-field filename value) + (when (maybe-value-set? value) + (list (format #f "~a/config/~a" work-directory filename) + (mixed-text-file filename (serialize-value value))))) + + (let ((filename-to-field `(("acl" . ,acl) + ("covercache_keep_days" . ,covercache-ttl) + ("http" . ,http?) + ("http_host" . ,host) + ("http_port" . ,port) + ("loglevel" . ,log-level) + ("lualibs" . ,lualibs) + ("scriptacl" . ,script-acl) + ("ssl" . ,ssl?) + ("ssl_port" . ,ssl-port) + ("ssl_cert" . ,ssl-cert) + ("ssl_key" . ,ssl-key) + ("pin_hash" . ,pin-hash)))) + (filter list? + (generic-serialize-alist list serialize-field + filename-to-field))))) + +(define (mympd-shepherd-service config) + (match-record config (package shepherd-requirement + user work-directory + cache-directory log-level log-to) + (let ((log-level* (format #f "MYMPD_LOGLEVEL=~a" log-level))) + (shepherd-service + (documentation "Run the myMPD daemon.") + (requirement `(loopback user-processes ,@shepherd-requirement)) + (provision '(mympd)) + (start #~(begin + (let* ((pw (getpwnam #$user)) + (uid (passwd:uid pw)) + (gid (passwd:gid pw))) + (for-each (lambda (dir) + (mkdir-p dir) + (chown dir uid gid)) + (list #$work-directory #$cache-directory))) + + (make-forkexec-constructor + `(#$(file-append package "/bin/mympd") + "--user" #$user + #$@(if (eqv? log-to 'syslog) '("--syslog") '()) + "--workdir" #$work-directory + "--cachedir" #$cache-directory) + #:environment-variables (list #$log-level*) + #:log-file #$(if (string? log-to) log-to #f)))) + (stop #~(make-kill-destructor)))))) + +(define (mympd-accounts config) + (match-record config (user group) + (list (user-group (name group) + (system? #t)) + (user-account (name user) + (group group) + (system? #t) + (comment "myMPD user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin")))))) + +(define (mympd-log-rotation config) + (match-record config (log-to) + (if (string? log-to) + (list (log-rotation + (files (list log-to)))) + '()))) + +(define mympd-service-type + (service-type + (name 'mympd) + (extensions + (list (service-extension shepherd-root-service-type + (compose list mympd-shepherd-service)) + (service-extension account-service-type + mympd-accounts) + (service-extension special-files-service-type + mympd-serialize-configuration) + (service-extension rottlog-service-type + mympd-log-rotation))) + (description "Run myMPD, a frontend for MPD. (Music Player Daemon)") + (default-value (mympd-configuration)))) diff --git a/gnu/tests/audio.scm b/gnu/tests/audio.scm index 8aa6d1e818..701496ee23 100644 --- a/gnu/tests/audio.scm +++ b/gnu/tests/audio.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 Peter Mikkelsen +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -22,9 +23,11 @@ (define-module (gnu tests audio) #:use-module (gnu system vm) #:use-module (gnu services) #:use-module (gnu services audio) + #:use-module (gnu services networking) #:use-module (gnu packages mpd) #:use-module (guix gexp) - #:export (%test-mpd)) + #:export (%test-mpd + %test-mympd)) (define %mpd-os (simple-operating-system @@ -76,3 +79,52 @@ (define %test-mpd (name "mpd") (description "Test that the mpd can run and be connected to.") (value (run-mpd-test)))) + + +(define (run-mympd-test) + (define os (marionette-operating-system + (simple-operating-system (service dhcp-client-service-type) + (service mympd-service-type)) + #:imported-modules '((gnu services herd)))) + + (define vm + (virtual-machine + (operating-system os) + (port-forwardings '((8080 . 80))))) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (srfi srfi-64) + (srfi srfi-8) + (web client) + (web response) + (gnu build marionette)) + + (define marionette + (make-marionette (list #$vm))) + + (test-runner-current (system-test-runner #$output)) + (test-begin "mympd") + (test-assert "service is running" + (marionette-eval '(begin + (use-modules (gnu services herd)) + + (start-service 'mympd)) + marionette)) + + (test-assert "HTTP port ready" + (wait-for-tcp-port 80 marionette)) + + (test-equal "http-head" + 200 + (receive (x _) (http-head "http://localhost:8080") (response-code x))) + + (test-end)))) + (gexp->derivation "mympd-test" test)) + +(define %test-mympd + (system-test + (name "mympd") + (description "Connect to a running myMPD service.") + (value (run-mympd-test)))) base-commit: 37fdb382dad47149d8f5be41af108478800e9d30 -- 2.38.1 From unknown Sun Aug 17 01:51:36 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#61122] [PATCH] services: Add mympd-service-type. Resent-From: Liliana Marie Prikler Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 03 Feb 2023 22:49:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 61122 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Bruno Victal , 61122@debbugs.gnu.org Received: via spool by 61122-submit@debbugs.gnu.org id=B61122.167546454123159 (code B ref 61122); Fri, 03 Feb 2023 22:49:01 +0000 Received: (at 61122) by debbugs.gnu.org; 3 Feb 2023 22:49:01 +0000 Received: from localhost ([127.0.0.1]:40127 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pO4rc-00061S-3a for submit@debbugs.gnu.org; Fri, 03 Feb 2023 17:49:01 -0500 Received: from mail-ej1-f65.google.com ([209.85.218.65]:35397) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pO4rZ-00061D-0R for 61122@debbugs.gnu.org; Fri, 03 Feb 2023 17:48:59 -0500 Received: by mail-ej1-f65.google.com with SMTP id qw12so19419091ejc.2 for <61122@debbugs.gnu.org>; Fri, 03 Feb 2023 14:48:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:from:to:cc:subject:date :message-id:reply-to; bh=m9hBEofPn/3++/USghefqXxdP5euC0UhVX0PzcqaBDs=; b=FoXKCbm/DDsTrjwcu4jFwAA7movdooOEixkVo3Mq9yQbMzd3eLFofgmCjn8d8OHYew vuZuednC534/depYprPdpNiRjPEunMUInctsCWtNwdI8TW7emkGY1SbHAmYencUIgSYT ye6zLI8AzrL8lB+X+h19aHYGaPzwMICSIbMXfxS/DideIOnjDWF55DaSxvjyGLoc8qE4 Hn3GDEyxFzEgHvgda8XDxB4esjIpIQsb0V0H1cUvdeZVjUkXhTzHIEJOT9uUlDX0I71h oFwsF0R+MMq/Fu4VypIEuUOhE4C/XaO1PWfsSUWUF0Bvxf5sKRMUS+gBjgrbgT8jCatJ mTVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=m9hBEofPn/3++/USghefqXxdP5euC0UhVX0PzcqaBDs=; b=QlnaU0OnFQR4iMPLIQVHj5YdnZ8GwPdz7nPanlon8WlCIH5gW1SEHZt2x8BDhTyg3Y xsI+RirxD03eDM7mzCVp2lclgqy9px6UlTpKHKClueOzbUp0oYeBFor4iP64c8Q86cqN ecT+8knugi8mWO08QB0zYpF3gygYmn4nvZp1TwgajmO9oDVo2p3mGqA4p0MfVJtVLvk+ eqc9BgmDIVcQ/MV4FJDvjVVmH/JV2pbg21rCR0MfzHKE7uSY5XRzDwYCXnYUs0hiJMNj KOc2FnyVjCWIRMOtlVjObZnkJuY0BHx+3h9+VMq45Wa6Kt6hogzqvhIM9TawMPBca+9c yvKw== X-Gm-Message-State: AO0yUKUy45DIxxyMmNAzS8g2epkcobr/PVO7dYS4NPrNC0+LCnHqUYFh E5WwNJyZ4Db/gFcXw1On7Vs= X-Google-Smtp-Source: AK7set9TrzW3Q2cm2Z0riXkjzuOWm7ph9JOnOL1CZy80NvZXprvmj6Jk/tyfVtNuPSyv5dpKBfm6tw== X-Received: by 2002:a17:906:bc8d:b0:874:e17e:2526 with SMTP id lv13-20020a170906bc8d00b00874e17e2526mr12694344ejb.72.1675464530822; Fri, 03 Feb 2023 14:48:50 -0800 (PST) Received: from lumine.fritz.box (85-127-52-93.dsl.dynamic.surfer.at. [85.127.52.93]) by smtp.gmail.com with ESMTPSA id e7-20020a170906080700b00887a28ac01asm1982144ejd.31.2023.02.03.14.48.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Feb 2023 14:48:50 -0800 (PST) Message-ID: From: Liliana Marie Prikler Date: Fri, 03 Feb 2023 23:48:47 +0100 In-Reply-To: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> References: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 User-Agent: Evolution 3.46.0 MIME-Version: 1.0 X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) QW0gU2Ftc3RhZywgZGVtIDI4LjAxLjIwMjMgdW0gMTM6NTMgKzAwMDAgc2NocmllYiBCcnVubyBW aWN0YWw6Cj4gKiBnbnUvc2VydmljZXMvYXVkaW8uc2NtIChteW1wZC1zZXJ2aWNlLXR5cGUpOiBO ZXcgdmFyaWFibGUuCj4gKiBnbnUvdGVzdHMvYXVkaW8uc2NtICgldGVzdC1teW1wZCk6IE5ldyB2 YXJpYWJsZS4KPiAqIGRvYy9ndWl4LnRleGk6IERvY3VtZW50IGl0Lgo+IC0tLQo+IMKgZG9jL2d1 aXgudGV4acKgwqDCoMKgwqDCoMKgwqDCoCB8IDExNSArKysrKysrKysrKysrKysrKwo+IMKgZ251 L3NlcnZpY2VzL2F1ZGlvLnNjbSB8IDI3Mwo+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKystCj4gwqBnbnUvdGVzdHMvYXVkaW8uc2NtwqDCoMKgIHzCoCA1NCArKysrKysr LQo+IMKgMyBmaWxlcyBjaGFuZ2VkLCA0NDAgaW5zZXJ0aW9ucygrKSwgMiBkZWxldGlvbnMoLSkK PiAKPiBkaWZmIC0tZ2l0IGEvZG9jL2d1aXgudGV4aSBiL2RvYy9ndWl4LnRleGkKPiBpbmRleCAy YjFhZDc3YmE1Li43OTA2OTY3ODNjIDEwMDY0NAo+IC0tLSBhL2RvYy9ndWl4LnRleGkKPiArKysg Yi9kb2MvZ3VpeC50ZXhpCj4gQEAgLTExMiw2ICsxMTIsNyBAQAo+IMKgQ29weXJpZ2h0IEBjb3B5 cmlnaHR7fSAyMDIyIEl2YW4gVmlsYXRhLWktQmFsYWd1ZXJAKgo+IMKgQ29weXJpZ2h0IEBjb3B5 cmlnaHR7fSAyMDIzIEdpYWNvbW8gTGVpZGlAKgo+IMKgQ29weXJpZ2h0IEBjb3B5cmlnaHR7fSAy MDIyIEFudGVybyBNZWpyQCoKPiArQ29weXJpZ2h0IEBjb3B5cmlnaHR7fSAyMDIyIEJydW5vIFZp Y3RhbEAqCkFyZSB5b3Ugc3VyZSBpdCdzIHN0aWxsIDIwMjI/Cj4gwqAKPiDCoFBlcm1pc3Npb24g aXMgZ3JhbnRlZCB0byBjb3B5LCBkaXN0cmlidXRlIGFuZC9vciBtb2RpZnkgdGhpcwo+IGRvY3Vt ZW50Cj4gwqB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBGcmVlIERvY3VtZW50YXRpb24gTGlj ZW5zZSwgVmVyc2lvbiAxLjMKPiBvcgo+IEBAIC0zMzI3Miw2ICszMzI3MywxMjAgQEAgQXVkaW8g U2VydmljZXMKPiDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqAgKHBvcnTCoMKgwqAgLiAiODA4MCIpKSkpKSkpKQo+IMKgQGVuZCBsaXNwCj4gwqAKPiArQHN1 YnN1YmhlYWRpbmcgbXlNUEQKPiArCj4gK0BjaW5kZXggTVBELCB3ZWIgaW50ZXJmYWNlCj4gK0Bj aW5kZXggbXlNUEQgc2VydmljZQo+ICsKPiArQHVyZWZ7aHR0cHM6Ly9qY29ycG9yYXRpb24uZ2l0 aHViLmlvL215TVBELywgbXlNUER9IGlzIGEgd2ViIHNlcnZlcgo+ICtmcm9udGVuZCBmb3IgTVBE IHRoYXQgcHJvdmlkZXMgYSBtb2JpbGUgZnJpZW5kbHkgd2ViIGNsaWVudCBmb3IgTVBELgo+ICsK PiArVGhlIGZvbGxvd2luZyBleGFtcGxlIHNob3dzIGEgbXlNUEQgaW5zdGFuY2UgbGlzdGVuaW5n IG9uIHBvcnQgODAsCj4gK3dpdGggYWxidW0gY292ZXIgY2FjaGluZyBkaXNhYmxlZC4KPiArCj4g K0BsaXNwCj4gKyhzZXJ2aWNlIG15bXBkLXNlcnZpY2UtdHlwZQo+ICvCoMKgwqDCoMKgwqDCoMKg IChteW1wZC1jb25maWd1cmF0aW9uCj4gK8KgwqDCoMKgwqDCoMKgwqDCoCAocG9ydCA4MCkKPiAr wqDCoMKgwqDCoMKgwqDCoMKgIChjb3ZlcmNhY2hlLXR0bCAwKSkpCj4gK0BlbmQgbGlzcAo+ICsK PiArQGRlZnZhciBteW1wZC1zZXJ2aWNlLXR5cGUKPiArVGhlIHNlcnZpY2UgdHlwZSBmb3IgQGNv bW1hbmR7bXltcGR9Lgo+ICtAZW5kIGRlZnZhcgo+ICsKPiArQGMgJXN0YXJ0IG9mIGZyYWdtZW50 Cj4gK0BkZWZ0cCB7RGF0YSBUeXBlfSBteW1wZC1jb25maWd1cmF0aW9uCj4gK0F2YWlsYWJsZSBA Y29kZXtteW1wZC1jb25maWd1cmF0aW9ufSBmaWVsZHMgYXJlOgo+ICsKPiArQHRhYmxlIEBhc2lz Cj4gK0BpdGVtIEBjb2Rle3BhY2thZ2V9IChkZWZhdWx0OiBAY29kZXtteW1wZH0pICh0eXBlOiBm aWxlLWxpa2UpCj4gK1RoZSBwYWNrYWdlIG9iamVjdCBvZiB0aGUgbXlNUEQgc2VydmVyLgo+ICsK PiArQGl0ZW0gQGNvZGV7c2hlcGhlcmQtcmVxdWlyZW1lbnR9IChkZWZhdWx0OiBAY29kZXsoKX0p ICh0eXBlOiBsaXN0LQo+IG9mLXN5bWJvbCkKPiArVGhpcyBpcyBhIGxpc3Qgb2Ygc3ltYm9scyBu YW1pbmcgU2hlcGhlcmQgc2VydmljZXMgdGhhdCB0aGlzIHNlcnZpY2UKPiArd2lsbCBkZXBlbmQg b24uCj4gKwo+ICtAaXRlbSBAY29kZXt1c2VyfSAoZGVmYXVsdDogQGNvZGV7Im15bXBkIn0pICh0 eXBlOiBzdHJpbmcpCj4gK093bmVyIG9mIHRoZSBAY29tbWFuZHtteW1wZH0gcHJvY2Vzcy4KPiAr Cj4gK0BpdGVtIEBjb2Rle2dyb3VwfSAoZGVmYXVsdDogQGNvZGV7Im5vZ3JvdXAifSkgKHR5cGU6 IHN0cmluZykKPiArT3duZXIgZ3JvdXAgb2YgdGhlIEBjb21tYW5ke215bXBkfSBwcm9jZXNzLgo+ ICsKPiArQGl0ZW0gQGNvZGV7d29yay1kaXJlY3Rvcnl9IChkZWZhdWx0OiBAY29kZXsiL3Zhci9s aWIvbXltcGQifSkKPiAodHlwZTogc3RyaW5nKQo+ICtXaGVyZSBteU1QRCB3aWxsIHN0b3JlIGl0 cyBkYXRhLgo+ICsKPiArQGl0ZW0gQGNvZGV7Y2FjaGUtZGlyZWN0b3J5fSAoZGVmYXVsdDogQGNv ZGV7Ii92YXIvY2FjaGUvbXltcGQifSkKPiAodHlwZTogc3RyaW5nKQo+ICtXaGVyZSBteU1QRCB3 aWxsIHN0b3JlIGl0cyBjYWNoZS4KPiArCj4gK0BpdGVtIEBjb2Rle2FjbH0gKHR5cGU6IG1heWJl LWlwLWFjbCkKPiArQUNMIHRvIGFjY2VzcyB0aGUgbXlNUEQgd2Vic2VydmVyLsKgIFNlZQo+ICtA dXJlZnsKPiBodHRwczovL2pjb3Jwb3JhdGlvbi5naXRodWIuaW8vbXlNUEQvY29uZmlndXJhdGlv bi9hY2wsbXlNUETCoEFDTH0KPiArZm9yIHN5bnRheC4KPiArCj4gK0BpdGVtIEBjb2Rle2NvdmVy Y2FjaGUtdHRsfSAoZGVmYXVsdDogQGNvZGV7MzF9KSAodHlwZTogbWF5YmUtCj4gaW50ZWdlcikK PiArSG93IGxvbmcgdG8ga2VlcCBjYWNoZWQgY292ZXJzLCBAY29kZXswfSBkaXNhYmxlcyBjb3Zl ciBjYWNoaW5nLgo+ICsKPiArQGl0ZW0gQGNvZGV7aHR0cD99IChkZWZhdWx0OiBAY29kZXsjdH0p ICh0eXBlOiBib29sZWFuKQo+ICtIVFRQIHN1cHBvcnQuCj4gKwo+ICtAaXRlbSBAY29kZXtob3N0 fSAoZGVmYXVsdDogQGNvZGV7Ils6Ol0ifSkgKHR5cGU6IHN0cmluZykKPiArSG9zdCBuYW1lIHRv IGxpc3RlbiBvbi4KPiArCj4gK0BpdGVtIEBjb2Rle3BvcnR9IChkZWZhdWx0OiBAY29kZXs4MH0p ICh0eXBlOiBtYXliZS1wb3J0KQo+ICtIVFRQIHBvcnQgdG8gbGlzdGVuIG9uLgo+ICsKPiArQGl0 ZW0gQGNvZGV7bG9nLWxldmVsfSAoZGVmYXVsdDogQGNvZGV7NX0pICh0eXBlOiBpbnRlZ2VyKQo+ ICtIb3cgbXVjaCBkZXRhaWwgdG8gaW5jbHVkZSBpbiBsb2dzLCBwb3NzaWJsZSB2YWx1ZXM6IEBj b2RlezB9IHRvCj4gK0Bjb2Rlezd9Lgo+ICsKPiArQGl0ZW0gQGNvZGV7bG9nLXRvfSAoZGVmYXVs dDogQGNvZGV7Ii92YXIvbG9nL215bXBkL2xvZyJ9KSAodHlwZToKPiBzdHJpbmctb3Itc3ltYm9s KQo+ICtXaGVyZSB0byBzZW5kIGxvZ3MuwqAgQnkgZGVmYXVsdCwgdGhlIHNlcnZpY2UgbG9ncyB0 bwo+ICtAZmlsZXsvdmFyL2xvZy9teW1wZC5sb2d9LsKgIFRoZSBhbHRlcm5hdGl2ZSBpcyBAY29k ZXsnc3lzbG9nfSwgd2hpY2gKPiArc2VuZHMgb3V0cHV0IHRvIHRoZSBydW5uaW5nIHN5c2xvZyBz ZXJ2aWNlIHVuZGVyIHRoZSBAc2FtcHtkYWVtb259Cj4gK2ZhY2lsaXR5Lgo+ICsKPiArQGl0ZW0g QGNvZGV7bHVhbGlic30gKGRlZmF1bHQ6IEBjb2RleyJhbGwifSkgKHR5cGU6IG1heWJlLXN0cmlu ZykKPiArU2VlCj4gK0B1cmVmewo+IGh0dHBzOi8vamNvcnBvcmF0aW9uLmdpdGh1Yi5pby9teU1Q RC9zY3JpcHRpbmcvI2x1YS1zdGFuZGFyZC1saWJyYXJpZQo+IHN9Lgo+ICsKPiArQGl0ZW0gQGNv ZGV7c2NyaXB0LWFjbH0gKGRlZmF1bHQ6IEBjb2RleyhpcC1hY2wgKGFsbG93Cj4gJygiMTI3LjAu MC4xIikpKX0pICh0eXBlOiBtYXliZS1pcC1hY2wpCj4gK0FDTCB0byBhY2Nlc3MgdGhlIG15TVBE IHNjcmlwdCBiYWNrZW5kLgo+ICsKPiArQGl0ZW0gQGNvZGV7c3NsP30gKGRlZmF1bHQ6IEBjb2Rl eyNmfSkgKHR5cGU6IGJvb2xlYW4pCj4gK1NTTC9UTFMgc3VwcG9ydC4KPiArCj4gK0BpdGVtIEBj b2Rle3NzbC1wb3J0fSAoZGVmYXVsdDogQGNvZGV7NDQzfSkgKHR5cGU6IG1heWJlLXBvcnQpCj4g K1BvcnQgdG8gbGlzdGVuIGZvciBIVFRQUy4KPiArCj4gK0BpdGVtIEBjb2Rle3NzbC1jZXJ0fSAo dHlwZTogbWF5YmUtc3RyaW5nKQo+ICtQYXRoIHRvIFBFTSBlbmNvZGVkIFguNTA5IFNTTC9UTFMg Y2VydGlmaWNhdGUgKHB1YmxpYyBrZXkpLgo+ICsKPiArQGl0ZW0gQGNvZGV7c3NsLWtleX0gKHR5 cGU6IG1heWJlLXN0cmluZykKPiArUGF0aCB0byBQRU0gZW5jb2RlZCBTU0wvVExTIHByaXZhdGUg a2V5Lgo+ICsKPiArQGl0ZW0gQGNvZGV7cGluLWhhc2h9ICh0eXBlOiBtYXliZS1zdHJpbmcpCj4g K1NIQS0yNTYgaGFzaGVkIHBpbiB1c2VkIGJ5IG15TVBEIHRvIGNvbnRyb2wgc2V0dGluZ3MgYWNj ZXNzIGJ5Cj4gcHJvbXB0aW5nCj4gK2EgcGluIGZyb20gdGhlIHVzZXIuCj4gKwo+ICtAZW5kIHRh YmxlCj4gK0BlbmQgZGVmdHAKPiArQGMgJWVuZCBvZiBmcmFnbWVudAo+ICsKPiArQGMgJXN0YXJ0 IG9mIGZyYWdtZW50Cj4gK0BkZWZ0cCB7RGF0YSBUeXBlfSBpcC1hY2wKPiArQXZhaWxhYmxlIEBj b2Rle2lwLWFjbH0gZmllbGRzIGFyZToKPiArCj4gK0B0YWJsZSBAYXNpcwo+ICtAaXRlbSBAY29k ZXthbGxvd30gKGRlZmF1bHQ6IEBjb2RleygpfSkgKHR5cGU6IGxpc3Qtb2Ytc3RyaW5nKQo+ICtB bGxvd2VkIElQIGFkZHJlc3Nlcy4KPiArCj4gK0BpdGVtIEBjb2Rle2Rlbnl9IChkZWZhdWx0OiBA Y29kZXsoKX0pICh0eXBlOiBsaXN0LW9mLXN0cmluZykKPiArRGlzYWxsb3dlZCBJUCBhZGRyZXNz ZXMuCj4gKwo+ICtAZW5kIHRhYmxlCj4gK0BlbmQgZGVmdHAKPiArQGMgJWVuZCBvZiBmcmFnbWVu dAo+IMKgCj4gwqBAbm9kZSBWaXJ0dWFsaXphdGlvbiBTZXJ2aWNlcwo+IMKgQHN1YnNlY3Rpb24g VmlydHVhbGl6YXRpb24gU2VydmljZXMKPiBkaWZmIC0tZ2l0IGEvZ251L3NlcnZpY2VzL2F1ZGlv LnNjbSBiL2dudS9zZXJ2aWNlcy9hdWRpby5zY20KPiBpbmRleCBjNjAwNTNmMzNjLi5jMzg0ZDNk MmI4IDEwMDY0NAo+IC0tLSBhL2dudS9zZXJ2aWNlcy9hdWRpby5zY20KPiArKysgYi9nbnUvc2Vy dmljZXMvYXVkaW8uc2NtCj4gQEAgLTIsNiArMiw3IEBACj4gwqA7OzsgQ29weXJpZ2h0IMKpIDIw MTcgUGV0ZXIgTWlra2Vsc2VuIDxwZXRlcm1pa2tlbHNlbjEwQGdtYWlsLmNvbT4KPiDCoDs7OyBD b3B5cmlnaHQgwqkgMjAxOSBSaWNhcmRvIFd1cm11cyA8cmVrYWRvQGVsZXBobHkubmV0Pgo+IMKg Ozs7IENvcHlyaWdodCDCqSAyMDIwIEx1ZG92aWMgQ291cnTDqHMgPGx1ZG9AZ251Lm9yZz4KPiAr Ozs7IENvcHlyaWdodCDCqSAyMDIyIEJydW5vIFZpY3RhbCA8bWlyYWlAbWFraW5hdGEuZXU+ClNh bWUgaGVyZS4KPiDCoDs7Owo+IMKgOzs7IFRoaXMgZmlsZSBpcyBwYXJ0IG9mIEdOVSBHdWl4Lgo+ IMKgOzs7Cj4gQEAgLTIxLDYgKzIyLDggQEAKPiDCoChkZWZpbmUtbW9kdWxlIChnbnUgc2Vydmlj ZXMgYXVkaW8pCj4gwqDCoCAjOnVzZS1tb2R1bGUgKGd1aXggZ2V4cCkKPiDCoMKgICM6dXNlLW1v ZHVsZSAoZ251IHNlcnZpY2VzKQo+ICvCoCAjOnVzZS1tb2R1bGUgKGdudSBzZXJ2aWNlcyBhZG1p bikKPiArwqAgIzp1c2UtbW9kdWxlIChnbnUgc2VydmljZXMgY29uZmlndXJhdGlvbikKPiDCoMKg ICM6dXNlLW1vZHVsZSAoZ251IHNlcnZpY2VzIHNoZXBoZXJkKQo+IMKgwqAgIzp1c2UtbW9kdWxl IChnbnUgc3lzdGVtIHNoYWRvdykKPiDCoMKgICM6dXNlLW1vZHVsZSAoZ251IHBhY2thZ2VzIGFk bWluKQo+IEBAIC0yOCwxMSArMzEsNDEgQEAgKGRlZmluZS1tb2R1bGUgKGdudSBzZXJ2aWNlcyBh dWRpbykKPiDCoMKgICM6dXNlLW1vZHVsZSAoZ3VpeCByZWNvcmRzKQo+IMKgwqAgIzp1c2UtbW9k dWxlIChpY2UtOSBtYXRjaCkKPiDCoMKgICM6dXNlLW1vZHVsZSAoaWNlLTkgZm9ybWF0KQo+ICvC oCAjOnVzZS1tb2R1bGUgKHNyZmkgc3JmaS0xKQo+ICvCoCAjOnVzZS1tb2R1bGUgKHNyZmkgc3Jm aS0yNikKPiDCoMKgICM6ZXhwb3J0IChtcGQtb3V0cHV0Cj4gwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgIG1wZC1vdXRwdXQ/Cj4gwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG1wZC1jb25maWd1cmF0 aW9uCj4gwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG1wZC1jb25maWd1cmF0aW9uPwo+IC3CoMKg wqDCoMKgwqDCoMKgwqDCoMKgIG1wZC1zZXJ2aWNlLXR5cGUpKQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIG1wZC1zZXJ2aWNlLXR5cGUKPiArCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgbXlt cGQtc2VydmljZS10eXBlCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJh dGlvbgo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15bXBkLWNvbmZpZ3VyYXRpb24/Cj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJhdGlvbi1wYWNrYWdlCj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJhdGlvbi1zaGVwaGVyZC1yZXF1aXJlbWVu dAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15bXBkLWNvbmZpZ3VyYXRpb24tdXNlcgo+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15bXBkLWNvbmZpZ3VyYXRpb24tZ3JvdXAKPiArwqDCoMKg wqDCoMKgwqDCoMKgwqDCoCBteW1wZC1jb25maWd1cmF0aW9uLXdvcmstZGlyZWN0b3J5Cj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJhdGlvbi1jYWNoZS1kaXJlY3RvcnkK PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBteW1wZC1jb25maWd1cmF0aW9uLWFjbAo+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIG15bXBkLWNvbmZpZ3VyYXRpb24tY292ZXJjYWNoZS10dGwKPiAr wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBteW1wZC1jb25maWd1cmF0aW9uLWh0dHA/Cj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJhdGlvbi1ob3N0Cj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJhdGlvbi1wb3J0Cj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqAgbXltcGQtY29uZmlndXJhdGlvbi1sb2ctbGV2ZWwKPiArwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCBteW1wZC1jb25maWd1cmF0aW9uLWxvZy10bwo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKg IG15bXBkLWNvbmZpZ3VyYXRpb24tbHVhbGlicwo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15 bXBkLWNvbmZpZ3VyYXRpb24tc2NyaXB0LWFjbAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15 bXBkLWNvbmZpZ3VyYXRpb24tc3NsPwo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15bXBkLWNv bmZpZ3VyYXRpb24tc3NsLXBvcnQKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBteW1wZC1jb25m aWd1cmF0aW9uLXNzbC1jZXJ0Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmln dXJhdGlvbi1zc2wta2V5Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqAgbXltcGQtY29uZmlndXJh dGlvbi1waW4taGFzaAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGlwLWFjbAo+ICvCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIGlwLWFjbD8KPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpcC1hY2wt YWxsb3cKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCBpcC1hY2wtZGVueSkpClRoaXMgc2hvdWxk IHByb2JhYmx5IGJlIG15bXBkLWlwLWFjbCoKPiDCoAo+IMKgOzs7IENvbW1lbnRhcnk6Cj4gwqA7 OzsKPiBAQCAtMTk3LDMgKzIzMCwyNDEgQEAgKGRlZmluZSBtcGQtc2VydmljZS10eXBlCj4gwqDC oMKgwqDCoMKgwqDCoMKgwqAgKHNlcnZpY2UtZXh0ZW5zaW9uIGFjdGl2YXRpb24tc2VydmljZS10 eXBlCj4gwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCBtcGQtc2VydmljZS1hY3RpdmF0aW9uKSkpCj4gwqDCoMKgIChkZWZhdWx0LXZhbHVl IChtcGQtY29uZmlndXJhdGlvbikpKSkKPiArCj4gKwwKPiArOzs7Cj4gKzs7OyBteU1QRAo+ICs7 OzsKPiArCj4gKyhkZWZpbmUgbGlzdC1vZi1zeW1ib2w/Cj4gK8KgIChsaXN0LW9mIHN5bWJvbD8p KQo+ICsKPiArKGRlZmluZSBsaXN0LW9mLXN0cmluZz8KPiArwqAgKGxpc3Qtb2Ygc3RyaW5nPykp Cj4gKwo+ICsoZGVmaW5lIChwb3J0PyBuKQo+ICvCoCAoYW5kIChpbnRlZ2VyPyBuKQo+ICvCoMKg wqDCoMKgwqAgKDw9IDAgbiA2NTUzNSkpKQo+ICsKPiArKGRlZmluZSAoc3RyaW5nLW9yLXN5bWJv bD8geCkKPiArwqAgKG9yIChzeW1ib2w/IHgpIChzdHJpbmc/IHgpKSkKPiArCj4gKyhkZWZpbmUt Y29uZmlndXJhdGlvbi9uby1zZXJpYWxpemF0aW9uIGlwLWFjbAo+ICvCoCAoYWxsb3cKPiArwqDC oCAobGlzdC1vZi1zdHJpbmcgJygpKQo+ICvCoMKgICJBbGxvd2VkIElQIGFkZHJlc3Nlcy4iKQo+ ICsKPiArwqAgKGRlbnkKPiArwqDCoCAobGlzdC1vZi1zdHJpbmcgJygpKQo+ICvCoMKgICJEaXNh bGxvd2VkIElQIGFkZHJlc3Nlcy4iKSkKPiArCj4gKyhkZWZpbmUtbWF5YmUvbm8tc2VyaWFsaXph dGlvbiBwb3J0KQo+ICsoZGVmaW5lLW1heWJlL25vLXNlcmlhbGl6YXRpb24gaW50ZWdlcikKPiAr KGRlZmluZS1tYXliZS9uby1zZXJpYWxpemF0aW9uIHN0cmluZykKPiArKGRlZmluZS1tYXliZS9u by1zZXJpYWxpemF0aW9uIGlwLWFjbCkKPiArCj4gKzs7IFhYWDogVGhlIHNlcmlhbGl6YXRpb24g cHJvY2VkdXJlcyBhcmUgaW5zdWZmaWNpZW50IHNpbmNlIHdlCj4gcmVxdWlyZQo+ICs7OyBhY2Nl c3MgdG8gbXVsdGlwbGUgZmllbGRzIGF0IG9uY2UuCj4gKzs7IEZpZWxkcyBtYXJrZWQgd2l0aCBl bXB0eS1zZXJpYWxpemVyIGFyZSBuZXZlciBzZXJpYWxpemVkIGFuZCBhcmUKPiArOzsgdXNlZCBm b3IgY29tbWFuZC1saW5lIGFyZ3VtZW50cyBvciBieSB0aGUgc2VydmljZSBkZWZpbml0aW9uLgo+ ICsoZGVmaW5lLWNvbmZpZ3VyYXRpb24vbm8tc2VyaWFsaXphdGlvbiBteW1wZC1jb25maWd1cmF0 aW9uCj4gK8KgIChwYWNrYWdlCj4gK8KgwqDCoCAoZmlsZS1saWtlIG15bXBkKQo+ICvCoMKgwqAg IlRoZSBwYWNrYWdlIG9iamVjdCBvZiB0aGUgbXlNUEQgc2VydmVyLiIKPiArwqDCoMKgIGVtcHR5 LXNlcmlhbGl6ZXIpCj4gKwo+ICvCoCAoc2hlcGhlcmQtcmVxdWlyZW1lbnQKPiArwqDCoCAobGlz dC1vZi1zeW1ib2wgJygpKQo+ICvCoMKgICJUaGlzIGlzIGEgbGlzdCBvZiBzeW1ib2xzIG5hbWlu ZyBTaGVwaGVyZCBzZXJ2aWNlcyB0aGF0IHRoaXMKPiBzZXJ2aWNlCj4gK3dpbGwgZGVwZW5kIG9u LiIKPiArwqDCoCBlbXB0eS1zZXJpYWxpemVyKQo+ICsKPiArwqAgKHVzZXIKPiArwqDCoCAoc3Ry aW5nICJteW1wZCIpCj4gK8KgwqAgIk93bmVyIG9mIHRoZSBAY29tbWFuZHtteW1wZH0gcHJvY2Vz cy4iCj4gK8KgwqAgZW1wdHktc2VyaWFsaXplcikKPiArCj4gK8KgIChncm91cAo+ICvCoMKgIChz dHJpbmcgIm5vZ3JvdXAiKQo+ICvCoMKgICJPd25lciBncm91cCBvZiB0aGUgQGNvbW1hbmR7bXlt cGR9IHByb2Nlc3MuIgo+ICvCoMKgIGVtcHR5LXNlcmlhbGl6ZXIpCj4gKwo+ICvCoCAod29yay1k aXJlY3RvcnkKPiArwqDCoCAoc3RyaW5nICIvdmFyL2xpYi9teW1wZCIpCj4gK8KgwqAgIldoZXJl IG15TVBEIHdpbGwgc3RvcmUgaXRzIGRhdGEuIgo+ICvCoMKgIGVtcHR5LXNlcmlhbGl6ZXIpCj4g Kwo+ICvCoCAoY2FjaGUtZGlyZWN0b3J5Cj4gK8KgwqAgKHN0cmluZyAiL3Zhci9jYWNoZS9teW1w ZCIpCj4gK8KgwqAgIldoZXJlIG15TVBEIHdpbGwgc3RvcmUgaXRzIGNhY2hlLiIKPiArwqDCoCBl bXB0eS1zZXJpYWxpemVyKQo+ICsKPiArwqAgKGFjbAo+ICvCoMKgIG1heWJlLWlwLWFjbAo+ICvC oMKgICJBQ0wgdG8gYWNjZXNzIHRoZSBteU1QRCB3ZWJzZXJ2ZXIuIFNlZQo+ICtAdXJlZnsKPiBo dHRwczovL2pjb3Jwb3JhdGlvbi5naXRodWIuaW8vbXlNUEQvY29uZmlndXJhdGlvbi9hY2wsbXlN UETCoEFDTH0KPiArZm9yIHN5bnRheC4iKQo+ICsKPiArwqAgKGNvdmVyY2FjaGUtdHRsCj4gK8Kg wqAgKG1heWJlLWludGVnZXIgMzEpCj4gK8KgwqAgIkhvdyBsb25nIHRvIGtlZXAgY2FjaGVkIGNv dmVycywgQGNvZGV7MH0gZGlzYWJsZXMgY292ZXIKPiBjYWNoaW5nLiIpCj4gKwo+ICvCoCAoaHR0 cD8KPiArwqDCoCAoYm9vbGVhbiAjdCkKPiArwqDCoCAiSFRUUCBzdXBwb3J0LiIpCj4gKwo+ICvC oCAoaG9zdAo+ICvCoMKgIChzdHJpbmcgIls6Ol0iKQo+ICvCoMKgICJIb3N0IG5hbWUgdG8gbGlz dGVuIG9uLiIpCj4gKwo+ICvCoCAocG9ydAo+ICvCoMKgIChtYXliZS1wb3J0IDgwKQo+ICvCoMKg ICJIVFRQIHBvcnQgdG8gbGlzdGVuIG9uLiIpCj4gKwo+ICvCoCAobG9nLWxldmVsCj4gK8KgwqAg KGludGVnZXIgNSkKPiArwqDCoCAiSG93IG11Y2ggZGV0YWlsIHRvIGluY2x1ZGUgaW4gbG9ncywg cG9zc2libGUgdmFsdWVzOiBAY29kZXswfSB0bwo+IEBjb2Rlezd9LiIpCj4gKwo+ICvCoCAobG9n LXRvCj4gK8KgwqAgKHN0cmluZy1vci1zeW1ib2wgIi92YXIvbG9nL215bXBkL2xvZyIpCj4gK8Kg wqAgIldoZXJlIHRvIHNlbmQgbG9ncy4gQnkgZGVmYXVsdCwgdGhlIHNlcnZpY2UgbG9ncyB0bwo+ ICtAZmlsZXsvdmFyL2xvZy9teW1wZC5sb2d9LiBUaGUgYWx0ZXJuYXRpdmUgaXMgQGNvZGV7J3N5 c2xvZ30sIHdoaWNoCj4gK3NlbmRzIG91dHB1dCB0byB0aGUgcnVubmluZyBzeXNsb2cgc2Vydmlj ZSB1bmRlciB0aGUgQHNhbXB7ZGFlbW9ufQo+IGZhY2lsaXR5LiIKPiArwqDCoCBlbXB0eS1zZXJp YWxpemVyKQo+ICsKPiArwqAgKGx1YWxpYnMKPiArwqDCoCAobWF5YmUtc3RyaW5nICJhbGwiKQo+ ICvCoMKgICJTZWUKPiArQHVybHsKPiBodHRwczovL2pjb3Jwb3JhdGlvbi5naXRodWIuaW8vbXlN UEQvc2NyaXB0aW5nLyNsdWEtc3RhbmRhcmQtbGlicmFyaWUKPiBzfS4iKQo+ICsKPiArwqAgKHNj cmlwdC1hY2wKPiArwqDCoCAobWF5YmUtaXAtYWNsIChpcC1hY2wKPiArwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoCAoYWxsb3cgJygiMTI3LjAuMC4xIikpKSkKPiArwqDCoCAiQUNM IHRvIGFjY2VzcyB0aGUgbXlNUEQgc2NyaXB0IGJhY2tlbmQuIikKPiArCj4gK8KgIChzc2w/Cj4g K8KgwqAgKGJvb2xlYW4gI2YpCj4gK8KgwqAgIlNTTC9UTFMgc3VwcG9ydC4iKQo+ICsKPiArwqAg KHNzbC1wb3J0Cj4gK8KgwqAgKG1heWJlLXBvcnQgNDQzKQo+ICvCoMKgICJQb3J0IHRvIGxpc3Rl biBmb3IgSFRUUFMuIikKPiArCj4gK8KgIChzc2wtY2VydAo+ICvCoMKgIG1heWJlLXN0cmluZwo+ ICvCoMKgICJQYXRoIHRvIFBFTSBlbmNvZGVkIFguNTA5IFNTTC9UTFMgY2VydGlmaWNhdGUgKHB1 YmxpYyBrZXkpLiIpCj4gKwo+ICvCoCAoc3NsLWtleQo+ICvCoMKgIG1heWJlLXN0cmluZwo+ICvC oMKgICJQYXRoIHRvIFBFTSBlbmNvZGVkIFNTTC9UTFMgcHJpdmF0ZSBrZXkuIikKPiArCj4gK8Kg IChwaW4taGFzaAo+ICvCoMKgIG1heWJlLXN0cmluZwo+ICvCoMKgICJTSEEtMjU2IGhhc2hlZCBw aW4gdXNlZCBieSBteU1QRCB0byBjb250cm9sIHNldHRpbmdzIGFjY2VzcyBieQo+ICtwcm9tcHRp bmcgYSBwaW4gZnJvbSB0aGUgdXNlci4iKSkKPiArCj4gKyhkZWZpbmUgKG15bXBkLXNlcmlhbGl6 ZS1jb25maWd1cmF0aW9uIGNvbmZpZykKPiArwqAgKGRlZmluZSBzZXJpYWxpemUtdmFsdWUKPiAr wqDCoMKgIChtYXRjaC1sYW1iZGEKPiArwqDCoMKgwqDCoCAoKD8gYm9vbGVhbj8gdmFsKSAoaWYg dmFsICJ0cnVlIiAiZmFsc2UiKSkKPiArwqDCoMKgwqDCoCAoKG9yICg/IHBvcnQ/IHZhbCkgKD8g aW50ZWdlcj8gdmFsKSkgKG51bWJlci0+c3RyaW5nIHZhbCkpCj4gK8KgwqDCoMKgwqAgKCg/IGlw LWFjbD8gdmFsKSAoaXAtYWNsLXNlcmlhbGl6ZS1jb25maWd1cmF0aW9uIHZhbCkpCj4gK8KgwqDC oMKgwqAgKCg/IHN0cmluZz8gdmFsKSB2YWwpKSkKPiArCj4gK8KgIChkZWZpbmUgKGlwLWFjbC1z ZXJpYWxpemUtY29uZmlndXJhdGlvbiBjb25maWcpCj4gK8KgwqDCoCAoZGVmaW5lIChzZXJpYWxp emUtbGlzdC1vZi1zdHJpbmcgcHJlZml4IGxzdCkKPiArwqDCoMKgwqDCoCAobWFwIChjdXQgZm9y bWF0ICNmICJ+YX5hIiBwcmVmaXggPD4pIGxzdCkpCj4gK8KgwqDCoCAoc3RyaW5nLWpvaW4KPiAr wqDCoMKgwqAgKGFwcGVuZAo+ICvCoMKgwqDCoMKgIChzZXJpYWxpemUtbGlzdC1vZi1zdHJpbmcg IisiIChpcC1hY2wtYWxsb3cgY29uZmlnKSkKPiArwqDCoMKgwqDCoCAoc2VyaWFsaXplLWxpc3Qt b2Ytc3RyaW5nICItIiAoaXAtYWNsLWRlbnkgY29uZmlnKSkpICIsIikpCj4gKwo+ICvCoCA7OyBt eU1QRCBjb25maWd1cmF0aW9uIGZpZWxkcyBhcmUgc2VyaWFsaXplZCBhcyBpbmRpdmlkdWFsIGZp bGVzCj4gdW5kZXIKPiArwqAgOzsgPHdvcmstZGlyZWN0b3J5Pi9jb25maWcvLgo+ICvCoCAobWF0 Y2gtcmVjb3JkIGNvbmZpZyA8bXltcGQtY29uZmlndXJhdGlvbj4gKHdvcmstZGlyZWN0b3J5IGFj bAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgY292ZXJjYWNoZS10dGwgaHR0 cD8KPiBob3N0IHBvcnQKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGxvZy1s ZXZlbCBsdWFsaWJzCj4gc2NyaXB0LWFjbAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqAgc3NsPyBzc2wtcG9ydCBzc2wtY2VydAo+IHNzbC1rZXkKPiArwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIHBpbi1oYXNoKQo+ICvCoMKgwqAgKGRlZmluZSAoc2VyaWFsaXpl LWZpZWxkIGZpbGVuYW1lIHZhbHVlKQo+ICvCoMKgwqDCoMKgICh3aGVuIChtYXliZS12YWx1ZS1z ZXQ/IHZhbHVlKQo+ICvCoMKgwqDCoMKgwqDCoCAobGlzdCAoZm9ybWF0ICNmICJ+YS9jb25maWcv fmEiIHdvcmstZGlyZWN0b3J5IGZpbGVuYW1lKQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCAobWl4ZWQtdGV4dC1maWxlIGZpbGVuYW1lIChzZXJpYWxpemUtdmFsdWUgdmFsdWUpKSkpKQo+ ICsKPiArwqDCoMKgIChsZXQgKChmaWxlbmFtZS10by1maWVsZCBgKCgiYWNsIiAuICxhY2wpCj4g K8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoCAoImNvdmVyY2FjaGVfa2VlcF9kYXlzIiAuCj4gLGNvdmVyY2FjaGUtdHRsKQo+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg KCJodHRwIsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIC4gLGh0dHA/KQo+ICvCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg KCJodHRwX2hvc3QiwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAuICxob3N0KQo+ICvCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKCJodHRw X3BvcnQiwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAuICxwb3J0KQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKCJsb2dsZXZlbCLC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgLiAsbG9nLWxldmVsKQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKCJsdWFsaWJzIsKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIC4gLGx1YWxpYnMpCj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoInNjcmlwdGFjbCLC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIC4gLHNjcmlwdC0KPiBhY2wpCj4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoInNzbCLCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIC4gLHNzbD8pCj4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoInNzbF9wb3J0 IsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAuICxzc2wtcG9ydCkKPiArwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgICgic3NsX2NlcnQi wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIC4gLHNzbC1jZXJ0KQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKCJzc2xfa2V5IsKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIC4gLHNzbC1rZXkpCj4gK8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoInBpbl9oYXNoIsKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAuICxwaW4tCj4gaGFzaCkpKSkKPiArwqDCoMKgwqDCoCAo ZmlsdGVyIGxpc3Q/Cj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChnZW5lcmljLXNlcmlh bGl6ZS1hbGlzdCBsaXN0IHNlcmlhbGl6ZS1maWVsZAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIGZp bGVuYW1lLXRvLWZpZWxkKSkpKSkKPiArCj4gKyhkZWZpbmUgKG15bXBkLXNoZXBoZXJkLXNlcnZp Y2UgY29uZmlnKQo+ICvCoCAobWF0Y2gtcmVjb3JkIGNvbmZpZyA8bXltcGQtY29uZmlndXJhdGlv bj4gKHBhY2thZ2Ugc2hlcGhlcmQtCj4gcmVxdWlyZW1lbnQKPiArwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIHVzZXIgd29yay1kaXJlY3RvcnkKPiArwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgIGNhY2hlLWRpcmVjdG9yeSBsb2ctCj4gbGV2ZWwgbG9nLXRvKQo+ICvC oMKgwqAgKGxldCAoKGxvZy1sZXZlbCogKGZvcm1hdCAjZiAiTVlNUERfTE9HTEVWRUw9fmEiIGxv Zy1sZXZlbCkpKQo+ICvCoMKgwqDCoMKgIChzaGVwaGVyZC1zZXJ2aWNlCj4gK8KgwqDCoMKgwqDC oCAoZG9jdW1lbnRhdGlvbiAiUnVuIHRoZSBteU1QRCBkYWVtb24uIikKPiArwqDCoMKgwqDCoMKg IChyZXF1aXJlbWVudCBgKGxvb3BiYWNrIHVzZXItcHJvY2Vzc2VzICxAc2hlcGhlcmQtCj4gcmVx dWlyZW1lbnQpKQo+ICvCoMKgwqDCoMKgwqAgKHByb3Zpc2lvbiAnKG15bXBkKSkKPiArwqDCoMKg wqDCoMKgIChzdGFydCAjfihiZWdpbgo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgIChsZXQqICgocHcgKGdldHB3bmFtICMkdXNlcikpCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAodWlkIChwYXNzd2Q6dWlkIHB3KSkKPiArwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChnaWQgKHBhc3N3 ZDpnaWQgcHcpKSkKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKGZv ci1lYWNoIChsYW1iZGEgKGRpcikKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKG1rZGlyLXAgZGlyKQo+ICvCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoY2hv d24gZGlyIHVpZCBnaWQpKQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIChsaXN0ICMkd29yay1kaXJlY3RvcnkgIyRjYWNoZS0KPiBk aXJlY3RvcnkpKSkKPiArCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKG1h a2UtZm9ya2V4ZWMtY29uc3RydWN0b3IKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgIGAoIyQoZmlsZS1hcHBlbmQgcGFja2FnZSAiL2Jpbi9teW1wZCIpCj4gK8KgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgIi0tdXNlciIgIyR1c2VyCj4gK8KgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgIyRAKGlmIChlcXY/IGxvZy10byAn c3lzbG9nKSAnKCItLXN5c2xvZyIpICcoKSkKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCAiLS13b3JrZGlyIiAjJHdvcmstZGlyZWN0b3J5Cj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgIi0tY2FjaGVkaXIiICMkY2FjaGUtZGlyZWN0 b3J5KQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgIzplbnZpcm9ubWVu dC12YXJpYWJsZXMgKGxpc3QgIyRsb2ctbGV2ZWwqKQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqAgIzpsb2ctZmlsZSAjJChpZiAoc3RyaW5nPyBsb2ctdG8pIGxvZy10byAj ZikpKSkKPiArwqDCoMKgwqDCoMKgIChzdG9wICN+KG1ha2Uta2lsbC1kZXN0cnVjdG9yKSkpKSkp Cj4gKwo+ICsoZGVmaW5lIChteW1wZC1hY2NvdW50cyBjb25maWcpCj4gK8KgIChtYXRjaC1yZWNv cmQgY29uZmlnIDxteW1wZC1jb25maWd1cmF0aW9uPiAodXNlciBncm91cCkKPiArwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgIChsaXN0ICh1c2VyLWdyb3VwIChuYW1lIGdyb3VwKQo+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqAgKHN5c3RlbT8gI3QpKQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqAgKHVzZXItYWNjb3VudCAobmFtZSB1c2VyKQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChn cm91cCBncm91cCkKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoc3lzdGVtPyAjdCkKPiArwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCAoY29tbWVudCAibXlNUEQgdXNlciIpCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKGhvbWUtZGlyZWN0b3J5 ICIvdmFyL2VtcHR5IikKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoc2hlbGwgKGZpbGUtYXBwZW5kIHNoYWRv dwo+ICIvc2Jpbi9ub2xvZ2luIikpKSkpKQo+ICsKPiArKGRlZmluZSAobXltcGQtbG9nLXJvdGF0 aW9uIGNvbmZpZykKPiArwqAgKG1hdGNoLXJlY29yZCBjb25maWcgPG15bXBkLWNvbmZpZ3VyYXRp b24+IChsb2ctdG8pCj4gK8KgwqDCoCAoaWYgKHN0cmluZz8gbG9nLXRvKQo+ICvCoMKgwqDCoMKg wqDCoCAobGlzdCAobG9nLXJvdGF0aW9uCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg KGZpbGVzIChsaXN0IGxvZy10bykpKSkKPiArwqDCoMKgwqDCoMKgwqAgJygpKSkpCj4gKwo+ICso ZGVmaW5lIG15bXBkLXNlcnZpY2UtdHlwZQo+ICvCoCAoc2VydmljZS10eXBlCj4gK8KgwqAgKG5h bWUgJ215bXBkKQo+ICvCoMKgIChleHRlbnNpb25zCj4gK8KgwqDCoCAobGlzdMKgIChzZXJ2aWNl LWV4dGVuc2lvbiBzaGVwaGVyZC1yb290LXNlcnZpY2UtdHlwZQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChjb21wb3NlIGxpc3Qg bXltcGQtc2hlcGhlcmQtc2VydmljZSkpCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgIChzZXJ2aWNl LWV4dGVuc2lvbiBhY2NvdW50LXNlcnZpY2UtdHlwZQo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG15bXBkLWFjY291bnRzKQo+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoCAoc2VydmljZS1leHRlbnNpb24gc3BlY2lhbC1maWxlcy1zZXJ2 aWNlLXR5cGUKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoCBteW1wZC1zZXJpYWxpemUtY29uZmlndXJhdGlvbikKPiArwqDCoMKgwqDC oMKgwqDCoMKgwqAgKHNlcnZpY2UtZXh0ZW5zaW9uIHJvdHRsb2ctc2VydmljZS10eXBlCj4gK8Kg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg bXltcGQtbG9nLXJvdGF0aW9uKSkpCj4gK8KgwqAgKGRlc2NyaXB0aW9uICJSdW4gbXlNUEQsIGEg ZnJvbnRlbmQgZm9yIE1QRC4gKE11c2ljIFBsYXllcgo+IERhZW1vbikiKQo+ICvCoMKgIChkZWZh dWx0LXZhbHVlIChteW1wZC1jb25maWd1cmF0aW9uKSkpKQo+IGRpZmYgLS1naXQgYS9nbnUvdGVz dHMvYXVkaW8uc2NtIGIvZ251L3Rlc3RzL2F1ZGlvLnNjbQo+IGluZGV4IDhhYTZkMWU4MTguLjcw MTQ5NmVlMjMgMTAwNjQ0Cj4gLS0tIGEvZ251L3Rlc3RzL2F1ZGlvLnNjbQo+ICsrKyBiL2dudS90 ZXN0cy9hdWRpby5zY20KPiBAQCAtMSw1ICsxLDYgQEAKPiDCoDs7OyBHTlUgR3VpeCAtLS0gRnVu Y3Rpb25hbCBwYWNrYWdlIG1hbmFnZW1lbnQgZm9yIEdOVQo+IMKgOzs7IENvcHlyaWdodCDCqSAy MDE3IFBldGVyIE1pa2tlbHNlbiA8cGV0ZXJtaWtrZWxzZW4xMEBnbWFpbC5jb20+Cj4gKzs7OyBD b3B5cmlnaHQgwqkgMjAyMiBCcnVubyBWaWN0YWwgPG1pcmFpQG1ha2luYXRhLmV1Pgo+IMKgOzs7 Cj4gwqA7OzsgVGhpcyBmaWxlIGlzIHBhcnQgb2YgR05VIEd1aXguCj4gwqA7OzsKPiBAQCAtMjIs OSArMjMsMTEgQEAgKGRlZmluZS1tb2R1bGUgKGdudSB0ZXN0cyBhdWRpbykKPiDCoMKgICM6dXNl LW1vZHVsZSAoZ251IHN5c3RlbSB2bSkKPiDCoMKgICM6dXNlLW1vZHVsZSAoZ251IHNlcnZpY2Vz KQo+IMKgwqAgIzp1c2UtbW9kdWxlIChnbnUgc2VydmljZXMgYXVkaW8pCj4gK8KgICM6dXNlLW1v ZHVsZSAoZ251IHNlcnZpY2VzIG5ldHdvcmtpbmcpCj4gwqDCoCAjOnVzZS1tb2R1bGUgKGdudSBw YWNrYWdlcyBtcGQpCj4gwqDCoCAjOnVzZS1tb2R1bGUgKGd1aXggZ2V4cCkKPiAtwqAgIzpleHBv cnQgKCV0ZXN0LW1wZCkpCj4gK8KgICM6ZXhwb3J0ICgldGVzdC1tcGQKPiArwqDCoMKgwqDCoMKg wqDCoMKgwqDCoCAldGVzdC1teW1wZCkpCj4gwqAKPiDCoChkZWZpbmUgJW1wZC1vcwo+IMKgwqAg KHNpbXBsZS1vcGVyYXRpbmctc3lzdGVtCj4gQEAgLTc2LDMgKzc5LDUyIEBAIChkZWZpbmUgJXRl c3QtbXBkCj4gwqDCoMKgIChuYW1lICJtcGQiKQo+IMKgwqDCoCAoZGVzY3JpcHRpb24gIlRlc3Qg dGhhdCB0aGUgbXBkIGNhbiBydW4gYW5kIGJlIGNvbm5lY3RlZCB0by4iKQo+IMKgwqDCoCAodmFs dWUgKHJ1bi1tcGQtdGVzdCkpKSkKPiArCj4gKwo+ICsoZGVmaW5lIChydW4tbXltcGQtdGVzdCkK PiArwqAgKGRlZmluZSBvcyAobWFyaW9uZXR0ZS1vcGVyYXRpbmctc3lzdGVtCj4gK8KgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgIChzaW1wbGUtb3BlcmF0aW5nLXN5c3RlbSAoc2VydmljZSBkaGNw LWNsaWVudC1zZXJ2aWNlLQo+IHR5cGUpCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgKHNlcnZpY2Ug bXltcGQtc2VydmljZS10eXBlKSkKPiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgIzppbXBv cnRlZC1tb2R1bGVzICcoKGdudSBzZXJ2aWNlcyBoZXJkKSkpKQo+ICsKPiArwqAgKGRlZmluZSB2 bQo+ICvCoMKgwqAgKHZpcnR1YWwtbWFjaGluZQo+ICvCoMKgwqDCoCAob3BlcmF0aW5nLXN5c3Rl bSBvcykKPiArwqDCoMKgwqAgKHBvcnQtZm9yd2FyZGluZ3MgJygoODA4MCAuIDgwKSkpKSkKPiAr Cj4gK8KgIChkZWZpbmUgdGVzdAo+ICvCoMKgwqAgKHdpdGgtaW1wb3J0ZWQtbW9kdWxlcyAnKChn bnUgYnVpbGQgbWFyaW9uZXR0ZSkpCj4gK8KgwqDCoMKgwqAgI34oYmVnaW4KPiArwqDCoMKgwqDC oMKgwqDCoMKgICh1c2UtbW9kdWxlcyAoc3JmaSBzcmZpLTY0KQo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoc3JmaSBzcmZpLTgpCj4gK8KgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgICh3ZWIgY2xpZW50KQo+ICvCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAod2ViIHJlc3BvbnNlKQo+ICvC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAoZ251IGJ1aWxkIG1h cmlvbmV0dGUpKQo+ICsKPiArwqDCoMKgwqDCoMKgwqDCoMKgIChkZWZpbmUgbWFyaW9uZXR0ZQo+ ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChtYWtlLW1hcmlvbmV0dGUgKGxpc3QgIyR2bSkpKQo+ ICsKPiArwqDCoMKgwqDCoMKgwqDCoMKgICh0ZXN0LXJ1bm5lci1jdXJyZW50IChzeXN0ZW0tdGVz dC1ydW5uZXIgIyRvdXRwdXQpKQo+ICvCoMKgwqDCoMKgwqDCoMKgwqAgKHRlc3QtYmVnaW4gIm15 bXBkIikKPiArwqDCoMKgwqDCoMKgwqDCoMKgICh0ZXN0LWFzc2VydCAic2VydmljZSBpcyBydW5u aW5nIgo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChtYXJpb25ldHRlLWV2YWwgJyhiZWdpbgo+ ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoCAodXNlLW1vZHVsZXMgKGdudSBzZXJ2aWNlcyBoZXJkKSkKPiArCj4gK8KgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChz dGFydC1zZXJ2aWNlICdteW1wZCkpCj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIG1hcmlvbmV0dGUpKQo+ICsKPiArwqDCoMKgwqDCoMKg wqDCoMKgICh0ZXN0LWFzc2VydCAiSFRUUCBwb3J0IHJlYWR5Igo+ICvCoMKgwqDCoMKgwqDCoMKg wqDCoMKgICh3YWl0LWZvci10Y3AtcG9ydCA4MCBtYXJpb25ldHRlKSkKPiArCj4gK8KgwqDCoMKg wqDCoMKgwqDCoCAodGVzdC1lcXVhbCAiaHR0cC1oZWFkIgo+ICvCoMKgwqDCoMKgwqDCoMKgwqDC oMKgIDIwMAo+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIChyZWNlaXZlICh4IF8pIChodHRwLWhl YWQgImh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIpCj4gKHJlc3BvbnNlLWNvZGUgeCkpKQo+ICsKPiAr wqDCoMKgwqDCoMKgwqDCoMKgICh0ZXN0LWVuZCkpKSkKPiArwqAgKGdleHAtPmRlcml2YXRpb24g Im15bXBkLXRlc3QiIHRlc3QpKQo+ICsKPiArKGRlZmluZSAldGVzdC1teW1wZAo+ICvCoCAoc3lz dGVtLXRlc3QKPiArwqDCoCAobmFtZSAibXltcGQiKQo+ICvCoMKgIChkZXNjcmlwdGlvbiAiQ29u bmVjdCB0byBhIHJ1bm5pbmcgbXlNUEQgc2VydmljZS4iKQo+ICvCoMKgICh2YWx1ZSAocnVuLW15 bXBkLXRlc3QpKSkpCj4gCj4gYmFzZS1jb21taXQ6IDM3ZmRiMzgyZGFkNDcxNDlkOGY1YmU0MWFm MTA4NDc4ODAwZTlkMzAKQ2hlZXJzCg== From unknown Sun Aug 17 01:51:36 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#61122] [PATCH] services: Add mympd-service-type. Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 04 Feb 2023 00:29:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 61122 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Liliana Marie Prikler Cc: 61122@debbugs.gnu.org Received: via spool by 61122-submit@debbugs.gnu.org id=B61122.16754704999142 (code B ref 61122); Sat, 04 Feb 2023 00:29:02 +0000 Received: (at 61122) by debbugs.gnu.org; 4 Feb 2023 00:28:19 +0000 Received: from localhost ([127.0.0.1]:40218 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pO6Pj-0002NO-1A for submit@debbugs.gnu.org; Fri, 03 Feb 2023 19:28:19 -0500 Received: from smtpm1.myservices.hosting ([185.26.105.232]:35848) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pO6Pg-0002NF-VH for 61122@debbugs.gnu.org; Fri, 03 Feb 2023 19:28:17 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpm1.myservices.hosting (Postfix) with ESMTP id 91C7C20421; Sat, 4 Feb 2023 01:28:14 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 4F05880096; Sat, 4 Feb 2023 01:28:14 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id YRC37QsZLqo3; Sat, 4 Feb 2023 01:28:14 +0100 (CET) Received: from [192.168.1.239] (unknown [10.192.1.83]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id F0C4180093; Sat, 4 Feb 2023 01:28:13 +0100 (CET) Message-ID: <10b37d0f-4631-b7b8-e860-5c7fd5daebdc@makinata.eu> Date: Sat, 4 Feb 2023 00:28:13 +0000 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.7.1 Content-Language: en-US References: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> From: Bruno Victal In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -1.1 (-) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.1 (--) On 2023-02-03 22:48, Liliana Marie Prikler wrote: > Am Samstag, dem 28.01.2023 um 13:53 +0000 schrieb Bruno Victal: >>  Copyright @copyright{} 2022 Antero Mejr@* >> +Copyright @copyright{} 2022 Bruno Victal@* > Are you sure it's still 2022? The code for this service was laid down in 2022 and although it has been refactored since, I'd prefer to keep its original date. Cheers, Bruno From unknown Sun Aug 17 01:51:36 2025 X-Loop: help-debbugs@gnu.org Subject: [bug#61122] [PATCH v2] services: Add mympd-service-type. References: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> In-Reply-To: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sat, 04 Feb 2023 20:29:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 61122 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 61122@debbugs.gnu.org Cc: Bruno Victal , liliana.prikler@gmail.com Received: via spool by 61122-submit@debbugs.gnu.org id=B61122.167554252720250 (code B ref 61122); Sat, 04 Feb 2023 20:29:02 +0000 Received: (at 61122) by debbugs.gnu.org; 4 Feb 2023 20:28:47 +0000 Received: from localhost ([127.0.0.1]:43525 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pOP9S-0005GW-7r for submit@debbugs.gnu.org; Sat, 04 Feb 2023 15:28:47 -0500 Received: from smtpm1.myservices.hosting ([185.26.105.232]:34696) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pOP9N-0005GL-Cr for 61122@debbugs.gnu.org; Sat, 04 Feb 2023 15:28:45 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpm1.myservices.hosting (Postfix) with ESMTP id DFEB92091A; Sat, 4 Feb 2023 21:28:39 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 9711180098; Sat, 4 Feb 2023 21:28:39 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id CbYi8h6fny2k; Sat, 4 Feb 2023 21:28:36 +0100 (CET) Received: from guix-nuc.home.arpa (bl9-118-236.dsl.telepac.pt [85.242.118.236]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id 79ABD80097; Sat, 4 Feb 2023 21:28:36 +0100 (CET) From: Bruno Victal Date: Sat, 4 Feb 2023 20:28:16 +0000 Message-Id: <90eae73e37906fdfdf33c2654206ceac1d3d9fc6.1675542344.git.mirai@makinata.eu> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: 0.0 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) * gnu/services/audio.scm (mympd-service-type): New variable. * gnu/tests/audio.scm (%test-mympd): New variable. * doc/guix.texi: Document it. --- Notable changes since v1: * renamed ip-acl to mympd-ip-acl. * added uri and save-caches? field (recently added upstream options) doc/guix.texi | 120 +++++++++++++++++ gnu/services/audio.scm | 285 ++++++++++++++++++++++++++++++++++++++++- gnu/tests/audio.scm | 54 +++++++- 3 files changed, 457 insertions(+), 2 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index d69be8586e..ea31f313f9 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -112,6 +112,7 @@ Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@* Copyright @copyright{} 2023 Giacomo Leidi@* Copyright @copyright{} 2022 Antero Mejr@* +Copyright @copyright{} 2022 Bruno Victal@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -33272,6 +33273,125 @@ Audio Services (port . "8080")))))))) @end lisp +@subsubheading myMPD + +@cindex MPD, web interface +@cindex myMPD service + +@uref{https://jcorporation.github.io/myMPD/, myMPD} is a web server +frontend for MPD that provides a mobile friendly web client for MPD. + +The following example shows a myMPD instance listening on port 80, +with album cover caching disabled. + +@lisp +(service mympd-service-type + (mympd-configuration + (port 80) + (covercache-ttl 0))) +@end lisp + +@defvar mympd-service-type +The service type for @command{mympd}. +@end defvar + +@c %start of fragment +@deftp {Data Type} mympd-configuration +Available @code{mympd-configuration} fields are: + +@table @asis +@item @code{package} (default: @code{mympd}) (type: file-like) +The package object of the myMPD server. + +@item @code{shepherd-requirement} (default: @code{()}) (type: list-of-symbol) +This is a list of symbols naming Shepherd services that this service +will depend on. + +@item @code{user} (default: @code{"mympd"}) (type: string) +Owner of the @command{mympd} process. + +@item @code{group} (default: @code{"nogroup"}) (type: string) +Owner group of the @command{mympd} process. + +@item @code{work-directory} (default: @code{"/var/lib/mympd"}) (type: string) +Where myMPD will store its data. + +@item @code{cache-directory} (default: @code{"/var/cache/mympd"}) (type: string) +Where myMPD will store its cache. + +@item @code{acl} (type: maybe-mympd-ip-acl) +ACL to access the myMPD webserver. + +@item @code{covercache-ttl} (default: @code{31}) (type: maybe-integer) +How long to keep cached covers, @code{0} disables cover caching. + +@item @code{http?} (default: @code{#t}) (type: boolean) +HTTP support. + +@item @code{host} (default: @code{"[::]"}) (type: string) +Host name to listen on. + +@item @code{port} (default: @code{80}) (type: maybe-port) +HTTP port to listen on. + +@item @code{log-level} (default: @code{5}) (type: integer) +How much detail to include in logs, possible values: @code{0} to +@code{7}. + +@item @code{log-to} (default: @code{"/var/log/mympd/log"}) (type: string-or-symbol) +Where to send logs. By default, the service logs to +@file{/var/log/mympd.log}. The alternative is @code{'syslog}, which +sends output to the running syslog service under the @samp{daemon} +facility. + +@item @code{lualibs} (default: @code{"all"}) (type: maybe-string) +See +@uref{https://jcorporation.github.io/myMPD/scripting/#lua-standard-libraries}. + +@item @code{uri} (type: maybe-string) +Override URI to myMPD. See +@uref{https://github.com/jcorporation/myMPD/issues/950}. + +@item @code{script-acl} (default: @code{(mympd-ip-acl (allow '("127.0.0.1")))}) (type: maybe-mympd-ip-acl) +ACL to access the myMPD script backend. + +@item @code{ssl?} (default: @code{#f}) (type: boolean) +SSL/TLS support. + +@item @code{ssl-port} (default: @code{443}) (type: maybe-port) +Port to listen for HTTPS. + +@item @code{ssl-cert} (type: maybe-string) +Path to PEM encoded X.509 SSL/TLS certificate (public key). + +@item @code{ssl-key} (type: maybe-string) +Path to PEM encoded SSL/TLS private key. + +@item @code{pin-hash} (type: maybe-string) +SHA-256 hashed pin used by myMPD to control settings access by prompting +a pin from the user. + +@item @code{save-caches?} (type: maybe-boolean) +Whether to preserve caches between service restarts. + +@end table +@end deftp +@c %end of fragment + +@c %start of fragment +@deftp {Data Type} mympd-ip-acl +Available @code{mympd-ip-acl} fields are: + +@table @asis +@item @code{allow} (default: @code{()}) (type: list-of-string) +Allowed IP addresses. + +@item @code{deny} (default: @code{()}) (type: list-of-string) +Disallowed IP addresses. + +@end table +@end deftp +@c %end of fragment @node Virtualization Services @subsection Virtualization Services diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm index c60053f33c..3cb4b6f9bf 100644 --- a/gnu/services/audio.scm +++ b/gnu/services/audio.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017 Peter Mikkelsen ;;; Copyright © 2019 Ricardo Wurmus ;;; Copyright © 2020 Ludovic Courtès +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -21,6 +22,8 @@ (define-module (gnu services audio) #:use-module (guix gexp) #:use-module (gnu services) + #:use-module (gnu services admin) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) @@ -28,11 +31,43 @@ (define-module (gnu services audio) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (ice-9 format) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (mpd-output mpd-output? mpd-configuration mpd-configuration? - mpd-service-type)) + mpd-service-type + + mympd-service-type + mympd-configuration + mympd-configuration? + mympd-configuration-package + mympd-configuration-shepherd-requirement + mympd-configuration-user + mympd-configuration-group + mympd-configuration-work-directory + mympd-configuration-cache-directory + mympd-configuration-acl + mympd-configuration-covercache-ttl + mympd-configuration-http? + mympd-configuration-host + mympd-configuration-port + mympd-configuration-log-level + mympd-configuration-log-to + mympd-configuration-lualibs + mympd-configuration-uri + mympd-configuration-script-acl + mympd-configuration-ssl? + mympd-configuration-ssl-port + mympd-configuration-ssl-cert + mympd-configuration-ssl-key + mympd-configuration-pin-hash + mympd-configuration-save-caches? + mympd-ip-acl + mympd-ip-acl? + mympd-ip-acl-allow + mympd-ip-acl-deny)) ;;; Commentary: ;;; @@ -197,3 +232,251 @@ (define mpd-service-type (service-extension activation-service-type mpd-service-activation))) (default-value (mpd-configuration)))) + + +;;; +;;; myMPD +;;; + +(define list-of-symbol? + (list-of symbol?)) + +(define list-of-string? + (list-of string?)) + +(define (port? n) + (and (integer? n) + (<= 0 n 65535))) + +(define (string-or-symbol? x) + (or (symbol? x) (string? x))) + +(define-configuration/no-serialization mympd-ip-acl + (allow + (list-of-string '()) + "Allowed IP addresses.") + + (deny + (list-of-string '()) + "Disallowed IP addresses.")) + +(define-maybe/no-serialization port) +(define-maybe/no-serialization boolean) +(define-maybe/no-serialization integer) +(define-maybe/no-serialization string) +(define-maybe/no-serialization mympd-ip-acl) + +;; XXX: The serialization procedures are insufficient since we require +;; access to multiple fields at once. +;; Fields marked with empty-serializer are never serialized and are +;; used for command-line arguments or by the service definition. +(define-configuration/no-serialization mympd-configuration + (package + (file-like mympd) + "The package object of the myMPD server." + empty-serializer) + + (shepherd-requirement + (list-of-symbol '()) + "This is a list of symbols naming Shepherd services that this service +will depend on." + empty-serializer) + + (user + (string "mympd") + "Owner of the @command{mympd} process." + empty-serializer) + + (group + (string "nogroup") + "Owner group of the @command{mympd} process." + empty-serializer) + + (work-directory + (string "/var/lib/mympd") + "Where myMPD will store its data." + empty-serializer) + + (cache-directory + (string "/var/cache/mympd") + "Where myMPD will store its cache." + empty-serializer) + + (acl + maybe-mympd-ip-acl + "ACL to access the myMPD webserver.") + + (covercache-ttl + (maybe-integer 31) + "How long to keep cached covers, @code{0} disables cover caching.") + + (http? + (boolean #t) + "HTTP support.") + + (host + (string "[::]") + "Host name to listen on.") + + (port + (maybe-port 80) + "HTTP port to listen on.") + + (log-level + (integer 5) + "How much detail to include in logs, possible values: @code{0} to @code{7}.") + + (log-to + (string-or-symbol "/var/log/mympd/log") + "Where to send logs. By default, the service logs to +@file{/var/log/mympd.log}. The alternative is @code{'syslog}, which +sends output to the running syslog service under the @samp{daemon} facility." + empty-serializer) + + (lualibs + (maybe-string "all") + "See +@url{https://jcorporation.github.io/myMPD/scripting/#lua-standard-libraries}.") + + (uri + maybe-string + "Override URI to myMPD. +See @url{https://github.com/jcorporation/myMPD/issues/950}.") + + (script-acl + (maybe-mympd-ip-acl (mympd-ip-acl + (allow '("127.0.0.1")))) + "ACL to access the myMPD script backend.") + + (ssl? + (boolean #f) + "SSL/TLS support.") + + (ssl-port + (maybe-port 443) + "Port to listen for HTTPS.") + + (ssl-cert + maybe-string + "Path to PEM encoded X.509 SSL/TLS certificate (public key).") + + (ssl-key + maybe-string + "Path to PEM encoded SSL/TLS private key.") + + (pin-hash + maybe-string + "SHA-256 hashed pin used by myMPD to control settings access by +prompting a pin from the user.") + + (save-caches? + maybe-boolean + "Whether to preserve caches between service restarts.")) + +(define (mympd-serialize-configuration config) + (define serialize-value + (match-lambda + ((? boolean? val) (if val "true" "false")) + ((or (? port? val) (? integer? val)) (number->string val)) + ((? mympd-ip-acl? val) (ip-acl-serialize-configuration val)) + ((? string? val) val))) + + (define (ip-acl-serialize-configuration config) + (define (serialize-list-of-string prefix lst) + (map (cut format #f "~a~a" prefix <>) lst)) + (string-join + (append + (serialize-list-of-string "+" (mympd-ip-acl-allow config)) + (serialize-list-of-string "-" (mympd-ip-acl-deny config))) ",")) + + ;; myMPD configuration fields are serialized as individual files under + ;; /config/. + (match-record config (work-directory acl + covercache-ttl http? host port + log-level lualibs uri script-acl + ssl? ssl-port ssl-cert ssl-key + pin-hash save-caches?) + (define (serialize-field filename value) + (when (maybe-value-set? value) + (list (format #f "~a/config/~a" work-directory filename) + (mixed-text-file filename (serialize-value value))))) + + (let ((filename-to-field `(("acl" . ,acl) + ("covercache_keep_days" . ,covercache-ttl) + ("http" . ,http?) + ("http_host" . ,host) + ("http_port" . ,port) + ("loglevel" . ,log-level) + ("lualibs" . ,lualibs) + ("mympd_uri" . ,uri) + ("scriptacl" . ,script-acl) + ("ssl" . ,ssl?) + ("ssl_port" . ,ssl-port) + ("ssl_cert" . ,ssl-cert) + ("ssl_key" . ,ssl-key) + ("pin_hash" . ,pin-hash) + ("save_caches" . ,save-caches?)))) + (filter list? + (generic-serialize-alist list serialize-field + filename-to-field))))) + +(define (mympd-shepherd-service config) + (match-record config (package shepherd-requirement + user work-directory + cache-directory log-level log-to) + (let ((log-level* (format #f "MYMPD_LOGLEVEL=~a" log-level))) + (shepherd-service + (documentation "Run the myMPD daemon.") + (requirement `(loopback user-processes ,@shepherd-requirement)) + (provision '(mympd)) + (start #~(begin + (let* ((pw (getpwnam #$user)) + (uid (passwd:uid pw)) + (gid (passwd:gid pw))) + (for-each (lambda (dir) + (mkdir-p dir) + (chown dir uid gid)) + (list #$work-directory #$cache-directory))) + + (make-forkexec-constructor + `(#$(file-append package "/bin/mympd") + "--user" #$user + #$@(if (eqv? log-to 'syslog) '("--syslog") '()) + "--workdir" #$work-directory + "--cachedir" #$cache-directory) + #:environment-variables (list #$log-level*) + #:log-file #$(if (string? log-to) log-to #f)))) + (stop #~(make-kill-destructor)))))) + +(define (mympd-accounts config) + (match-record config (user group) + (list (user-group (name group) + (system? #t)) + (user-account (name user) + (group group) + (system? #t) + (comment "myMPD user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin")))))) + +(define (mympd-log-rotation config) + (match-record config (log-to) + (if (string? log-to) + (list (log-rotation + (files (list log-to)))) + '()))) + +(define mympd-service-type + (service-type + (name 'mympd) + (extensions + (list (service-extension shepherd-root-service-type + (compose list mympd-shepherd-service)) + (service-extension account-service-type + mympd-accounts) + (service-extension special-files-service-type + mympd-serialize-configuration) + (service-extension rottlog-service-type + mympd-log-rotation))) + (description "Run myMPD, a frontend for MPD. (Music Player Daemon)") + (default-value (mympd-configuration)))) diff --git a/gnu/tests/audio.scm b/gnu/tests/audio.scm index 8aa6d1e818..701496ee23 100644 --- a/gnu/tests/audio.scm +++ b/gnu/tests/audio.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 Peter Mikkelsen +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -22,9 +23,11 @@ (define-module (gnu tests audio) #:use-module (gnu system vm) #:use-module (gnu services) #:use-module (gnu services audio) + #:use-module (gnu services networking) #:use-module (gnu packages mpd) #:use-module (guix gexp) - #:export (%test-mpd)) + #:export (%test-mpd + %test-mympd)) (define %mpd-os (simple-operating-system @@ -76,3 +79,52 @@ (define %test-mpd (name "mpd") (description "Test that the mpd can run and be connected to.") (value (run-mpd-test)))) + + +(define (run-mympd-test) + (define os (marionette-operating-system + (simple-operating-system (service dhcp-client-service-type) + (service mympd-service-type)) + #:imported-modules '((gnu services herd)))) + + (define vm + (virtual-machine + (operating-system os) + (port-forwardings '((8080 . 80))))) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (srfi srfi-64) + (srfi srfi-8) + (web client) + (web response) + (gnu build marionette)) + + (define marionette + (make-marionette (list #$vm))) + + (test-runner-current (system-test-runner #$output)) + (test-begin "mympd") + (test-assert "service is running" + (marionette-eval '(begin + (use-modules (gnu services herd)) + + (start-service 'mympd)) + marionette)) + + (test-assert "HTTP port ready" + (wait-for-tcp-port 80 marionette)) + + (test-equal "http-head" + 200 + (receive (x _) (http-head "http://localhost:8080") (response-code x))) + + (test-end)))) + (gexp->derivation "mympd-test" test)) + +(define %test-mympd + (system-test + (name "mympd") + (description "Connect to a running myMPD service.") + (value (run-mympd-test)))) -- 2.38.1 From unknown Sun Aug 17 01:51:36 2025 MIME-Version: 1.0 X-Mailer: MIME-tools 5.505 (Entity 5.505) X-Loop: help-debbugs@gnu.org From: help-debbugs@gnu.org (GNU bug Tracking System) To: Bruno Victal Subject: bug#61122: closed (Re: [PATCH v2] services: Add mympd-service-type.) Message-ID: References: <1eac629a0fa6975babbec1e7de57dcedd94d6b48.camel@gmail.com> <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> X-Gnu-PR-Message: they-closed 61122 X-Gnu-PR-Package: guix-patches X-Gnu-PR-Keywords: patch Reply-To: 61122@debbugs.gnu.org Date: Sun, 05 Feb 2023 06:12:03 +0000 Content-Type: multipart/mixed; boundary="----------=_1675577523-12596-1" This is a multi-part message in MIME format... ------------=_1675577523-12596-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Your bug report #61122: [PATCH] services: Add mympd-service-type. which was filed against the guix-patches package, has been closed. The explanation is attached below, along with your original report. If you require more details, please reply to 61122@debbugs.gnu.org. --=20 61122: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D61122 GNU Bug Tracking System Contact help-debbugs@gnu.org with problems ------------=_1675577523-12596-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at 61122-done) by debbugs.gnu.org; 5 Feb 2023 06:11:46 +0000 Received: from localhost ([127.0.0.1]:43854 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pOYFe-0003GQ-CM for submit@debbugs.gnu.org; Sun, 05 Feb 2023 01:11:46 -0500 Received: from mail-ej1-f65.google.com ([209.85.218.65]:46596) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pOYFd-0003GC-1k for 61122-done@debbugs.gnu.org; Sun, 05 Feb 2023 01:11:45 -0500 Received: by mail-ej1-f65.google.com with SMTP id p26so25845355ejx.13 for <61122-done@debbugs.gnu.org>; Sat, 04 Feb 2023 22:11:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:from:to:cc:subject:date :message-id:reply-to; bh=SjQ5N4Lrzfcqi5PKAhf5gH46g7jl6M96jOANeiDJlrs=; b=UVlniwB9Oh5D5DQJea+XbpCXkbseb/C6A7A3U+urfP39HN7rmCoYFpHPHI+HBH5+d7 CkfmmVO9krLXWVLwseNEg4yyV5oL2E1fbzxxpBnVprt+6ANiZoLO+sTomz9GlX/zVhfI 0YHyaa8VkUVRGoYVkLfqcPZ+T7D5xqWk7gHZiRJKzGwbbQZP8WhQ7lBWaY0xyBPbqdnt M3pccJMFw44D/2ESgr3elUvZF54n076fW2YZaXfRMOA+Z7CzBiyIcwWGKrNC2i5EZRZL vENYU0wFBvmZvWhCBKWOZnag5SYCIyAGUAGmN3CB9EfUa1/nky1Ye7brnNPSX9S4wVfg 9qKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=SjQ5N4Lrzfcqi5PKAhf5gH46g7jl6M96jOANeiDJlrs=; b=wTlIhqy5g9BjQYzDVL+0O2NnusqCBDM4qrahkBXgkMgMO6KWrrhR7TxPQcNbX2DR1S jFPPlO98sAgLNdZEEAYOL7O1l617gIv6wvcCAeu5eEiE7biRSr2tcVOV4BI9E1lfpoD0 EUnstNZtD5VxO1knwtRmRMpO/p9302PtXmFu4WIpMfnJJiFwTLhVxmNpp6DzTVvqjQBb 0qkOlZF3HWiFydUVulGfP4c79BNyLPZJhhdkISHwMMmOnuT4lIh/lA5lUVsiw8yeF+1x 808KLEgrZZzesKIOElqBo+f0nDH4cYrl64Oql3trAfPdiypcpboqBYr/KjGwfigG1acD 0WYg== X-Gm-Message-State: AO0yUKV90SzccRllKpZLh+1vVwSnkOOozWXCNfpjQArtqwtX9JB5aKDo 1gZ5+mNjqtwdazdYTeC9LBQ= X-Google-Smtp-Source: AK7set/cFILk8DaxSj7AMqSOQFaz2pVh3V8Z7y5pzf6davf0LKmigVeP+X2eV5dSddUKNKyMq7R6qw== X-Received: by 2002:a17:906:7e42:b0:88c:b5b3:ac03 with SMTP id z2-20020a1709067e4200b0088cb5b3ac03mr15951214ejr.24.1675577499490; Sat, 04 Feb 2023 22:11:39 -0800 (PST) Received: from lumine.fritz.box (85-127-52-93.dsl.dynamic.surfer.at. [85.127.52.93]) by smtp.gmail.com with ESMTPSA id gz22-20020a170906f2d600b0088f88d1d36bsm3695987ejb.166.2023.02.04.22.11.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 04 Feb 2023 22:11:39 -0800 (PST) Message-ID: <1eac629a0fa6975babbec1e7de57dcedd94d6b48.camel@gmail.com> Subject: Re: [PATCH v2] services: Add mympd-service-type. From: Liliana Marie Prikler To: Bruno Victal , 61122-done@debbugs.gnu.org Date: Sun, 05 Feb 2023 07:11:38 +0100 In-Reply-To: <90eae73e37906fdfdf33c2654206ceac1d3d9fc6.1675542344.git.mirai@makinata.eu> References: <90eae73e37906fdfdf33c2654206ceac1d3d9fc6.1675542344.git.mirai@makinata.eu> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.46.0 MIME-Version: 1.0 X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 61122-done X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Am Samstag, dem 04.02.2023 um 20:28 +0000 schrieb Bruno Victal: > * gnu/services/audio.scm (mympd-service-type): New variable. > * gnu/tests/audio.scm (%test-mympd): New variable. > * doc/guix.texi: Document it. Rebased on top of mpd-service-type and pushed. Cheers ------------=_1675577523-12596-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at submit) by debbugs.gnu.org; 28 Jan 2023 13:54:15 +0000 Received: from localhost ([127.0.0.1]:39904 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pLleo-0007xl-5G for submit@debbugs.gnu.org; Sat, 28 Jan 2023 08:54:15 -0500 Received: from lists.gnu.org ([209.51.188.17]:60914) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pLlel-0007xd-TD for submit@debbugs.gnu.org; Sat, 28 Jan 2023 08:54:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLlel-0000PV-Lt for guix-patches@gnu.org; Sat, 28 Jan 2023 08:54:11 -0500 Received: from smtpm1.myservices.hosting ([185.26.105.232]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pLlei-0007Ap-VG for guix-patches@gnu.org; Sat, 28 Jan 2023 08:54:11 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpm1.myservices.hosting (Postfix) with ESMTP id 31CC720865 for ; Sat, 28 Jan 2023 14:53:57 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id CAEA380098; Sat, 28 Jan 2023 14:53:57 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 1UlGWltVrFiE; Sat, 28 Jan 2023 14:53:53 +0100 (CET) Received: from guix-nuc.home.arpa (bl9-118-236.dsl.telepac.pt [85.242.118.236]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id ED0A380097; Sat, 28 Jan 2023 14:53:52 +0100 (CET) From: Bruno Victal To: guix-patches@gnu.org Subject: [PATCH] services: Add mympd-service-type. Date: Sat, 28 Jan 2023 13:53:43 +0000 Message-Id: <26049376dd4cec9bb473fa889b73409bc71b14ba.1674913975.git.mirai@makinata.eu> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=185.26.105.232; envelope-from=mirai@makinata.eu; helo=smtpm1.myservices.hosting X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-Debbugs-Envelope-To: submit Cc: Bruno Victal X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) * gnu/services/audio.scm (mympd-service-type): New variable. * gnu/tests/audio.scm (%test-mympd): New variable. * doc/guix.texi: Document it. --- doc/guix.texi | 115 +++++++++++++++++ gnu/services/audio.scm | 273 ++++++++++++++++++++++++++++++++++++++++- gnu/tests/audio.scm | 54 +++++++- 3 files changed, 440 insertions(+), 2 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 2b1ad77ba5..790696783c 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -112,6 +112,7 @@ Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@* Copyright @copyright{} 2023 Giacomo Leidi@* Copyright @copyright{} 2022 Antero Mejr@* +Copyright @copyright{} 2022 Bruno Victal@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -33272,6 +33273,120 @@ Audio Services (port . "8080")))))))) @end lisp +@subsubheading myMPD + +@cindex MPD, web interface +@cindex myMPD service + +@uref{https://jcorporation.github.io/myMPD/, myMPD} is a web server +frontend for MPD that provides a mobile friendly web client for MPD. + +The following example shows a myMPD instance listening on port 80, +with album cover caching disabled. + +@lisp +(service mympd-service-type + (mympd-configuration + (port 80) + (covercache-ttl 0))) +@end lisp + +@defvar mympd-service-type +The service type for @command{mympd}. +@end defvar + +@c %start of fragment +@deftp {Data Type} mympd-configuration +Available @code{mympd-configuration} fields are: + +@table @asis +@item @code{package} (default: @code{mympd}) (type: file-like) +The package object of the myMPD server. + +@item @code{shepherd-requirement} (default: @code{()}) (type: list-of-symbol) +This is a list of symbols naming Shepherd services that this service +will depend on. + +@item @code{user} (default: @code{"mympd"}) (type: string) +Owner of the @command{mympd} process. + +@item @code{group} (default: @code{"nogroup"}) (type: string) +Owner group of the @command{mympd} process. + +@item @code{work-directory} (default: @code{"/var/lib/mympd"}) (type: string) +Where myMPD will store its data. + +@item @code{cache-directory} (default: @code{"/var/cache/mympd"}) (type: string) +Where myMPD will store its cache. + +@item @code{acl} (type: maybe-ip-acl) +ACL to access the myMPD webserver. See +@uref{https://jcorporation.github.io/myMPD/configuration/acl,myMPD ACL} +for syntax. + +@item @code{covercache-ttl} (default: @code{31}) (type: maybe-integer) +How long to keep cached covers, @code{0} disables cover caching. + +@item @code{http?} (default: @code{#t}) (type: boolean) +HTTP support. + +@item @code{host} (default: @code{"[::]"}) (type: string) +Host name to listen on. + +@item @code{port} (default: @code{80}) (type: maybe-port) +HTTP port to listen on. + +@item @code{log-level} (default: @code{5}) (type: integer) +How much detail to include in logs, possible values: @code{0} to +@code{7}. + +@item @code{log-to} (default: @code{"/var/log/mympd/log"}) (type: string-or-symbol) +Where to send logs. By default, the service logs to +@file{/var/log/mympd.log}. The alternative is @code{'syslog}, which +sends output to the running syslog service under the @samp{daemon} +facility. + +@item @code{lualibs} (default: @code{"all"}) (type: maybe-string) +See +@uref{https://jcorporation.github.io/myMPD/scripting/#lua-standard-libraries}. + +@item @code{script-acl} (default: @code{(ip-acl (allow '("127.0.0.1")))}) (type: maybe-ip-acl) +ACL to access the myMPD script backend. + +@item @code{ssl?} (default: @code{#f}) (type: boolean) +SSL/TLS support. + +@item @code{ssl-port} (default: @code{443}) (type: maybe-port) +Port to listen for HTTPS. + +@item @code{ssl-cert} (type: maybe-string) +Path to PEM encoded X.509 SSL/TLS certificate (public key). + +@item @code{ssl-key} (type: maybe-string) +Path to PEM encoded SSL/TLS private key. + +@item @code{pin-hash} (type: maybe-string) +SHA-256 hashed pin used by myMPD to control settings access by prompting +a pin from the user. + +@end table +@end deftp +@c %end of fragment + +@c %start of fragment +@deftp {Data Type} ip-acl +Available @code{ip-acl} fields are: + +@table @asis +@item @code{allow} (default: @code{()}) (type: list-of-string) +Allowed IP addresses. + +@item @code{deny} (default: @code{()}) (type: list-of-string) +Disallowed IP addresses. + +@end table +@end deftp +@c %end of fragment @node Virtualization Services @subsection Virtualization Services diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm index c60053f33c..c384d3d2b8 100644 --- a/gnu/services/audio.scm +++ b/gnu/services/audio.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017 Peter Mikkelsen ;;; Copyright © 2019 Ricardo Wurmus ;;; Copyright © 2020 Ludovic Courtès +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -21,6 +22,8 @@ (define-module (gnu services audio) #:use-module (guix gexp) #:use-module (gnu services) + #:use-module (gnu services admin) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) @@ -28,11 +31,41 @@ (define-module (gnu services audio) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (ice-9 format) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (mpd-output mpd-output? mpd-configuration mpd-configuration? - mpd-service-type)) + mpd-service-type + + mympd-service-type + mympd-configuration + mympd-configuration? + mympd-configuration-package + mympd-configuration-shepherd-requirement + mympd-configuration-user + mympd-configuration-group + mympd-configuration-work-directory + mympd-configuration-cache-directory + mympd-configuration-acl + mympd-configuration-covercache-ttl + mympd-configuration-http? + mympd-configuration-host + mympd-configuration-port + mympd-configuration-log-level + mympd-configuration-log-to + mympd-configuration-lualibs + mympd-configuration-script-acl + mympd-configuration-ssl? + mympd-configuration-ssl-port + mympd-configuration-ssl-cert + mympd-configuration-ssl-key + mympd-configuration-pin-hash + ip-acl + ip-acl? + ip-acl-allow + ip-acl-deny)) ;;; Commentary: ;;; @@ -197,3 +230,241 @@ (define mpd-service-type (service-extension activation-service-type mpd-service-activation))) (default-value (mpd-configuration)))) + + +;;; +;;; myMPD +;;; + +(define list-of-symbol? + (list-of symbol?)) + +(define list-of-string? + (list-of string?)) + +(define (port? n) + (and (integer? n) + (<= 0 n 65535))) + +(define (string-or-symbol? x) + (or (symbol? x) (string? x))) + +(define-configuration/no-serialization ip-acl + (allow + (list-of-string '()) + "Allowed IP addresses.") + + (deny + (list-of-string '()) + "Disallowed IP addresses.")) + +(define-maybe/no-serialization port) +(define-maybe/no-serialization integer) +(define-maybe/no-serialization string) +(define-maybe/no-serialization ip-acl) + +;; XXX: The serialization procedures are insufficient since we require +;; access to multiple fields at once. +;; Fields marked with empty-serializer are never serialized and are +;; used for command-line arguments or by the service definition. +(define-configuration/no-serialization mympd-configuration + (package + (file-like mympd) + "The package object of the myMPD server." + empty-serializer) + + (shepherd-requirement + (list-of-symbol '()) + "This is a list of symbols naming Shepherd services that this service +will depend on." + empty-serializer) + + (user + (string "mympd") + "Owner of the @command{mympd} process." + empty-serializer) + + (group + (string "nogroup") + "Owner group of the @command{mympd} process." + empty-serializer) + + (work-directory + (string "/var/lib/mympd") + "Where myMPD will store its data." + empty-serializer) + + (cache-directory + (string "/var/cache/mympd") + "Where myMPD will store its cache." + empty-serializer) + + (acl + maybe-ip-acl + "ACL to access the myMPD webserver. See +@uref{https://jcorporation.github.io/myMPD/configuration/acl,myMPD ACL} +for syntax.") + + (covercache-ttl + (maybe-integer 31) + "How long to keep cached covers, @code{0} disables cover caching.") + + (http? + (boolean #t) + "HTTP support.") + + (host + (string "[::]") + "Host name to listen on.") + + (port + (maybe-port 80) + "HTTP port to listen on.") + + (log-level + (integer 5) + "How much detail to include in logs, possible values: @code{0} to @code{7}.") + + (log-to + (string-or-symbol "/var/log/mympd/log") + "Where to send logs. By default, the service logs to +@file{/var/log/mympd.log}. The alternative is @code{'syslog}, which +sends output to the running syslog service under the @samp{daemon} facility." + empty-serializer) + + (lualibs + (maybe-string "all") + "See +@url{https://jcorporation.github.io/myMPD/scripting/#lua-standard-libraries}.") + + (script-acl + (maybe-ip-acl (ip-acl + (allow '("127.0.0.1")))) + "ACL to access the myMPD script backend.") + + (ssl? + (boolean #f) + "SSL/TLS support.") + + (ssl-port + (maybe-port 443) + "Port to listen for HTTPS.") + + (ssl-cert + maybe-string + "Path to PEM encoded X.509 SSL/TLS certificate (public key).") + + (ssl-key + maybe-string + "Path to PEM encoded SSL/TLS private key.") + + (pin-hash + maybe-string + "SHA-256 hashed pin used by myMPD to control settings access by +prompting a pin from the user.")) + +(define (mympd-serialize-configuration config) + (define serialize-value + (match-lambda + ((? boolean? val) (if val "true" "false")) + ((or (? port? val) (? integer? val)) (number->string val)) + ((? ip-acl? val) (ip-acl-serialize-configuration val)) + ((? string? val) val))) + + (define (ip-acl-serialize-configuration config) + (define (serialize-list-of-string prefix lst) + (map (cut format #f "~a~a" prefix <>) lst)) + (string-join + (append + (serialize-list-of-string "+" (ip-acl-allow config)) + (serialize-list-of-string "-" (ip-acl-deny config))) ",")) + + ;; myMPD configuration fields are serialized as individual files under + ;; /config/. + (match-record config (work-directory acl + covercache-ttl http? host port + log-level lualibs script-acl + ssl? ssl-port ssl-cert ssl-key + pin-hash) + (define (serialize-field filename value) + (when (maybe-value-set? value) + (list (format #f "~a/config/~a" work-directory filename) + (mixed-text-file filename (serialize-value value))))) + + (let ((filename-to-field `(("acl" . ,acl) + ("covercache_keep_days" . ,covercache-ttl) + ("http" . ,http?) + ("http_host" . ,host) + ("http_port" . ,port) + ("loglevel" . ,log-level) + ("lualibs" . ,lualibs) + ("scriptacl" . ,script-acl) + ("ssl" . ,ssl?) + ("ssl_port" . ,ssl-port) + ("ssl_cert" . ,ssl-cert) + ("ssl_key" . ,ssl-key) + ("pin_hash" . ,pin-hash)))) + (filter list? + (generic-serialize-alist list serialize-field + filename-to-field))))) + +(define (mympd-shepherd-service config) + (match-record config (package shepherd-requirement + user work-directory + cache-directory log-level log-to) + (let ((log-level* (format #f "MYMPD_LOGLEVEL=~a" log-level))) + (shepherd-service + (documentation "Run the myMPD daemon.") + (requirement `(loopback user-processes ,@shepherd-requirement)) + (provision '(mympd)) + (start #~(begin + (let* ((pw (getpwnam #$user)) + (uid (passwd:uid pw)) + (gid (passwd:gid pw))) + (for-each (lambda (dir) + (mkdir-p dir) + (chown dir uid gid)) + (list #$work-directory #$cache-directory))) + + (make-forkexec-constructor + `(#$(file-append package "/bin/mympd") + "--user" #$user + #$@(if (eqv? log-to 'syslog) '("--syslog") '()) + "--workdir" #$work-directory + "--cachedir" #$cache-directory) + #:environment-variables (list #$log-level*) + #:log-file #$(if (string? log-to) log-to #f)))) + (stop #~(make-kill-destructor)))))) + +(define (mympd-accounts config) + (match-record config (user group) + (list (user-group (name group) + (system? #t)) + (user-account (name user) + (group group) + (system? #t) + (comment "myMPD user") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin")))))) + +(define (mympd-log-rotation config) + (match-record config (log-to) + (if (string? log-to) + (list (log-rotation + (files (list log-to)))) + '()))) + +(define mympd-service-type + (service-type + (name 'mympd) + (extensions + (list (service-extension shepherd-root-service-type + (compose list mympd-shepherd-service)) + (service-extension account-service-type + mympd-accounts) + (service-extension special-files-service-type + mympd-serialize-configuration) + (service-extension rottlog-service-type + mympd-log-rotation))) + (description "Run myMPD, a frontend for MPD. (Music Player Daemon)") + (default-value (mympd-configuration)))) diff --git a/gnu/tests/audio.scm b/gnu/tests/audio.scm index 8aa6d1e818..701496ee23 100644 --- a/gnu/tests/audio.scm +++ b/gnu/tests/audio.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2017 Peter Mikkelsen +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -22,9 +23,11 @@ (define-module (gnu tests audio) #:use-module (gnu system vm) #:use-module (gnu services) #:use-module (gnu services audio) + #:use-module (gnu services networking) #:use-module (gnu packages mpd) #:use-module (guix gexp) - #:export (%test-mpd)) + #:export (%test-mpd + %test-mympd)) (define %mpd-os (simple-operating-system @@ -76,3 +79,52 @@ (define %test-mpd (name "mpd") (description "Test that the mpd can run and be connected to.") (value (run-mpd-test)))) + + +(define (run-mympd-test) + (define os (marionette-operating-system + (simple-operating-system (service dhcp-client-service-type) + (service mympd-service-type)) + #:imported-modules '((gnu services herd)))) + + (define vm + (virtual-machine + (operating-system os) + (port-forwardings '((8080 . 80))))) + + (define test + (with-imported-modules '((gnu build marionette)) + #~(begin + (use-modules (srfi srfi-64) + (srfi srfi-8) + (web client) + (web response) + (gnu build marionette)) + + (define marionette + (make-marionette (list #$vm))) + + (test-runner-current (system-test-runner #$output)) + (test-begin "mympd") + (test-assert "service is running" + (marionette-eval '(begin + (use-modules (gnu services herd)) + + (start-service 'mympd)) + marionette)) + + (test-assert "HTTP port ready" + (wait-for-tcp-port 80 marionette)) + + (test-equal "http-head" + 200 + (receive (x _) (http-head "http://localhost:8080") (response-code x))) + + (test-end)))) + (gexp->derivation "mympd-test" test)) + +(define %test-mympd + (system-test + (name "mympd") + (description "Connect to a running myMPD service.") + (value (run-mympd-test)))) base-commit: 37fdb382dad47149d8f5be41af108478800e9d30 -- 2.38.1 ------------=_1675577523-12596-1--