From: Bernhard Bitsch <bbitsch@ipfire.org>
To: development@lists.ipfire.org
Subject: Re: [PATCH] RPZ: update code to include WEBGUI and additional languages
Date: Wed, 6 Aug 2025 14:32:12 +0200 [thread overview]
Message-ID: <4d7fda4f-0de9-4a77-99b1-6276b161f68a@ipfire.org> (raw)
In-Reply-To: <ema5a481b0-4e49-4983-9d76-668c8e09a1f7@af5f0be5.com>
Am 05.08.2025 um 18:53 schrieb Jon Murphy:
>
> Q. * The problem are the sources and the quality of the blacklists.
> Unless those are available to us and our users the entire technology is
> becoming worthless. This is exactly what we have with the URL filter.
>
> A. To me this is similar to many other open source items. If the head
> MFiC walks away, then the open source becomes toast. If the projects is
> sold or transferred to a paid service, then the open source project is
> toast. I don’t like it, but unless IPFire becomes the mix-master of
> blocklists (collect, filter, publish, etc.) then there is no way around
> this.
>
> ==
>
> Q. * Unbound itself is a whole mess and I hope we will be able to launch
> our plans to replace it as soon as possible.
>
> A. This one I cannot answer since I don’t know the issues others have
> experienced. I started near the time when IPFire went from dnsmasq to
> unbound and to me unbound seems A-OK. But again I don’t know the issues.
>
What alternative is planned for unbound? Does it support RPZ or
something alike?
I think it can be agreed, that such a sort of filtering is meaningful.
Bernhard
EDIT: The case of controlled lists is in solution by Erik's work
(https://github.com/twitOne/RPZ-Blocklists/tree/main)> ==
>
> Specifically, what questions are remaining unanswered?
>
>
>
> ------ Original Message ------
> From "Michael Tremer" <michael.tremer@ipfire.org>
> To "Jon Murphy" <jon.murphy@ipfire.org>
> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: Development-List"
> <development@lists.ipfire.org>
> Date 5/23/2025 5:35:58 AM
> Subject Re: [PATCH] RPZ: update code to include WEBGUI and additional
> languages
>
>> Hello Jon,
>>
>> You need to be a little bit more precise with what you actually want
>> to know.
>>
>> I think I have covered this before and can only refer to the previous
>> emails in this conversation.
>>
>> * RPZ itself is fine as a feature. It is a powerful tool we could
>> leverage for a lot a of things. It would have the potential to allow
>> content filtering without the proxy.
>>
>> * The problem are the sources and the quality of the blacklists.
>> Unless those are available to us and our users the entire technology
>> is becoming worthless. This is exactly what we have with the URL filter.
>>
>> * Unbound itself is a whole mess and I hope we will be able to launch
>> our plans to replace it as soon as possible.
>>
>> Best,
>> -Michael
>>
>>> On 22 May 2025, at 20:45, Jon Murphy <jon.murphy@ipfire.org> wrote:
>>>
>>>
>>> I understand that "Unbound, RPZ and a blacklist" was unsuitable. I
>>> am curious what was suitable.
>>>
>>>
>>>
>>> ------ Original Message ------
>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: Development-
>>> List" <development@lists.ipfire.org>
>>> Date 5/22/2025 10:46:25 AM
>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and
>>> additional languages
>>>
>>>> Unbound, RPZ and a blacklist that I deemed suitable. It isn’t.
>>>>
>>>>> On 22 May 2025, at 16:45, Jon Murphy <jon.murphy@ipfire.org> wrote:
>>>>>
>>>>> Still curious… What are you using to block adult websites?
>>>>>
>>>>>
>>>>>
>>>>> ------ Original Message ------
>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: Development-
>>>>> List" <development@lists.ipfire.org>
>>>>> Date 5/22/2025 10:43:55 AM
>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and
>>>>> additional languages
>>>>>
>>>>>> I stated that before. I need to block adult websites.
>>>>>>
>>>>>>> On 22 May 2025, at 16:42, Jon Murphy <jon.murphy@ipfire.org> wrote:
>>>>>>>
>>>>>>> Now I am curious! What is your use-case? Tell me more...
>>>>>>>
>>>>>>>
>>>>>>> ------ Original Message ------
>>>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>>>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: Development-
>>>>>>> List" <development@lists.ipfire.org>
>>>>>>> Date 5/22/2025 10:40:38 AM
>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and
>>>>>>> additional languages
>>>>>>>
>>>>>>>> Hello Jon,
>>>>>>>>
>>>>>>>> I have not been spending on time on this at all since we talked
>>>>>>>> last.
>>>>>>>>
>>>>>>>> I don’t need Unbound to download any files for my use-case either.
>>>>>>>>
>>>>>>>> -Michael
>>>>>>>>
>>>>>>>>> On 20 May 2025, at 17:30, Jon Murphy <jon.murphy@ipfire.org>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> Michael,
>>>>>>>>>
>>>>>>>>> Were you able to debug RPZ and get Unbound to download `.rpz`
>>>>>>>>> files?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Jon
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ------ Original Message ------
>>>>>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>>>>>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire:
>>>>>>>>> Development-List" <development@lists.ipfire.org>
>>>>>>>>> Date 3/24/2025 9:43:37 AM
>>>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and
>>>>>>>>> additional languages
>>>>>>>>>
>>>>>>>>>> Yes, I don’t need any debugging of this...
>>>>>>>>>>
>>>>>>>>>>> On 24 Mar 2025, at 14:42, Jon Murphy <jon.murphy@ipfire.org>
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>> Is there a:
>>>>>>>>>>>
>>>>>>>>>>> server:
>>>>>>>>>>> module-config: "respip validator iterator"
>>>>>>>>>>>
>>>>>>>>>>> In your RPZ set-up?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> ------ Original Message ------
>>>>>>>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>>>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>>>>>>>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire:
>>>>>>>>>>> Development-List" <development@lists.ipfire.org>
>>>>>>>>>>> Date 3/24/2025 9:40:15 AM
>>>>>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and
>>>>>>>>>>> additional languages
>>>>>>>>>>>
>>>>>>>>>>>> Because it is not doing it on my system...
>>>>>>>>>>>>
>>>>>>>>>>>>> On 24 Mar 2025, at 14:38, Jon Murphy
>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> Actually it did.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Why do you think Unbound did not?
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> ------ Original Message ------
>>>>>>>>>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>>>>>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>>>>>>>>>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire:
>>>>>>>>>>>>> Development-List" <development@lists.ipfire.org>
>>>>>>>>>>>>> Date 3/24/2025 9:36:53 AM
>>>>>>>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and
>>>>>>>>>>>>> additional languages
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Unbound did not put those there...
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 24 Mar 2025, at 14:33, Jon Murphy
>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> And where are these stored?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> In `/etc/unbound/zonefiles`:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> [root@ipfire ~] # ls -al /etc/unbound/zonefiles
>>>>>>>>>>>>>>> total 20664
>>>>>>>>>>>>>>> drwxr-xr-x 2 nobody nobody 4096 Mar 24 04:40 .
>>>>>>>>>>>>>>> drwxr-xr-x 4 root root 4096 Mar 19 16:24 ..
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 3999087 Mar 23 15:11
>>>>>>>>>>>>>>> adhocSB.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 1411 Mar 23 14:23 allow.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 25355 Mar 24 04:40
>>>>>>>>>>>>>>> AmazonTrkrHZ.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 7241 Mar 24 04:40
>>>>>>>>>>>>>>> AppleTrkrHZ.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 178 Mar 23 14:23 block.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 78496 Mar 24 04:40
>>>>>>>>>>>>>>> DOHblockHZ.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 16983551 Mar 24 04:40
>>>>>>>>>>>>>>> MxProPlusHZ.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 2893 Mar 24 04:40 tldHZ.rpz
>>>>>>>>>>>>>>> -rw-r--r-- 1 nobody nobody 29419 Mar 24 04:40
>>>>>>>>>>>>>>> WinTrkrHZ.rpz
>>>>>>>>>>>>>>> [root@ipfire ~] #
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> ------ Original Message ------
>>>>>>>>>>>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>>>>>>>>>>>> To "Bernhard Bitsch" <bbitsch@ipfire.org>
>>>>>>>>>>>>>>> Cc development@lists.ipfire.org
>>>>>>>>>>>>>>> Date 3/24/2025 9:25:40 AM
>>>>>>>>>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI
>>>>>>>>>>>>>>> and additional languages
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Hello,
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> On 24 Mar 2025, at 13:33, Bernhard Bitsch
>>>>>>>>>>>>>>>>> <bbitsch@ipfire.org> wrote:
>>>>>>>>>>>>>>>>> Am 24.03.2025 um 11:17 schrieb Michael Tremer:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Hello Jon,
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> On 24 Mar 2025, at 00:00, Jon Murphy
>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>>>>>>>> FYI - I was wrong Unbound RPZ is _not_ watching the
>>>>>>>>>>>>>>>>>>> serial number, it is watching the "refresh", the
>>>>>>>>>>>>>>>>>>> number after the serial number.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Refresh just tells the client how often to check for
>>>>>>>>>>>>>>>>>> an update.
>>>>>>>>>>>>>>>>>> If that is actually being set by the list publisher,
>>>>>>>>>>>>>>>>>> then we have another problem here, because they could
>>>>>>>>>>>>>>>>>> put some insanely low value there and we would then
>>>>>>>>>>>>>>>>>> DDoS their infrastructure. I think we should keep it
>>>>>>>>>>>>>>>>>> like we have it in other places that we control how
>>>>>>>>>>>>>>>>>> often we want to check or pull for updates.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> You are right. But an extra update process wastes
>>>>>>>>>>>>>>>>> additional processor time. The update mechanism of
>>>>>>>>>>>>>>>>> unbound does the check for update ( however it is
>>>>>>>>>>>>>>>>> realized ) nevertheless.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Yes, doing more things needs resources. But we are not
>>>>>>>>>>>>>>>> seriously considering whether an IPFire system has
>>>>>>>>>>>>>>>> enough resources to perform the download of a text file,
>>>>>>>>>>>>>>>> or are we?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> I understand that you don’t speak C, but you got the
>>>>>>>>>>>>>>>>>>> information from somewhere. Documentation maybe?
>>>>>>>>>>>>>>>>>>> Since that is out of date very often I like to
>>>>>>>>>>>>>>>>>>> consult the code.
>>>>>>>>>>>>>>>>>>> From testing. Downloading rpz files using rpz
>>>>>>>>>>>>>>>>>>> unbound, and watching what happens. If the rpz file
>>>>>>>>>>>>>>>>>>> is setup for "once per day" refresh, then it only
>>>>>>>>>>>>>>>>>>> downloads one time.
>>>>>>>>>>>>>>>>>>> However that won’t solve our problem . . . and
>>>>>>>>>>>>>>>>>>> having no cache.
>>>>>>>>>>>>>>>>>>> In `/etc/unbound/tuning.conf` there is `rrset-cache-
>>>>>>>>>>>>>>>>>>> size: 128m`. Are you referring to a different cache.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Naturally unbound is loading the zone into its memory
>>>>>>>>>>>>>>>>>> which we generally call cache.
>>>>>>>>>>>>>>>>>> When I say cache I am thinking about persistent data
>>>>>>>>>>>>>>>>>> storage across multiple restarts of Unbound. If I am
>>>>>>>>>>>>>>>>>> downloading 100 MiB of RPZ lists (which is presumably
>>>>>>>>>>>>>>>>>> still on the lower end) and I reboot my firewall, I do
>>>>>>>>>>>>>>>>>> not want to download the same data again. We can only
>>>>>>>>>>>>>>>>>> ever download a list *once* unless we are 100% certain
>>>>>>>>>>>>>>>>>> that it has changed. Then we can download it once again.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> The RPZ lists are stored in files in persistent
>>>>>>>>>>>>>>>>> storage. Unbound creates the internal cache from these.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> And where are these stored?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Maybe we need to implement both?
>>>>>>>>>>>>>>>>>>> Yes. There are very few AXFR list (I think only
>>>>>>>>>>>>>>>>>>> four were found). And many more HTTPS rpz files.
>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>> ------ Original Message ------
>>>>>>>>>>>>>>>>>>> From "Michael Tremer" <michael.tremer@ipfire.org>
>>>>>>>>>>>>>>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org>
>>>>>>>>>>>>>>>>>>> Cc "IPFire: Development-List"
>>>>>>>>>>>>>>>>>>> <development@lists.ipfire.org>
>>>>>>>>>>>>>>>>>>> Date 3/20/2025 11:26:43 AM
>>>>>>>>>>>>>>>>>>> Subject Re: [PATCH] RPZ: update code to include
>>>>>>>>>>>>>>>>>>> WEBGUI and additional languages
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Hello Jon,
>>>>>>>>>>>>>>>>>>>> Please don’t forget to Cc the list...
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> On 19 Mar 2025, at 18:27, Jon Murphy
>>>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Where in the code is this implemented? I cannot
>>>>>>>>>>>>>>>>>>>>>> find anything like this:
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Keep in mind I am not a "C" person. Maybe in this
>>>>>>>>>>>>>>>>>>>>> section?:
>>>>>>>>>>>>>>>>>>>>> https://git.ipfire.org/?p=thirdparty/
>>>>>>>>>>>>>>>>>>>>> unbound.git;a=blob;f=services/
>>>>>>>>>>>>>>>>>>>>> authzone.c;hb=30b9cb5f813003d0a2b1c2e678652396615b1b7d#l5875
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> This where the AXFR response is being handled when
>>>>>>>>>>>>>>>>>>>> doing a DNS zone transfer. This code is not being
>>>>>>>>>>>>>>>>>>>> called when performing a HTTP download.
>>>>>>>>>>>>>>>>>>>> I understand that you don’t speak C, but you got
>>>>>>>>>>>>>>>>>>>> the information from somewhere. Documentation maybe?
>>>>>>>>>>>>>>>>>>>> Since that is out of date very often I like to
>>>>>>>>>>>>>>>>>>>> consult the code.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> —
>>>>>>>>>>>>>>>>>>>>> When I was just learning about RPZ I created a
>>>>>>>>>>>>>>>>>>>>> separate RPZ file for testing. When I changed the
>>>>>>>>>>>>>>>>>>>>> SOA line with a new serial number, the RPZ file
>>>>>>>>>>>>>>>>>>>>> download would happen in about 5 minutes.
>>>>>>>>>>>>>>>>>>>>> https://people.ipfire.org/~jon/sblack-adhoc.rpz
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> It might well be that the file is not being
>>>>>>>>>>>>>>>>>>>> reloaded if the download matches the content that
>>>>>>>>>>>>>>>>>>>> unbound already has. That would of course save some
>>>>>>>>>>>>>>>>>>>> resources.
>>>>>>>>>>>>>>>>>>>> However that won’t solve our problem with redundant
>>>>>>>>>>>>>>>>>>>> downloads and having no cache.
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> That is how I found out the SOA line is watched
>>>>>>>>>>>>>>>>>>>>> for a serial number change.
>>>>>>>>>>>>>>>>>>>>> I’ll reconfirm my findings.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> The second reason is that we have a lot of
>>>>>>>>>>>>>>>>>>>>>>>> firewalls out there. Not all of them will enable
>>>>>>>>>>>>>>>>>>>>>>>> this feature and all of the lists, but even if
>>>>>>>>>>>>>>>>>>>>>>>> it is a good chunk, we will generate terabytes
>>>>>>>>>>>>>>>>>>>>>>>> of traffic which put load on the infrastructure
>>>>>>>>>>>>>>>>>>>>>>>> and will cost money. It simply is not what we
>>>>>>>>>>>>>>>>>>>>>>>> want to do, regardless of self-hosting those
>>>>>>>>>>>>>>>>>>>>>>>> lists and pulling them from somewhere else.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> So I understand, are you thinking of hosting RPZ
>>>>>>>>>>>>>>>>>>>>> AXFR (DNS zone transfer) on IPFire infrastructure?
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> No, I don’t think that we can generally do this.
>>>>>>>>>>>>>>>>>>>> The biggest problem is licensing as we cannot take
>>>>>>>>>>>>>>>>>>>> anyones content and host it ourselves. We would re-
>>>>>>>>>>>>>>>>>>>> distribute those lists and that will only work with
>>>>>>>>>>>>>>>>>>>> permission of the publishers. I assume that would be
>>>>>>>>>>>>>>>>>>>> too much work to actually get some useful content
>>>>>>>>>>>>>>>>>>>> out there. We might limit ourselves to only those
>>>>>>>>>>>>>>>>>>>> lists that are under a very permissive license.
>>>>>>>>>>>>>>>>>>>> Nobody wants that.
>>>>>>>>>>>>>>>>>>>> From a technical point of view, DNS over TCP might
>>>>>>>>>>>>>>>>>>>> not be very nice in terms of forging the transfer
>>>>>>>>>>>>>>>>>>>> and so we would need TLS as well… It should work,
>>>>>>>>>>>>>>>>>>>> but even if we would be able to encourage other
>>>>>>>>>>>>>>>>>>>> people to publish their lists I doubt they would
>>>>>>>>>>>>>>>>>>>> implement DNS over TLS for authoritative DNS. That
>>>>>>>>>>>>>>>>>>>> standard is in very early stages as well.
>>>>>>>>>>>>>>>>>>>> As far as I can see, those vendors who offer a list
>>>>>>>>>>>>>>>>>>>> as a commercial product are using DNS to distribute
>>>>>>>>>>>>>>>>>>>> it (e.g. Spamhaus). Those people who have made this
>>>>>>>>>>>>>>>>>>>> all a hobby are throwing the lists onto GitHub and
>>>>>>>>>>>>>>>>>>>> let them handle the traffic.
>>>>>>>>>>>>>>>>>>>> Maybe we need to implement both?
>>>>>>>>>>>>>>>>>>>> -Michael
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>> On 3/19/25 5:35 AM, Michael Tremer wrote:
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>> Hello Jon,
>>>>>>>>>>>>>>>>>>>>>> Where in the code is this implemented? I cannot
>>>>>>>>>>>>>>>>>>>>>> find anything like this:
>>>>>>>>>>>>>>>>>>>>>> Unbound loads the entire file into memory and
>>>>>>>>>>>>>>>>>>>>>> then starts parsing it. The only special treatment
>>>>>>>>>>>>>>>>>>>>>> there is is to check whether the first line is a
>>>>>>>>>>>>>>>>>>>>>> valid zone entry. It does not even have to be a
>>>>>>>>>>>>>>>>>>>>>> SOA record.
>>>>>>>>>>>>>>>>>>>>>> https://git.ipfire.org/?p=thirdparty/
>>>>>>>>>>>>>>>>>>>>>> unbound.git;a=blob;f=services/
>>>>>>>>>>>>>>>>>>>>>> authzone.c;hb=30b9cb5f813003d0a2b1c2e678652396615b1b7d#l1188
>>>>>>>>>>>>>>>>>>>>>> I am also concerned that Unbound will not be able
>>>>>>>>>>>>>>>>>>>>>> to support an upstream proxy for any downloads.
>>>>>>>>>>>>>>>>>>>>>> The caching situation is also unclear for me, so I
>>>>>>>>>>>>>>>>>>>>>> believe that we will be looking at writing a
>>>>>>>>>>>>>>>>>>>>>> custom downloader that implements all these things.
>>>>>>>>>>>>>>>>>>>>>> -Michael
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> On 19 Mar 2025, at 02:58, Jon Murphy
>>>>>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> The emphasis is on the repeated downloads of
>>>>>>>>>>>>>>>>>>>>>>>> the same list. That is
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> > what cannot happen.
>>>>>>>>>>>>>>>>>>>>>>> The Unbound RPZ code, as installed within
>>>>>>>>>>>>>>>>>>>>>>> IPFire, watches for a change
>>>>>>>>>>>>>>>>>>>>>>> in the SOA line of each RPZ file. This is an
>>>>>>>>>>>>>>>>>>>>>>> example of the first few
>>>>>>>>>>>>>>>>>>>>>>> lines for every RPZ file.
>>>>>>>>>>>>>>>>>>>>>>> $TTL 300
>>>>>>>>>>>>>>>>>>>>>>> @ SOA localhost. root.localhost. 1742298960
>>>>>>>>>>>>>>>>>>>>>>> 43200 3600 86400 300
>>>>>>>>>>>>>>>>>>>>>>> NS localhost.
>>>>>>>>>>>>>>>>>>>>>>> ;
>>>>>>>>>>>>>>>>>>>>>>> ; Title: HaGeZi's Pop-Up Ads DNS Blocklist
>>>>>>>>>>>>>>>>>>>>>>> ; Description: Blocks annoying and malicious
>>>>>>>>>>>>>>>>>>>>>>> pop-up ads.
>>>>>>>>>>>>>>>>>>>>>>> If the SOA serial number changes (e.g. the
>>>>>>>>>>>>>>>>>>>>>>> 1742298960), then Unbound RPZ
>>>>>>>>>>>>>>>>>>>>>>> code does its thing and downloads. Otherwise
>>>>>>>>>>>>>>>>>>>>>>> there is no download.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> So there has to be a way to ensure that we
>>>>>>>>>>>>>>>>>>>>>>>> won’t download a list again
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> > unless it has actually changed.
>>>>>>>>>>>>>>>>>>>>>>> This should do what you want but I may be
>>>>>>>>>>>>>>>>>>>>>>> missing your point.
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> DNS has a builtin functionality called AXFR.
>>>>>>>>>>>>>>>>>>>>>>>> It simply does the job
>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>> > for you. I was just wondering whether that
>>>>>>>>>>>>>>>>>>>>>>> was not being used.
>>>>>>>>>>>>>>>>>>>>>>> I need to read about AXFR/IXFR and learn a
>>>>>>>>>>>>>>>>>>>>>>> little more.
>>>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>>>> On 3/17/25 5:35 AM, Michael Tremer wrote:
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> Good Morning Jon,
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> On 16 Mar 2025, at 17:00, Jon Murphy
>>>>>>>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>>>>>>>>>>>>>> I was reading through you response again an I
>>>>>>>>>>>>>>>>>>>>>>>>> want to understand this post:
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> I have also stated that we cannot download
>>>>>>>>>>>>>>>>>>>>>>>>>> any lists over HTTPS again and again and
>>>>>>>>>>>>>>>>>>>>>>>>>> again. The implementation that we have here
>>>>>>>>>>>>>>>>>>>>>>>>>> seems to exactly do that and therefore I think
>>>>>>>>>>>>>>>>>>>>>>>>>> that my feedback has been dismissed entirely.
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> So if RPZ doesn't use HTTPS, what is it
>>>>>>>>>>>>>>>>>>>>>>>>> using? I am missing a key point here.
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>> The emphasis is on the repeated downloads of
>>>>>>>>>>>>>>>>>>>>>>>> the same list. That is what cannot happen.
>>>>>>>>>>>>>>>>>>>>>>>> Although it might not affect a lot of people in
>>>>>>>>>>>>>>>>>>>>>>>> our general user-base, there are some that have
>>>>>>>>>>>>>>>>>>>>>>>> a metered connection and will pay for data by
>>>>>>>>>>>>>>>>>>>>>>>> volume. Some of the lists I looked at are just
>>>>>>>>>>>>>>>>>>>>>>>> under 20 MiB. Therefore we need to keep any
>>>>>>>>>>>>>>>>>>>>>>>> traffic down to a minimum. The second reason is
>>>>>>>>>>>>>>>>>>>>>>>> that we have a lot of firewalls out there. Not
>>>>>>>>>>>>>>>>>>>>>>>> all of them will enable this feature and all of
>>>>>>>>>>>>>>>>>>>>>>>> the lists, but even if it is a good chunk, we
>>>>>>>>>>>>>>>>>>>>>>>> will generate terabytes of traffic which put
>>>>>>>>>>>>>>>>>>>>>>>> load on the infrastructure and will cost money.
>>>>>>>>>>>>>>>>>>>>>>>> It simply is not what we want to do, regardless
>>>>>>>>>>>>>>>>>>>>>>>> of self-hosting those lists and pulling them
>>>>>>>>>>>>>>>>>>>>>>>> from somewhere else.
>>>>>>>>>>>>>>>>>>>>>>>> So there has to be a way to ensure that we
>>>>>>>>>>>>>>>>>>>>>>>> won’t download a list again unless it has
>>>>>>>>>>>>>>>>>>>>>>>> actually changed.
>>>>>>>>>>>>>>>>>>>>>>>> DNS has a builtin functionality called AXFR. It
>>>>>>>>>>>>>>>>>>>>>>>> simply does the job for you. I was just
>>>>>>>>>>>>>>>>>>>>>>>> wondering whether that was not being used.
>>>>>>>>>>>>>>>>>>>>>>>> HTTPS is an option because that is simply what
>>>>>>>>>>>>>>>>>>>>>>>> we use elsewhere, but extra functionality will
>>>>>>>>>>>>>>>>>>>>>>>> have to be built for it.
>>>>>>>>>>>>>>>>>>>>>>>> -Michael
>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>>>>>> On 2/13/25 3:34 PM, jon wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>>>>>>>>>>>>>>> I’ve read through your comments a few times
>>>>>>>>>>>>>>>>>>>>>>>>>> and I ended up with many more questions.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> What I rather mean is that it has never
>>>>>>>>>>>>>>>>>>>>>>>>>>> been added as a topic on the agenda and it
>>>>>>>>>>>>>>>>>>>>>>>>>>> has not been pitched by yourself.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> To me the efforts to get new code accepted
>>>>>>>>>>>>>>>>>>>>>>>>>> seem to have changed and it seemed easier in
>>>>>>>>>>>>>>>>>>>>>>>>>> the past. In the past I made the Core Team
>>>>>>>>>>>>>>>>>>>>>>>>>> aware via the Dev Mailing List and wrote a
>>>>>>>>>>>>>>>>>>>>>>>>>> simple two or three paragraphs of "What is
>>>>>>>>>>>>>>>>>>>>>>>>>> it? / What is the value? / Here is the code"
>>>>>>>>>>>>>>>>>>>>>>>>>> So in an effort to move forward: How exactly
>>>>>>>>>>>>>>>>>>>>>>>>>> is something presented to the Core Team?
>>>>>>>>>>>>>>>>>>>>>>>>>> Is there an example of a recent effort that
>>>>>>>>>>>>>>>>>>>>>>>>>> was presented that I can see as a sample?
>>>>>>>>>>>>>>>>>>>>>>>>>> (This type of info can also be added to the Wiki)
>>>>>>>>>>>>>>>>>>>>>>>>>> I understand you want it this way, but I
>>>>>>>>>>>>>>>>>>>>>>>>>> don’t know what exactly is needed. Please be
>>>>>>>>>>>>>>>>>>>>>>>>>> specific.
>>>>>>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>>>>>>> PS - I am not ignoring your other comments, I
>>>>>>>>>>>>>>>>>>>>>>>>>> am just trying to move forward and keep things
>>>>>>>>>>>>>>>>>>>>>>>>>> simple.
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> On Feb 8, 2025, at 1:27 PM, Michael Tremer
>>>>>>>>>>>>>>>>>>>>>>>>>>> <michael.tremer@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello Jon,
>>>>>>>>>>>>>>>>>>>>>>>>>>> Thanks for your reply. And good that you are
>>>>>>>>>>>>>>>>>>>>>>>>>>> copying everyone into this conversation.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 8 Feb 2025, at 18:41, jon
>>>>>>>>>>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Michael,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I think I have covered this all at
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lengths before that this project has been
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> started as a separate effort
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes, this has been a separate effort (a
>>>>>>>>>>>>>>>>>>>>>>>>>>>> very public separate effort). Yes, as you
>>>>>>>>>>>>>>>>>>>>>>>>>>>> pointed this out early on with the "proof-
>>>>>>>>>>>>>>>>>>>>>>>>>>>> of-concept" and then my request for people
>>>>>>>>>>>>>>>>>>>>>>>>>>>> to help test RPZ. Nothing was hidden.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> This was done because you (and maybe
>>>>>>>>>>>>>>>>>>>>>>>>>>>> others) did not have the time and I wanted
>>>>>>>>>>>>>>>>>>>>>>>>>>>> to help and because I needed assistance with
>>>>>>>>>>>>>>>>>>>>>>>>>>>> RPZ. I tried my best to do this without
>>>>>>>>>>>>>>>>>>>>>>>>>>>> bothering you.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> I don’t that it is accurate that nobody
>>>>>>>>>>>>>>>>>>>>>>>>>>> wanted to help on this. The list was always
>>>>>>>>>>>>>>>>>>>>>>>>>>> open - although not every email has been
>>>>>>>>>>>>>>>>>>>>>>>>>>> replied to swiftly it is also your
>>>>>>>>>>>>>>>>>>>>>>>>>>> responsibility to raise a question again if
>>>>>>>>>>>>>>>>>>>>>>>>>>> it was missed. People here have open ears.
>>>>>>>>>>>>>>>>>>>>>>>>>>> It was also stated on this very list on in
>>>>>>>>>>>>>>>>>>>>>>>>>>> our documentation that working on something
>>>>>>>>>>>>>>>>>>>>>>>>>>> without involving the core team is a risky
>>>>>>>>>>>>>>>>>>>>>>>>>>> undertaking. Of course IPFire is free
>>>>>>>>>>>>>>>>>>>>>>>>>>> software and so everyone is free to fork if
>>>>>>>>>>>>>>>>>>>>>>>>>>> they wish to do so.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and as far as I am aware none of the other
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> team members has been involved. This has
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> not been discussed either on this list, on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> our calls.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> You were aware many steps along the way.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> See your email on July 28, 2024, August 15,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2024, September 30, 2024, December 23, 2024,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> and January 16. My attempts to get the team
>>>>>>>>>>>>>>>>>>>>>>>>>>>> involved were met with "things are busy" and
>>>>>>>>>>>>>>>>>>>>>>>>>>>> sometimes silence. (Yes, I get it, people
>>>>>>>>>>>>>>>>>>>>>>>>>>>> are busy.)
>>>>>>>>>>>>>>>>>>>>>>>>>>>> You and Adolf, Leo, Erik and Bernhard have
>>>>>>>>>>>>>>>>>>>>>>>>>>>> been aware since the beginning. You mention
>>>>>>>>>>>>>>>>>>>>>>>>>>>> you were aware of the "proof-of-concept". If
>>>>>>>>>>>>>>>>>>>>>>>>>>>> you include those beginning posts, since Sep
>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2023.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes, I am aware of a proof-of-concept that
>>>>>>>>>>>>>>>>>>>>>>>>>>> I have been running myself for a long time. I
>>>>>>>>>>>>>>>>>>>>>>>>>>> am also aware of the efforts that you have
>>>>>>>>>>>>>>>>>>>>>>>>>>> been taking.
>>>>>>>>>>>>>>>>>>>>>>>>>>> Yet I don’t think there has ever been any
>>>>>>>>>>>>>>>>>>>>>>>>>>> joint effort, or am I seeing that wrong?
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This has not been discussed . . . on our
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> calls.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> On the July 28th you stated:
>>>>>>>>>>>>>>>>>>>>>>>>>>>> "We have talked about RPZ many times on the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> monthly call since the URL filter feature is
>>>>>>>>>>>>>>>>>>>>>>>>>>>> falling more and more out of fashion. I
>>>>>>>>>>>>>>>>>>>>>>>>>>>> think there is also many posts about this on
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the forum."
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please don’t insult me again by stating
>>>>>>>>>>>>>>>>>>>>>>>>>>>> "you know what I mean".
>>>>>>>>>>>>>>>>>>>>>>>>>>>> And it has been discussed but not
>>>>>>>>>>>>>>>>>>>>>>>>>>>> documented in the Monthly Meeting notes.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> I am not at all insulting you. I don’t want
>>>>>>>>>>>>>>>>>>>>>>>>>>> to take this down to a personal level at all.
>>>>>>>>>>>>>>>>>>>>>>>>>>> This is a public mailing list and people who
>>>>>>>>>>>>>>>>>>>>>>>>>>> read this don’t need to listen to an argument
>>>>>>>>>>>>>>>>>>>>>>>>>>> we are having. They are here for the tech
>>>>>>>>>>>>>>>>>>>>>>>>>>> inside IPFire.
>>>>>>>>>>>>>>>>>>>>>>>>>>> When I wrote that it has not been discussed
>>>>>>>>>>>>>>>>>>>>>>>>>>> that does not mean that we have not been
>>>>>>>>>>>>>>>>>>>>>>>>>>> touching on the topic. We have been talking
>>>>>>>>>>>>>>>>>>>>>>>>>>> about lots of things on the calls, the
>>>>>>>>>>>>>>>>>>>>>>>>>>> weather, politics, how our pets are. None of
>>>>>>>>>>>>>>>>>>>>>>>>>>> that makes it to the logs. What I rather mean
>>>>>>>>>>>>>>>>>>>>>>>>>>> is that it has never been added as a topic on
>>>>>>>>>>>>>>>>>>>>>>>>>>> the agenda and it has not been pitched by
>>>>>>>>>>>>>>>>>>>>>>>>>>> yourself.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Instead there has been a separate
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> conversation on the forum with the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> occasional dip here to the list. But that
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> was not a regular two-way conversation.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Regular conversation on the Dev Mailing
>>>>>>>>>>>>>>>>>>>>>>>>>>>> list is many times met with silence. I get
>>>>>>>>>>>>>>>>>>>>>>>>>>>> it, people are busy.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> And regular two-way conversation doesn’t
>>>>>>>>>>>>>>>>>>>>>>>>>>>> happen on the list. At least not with me.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> I’d be happy to point out the posts that
>>>>>>>>>>>>>>>>>>>>>>>>>>>> were met with silence.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Again, I get it, people are busy.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> And you think my emails are not being met
>>>>>>>>>>>>>>>>>>>>>>>>>>> with silence? This has nothing to do with
>>>>>>>>>>>>>>>>>>>>>>>>>>> this specific topic. This has something to do
>>>>>>>>>>>>>>>>>>>>>>>>>>> with how occupied people are and how engaged
>>>>>>>>>>>>>>>>>>>>>>>>>>> they are on certain topics. Not everyone is
>>>>>>>>>>>>>>>>>>>>>>>>>>> involved in all the things and simply will
>>>>>>>>>>>>>>>>>>>>>>>>>>> ignore emails simply based on their subject
>>>>>>>>>>>>>>>>>>>>>>>>>>> line.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> But the "dip here to the list" were my
>>>>>>>>>>>>>>>>>>>>>>>>>>>> attempts to get a conversation started. As I
>>>>>>>>>>>>>>>>>>>>>>>>>>>> said, many time met with silence.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> The only place I was not met with silence
>>>>>>>>>>>>>>>>>>>>>>>>>>>> was on the Community. You have a great group
>>>>>>>>>>>>>>>>>>>>>>>>>>>> of people in the Community. It is a shame
>>>>>>>>>>>>>>>>>>>>>>>>>>>> you don’t want to have others help. It would
>>>>>>>>>>>>>>>>>>>>>>>>>>>> reduce your workload.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> You should stop making statements that are
>>>>>>>>>>>>>>>>>>>>>>>>>>> not true. Who doesn’t want anyone to help?
>>>>>>>>>>>>>>>>>>>>>>>>>>> Not having this conversation on a Saturday
>>>>>>>>>>>>>>>>>>>>>>>>>>> evening would reduce my workload. At least it
>>>>>>>>>>>>>>>>>>>>>>>>>>> would free up time for something else.
>>>>>>>>>>>>>>>>>>>>>>>>>>> Helping with the things that are already on
>>>>>>>>>>>>>>>>>>>>>>>>>>> the go would reduce the workload of the
>>>>>>>>>>>>>>>>>>>>>>>>>>> entire team. Starting one thing at a time and
>>>>>>>>>>>>>>>>>>>>>>>>>>> finishing it is a lot better to manage than
>>>>>>>>>>>>>>>>>>>>>>>>>>> starting a hundred things and not even finish
>>>>>>>>>>>>>>>>>>>>>>>>>>> one. I can tell you that I already have a
>>>>>>>>>>>>>>>>>>>>>>>>>>> hundred things on the go.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Therefore, what am I supposed to do with
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> this email?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> To me it is beyond obvious…
>>>>>>>>>>>>>>>>>>>>>>>>>>>> If it isn’t what you want, then guide me
>>>>>>>>>>>>>>>>>>>>>>>>>>>> with how to do this the correct way. And be
>>>>>>>>>>>>>>>>>>>>>>>>>>>> specific. I am trying to help. I am trying
>>>>>>>>>>>>>>>>>>>>>>>>>>>> to make things better. I am trying to do
>>>>>>>>>>>>>>>>>>>>>>>>>>>> things the right way.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> To me it isn’t. This is yet another project
>>>>>>>>>>>>>>>>>>>>>>>>>>> that has been dumped to the list like so many
>>>>>>>>>>>>>>>>>>>>>>>>>>> before and later on everyone has left to have
>>>>>>>>>>>>>>>>>>>>>>>>>>> the team deal with the rest.
>>>>>>>>>>>>>>>>>>>>>>>>>>> It is a huge patch set. You explained what
>>>>>>>>>>>>>>>>>>>>>>>>>>> the vision is, but that is about it. There is
>>>>>>>>>>>>>>>>>>>>>>>>>>> no chance this will continue if this
>>>>>>>>>>>>>>>>>>>>>>>>>>> disagreement isn’t solved first. I didn’t
>>>>>>>>>>>>>>>>>>>>>>>>>>> even look at the code.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don’t want to merge code that I don’t
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> agree with.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> I asked multiple times if you "agreed with
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the concept" and again, met with silence.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes I get it, people are busy.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Having support for RPZ? Yes, it was
>>>>>>>>>>>>>>>>>>>>>>>>>>> definitely on the roadmap. That I agree with.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> So many fundamental things that I have
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> been raising have either not been discussed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> or outright dismissed.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> You mentioned this a in the past, but for
>>>>>>>>>>>>>>>>>>>>>>>>>>>> some reason you do not disclose what I
>>>>>>>>>>>>>>>>>>>>>>>>>>>> dismissed. Why do you continue to make this
>>>>>>>>>>>>>>>>>>>>>>>>>>>> harder, wouldn’t it not be easier to tell me
>>>>>>>>>>>>>>>>>>>>>>>>>>>> what I have dismissed?
>>>>>>>>>>>>>>>>>>>>>>>>>>>> I have sent multiple emails trying to
>>>>>>>>>>>>>>>>>>>>>>>>>>>> answer your concerns and comments. On July
>>>>>>>>>>>>>>>>>>>>>>>>>>>> 28, Aug 14, Aug 22, Aug 23, Sep 30, etc.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> I’ve gone through all of the questions you
>>>>>>>>>>>>>>>>>>>>>>>>>>>> asked and I cannot find a "dismissed" item.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Maybe I need to be *more clear*. I feel
>>>>>>>>>>>>>>>>>>>>>>>>>>> humoured by this.
>>>>>>>>>>>>>>>>>>>>>>>>>>> It is late on a Saturday and I want my
>>>>>>>>>>>>>>>>>>>>>>>>>>> dinner soon, but certainly I have stated that
>>>>>>>>>>>>>>>>>>>>>>>>>>> this should never be an add-on considering it
>>>>>>>>>>>>>>>>>>>>>>>>>>> is supposed to replace URL Filter. We should
>>>>>>>>>>>>>>>>>>>>>>>>>>> never allow people to add their own sources.
>>>>>>>>>>>>>>>>>>>>>>>>>>> I have also stated that we cannot download
>>>>>>>>>>>>>>>>>>>>>>>>>>> any lists over HTTPS again and again and
>>>>>>>>>>>>>>>>>>>>>>>>>>> again. The implementation that we have here
>>>>>>>>>>>>>>>>>>>>>>>>>>> seems to exactly do that and therefore I
>>>>>>>>>>>>>>>>>>>>>>>>>>> think that my feedback has been dismissed
>>>>>>>>>>>>>>>>>>>>>>>>>>> entirely.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don’t want to merge code that has no
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> future inside IPFire as there is no
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> constructive conversation with the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> maintainers of it.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> The maintainers of Unbound and/or RPZ?
>>>>>>>>>>>>>>>>>>>>>>>>>>>> The maintainers of Hagezi list, the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> threatfox list, the urlhaus list, etc.?
>>>>>>>>>>>>>>>>>>>>>>>>>>>> What else? The maintainers or the RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>> scripts? That is me. Let’s talk!
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> You. I don’t care much about the providers
>>>>>>>>>>>>>>>>>>>>>>>>>>> of the lists.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> See, this is where it gets confusing.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> There are hundreds of open source packages
>>>>>>>>>>>>>>>>>>>>>>>>>>>> as part of IPFire. Pick the last five years
>>>>>>>>>>>>>>>>>>>>>>>>>>>> of items added to the IPFire build. You're
>>>>>>>>>>>>>>>>>>>>>>>>>>>> telling me you have "constructive
>>>>>>>>>>>>>>>>>>>>>>>>>>>> conversation with the maintainers" of all of
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the added packages?
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> They publish their software and they don’t
>>>>>>>>>>>>>>>>>>>>>>>>>>> care whether I am pulling it or not. They
>>>>>>>>>>>>>>>>>>>>>>>>>>> publish it with the commitment to maintain it
>>>>>>>>>>>>>>>>>>>>>>>>>>> - sometimes for better and sometimes for worse.
>>>>>>>>>>>>>>>>>>>>>>>>>>> You care about me pulling your code and I
>>>>>>>>>>>>>>>>>>>>>>>>>>> don’t know whether you would commit to
>>>>>>>>>>>>>>>>>>>>>>>>>>> maintain this.
>>>>>>>>>>>>>>>>>>>>>>>>>>> These two are very different cases.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Pick the IP Blocklists list (i.e.,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> 3CORESEC, ABUSECH, DSHIELD, SPAMHAUS, etc.)
>>>>>>>>>>>>>>>>>>>>>>>>>>>> or the Suricata lists
>>>>>>>>>>>>>>>>>>>>>>>>>>>> (i.e.,Emergingthreats.net <http://
>>>>>>>>>>>>>>>>>>>>>>>>>>>> emergingthreats.net/>,Abuse.ch <http://
>>>>>>>>>>>>>>>>>>>>>>>>>>>> abuse.ch/>, etc.). So you’ve have
>>>>>>>>>>>>>>>>>>>>>>>>>>>> "constructive conversation with the
>>>>>>>>>>>>>>>>>>>>>>>>>>>> maintainers"?
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Yes, occasionally I have phone calls with a
>>>>>>>>>>>>>>>>>>>>>>>>>>> few of these providers.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Having been trying for a long time to make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> you aware of this, nothing of this should
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> come as a surprise.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Ha! Yes a surprise. In the beginning you
>>>>>>>>>>>>>>>>>>>>>>>>>>>> seemed interested as IPFire needed a
>>>>>>>>>>>>>>>>>>>>>>>>>>>> replacement for URL Filter. You asked good
>>>>>>>>>>>>>>>>>>>>>>>>>>>> questions about the lists picked, asked for
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the value to the users, etc. And I answered
>>>>>>>>>>>>>>>>>>>>>>>>>>>> the best I could.
>>>>>>>>>>>>>>>>>>>>>>>>>>>> You even asked: “Why is this realised as an
>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on and not part of the core system?”
>>>>>>>>>>>>>>>>>>>>>>>>>>>> from your Jul 28, 2024 email.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Ah, so, why is the patch creating an add-
>>>>>>>>>>>>>>>>>>>>>>>>>>> on? Not that I am saying that what I say is
>>>>>>>>>>>>>>>>>>>>>>>>>>> law, but it has not been challenged either.
>>>>>>>>>>>>>>>>>>>>>>>>>>> If my input is being ignored, why should I
>>>>>>>>>>>>>>>>>>>>>>>>>>> put this to the top of my list of priorities?
>>>>>>>>>>>>>>>>>>>>>>>>>>> I am not disappointed about this, just trying
>>>>>>>>>>>>>>>>>>>>>>>>>>> to be very good with my time.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> And on January 16, 2025 I wrote a message
>>>>>>>>>>>>>>>>>>>>>>>>>>>> looking for help. And you were kind to
>>>>>>>>>>>>>>>>>>>>>>>>>>>> respond quickly. So in three weeks time,
>>>>>>>>>>>>>>>>>>>>>>>>>>>> since the kind response, something has
>>>>>>>>>>>>>>>>>>>>>>>>>>>> changed. You went from supportive to "this".
>>>>>>>>>>>>>>>>>>>>>>>>>>>> So yes, I am surprised.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Well, maybe I should not have replied to
>>>>>>>>>>>>>>>>>>>>>>>>>>> that email. It was clear that you were on
>>>>>>>>>>>>>>>>>>>>>>>>>>> some path that was not right, but you were
>>>>>>>>>>>>>>>>>>>>>>>>>>> not interested before in finding the right
>>>>>>>>>>>>>>>>>>>>>>>>>>> path from the beginning.
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please consider if that can be changed and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> if there is a path forward with this.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Be more specific, what has to change? What
>>>>>>>>>>>>>>>>>>>>>>>>>>>> exactly did I dismiss?
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>> Dismissal is just my assumption. I don’t
>>>>>>>>>>>>>>>>>>>>>>>>>>> know what you actually did with my feedback.
>>>>>>>>>>>>>>>>>>>>>>>>>>> I can only see the end product that does not
>>>>>>>>>>>>>>>>>>>>>>>>>>> seem contain much of it. Repeatedly I have
>>>>>>>>>>>>>>>>>>>>>>>>>>> been pointing out that we should think before
>>>>>>>>>>>>>>>>>>>>>>>>>>> we build. I am sure a lot of hours have now
>>>>>>>>>>>>>>>>>>>>>>>>>>> gone into some code that simply does not
>>>>>>>>>>>>>>>>>>>>>>>>>>> satisfy me. And I am not not talking about
>>>>>>>>>>>>>>>>>>>>>>>>>>> the code itself, what it does is what I don’t
>>>>>>>>>>>>>>>>>>>>>>>>>>> think is right for us.
>>>>>>>>>>>>>>>>>>>>>>>>>>> The process is very clear for me that we
>>>>>>>>>>>>>>>>>>>>>>>>>>> should first of all think whether we want a
>>>>>>>>>>>>>>>>>>>>>>>>>>> certain feature now. Then there should be a
>>>>>>>>>>>>>>>>>>>>>>>>>>> clear roadmap for everyone to follow; tasks
>>>>>>>>>>>>>>>>>>>>>>>>>>> can be split-up as we go and hopefully then
>>>>>>>>>>>>>>>>>>>>>>>>>>> have something that is maintainable,
>>>>>>>>>>>>>>>>>>>>>>>>>>> interesting for our users and even would do
>>>>>>>>>>>>>>>>>>>>>>>>>>> us proud. This is how this should work.
>>>>>>>>>>>>>>>>>>>>>>>>>>> So, what has to change? I don’t think with
>>>>>>>>>>>>>>>>>>>>>>>>>>> shouting at each other, throwing patches
>>>>>>>>>>>>>>>>>>>>>>>>>>> around and making me generally unhappy is a
>>>>>>>>>>>>>>>>>>>>>>>>>>> good start.
>>>>>>>>>>>>>>>>>>>>>>>>>>> -Michael
>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On Feb 6, 2025, at 2:13 PM, Michael
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Tremer <michael.tremer@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Hello Jon,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Well, here we are again with another patch
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> regarding this feature.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I cannot quite see from your email what
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the question is, but if this is a request
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to have this merged into IPFire, I am once
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> again sorry to disappoint you.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I think I have covered this all at lengths
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> before that this project has been started
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> as a separate effort and as far as I am
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> aware none of the other team members has
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> been involved. This has not been discussed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> either on this list, on our calls. Instead
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> there has been a separate conversation on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the forum with the occasional dip here to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the list. But that was not a regular two-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> way conversation. Therefore, what am I
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> supposed to do with this email?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don’t want to merge code that I don’t
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> agree with. So many fundamental things that
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I have been raising have either not been
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> discussed or outright dismissed.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I don’t want to merge code that has no
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> future inside IPFire as there is no
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> constructive conversation with the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> maintainers of it.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Having been trying for a long time to make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> you aware of this, nothing of this should
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> come as a surprise.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Please consider if that can be changed and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> if there is a path forward with this.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> All the best,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -Michael
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> On 6 Feb 2025, at 16:35, Jon Murphy
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org> wrote:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> What is it?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Response Policy Zone (RPZ) is a mechanism
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to define local policies in a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> standardized way and load those policies
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from external sources.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bottom line: RPZ allows admins to easily
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block access to websites via DNS lookup.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RPZ can block websites via categories.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Examples include: fake websites, annoying
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pop-up ads, newly registered domains, DoH
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bypass sites, bad "host" services,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> maliscious top level domains (e.g.,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *.zip, *.mov), piracy, gambling, pornography,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and more. RPZ lists come from various RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> providers and their available
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> catagories.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> This RPZ add-on enables the RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> functionality by adding a couple lines in a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> configuration file. This add-on simply
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> adds configuration files and adds
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> scripts (config, metrics and sleep) to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> make RPZ easier for the admin to use.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> The RPZ scripts include additional
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> languages: German, Spanish, French, Turkish,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and Italian.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RPZ itself was release in 2010 and has
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> been part of the IPFire build since ~2015.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Why is it needed? What is its value?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - The RPZ concept places this filtering
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> into IPFire, our internet access
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> gateway, which is (should be) solely used
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> as DNS source of the internal network.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - As most sites use HTTPS it makes it
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> difficult to filter traffic with URL
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Filter without also properly configuring
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> conventional (non-transparent)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> mode on the proxy. RPZ is a nice
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> replacement for the URL Filter.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - No need to install and maintain an
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> additional device like PiHole or AdBlock
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> browser extensions on multiple user devices.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - This is an additional layer of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> protection for users. Less worry someone will
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> click on something that gets them into
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> trouble. And, saying this with emphasis,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the ability to do it in one place!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - Blocked sites save on unneeded traffic
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and can lessen the threat of malware
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> in advertisements
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - Logging allows the admin to see the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> site blocked and take actions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - RPZ will be used at the home, home-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> office (work from home), schools,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ministerial, and at the office. Device
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> counts are small (2-6) to medium (~80)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to mediam-large (200+).
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - RPZ can block ads, popups, phishing,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> scammers, spyware, malware, annoying
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> popups, NSFW links, DOH servers, and the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> usual internet trash.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ------------------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Change Log for RPZ add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-1.0.0-18 on 2025-02-05
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - Build for approval & release as IPFire
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.18-18.ipfire on 2025-02-01
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added a mod key to force a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unbound restart
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config and rpz-make:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added action for unbound
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> restart `rpz-config unbound-restart`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-metrics:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - simple reformatting
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - rename far right column from "last
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> update" to "last download"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.17-17.ipfire on 2024-12-09
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected validation regex for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wildcards like: `*.domain.com`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.16-16.ipfire on 2024-11-18
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: updated validation regex
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: moved validation to beginning
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> of process. Now we validate before
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> creating config files.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: use CSS color variables of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the main ipfire theme
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: empty zonefile remarks were
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> stored as “undef” and caused a warning
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: HTML textarea removes the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> first empty line in a custom list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - thank you Leo!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.15-15.ipfire on 2024-11-04
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for Turkish (thank you Peppe)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected empty allow/block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> list issue. An empty allow/block list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> will now remove contents of allow/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block.rpz files and remove unneeded
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allow/block.conf file. (thank you iptom)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.14-14.ipfire on 2024-10-29
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: correct missing rpz extension.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> `rpz-config list` displayed URL
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> incorrectly (thank you Bernhard)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: remove extra `"` in language
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> files (thank you Bernhard)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: slightly dim "apply"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> button when not enabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.13-13.ipfire on 2024-10-27
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - skipped
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.12-12.ipfire on 2024-10-21
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for French (thank you gw-ipfire)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.11-11.ipfire on 2024-10-18
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for Italian (thank you umberto)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for Spanish (thank you Roberto)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.10-10.ipfire on 2024-10-15
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-make:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected validation error for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> a custom list entry (thank you siosios)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - e.g., `*.cloudflare-dns.com`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> install.sh:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: add chown to correct user
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> created files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> update.sh:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: add chown to correct user
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> created files (thank you siosios)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.9-9.ipfire on 2024-10-08
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for German (thank you Leo)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: add missing "rpz exitcode 110"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected missing RPZ menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> item at menu > IPFire
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.8-8.ipfire on 2024-10-04
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - skipped
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.7-7.ipfire on 2024-10-03
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> All:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: includes beta version
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> numbers for pakfire package,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> instead of only `rpz-1.0.0-1.ipfire`, for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> each release.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new WebGUI at `rpz.cgi`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - a BIG thank you to Leo Hofmann for all
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> of his work creating the webgui!!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected missing RPZ menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> item at menu > IPFire
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-make:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: validate entries in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allowlist and blocklist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: add "no-reload" option for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WebGUI
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-metrics:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - new feature: info can be sorted by
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> name, by hit count, by line count, by
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "enabled" list or all lists
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> backups:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: include all files in `/var/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ipfire/dns/rpz` directory in backup
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> update.sh:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected ownership for `/var/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ipfire/dns/rpz` directory during an
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> update
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Build:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - bug fix: `block.rpz.conf` and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> `block.rpz` from build. Files to be created
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> by `rpz-make`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> WebGUI and German language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Leo-Andres Hofmann
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <hofmann@leo-andres.de>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Spanish language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Roberto Peña
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Italian language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Umberto Parma
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> French language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: gw-ipfire
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Turkish language file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Peppe Tech
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Bernhard Bitsch
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <bbitsch@ipfire.org>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Erik Kapfer
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <erik.kapfer@ipfire.org>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Signed-off-by: Jon Murphy
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <jon.murphy@ipfire.org
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/backup/includes/rpz | 4 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/cfgroot/manualpages | 1 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/menu/EX-rpz.menu | 6 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rootfiles/common/configroot | 1 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rootfiles/common/web-user-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> interface | 1 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rootfiles/packages/rpz | 20 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/00-rpz.conf | 10 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-config | 130 +++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-functions | 85 ++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-make | 203 +++++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-metrics | 170 ++++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-sleep | 58 ++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.de.pl | 30 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.en.pl | 30 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.es.pl | 30 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.fr.pl | 30 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.it.pl | 30 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.tr.pl | 30 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> html/cgi-bin/rpz.cgi | 923 ++++++++++++++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++++++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lfs/rpz | 96 +++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> make.sh | 3 +-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/install.sh | 36 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/uninstall.sh | 38 +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/update.sh | 52 ++
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 24 files changed, 2016 insertions(+), 1
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> deletion(-)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/backup/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> includes/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/menu/EX-rpz.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rootfiles/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> packages/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/00-rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz-functions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100755 config/rpz/rpz-metrics
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100755 config/rpz/rpz-sleep
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.de.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.en.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.es.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.fr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.it.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.tr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 html/cgi-bin/rpz.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 lfs/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 src/paks/rpz/install.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 src/paks/rpz/uninstall.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 src/paks/rpz/update.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/backup/includes/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> b/config/backup/includes/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..36513e494
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/backup/includes/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,4 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/var/ipfire/dns/rpz/*
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/unbound/zonefiles/allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/unbound/zonefiles/block.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/unbound/local.d/*rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/cfgroot/manualpages
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> b/config/cfgroot/manualpages
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 1f7e01efc..d3a48c633 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- a/config/cfgroot/manualpages
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/cfgroot/manualpages
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -70,6 +70,7 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pakfire.cgi=configuration/ipfire/pakfire
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wlanap.cgi=addons/wireless
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> tor.cgi=addons/tor
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> samba.cgi=addons/samba
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpz.cgi=addons/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> # Logs menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> logs.cgi/summary.dat=configuration/logs/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> summary
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/menu/EX-rpz.menu b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/menu/EX-rpz.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..2f4daf410
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/menu/EX-rpz.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,6 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +$subipfire->{'20.rpz'} = {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'caption' => $Lang::tr{'rpz'},
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'uri' => '/cgi-bin/rpz.cgi',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'title' => "RPZ",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'enabled' => 1,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rootfiles/common/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> configroot b/config/rootfiles/common/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> configroot
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 9839eee45..b30d6aae4 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- a/config/rootfiles/common/configroot
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rootfiles/common/configroot
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -120,6 +120,7 @@ var/ipfire/menu.d/70-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> log.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-apcupsd.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-guardian.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-mympd.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#var/ipfire/menu.d/EX-rpz.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-samba.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-tor.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-transmission.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rootfiles/common/web-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> user-interface b/config/rootfiles/common/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> web-user-interface
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 816241dae..e00464076 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- a/config/rootfiles/common/web-user-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> interface
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rootfiles/common/web-user-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> interface
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -69,6 +69,7 @@ srv/web/ipfire/cgi-bin/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> proxy.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/qos.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/remote.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/routing.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#srv/web/ipfire/cgi-bin/rpz.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #srv/web/ipfire/cgi-bin/samba.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/services.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/shutdown.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rootfiles/packages/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz b/config/rootfiles/packages/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..1c8663049
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rootfiles/packages/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,20 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +etc/unbound/local.d/00-rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +etc/unbound/zonefiles
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +etc/unbound/zonefiles/allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-functions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-metrics
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-sleep
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.de.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.en.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.es.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.fr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.it.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.tr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/backup/addons/includes/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/dns/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/dns/rpz/allowlist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/dns/rpz/blocklist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/menu.d/EX-rpz.menu
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +srv/web/ipfire/cgi-bin/rpz.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/00-rpz.conf b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/00-rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..f005a4f2e
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/00-rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,10 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +server:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + module-config: "respip validator iterator"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpz:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + name: allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + zonefile: /etc/unbound/zonefiles/allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-action-override: passthru
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-log: yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-log-name: allow
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-signal-nxdomain-ra: yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-config b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..c72d50f9b
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,130 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024-2025 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +version="2025-01-11 - v44"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +source /usr/sbin/rpz-functions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Main ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +tagName="unbound"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzAction="${1}" # input RPZ action
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzName="${2}" # input RPZ name
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzURL="${3}" # input RPZ URL
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzOption1="${4}" # input RPZ option #1
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzOption2="${5}" # input RPZ option #2
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzConfig="/etc/unbound/local.d/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${rpzName}.rpz.conf" # output zone conf file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzFile="/etc/unbound/zonefiles/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${rpzName}.rpz" # output for RPZ file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzLog="yes" # log default is yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +ucReload="yes" # reload default is yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +while [[ $# -gt 0 ]] ; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + case "$1" in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --no-log ) rpzLog="no" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --no-reload ) ucReload="no" ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> checkConf="no" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + esac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + shift # Shift after checking all the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> cases to get next option
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +done
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +case "${rpzAction}" in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # add new rpz list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + add )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + check_name "${rpzName}" # is this a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid name?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # does this config already exist? If
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> yes, then exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ -f "${rpzConfig}" ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: duplicate -
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${rpzConfig} already exists. exit"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 104
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # is this a valid URL?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + regex='^https://[-[:alnum:]\+&@#/%?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> =~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if ! [[ "${rpzURL}" =~ $regex ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: the URL is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid: \"${rpzURL}\". exit."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 105
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # create the zone config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo "rpz:"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " name: ${rpzName}.rpz"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " zonefile: ${rpzFile}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " url: ${rpzURL}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-action-override: nxdomain"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-log: ${rpzLog}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-log-name: ${rpzName}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-signal-nxdomain-ra: yes"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } > "${rpzConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # create an empty rpz file if it does
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> not exist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ ! -f "${rpzFile}" ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + touch "${rpzFile}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # unbound requires these settings for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${rpzFile}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${rpzConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # trash config file & rpz file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + remove )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if ! [[ -f "${rpzConfig}" ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: cannot remove
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${rpzConfig}, does not exist. exit"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 106
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: remove config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> & rpz file \"${rpzName}\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rm "${rpzConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rm "${rpzFile}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + reload )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + list )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + awk -F':' '/^\s*name:/{ gsub(/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [[:blank:]]|\.rpz/, "",$2) ; NAME=$2 } \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /^\s*url:/{ gsub(/[[:blank:]]/, "") ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> print NAME"="$2":"$3} ' \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/local.d/*rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unbound-restart )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unbound_restart
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: missing or
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> incorrect parameter"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "Usage: $(basename "$0")
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <ACTION> <NAME> <URL> <OPTION> <OPTION>\n"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "Version: ${version}\n"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 108
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +esac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +unbound_control_reload "${ucReload}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-functions b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-functions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..ace1d2690
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-functions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,85 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +version="2024-12-10 - v02"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +msg_log () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + logger --tag "${tagName}" "$*"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if tty --silent ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo "${tagName}:" "$*"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# check for a valid name
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +check_name () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theName="${1}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + regex='^[a-zA-Z0-9_]+$' # no dash or
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> plus, alpha numeric only
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + regex1='^(allow|block)$' # allow and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block are reserved NAMEs
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ ! "${theName}" =~ $regex ]] ||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [[ "${theName}" =~ $regex1 ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: the NAME is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid: \"${theName}\". exit."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 101
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +set_permissions () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chown nobody:nobody "$@"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chmod 644 "$@"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +check_unbound_conf () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local thecheckConf="${1:-yes}" # check
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config default is yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # check the above config files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ "${thecheckConf}" == yes ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: check for errors
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> with \"unbound-checkconf\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if ! unbound-checkconf ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> found invalid configuration."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + "error: rpz: In Terminal run the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> command \"unbound-checkconf\" for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> information. exit."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 102
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +unbound_control_reload () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theReload="${1:-yes}" # reload
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> default is yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ "${theReload}" == yes ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # reload due to the changes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: run \"unbound-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> control reload\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if ! unbound-control reload ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload. exit."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 109
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +unbound_restart () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # restart due to the changes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: run \"unbound
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> restart\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /usr/local/bin/unboundctrl restart
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-make b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..927d55170
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-make
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,203 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024-2025 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +version="2025-01-11 - v14"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +source /usr/sbin/rpz-functions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# create the config file for allow
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +make_allow_config () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theLog="${1:-yes}" # log default ON
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theConfig="/etc/unbound/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> local.d/00-rpz.conf" # output zone conf file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theList="/var/ipfire/dns/rpz/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allowlist" # input custom list of domains
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: make config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \"00-rpz.conf\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo "server:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + module-config: \"respip validator
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> iterator\"" > "${theConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # does allow list exist?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ -s "${theList}" ]] && grep -q .
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${theList}" ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo "rpz:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + name: allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + zonefile: /etc/unbound/zonefiles/allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-action-override: passthru
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-log: ${theLog}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-log-name: allow
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-signal-nxdomain-ra: yes" >>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${theConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile - unbound requires
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> these settings for rpz files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# create the config file for block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +make_block_config () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theLog="${1:-yes}" # log default ON
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theConfig="/etc/unbound/local.d/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block.rpz.conf" # output zone conf file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theList="/var/ipfire/dns/rpz/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> blocklist" # input custom list of domains
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: make config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \"block.rpz.conf\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # does block list exist?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ -s "${theList}" ]] && grep -q .
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${theList}" ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo "rpz:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + name: block.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + zonefile: /etc/unbound/zonefiles/block.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-action-override: nxdomain
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-log: ${theLog}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-log-name: block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rpz-signal-nxdomain-ra: yes" >
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${theConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile - unbound requires
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> these settings for rpz files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theConfig}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # no - trash the config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rm --verbose /etc/unbound/local.d/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block.rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# create an RPZ file for allow or block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +make_rpz_file () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theName="${1}" # allow or block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theAction='.' # the default is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nxdomain or block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local actionList
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theList="/var/ipfire/dns/rpz/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theName}list" # input custom list of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domains
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theZonefile="/etc/unbound/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> zonefiles/${theName}.rpz" # output file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # does a list exist?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ -s "${theList}" ]] && grep -q .
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${theList}" ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # for allow set to passthru
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + [[ "${theName}" == allow ]] &&
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> theAction='rpz-passthru.'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # drop any extra "blanks" and add
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "CNAME <RPZ action>." to each line
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + actionList=$( awk '{$1=$1};1'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${theList}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + sed "/^[^;].*[[:alnum:]]/ s|$| CNAME
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theAction}|" )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: create zonefile for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \"${theName}list\""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +echo "; Name: ${theName} list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +; Last modified: $(date "+%Y-%m-%d at
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %H.%M.%S %Z")
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +; domains with actions list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +${actionList}" > "${theZonefile}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile - unbound requires
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> these settings for rpz files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theZonefile}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # set-up allow/block list files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theList}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: the ${theList} is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> empty."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + rm --verbose "${theZonefile}" # trash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the RPZ file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# check if allow/block list is valid
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +validate_list () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theName="${1}" # allow or block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + local theList="/var/ipfire/dns/rpz/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theName}list" # input custom list of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domains
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # remove good:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # - properly formated domain names with
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> or without leading wildcard
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # - properly formated top level domain
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (TLD) names with wildcard
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # - blank lines and comment lines
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # remaining lines are considered "bad"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + bad_lines=$( sed --regexp-extended \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + '/^(\*\.)?([a-zA-Z0-9](([a-zA-Z0-9\-])
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {0,61}[a-zA-Z0-9])?\.)+([a-zA-Z]{2,}|xn--
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])$/d ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /^(\*\.)([a-z]{2,61}|xn--[a-z0-9]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {1,60})$/d ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /^$/d ; /^;/d' "${theList}" )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ ! -z "${bad_lines}" ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: invalid line(s) in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theList}."
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "%s\n" "bad line(s): ${bad_lines}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 110
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Main ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +tagName="unbound"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzName="${1}" # input RPZ name
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzLog="yes" # log default is yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +ucReload="yes" # reload default is yes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +while [[ $# -gt 0 ]] ; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + case "$1" in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --no-log ) rpzLog="no" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --no-reload ) ucReload="no" ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> checkConf="no" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + esac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + shift # Shift after checking all the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> cases to get next option
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +done
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +case "${rpzName}" in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # make a new allow or block rpz file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + allow )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + validate_list 'allow' # is the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allowlist valid?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + make_allow_config "${rpzLog}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + make_rpz_file 'allow'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + allowblock )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + validate_list 'allow' # is the list valid?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + make_allow_config "${rpzLog}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + make_rpz_file 'allow'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;&
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + block )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + validate_list 'block' # is the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> blocklist valid?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + make_block_config "${rpzLog}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + make_rpz_file 'block'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + reload )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unbound-restart )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unbound_restart
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: missing or
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> incorrect parameter"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "Usage: $(basename "$0") <NAME>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <OPTION> <OPTION>\n"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "Version: ${version}\n"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit 108
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +esac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +unbound_control_reload "${ucReload}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-metrics b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-metrics
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100755
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..4d43e1629
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-metrics
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,170 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +version="2025-01-20 - v25"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Main ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +weeks="2" # default to two message logs
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sortBy="name" # default "by name"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzActive="enabled" # default "enabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> only"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +while [[ $# -gt 0 ]] ; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + case "$1" in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --by-names | --by-name | name )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sortBy="name" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --by-hits | --by-hit | hits | hit )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sortBy="hit" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --by-lines | --by-line | lines | line )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sortBy="line" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --by-effect ) sortBy="effect" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --enabled-only ) rpzActive="enabled" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --active-all | --all | all )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpzActive="all" ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + [0-9] | [0-9][0-9] ) weeks=$1 ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + esac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + shift # Shift after checking all the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> cases to get next option
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +done
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get the list of message logs for N weeks
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +messageLogs=$( find /var/log/messages* -
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> type f | sort --version-sort |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + head -"${weeks}" )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get the list of RPZ names & counts
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from the message log(s)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzNameCount=$( for logf in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${messageLogs} ; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + zgrep --text --fixed-strings 'info:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz: applied' "${logf}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + awk '$10 ~ /\[\w*]/ { print $10 }' ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + done | sort | uniq --count )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# flip results and remove brackets `[`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> and `]`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzNameCount=$( echo "${rpzNameCount}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + awk '{ print $2, $1 }' |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + sed --regexp-extended 's|^\[(.*)\]|\1|' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# grab only names
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzNames=$( echo "${rpzNameCount}" | awk
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '{ print $1 }' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get list of RPZ files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzFileList=$( find /etc/unbound/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> zonefiles -type f -iname "*.rpz" )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get basename of those files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzBaseNames=$( echo "${rpzFileList}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + sed 's|/etc/unbound/zonefiles/||g ; s|
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \.rpz||g ;' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# add to rpzNames
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzNames="${rpzNames}"$'\n'"${rpzBaseNames}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# drop duplicate names
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +rpzNames=$( echo "${rpzNames}" | sort --
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unique )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get line count for each RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +lineCount=$( echo "${rpzFileList}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> xargs wc -l )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get comment line count and blank line
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> count for each RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +commentCount=$( echo "${rpzFileList}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> xargs grep --count -e "^$" -e "^;" )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get modified date each RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +modDateList=$( echo "${rpzFileList}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> xargs stat -c '%.10y %n' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +ucListAuthZones=$( unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> list_auth_zones )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# get width of RPZ names
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +pWidth=$( echo "${rpzNames}" | awk
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '{ print $1" " }' | wc -L )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +pFormat="%-${pWidth}s %-8s %-8s %8s %12s
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %12s\n"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# print title line
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +printf "${pFormat}" "name" "hits"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "active" "lines" " hits/line" "last download"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +printf -- "--------------"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +theResults=""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +totalLines=0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +totalHits=0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +while read -r theName
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf -- "--" # pretend progress bar
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # is this RPZ list active?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theActive="disabled"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if grep --quiet "^${theName}\.rpz" <<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${ucListAuthZones}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theActive="enabled"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + else
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + [[ "${rpzActive}" == enabled ]] &&
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> continue
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # get hit count
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theHits="0"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if output=$( grep "^${theName}\s" <<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${rpzNameCount}" ) ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theHits=$( echo "${output}" | awk
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '{ print $2 }' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + totalHits=$(( totalHits + theHits ))
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # get line count
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theLines="n/a"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + hitsPerLine="0"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if output=$( grep --fixed-strings "/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theName}.rpz" <<< "${lineCount}" ) ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theLines=$( echo "${output}" | awk
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '{ print $1 }' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + totalLines=$(( totalLines + theLines ))
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if [[ "${theLines}" -gt 2 ]] ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + hitsPerLine=$(( 100 * theHits /
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> theLines ))
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # get modification date
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theModDate="n/a"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if output=$( grep --fixed-strings "/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theName}.rpz" <<< "${modDateList}" ) ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theModDate=$( echo "${output}" | awk
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '{ print $1 }' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # add to results list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + theResults+="${theName} ${theHits}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theActive} ${theLines} ${hitsPerLine}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${theModDate}"$'\n'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +done <<< "${rpzNames}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +case "${sortBy}" in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "name"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + name) sortArg=(-k3,3r -k1,1) ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "hits" then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> by "name"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + hit) sortArg=(-k3,3r -k2,2nr -k1,1) ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "lines" then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> by "name"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + line) sortArg=(-k3,3r -k4,4nr -k1,1) ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "effect"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> then by "name"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + effect) sortArg=(-k3,3r -k5,5nr -k1,1) ;;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +esac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +printf -- "--------------\n"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# remove blank lines, sort, print as
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> columns
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +echo "${theResults}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + awk '!/^[[:space:]]*$/' |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + sort "${sortArg[@]}" |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + awk --assign=width="${pWidth}" \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + '{ printf "%-*s %-8s %-8s %8s %10s %%
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %12s\n", width, $1, $2, $3, $4, $5, $6 }'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +printf "${pFormat}" "" "=======" ""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "========" "" ""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +printf "${pFormat}" "Totals -->"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${totalHits}" "" "${totalLines}" "" ""
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-sleep b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-sleep
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100755
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..dd3603599
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-sleep
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,58 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +version="2024-08-16" # v05
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# send message to message log
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +msg_log () {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + logger --tag "${tagName}" "$*"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if tty --silent ; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + echo "${tagName}:" "$*"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +############### Main ###############
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +tagName="unbound"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sleepTime="${1:-5m}" # default to sleep
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for 5m (5 minutes)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +zoneList=$( unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> list_auth_zones | awk '{print $1}' )
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +for zone in ${zoneList} ; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "disable ${zone}\t"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unbound-control rpz_disable "${zone}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +done
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +msg_log "info: rpz: disabled all zones
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for ${sleepTime}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sleep "${sleepTime}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +for zone in ${zoneList} ; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + printf "enable ${zone}\t"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unbound-control rpz_enable "${zone}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +done
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +msg_log "info: rpz: enabled all zones"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +exit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.de.pl b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.de.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..3770c6bb0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.de.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +%tr = (%tr,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz' => 'Response Policy Zones (RPZ)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' => 'Übernehmen',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'Benutzerdefinierte Allowlist aktivieren:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' => 'Zugelassene
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Domains (eine pro Zeile)<br>Beispiel:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' => 'Benutzerdefinierte
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Allowlist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'Benutzerdefinierte Blocklist aktivieren:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' => 'Gesperrte
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Domains (eine pro Zeile)<br>Beispiel:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' => 'Benutzerdefinierte
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Blocklist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' => 'Benutzerdefinierte Listen',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' => 'Der Name enthält
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unzulässige Zeichen',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' => 'unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hat eine fehlerhafte Konfiguration
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ermittelt. Führen Sie das Kommando
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unbound-checkconf auf der Konsole aus, um
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> weitere Informationen zu erhalten.',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' => 'Die
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> benutzerdefinierte Allow-/Blocklist ist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> leer',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' => 'Ein Eintrag mit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> identischem Namen existiert bereits',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' => 'Die URL ist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ungültig',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' => 'Eintrag kann
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nicht entfernt werden, der Name existiert
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nicht',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' => 'Der Name ist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ungültig - nur "allow" oder "block" möglich',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' => 'Fehlende oder
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> inkorrekte Parameter',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' => 'unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload ist fehlgeschlagen',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' => 'Die
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> benutzerdefinierte Allow-/Blocklist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> enthält unzulässige Einträge',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' => 'Die Anmerkung
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> enthält unzulässige Zeichen',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' => 'Ungültiger
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Eintrag in der benutzerdefinierten
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Allowlist, Zeile ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' => 'Ungültiger
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Eintrag in der benutzerdefinierten
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Blocklist, Zeile ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' => 'Ausgewählter
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Eintrag existiert nicht: ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' => 'Zonendatei-Eintrag
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bearbeiten',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' => '(importiert aus
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' => 'Erlaubte
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Zeichen sind a-z, A-Z, 0-9 und Unterstriche',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' => 'Zonendateien',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.en.pl b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.en.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..0720a8940
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.en.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +%tr = (%tr,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz' => 'Response Policy Zones (RPZ)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' => 'Apply',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' => 'Enable custom
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allowlist:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' => 'Allowed domains
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (one per line)<br>Example: domain.com,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' => 'Custom allowlist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' => 'Enable custom
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> blocklist:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' => 'Blocked domains
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (one per line)<br>Example: domain.com,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' => 'Custom blocklist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' => 'Custom lists',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' => 'the NAME is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' => 'unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> found invalid configuration. In the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Terminal run the command unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for more information',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' => 'the allow/block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> list is empty',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' => 'duplicate - NAME
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> already exists',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' => 'the URL is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' => 'cannot remove the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAME does not exist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' => 'the NAME is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid - "allow" or "block" only',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' => 'missing or
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> incorrect parameter',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' => 'unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload failed',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' => 'custom Allowlist/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Blocklist contains invalid entries',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' => 'the REMARK is not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valid',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' => 'invalid entry in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allowlist, line ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' => 'invalid entry in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> blocklist, line ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' => 'Selected entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> does not exist: ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' => 'Edit zonefiles entry',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' => '(imported from
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' => 'Valid
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> characters are a-z, A-Z, 0-9 and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> underscore.',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' => 'Zonefiles',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.es.pl b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.es.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..98628e4aa
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.es.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +%tr = (%tr,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz' => 'Zonas de política de respuesta
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (RPZ)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' => 'Aplicar',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' => 'Habilitar la
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lista blanca personalizada:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' => 'Dominio
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> permitido (uno por línea)<br>Ejemplo:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' => 'Lista blanca
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> personalizada',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' => 'Habilitar la
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lista negra personalizada:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' => 'Dominio
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bloqueado (uno por línea)<br>Ejemplo:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' => 'Lista negra
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> personalizada',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' => 'Lista personalizada',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' => 'El NOMBRE no es
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> válido',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' => 'unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ha encontrado una configuración no válida.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Desde Terminal, ejecute el comando
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unbound-checkconf para mayor información',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' => 'La lista de
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> permitidos/bloqueados está vacía',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' => 'duplicado -
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NOMBRE ya existe',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' => 'la URL no es
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> válida',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' => 'no es posible
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> eliminar el NOMBRE que no existe',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' => 'el NOMBRE no es
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> válido - sólo "permitir" o "bloquear"',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' => 'parámetro
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> faltante o incorrecto',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' => 'Error al recargar
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unbound-control',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' => 'la Lista blanca/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Lista negra personalizada contiene
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entradas no válidas',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' => 'el COMENTARIO no
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> es válido',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' => 'entrada no válida
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> en la lista blanca, línea ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' => 'entrada no válida
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> en la lista negra, línea ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' => 'La entrada
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> seleccionada no existe: ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' => 'Editar la entrada de
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> archivos de zona',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' => '(importado de rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' => 'Los caracteres
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> válidos son a-z, A-Z, 0-9 y guión bajo',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' => 'Archivos de zona',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.fr.pl b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.fr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..f35f3c2d0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.fr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +%tr = (%tr,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz' => 'Response Policy Zones (RPZ)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' => 'Appliquer',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' => 'Activer la
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> liste d\'autorisations personnalisée:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' => 'Domaines
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> autorisés (un par ligne)<br>Example:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' => 'Liste
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> d\'autorisations personnalisée',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' => 'Activer la
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> liste de blocage personnalisée:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' => 'Domaines bloqués
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (un par ligne)<br>Example: domain.com,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' => 'liste de blocage
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> personnalisé',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' => 'Listes personnalisées',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' => 'le NOM n\'est pas
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valide',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' => 'unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> configuration non valide trouvée. Dans le
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> terminal, exécutez la commande unbound-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> checkconf pour plus d\'informations',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' => 'la liste
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> autoriser/bloquer est vide',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' => 'le NOM existe déjà',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' => 'L\'URL n\'est pas
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valide',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' => 'impossible de
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> supprimer le NOM n\'existe pas',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' => 'le NOM n\'est pas
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valide - « autoriser » ou « bloquer »
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> seulement',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' => 'paramètre
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> manquant ou incorrect',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' => 'unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rechargement échoué',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' => 'la liste
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> autoriser/bloquer contient des entrées non
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valides',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' => 'la REMARQUE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> n\'est pas valable',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' => 'entrée non valide
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dans la liste d\'autorisation, ligne ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' => 'entrée non valide
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dans la liste de blocs, ligne ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' => 'L\'entrée
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sélectionnée n\'existe pas: ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' => 'Modifier l\'entrée
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Fichiers Zone',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' => '(importé de rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' => 'Les caractères
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valides sont a-z, A-Z, 0-9 et soulignement.',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' => 'Fichiers Zone',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.it.pl b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.it.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..ee81605c9
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.it.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> add-on
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +%tr = (%tr,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz' => 'Response Policy Zones (RPZ)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' => 'Applica',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' => 'Abilita la
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Whitelist personalizzata:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' => 'Domini
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> consentiti (uno per riga)<br>Esempio:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' => 'Whitelist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> personalizzata',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' => 'Abilita la
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Blacklist personalizzata:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' => 'Domini bloccati
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (uno per riga)<br>Esempio: domain.com,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' => 'Blacklist
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> personalizzata',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' => 'Liste personalizzate',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' => 'il NOME non è
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valido',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' => 'unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ha trovato una configurazione non valida.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Dal Terminale esegui il comando unbound-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> checkconf per maggiori informazioni',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' => 'l\'elenco
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> consentiti/bloccati è vuoto',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' => 'duplicato - NAME
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> esiste di già',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' => 'l\'URL non è
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valido',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' => 'non è possibile
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rimuovere il NOME non esiste',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' => 'il NOME non è
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valido - solo "consenti" o "blocca"',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' => 'parametro
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> mancante o non corretto',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' => 'ricaricamento del
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> controllo non associato non riuscito',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' => 'la Whitelist/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Blacklist personalizzata contiene voci non
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> valide',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' => 'l"OSSERVAZIONE
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> non è valida',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' => 'voce non valida
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nella Whitelist, riga ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' => 'voce non valida
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nella Blacklist, riga ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' => 'La voce
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> selezionata non esiste: ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' => 'Modifica la voce dei
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> file di zona',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' => '(importato da rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' => 'I caratteri
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> validi sono a-z, A-Z, 0-9 e trattino basso',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' => 'Zonefiles',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.tr.pl b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.tr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..00226e192
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.tr.pl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# I�in eklendi Ayriyeten Response Policy
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Zone (RPZ)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +%tr = (%tr,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz' => 'Response Policy Zones (RPZ)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' => 'Uygulamak',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' => '�zel
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Etkinlestir allowlist:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' => 'Izin verilmis
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domains (satir basina bir)<br>�rnegin:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' => 'Etkinlestir allowlist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' => '�zel
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Etkinlestir blocklist:',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' => 'Engellenmis
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domains (satir basina bir)<br>�rnegin:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> domain.com, *.domain.com',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' => 'Engellenmis blocklist',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' => 'Engellenmis lists',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' => 'NAME ge�erli degil',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' => 'unbound-checkconf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ge�ersiz yapilandirma bulundu. Terminalde
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> daha fazla bilgi i�in Unbound-checkConf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> komutunu �alistirin',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' => 'allow/block liste
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> bos',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' => 'kopyalamak - NAME
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> zaten var',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' => 'URL ge�erli degil',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' => '�ikarilamiyor
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAME yok',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' => 'NAME ge�erli
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> degil - "allow" veya "block" yalniz',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' => 'Parametre eksik
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> veya yanlis',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' => 'unbound-control
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> basarisiz',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' => 'Engellenmis
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Allowlist/Blocklist ge�ersiz girisler
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> i�erir',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' => 'REMARK ge�erli
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> degil',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' => 'Ge�ersiz giris
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allowlist, line ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' => 'Ge�ersiz giris
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> blocklist, line ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' => 'Se�ilen giris
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> yok: ',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' => 'yazimlamak zonefiles
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> giris',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' => '(ithal edildi rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config)',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' => 'Ge�erli
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> karakterler a-z, A-Z, 0-9ve alt�st.',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' => 'Zonefiles',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/html/cgi-bin/rpz.cgi b/html/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> cgi-bin/rpz.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..a821c92ac
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/html/cgi-bin/rpz.cgi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,923 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/usr/bin/perl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2005-2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +use strict;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +use Scalar::Util qw(looks_like_number);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# debugging
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#use warnings;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#use CGI::Carp 'fatalsToBrowser';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#use Data::Dumper;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +require '/var/ipfire/general-functions.pl';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +require "${General::swroot}/lang.pl";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +require "${General::swroot}/header.pl";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Extra HTML ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $extraHead = <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<style>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /* alternating row background */
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + .tbl tr:nth-child(2n+2) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + background-color: var(--color-light-grey);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + .tbl tr:nth-child(2n+3) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + background-color: var(--color-grey);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /* text styles */
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + .tbl th:not(:last-child) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + text-align: left;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + div.right {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + text-align: right;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + margin-top: 0.5em;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /* customlist input */
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + textarea.domainlist {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + margin: 0.5em 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + resize: vertical;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + min-height: 10em;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + overflow: auto;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + white-space: pre;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + button[type=submit]:disabled {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + opacity: 0.6;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</style>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- End of extra HTML ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +### Settings ###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Request DNS service reload after
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> configuration change
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $RPZ_RELOAD_FLAG =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${General::swroot}/dns/rpz/reload.flag";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Configuration file for all available
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> zonefiles
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Format: index, name (unique), enabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (on/off), URL, remark
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $ZONEFILES_CONF =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${General::swroot}/dns/rpz/zonefiles.conf";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Configuration file for custom lists
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IDs: 0=allowlist, 1=blocklist,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2=options (allow/block enabled)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $CUSTOMLISTS_CONF =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${General::swroot}/dns/rpz/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> customlists.conf";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Export custom lists to rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $RPZ_ALLOWLIST = "${General::swroot}/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dns/rpz/allowlist";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $RPZ_BLOCKLIST = "${General::swroot}/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dns/rpz/blocklist";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +### Preparation ###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Create missing config files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +unless(-f $ZONEFILES_CONF)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> { &General::system('touch',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "$ZONEFILES_CONF"); }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +unless(-f $CUSTOMLISTS_CONF)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> { &General::system('touch',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "$CUSTOMLISTS_CONF"); }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +## Global gui data
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $errormessage = "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +## Global configuration data
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my %zonefiles = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my %customlists = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&_zonefiles_load();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&_customlists_load();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +## Global CGI form data
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my %cgiparams = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&Header::getcgihash(\%cgiparams);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $action = $cgiparams{'ACTION'} //
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +my $action_key = $cgiparams{'KEY'} //
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ''; # entry being edited, empty = none/new
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Process form actions ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Zonefiles action: Check whether the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> requested entry exists
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +if((substr($action, 0, 3) eq 'ZF_') &&
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ($action_key)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unless(defined $zonefiles{$action_key}) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $errormessage = &_rpz_error_tr(204,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $action_key);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +## Perform actions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +if($action eq 'ZF_SAVE') { ## Save new
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> or modified zonefiles entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_zf_save()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE'; # success, return to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> main page
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'ZF_EDIT'; # error occured,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> keep editing
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'ZF_TOGGLE') { ##
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Toggle on/off
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_zf_toggle()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'ZF_REMOVE') { ##
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Remove entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_zf_remove()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'CL_SAVE') { ## Save
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> custom lists
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_cl_save()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'RPZ_RELOAD') { ##
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Reload dns configuration
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_rpz_reload()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'UNB_RESTART') { ##
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Restart unbound service
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_unb_restart()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action = 'NONE';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Start GUI ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +## Start http output
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&Header::showhttpheaders();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Start HTML
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&Header::openpage($Lang::tr{'rpz'}, 1,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $extraHead);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&Header::openbigbox('100%', 'left', '');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Show error messages
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +if($errormessage) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_print_message($errormessage);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Handle zonefile add/edit mode
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +if($action eq "ZF_EDIT") {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_print_zonefile_editor();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Finalize page and exit cleanly
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebigbox();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::closepage();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + exit(0);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Show gui elements
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&_print_zonefiles();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&_print_customlists();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&_print_gui_extras();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&Header::closebigbox();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +&Header::closepage();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- End of GUI ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal configuration file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> functions ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Load all available zonefiles from rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config and the internal configuration
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _zonefiles_load {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Clean start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + %zonefiles = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Source 1: Get the currently enabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> zonefiles from rpz-config (expected format
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [name]=[URL])
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my @enabled_files =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &General::system_output('/usr/sbin/rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> config', 'list');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $row (@enabled_files) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chomp($row);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Use regex instead of split() to skip
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> non-matching lines
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + next unless($row =~ /^(\w+)=(.+)$/);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($name, $url) = ($1, $2);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Unique names are already guaranteed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> by rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_rpz_validate_zonefile($name, $url,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '', 0) == 0) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Populate global data hash, mark all
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> found entries as enabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %entry = ('enabled' => 'on',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'url' => $url,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'remark' => $Lang::tr{'rpz zf imported'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name} = \%entry;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Source 2: Get additional data and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> disabled entries from configuration file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %configured_files = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &General::readhasharray($ZONEFILES_CONF, \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %configured_files);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $row (values
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (%configured_files)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($name, $enabled, $url, $remark) =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @$row;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $remark //= "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + next unless($name);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Check whether this row belongs to an
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entry already imported from rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(defined $zonefiles{$name}) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Existing entry, only merge additional
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> data
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'remark'} = $remark;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Skip entry if it is marked as enabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> but not found by rpz-config. It was then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> deleted manually
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($enabled ne 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Populate global data hash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %entry = ('enabled' => 'off',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'url' => $url // "",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'remark' => $remark);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name} = \%entry;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Save internal zonefiles configuration
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _zonefiles_save_conf {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $index = 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %export = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Loop trough all zonefiles and create
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "hasharray" type export
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $name (keys %zonefiles) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my @entry = ($name,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'enabled'},
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'url'},
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'remark'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $export{$index++} = \@entry;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &General::writehasharray($ZONEFILES_CONF,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \%export);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Load custom lists from rpz-config and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the internal configuration
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _customlists_load {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Clean start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + %customlists = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Load configuration file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %lists_conf = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &General::readhasharray($CUSTOMLISTS_CONF,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \%lists_conf);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Get list options, enabled by default
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to start import
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'enabled'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $lists_conf{2}[0] // 'on';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'enabled'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $lists_conf{2}[1] // 'on';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Import enabled list from rpz-config,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> otherwise retrieve stored or empty list
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> from configuration file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($customlists{'allow'}{'enabled'} eq
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_import('allow',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $RPZ_ALLOWLIST);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'list'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $lists_conf{0} // [];
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($customlists{'block'}{'enabled'} eq
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_import('block',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $RPZ_BLOCKLIST);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'list'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $lists_conf{1} // [];
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Save internal custom lists configuration
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _customlists_save_conf {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %export = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Match IDs with import function
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $export{0} = $customlists{'allow'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'list'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $export{1} = $customlists{'block'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'list'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $export{2} = [$customlists{'allow'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'enabled'}, $customlists{'block'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'enabled'}];
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &General::writehasharray($CUSTOMLISTS_CONF, \%export);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Import a custom list from plain file,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> returns empty list if file is missing
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _customlist_import {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($listname, $filename) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my @list = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # File exists, load and check all lines
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(-f $filename) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + open(my $FH, '<', $filename) or die
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "Can't read $filename: $!";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + while(my $line = <$FH>) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chomp($line);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + push(@list, $line);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + close($FH);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Clean up imported data
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_rpz_validate_customlist(\@list, 1);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{$listname}{'list'} = \@list;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Export a custom list to plain file or
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> clear file if list is disabled
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _customlist_export {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($listname, $filename) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless(defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $customlists{$listname});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Write enabled domain list to file,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> otherwise save empty file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + open(my $FH, '>', $filename) or die
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "Can't write $filename: $!";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($customlists{$listname}{'enabled'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> eq 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $line
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (@{$customlists{$listname}{'list'}}) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print $FH "$line\n";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print $FH "; Note: This list is
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> currently disabled by $ENV{'SCRIPT_NAME'}\n";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + close($FH);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal gui functions ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Show simple message box
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _print_message {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($message, $title) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $title ||= $Lang::tr{'error messages'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left', $title);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print "<span>$message</span>";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Show all zone files and related gui
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> elements
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _print_zonefiles {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $Lang::tr{'rpz zf'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<table class="tbl" width="100%">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <th>$Lang::tr{'name'}</th>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <th>URL</th>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <th>$Lang::tr{'remark'}</th>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <th colspan="3">$Lang::tr{'action'}</th>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Sort zonefiles by name and loop
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> trough all entries
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $name (sort keys %zonefiles) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Toggle button label translation
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $toggle_tr = ($zonefiles{$name}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'enabled'} eq 'on') ? $Lang::tr{'click to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> disable'} : $Lang::tr{'click to enable'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td>$name</td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td>$zonefiles{$name}{'url'}</td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td>$zonefiles{$name}{'remark'}</td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td align="center" width="5%">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="KEY"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$name">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="ZF_TOGGLE">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="image" src="/images/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$name}{'enabled'}.gif"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> title="$toggle_tr" alt="$toggle_tr">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td align="center" width="5%">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="KEY"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$name">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="ZF_EDIT">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="image" src="/images/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> edit.gif" title="$Lang::tr{'edit'}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> alt="$Lang::tr{'edit'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td align="center" width="5%">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="KEY"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$name">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="ZF_REMOVE">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="image" src="/images/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> delete.gif" title="$Lang::tr{'remove'}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> alt="$Lang::tr{'remove'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Disable reload button if not needed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $reload_state =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_needs_reload() ? "" : " disabled";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</table>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<div class="right">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <input type="hidden" name="KEY" value="">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <button type="submit" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="ZF_EDIT">$Lang::tr{'add'}</button>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <button type="submit" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="RPZ_RELOAD"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> class="commit"$reload_state>$Lang::tr{'rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> apply'}</button>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</div>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Show zonefiles entry editor
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _print_zonefile_editor {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Key specified: Edit existing entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(($action_key) && (defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key})) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Load data to be edited, but don't
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> override already present values (allows
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> user to edit after error)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_NAME'} //= $action_key;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_URL'} //=
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key}{'url'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_REMARK'} //=
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key}{'remark'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Fallback to empty form
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_NAME'} //= "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_URL'} //= "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_REMARK'} //= "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $Lang::tr{'rpz zf editor'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<input type="hidden" name="KEY"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$action_key">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<table width="100%">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> width="20%">$Lang::tr{'name'}: <img
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src="/blob.gif" alt="*"></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td><input type="text" name="ZF_NAME"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$cgiparams{'ZF_NAME'}" size="40"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> maxlength="32" title="$Lang::tr{'rpz zf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> remark info'}" pattern="[a-zA-Z0-9_]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {1,32}" required></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td width="20%">URL: <img src="/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> blob.gif" alt="*"></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td><input type="url" name="ZF_URL"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$cgiparams{'ZF_URL'}" size="40"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> maxlength="128" required></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td width="20%">$Lang::tr{'remark'}:</td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td><input type="text" name="ZF_REMARK"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="$cgiparams{'ZF_REMARK'}" size="40"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> maxlength="32"></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td colspan="2"><hr></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td width="55%"><img src="/blob.gif"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> alt="*"> $Lang::tr{'required field'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> </td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td align="right"><button type="submit"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="ZF_SAVE">$Lang::tr{'save'}</
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> button></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</table>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<div class="right">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <button type="submit" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="NONE">$Lang::tr{'back'}</button>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</div>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Show custom allow/block files and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> related gui elements
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _print_customlists {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Load lists from config, unless they
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> are currently being edited
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($action ne 'CL_SAVE') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ALLOW_LIST'} = join("\n",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @{$customlists{'allow'}{'list'}});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'BLOCK_LIST'} = join("\n",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @{$customlists{'block'}{'list'}});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ALLOW_ENABLED'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ($customlists{'allow'}{'enabled'} eq
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'on') ? 'on' : undef;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'BLOCK_ENABLED'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ($customlists{'block'}{'enabled'} eq
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'on') ? 'on' : undef;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Fallback to empty form
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ALLOW_LIST'} //= "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'BLOCK_LIST'} //= "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # HTML checkboxes, unchecked = no or
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> undef value in POST data
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %checked = ();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $checked{'ALLOW_ENABLED'} = (defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $cgiparams{'ALLOW_ENABLED'}) ? "
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> checked" : "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $checked{'BLOCK_ENABLED'} = (defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $cgiparams{'BLOCK_ENABLED'}) ? "
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> checked" : "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Disable reload button if not needed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $reload_state =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_needs_reload() ? "" : " disabled";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $Lang::tr{'rpz cl'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<form method="post"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> action="$ENV{'SCRIPT_NAME'}">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<table width="100%">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td colspan="2"><b>$Lang::tr{'rpz cl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allow'}</b><br>$Lang::tr{'rpz cl allow
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> info'}</td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td colspan="2"><b>$Lang::tr{'rpz cl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block'}</b><br>$Lang::tr{'rpz cl block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> info'}</td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td colspan="2"><textarea
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> name="ALLOW_LIST" class="domainlist"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> cols="45">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +$cgiparams{'ALLOW_LIST'}</textarea></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td colspan="2"><textarea
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> name="BLOCK_LIST" class="domainlist"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> cols="45">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +$cgiparams{'BLOCK_LIST'}</textarea></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td><label
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for="allow_enabled">$Lang::tr{'rpz cl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> allow enable'}</label></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td width="15%"><input type="checkbox"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> name="ALLOW_ENABLED"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> id="allow_enabled"$checked{'ALLOW_ENABLED'}></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td><label
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> for="block_enabled">$Lang::tr{'rpz cl
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block enable'}</label></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td width="15%"><input type="checkbox"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> name="BLOCK_ENABLED"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> id="block_enabled"$checked{'BLOCK_ENABLED'}></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td colspan="4"><hr></td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <tr>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <td align="right" colspan="4">
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <button type="submit" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="CL_SAVE">$Lang::tr{'save'}</button>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + <button type="submit" name="ACTION"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> value="RPZ_RELOAD"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> class="commit"$reload_state>$Lang::tr{'rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> apply'}</button>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + </td>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</table>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</form>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Output javascript and extra gui elements
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _print_gui_extras {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Apply/Restart button modifier key
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> handler
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(&_rpz_needs_reload()) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print <<END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +<script>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Commit modifier key handler
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + (function(jq, document) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + var keyEventsOn = false; // Keyboard
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> events attached
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + var keyModify = false; // Modifier key
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> pressed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + var mouseHover = false; // Mouse over
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> commit button
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + var btnModified = false; // Button
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> modified to "Restart"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Document-level key events, enable
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> only while cursor is over button
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + function attachKeyEvents() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(keyEventsOn) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + keyEventsOn = true;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + jq(document).on("keydown.rpz",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> function(event) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if((!keyModify) && event.shiftKey) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + keyModify = true;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + handleModify();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + });
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + jq(document).on("keyup.rpz",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> function(event) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(keyModify && (!event.shiftKey)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + keyModify = false;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + handleModify();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + });
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + function removeKeyEvents() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + keyModify = false;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(keyEventsOn) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + jq(document).off("keydown.rpz keyup.rpz");
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + keyEventsOn = false;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Attach mouse hover events to commit
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> buttons
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + function attachMouseEvents() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + jq("button.commit").on("mouseenter",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> function(event) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(!mouseHover) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + mouseHover = true;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + attachKeyEvents();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Handle already pressed key
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + keyModify = !!(event.shiftKey);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + handleModify();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + });
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Cursor moved away: Disable key
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> listener to minimize events
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + jq("button.commit").on("mouseleave",
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> function() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(mouseHover) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + mouseHover = false;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + removeKeyEvents();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + handleModify();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + });
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Modify commit button
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + function handleModify() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + let modify = mouseHover && keyModify;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(btnModified != modify) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(modify) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> jq("button.commit").text("$Lang::tr{'restart'}").val("UNB_RESTART");
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> jq("button.commit").text("$Lang::tr{'rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> apply'}").val("RPZ_RELOAD");
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + btnModified = modify;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // jQuery DOM ready
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + jq(function() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + attachMouseEvents();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + });
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + })(jQuery, document);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +</script>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +END
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } # End of modifier key handler
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal action processing
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> functions ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Toggle zonefile on/off
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _action_zf_toggle {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless(defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $result = 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $enabled = $zonefiles{$action_key}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'enabled'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Perform toggle action
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($enabled eq 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $enabled = 'off';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result = &General::system('/usr/sbin/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config', 'remove', $action_key, '--no-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + } else {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $enabled = 'on';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result = &General::system('/usr/sbin/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config', 'add', $action_key,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key}{'url'}, '--no-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Check for errors, request service
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload on success
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_check_result($result, 1);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Save changes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$action_key}{'enabled'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $enabled;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Remove zonefile
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _action_zf_remove {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless(defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Remove from rpz-config if currently
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> active
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($zonefiles{$action_key}{'enabled'}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> eq 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $result = &General::system('/usr/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sbin/rpz-config', 'remove', $action_key,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '--no-reload');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Check for errors, request service
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload on success
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_check_result($result, 1);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Remove from data hash and save changes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + delete $zonefiles{$action_key};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Clear action_key, as the entry is now
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> removed entirely
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $action_key = "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Create or update zonefile entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Returns undef if gui needs to stay in
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> editor mode
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _action_zf_save {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $result = 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $name = $cgiparams{'ZF_NAME'} // "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $url = $cgiparams{'ZF_URL'} // "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $remark = $cgiparams{'ZF_REMARK'} //
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $enabled = 'on'; # Enable new
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entries by default
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Note on variables:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # name = unique key, will be used to
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> address the entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # action_key = name of the entry being
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> edited, empty for new entry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Only check for unique name if it changed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # (this also checks new entries because
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the action_key is empty in this case)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_validate_zonefile($name, $url,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $remark, (lc($name) ne lc($action_key)));
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_check_result($result, 0);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Edit existing entry: Determine what
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> was changed
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(($action_key) && (defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key})) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Name und URL remain unchanged, only
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> save remark and finish
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(($name eq $action_key) && ($url eq
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $zonefiles{$action_key}{'url'})) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$action_key}{'remark'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $remark;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Entry was changed and needs to be
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> recreated, preserve status
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $enabled = $zonefiles{$action_key}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {'enabled'};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Remove from rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless &_action_zf_remove();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Add new entry to rpz-config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($enabled eq 'on') {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result = &General::system('/usr/sbin/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config', 'add', $name, $url, '--no-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Check for errors, request service
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload on success
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_check_result($result, 1);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Add to global data hash and save changes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my %entry = ('enabled' => $enabled,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'url' => $url,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + 'remark' => $remark);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name} = \%entry;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Save custom lists
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _action_cl_save {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless((defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $cgiparams{'ALLOW_LIST'}) && (defined
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $cgiparams{'BLOCK_LIST'}));
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $result = 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my @allowlist = split(/\R/,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $cgiparams{'ALLOW_LIST'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my @blocklist = split(/\R/,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $cgiparams{'BLOCK_LIST'});
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Validate lists
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_validate_customlist(\@allowlist);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($result != 0) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $errormessage = &_rpz_error_tr(202,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $result);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_validate_customlist(\@blocklist);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($result != 0) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $errormessage = &_rpz_error_tr(203,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $result);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Add to global data hash and save changes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'list'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \@allowlist;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'list'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \@blocklist;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'enabled'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (defined $cgiparams{'ALLOW_ENABLED'}) ?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'on' : 'off';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'enabled'} =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> (defined $cgiparams{'BLOCK_ENABLED'}) ?
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 'on' : 'off';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_customlists_save_conf();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_export('allow',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $RPZ_ALLOWLIST);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_export('block',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $RPZ_BLOCKLIST);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Make new lists, request service
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reload on success
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $result = &General::system('/usr/sbin/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-make', 'allowblock', '--no-reload');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return unless
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &_rpz_check_result($result, 1);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Trigger rpz-config reload
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _action_rpz_reload {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1 unless &_rpz_needs_reload();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Immediately clear flag to prevent
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> multiple reloads
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(-f $RPZ_RELOAD_FLAG) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unlink($RPZ_RELOAD_FLAG) or die "Can't
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> remove $RPZ_RELOAD_FLAG: $!";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Perform reload, recreate reload flag
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> on error to enable retry
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $result = &General::system('/usr/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> sbin/rpz-config', 'reload');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(not &_rpz_check_result($result, 0)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &General::system('touch',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "$RPZ_RELOAD_FLAG");
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Trigger unbound restart
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _action_unb_restart {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1 unless &_rpz_needs_reload();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Immediately clear flag to prevent
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> multiple restarts
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(-f $RPZ_RELOAD_FLAG) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unlink($RPZ_RELOAD_FLAG) or die "Can't
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> remove $RPZ_RELOAD_FLAG: $!";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Perform restart, unboundctrl always
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> exits zero
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &General::system('/usr/local/bin/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unboundctrl', 'restart');
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal rpz-config functions ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Translate rpz-config exitcodes and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> messages
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# 100-199: rpz-config, 200-299: webgui
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_error_tr {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($error, $append) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $append //= '';
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Translate numeric exit codes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(looks_like_number($error)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(defined $Lang::tr{"rpz exitcode
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $error"}) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $error = $Lang::tr{"rpz exitcode $error"};
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return "RPZ $Lang::tr{'error'}:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $error" . &Header::escape($append);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Check result of rpz-config system
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> call, request reload on success
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_check_result {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($result, $request_reload) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $request_reload //= 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # exitcode 0 = success
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($result != 0) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $errormessage = &_rpz_error_tr($result);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Set reload flag
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($request_reload) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + &General::system('touch',
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "$RPZ_RELOAD_FLAG");
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Test whether reload flag is set
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_needs_reload {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return (-f $RPZ_RELOAD_FLAG);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Validate a zonefile entry, returns
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz-config exitcode on failure. Use
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _rpz_check_result to verify.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# unique = check for unique name
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_validate_zonefile {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($name, $url, $remark, $unique) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $unique //= 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unless($name =~ /^[a-zA-Z0-9_]{1,32}$/) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 101;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unless($url =~ /^[\w+\.:;\/\\&@#%?=\-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ~|!]{1,128}$/) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 105;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unless($remark =~ /^[\w \-()\.:;*\/\\?!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &=]{0,32}$/) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 201;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Check against already existing names
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if($unique) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $existing (keys %zonefiles) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if(lc($name) eq lc($existing)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 104;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Validate a custom list, returns number
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> of rejected line on failure. Check for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> non-zero results.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# listref = array reference, cleanup =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> remove invalid entries instead of
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> returning an error
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_validate_customlist {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my ($listref, $cleanup) = @_;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $cleanup //= 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + foreach my $index (reverse 0..
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $#{$listref}) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $row = @$listref[$index];
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + next unless($row); # Skip/allow empty
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lines
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Reject/remove everything besides
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> wildcard domains and remarks
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + if((not
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &General::validwildcarddomainname($row))
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> && (not $row =~ /^;[\w \-()\.:;*\/\\?!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &=]*$/)) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + unless($cleanup) {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # +1 for user friendly line number and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> to ensure non-zero exitcode
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return $index + 1;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Remove current row
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + splice(@$listref, $index, 1);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + }
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + return 0;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal misc functions ---###
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Send HTTP 303 redirect headers for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> post/request/get pattern
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (Must be sent before calling
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &Header::showhttpheaders())
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +sub _http_prg_redirect {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + my $location = "https://
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $ENV{'SERVER_NAME'}:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $ENV{'SERVER_PORT'}$ENV{'SCRIPT_NAME'}";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print "Status: 303 See Other\n";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + print "Location: $location\n";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/lfs/rpz b/lfs/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..7ddbc38e5
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/lfs/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,96 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Definitions
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +include Config
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +SUMMARY = response policy zone - RPZ
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> reputation system for unbound DNS
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +VER = 1.0.0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +THISAPP = rpz-$(VER)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +DIR_APP = $(DIR_SRC)/$(THISAPP)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +TARGET = $(DIR_INFO)/$(THISAPP)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +PROG = rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +PAK_VER = 18
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +DEPS =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +SERVICES =
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Top-level Rules
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +install : $(TARGET)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +check :
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +download :
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +b2 :
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +dist:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + @$(PAK)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Installation Details
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +$(TARGET) :
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + @$(PREBUILD)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + @rm -rf $(DIR_APP)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # RPZ scripts
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + install --verbose --mode=755 \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $(DIR_CONF)/rpz/{rpz-config,rpz-
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> metrics,rpz-sleep,rpz-make,rpz-functions} \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --target-directory=/usr/sbin
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # RPZ config files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + mkdir -pv /etc/unbound/local.d
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + install --verbose --mode=644 --
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> owner=nobody --group=nobody \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + $(DIR_CONF)/rpz/00-rpz.conf \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --target-directory=/etc/unbound/local.d
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chown --verbose --recursive
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nobody:nobody /etc/unbound/local.d
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # RPZ custom list files for allow and
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> block
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + mkdir -pv /var/ipfire/dns/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + touch /var/ipfire/dns/rpz/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> {allowlist,blocklist}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chown --verbose --recursive
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nobody:nobody /var/ipfire/dns/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # RPZ zone files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # create empty RPZ config file to avoid
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> a unbound config error
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + mkdir -pv /etc/unbound/zonefiles
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + touch /etc/unbound/zonefiles/allow.rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + chown --verbose --recursive
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> nobody:nobody /etc/unbound/zonefiles
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Install addon-specific language-files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + install --verbose --mode=004
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $(DIR_CONF)/rpz/rpz.*.pl \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + --target-directory=/var/ipfire/addon-lang
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + # Install backup definition
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + cp -vf $(DIR_CONF)/backup/includes/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> rpz /var/ipfire/backup/addons/includes/rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + @rm -rf $(DIR_APP)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + @$(POSTBUILD)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/make.sh b/make.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 827ea9e77..a77535b13 100755
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- a/make.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/make.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -390,7 +390,7 @@ prepareenv() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> if [ "${free_space}" -lt
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${required_space}" ]; then
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> # Add any consumed space
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> while read -r consumed_space path; do
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - (( free_space += consumed_space /
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1024 / 1024 ))
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + (( free_space += consumed_space /
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1024 / 1024 ))
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> done <<< "$(du --summarize --bytes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${BUILD_DIR}" "${IMAGES_DIR}"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> "${LOG_DIR}" 2>/dev/null)"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> fi
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -2087,6 +2087,7 @@ build_system() {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 btrfs-progs
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 inotify-tools
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 grub-btrfs
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + lfsmake2 rpz
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 linux
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 rtl8812au
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/src/paks/rpz/install.sh b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/install.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..ef99bf742
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/src/paks/rpz/install.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,36 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +. /opt/pakfire/lib/functions.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +extract_files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +restore_backup ${NAME}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# fix user created files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +chown --verbose --recursive nobody:nobody \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /var/ipfire/dns/rpz \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/zonefiles \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/local.d
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Update Language cache
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/usr/local/bin/update-lang-cache
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# restart unbound to load config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound restart
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/src/paks/rpz/uninstall.sh b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/uninstall.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..e11427df3
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/src/paks/rpz/uninstall.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,38 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +. /opt/pakfire/lib/functions.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# stop unbound to delete RPZ conf file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound stop
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +make_backup ${NAME}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +remove_files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# delete rpz config files. Otherwise
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unbound will throw error:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# "[1723428668] unbound-control[17117:0]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> error: connect: Connection refused for
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 127.0.0.1 port 8953"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/bin/rm --verbose --force /etc/unbound/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> local.d/*.rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Update Language cache
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/usr/local/bin/update-lang-cache
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# start unbound to load unbound config file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/src/paks/rpz/update.sh b/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/update.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> index 000000000..9bc340bc6
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +++ b/src/paks/rpz/update.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,52 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <info@ipfire.org> #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> redistribute it and/or modify #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Public License as published by #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> version 3 of the License, or #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> hope that it will be useful, #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> the implied warranty of #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PARTICULAR PURPOSE. See the #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> details. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> GNU General Public License #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <http://www.gnu.org/licenses/>. #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +###############################################################################
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +. /opt/pakfire/lib/functions.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# from update.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +extract_backup_includes
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# stop unbound to delete RPZ conf file
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound stop
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# from uninstall.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +make_backup ${NAME}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +remove_files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# delete rpz config files. Otherwise
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> unbound will throw error:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# "unbound-control[nn:0] error: connect:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Connection refused for 127.0.0.1 port 8953"
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/bin/rm --verbose --force /etc/unbound/
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> local.d/*.rpz.conf
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# from install.sh
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +extract_files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +restore_backup ${NAME}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# fix user created files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +chown --verbose --recursive nobody:nobody \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /var/ipfire/dns/rpz \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/zonefiles \
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/local.d
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# Update Language cache
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/usr/local/bin/update-lang-cache
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# restart unbound to load config files
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound start
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2.39.5
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>>>>>>>>>>>>>> Jon Murphy
>>>>>>>>>>>>>>>>>>>>>>>>>>>> jon.murphy@ipfire.org
>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>> Jon
>>>>>>>>>>>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>>>>>>>>>>>> Jon Murphy
>>>>>>>>>>>>>>>>>>>>>>>>>> jon.murphy@ipfire.org
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>>
>>
>>
>
next prev parent reply other threads:[~2025-08-06 12:32 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-06 16:35 Jon Murphy
2025-02-06 19:35 ` Bernhard Bitsch
2025-02-06 20:13 ` Michael Tremer
2025-02-08 18:41 ` jon
2025-02-08 19:27 ` Michael Tremer
[not found] ` <C28A0D7E-6C16-4F6F-9366-A8498F40631E@ipfire.org>
2025-02-14 12:07 ` Michael Tremer
2025-02-14 12:58 ` Bernhard Bitsch
2025-02-14 13:52 ` Michael Tremer
2025-02-14 14:16 ` Bernhard Bitsch
2025-03-01 10:18 ` Adolf Belka
[not found] ` <3BF29525-C9F4-4FD2-834D-FBE791E99E8C@ipfire.org>
2025-03-02 10:51 ` Adolf Belka
2025-03-10 17:47 ` jon
2025-03-16 17:00 ` Jon Murphy
2025-03-17 10:35 ` Michael Tremer
2025-03-19 2:58 ` Jon Murphy
2025-03-19 10:35 ` Michael Tremer
2025-03-19 18:22 ` Jon Murphy
[not found] ` <afcb2a99-1281-43e3-bd3d-d915024683f6@ipfire.org>
2025-03-20 16:26 ` Michael Tremer
2025-03-24 0:00 ` Re[2]: " Jon Murphy
2025-03-24 10:17 ` Michael Tremer
2025-03-24 13:33 ` Bernhard Bitsch
2025-03-24 14:25 ` Michael Tremer
2025-03-24 14:33 ` Re[2]: " Jon Murphy
2025-03-24 14:36 ` Michael Tremer
2025-03-24 14:38 ` Re[2]: " Jon Murphy
2025-03-24 14:40 ` Michael Tremer
2025-03-24 14:42 ` Re[2]: " Jon Murphy
2025-03-24 14:43 ` Michael Tremer
2025-05-20 16:30 ` Re[2]: " Jon Murphy
2025-05-22 15:40 ` Michael Tremer
2025-05-22 15:42 ` Re[2]: " Jon Murphy
2025-05-22 15:43 ` Michael Tremer
2025-05-22 15:45 ` Re[2]: " Jon Murphy
2025-05-22 15:46 ` Michael Tremer
2025-05-22 19:45 ` Re[2]: " Jon Murphy
2025-05-23 10:35 ` Michael Tremer
2025-08-05 16:53 ` Re[2]: " Jon Murphy
2025-08-06 7:31 ` Bernhard Bitsch
2025-08-06 12:32 ` Bernhard Bitsch [this message]
2025-08-07 8:17 ` Michael Tremer
2025-08-07 9:18 ` Bernhard Bitsch
2025-08-07 13:40 ` Michael Tremer
2025-08-07 14:55 ` Bernhard Bitsch
2025-08-07 18:03 ` Michael Tremer
2025-08-07 8:17 ` Michael Tremer
2025-03-24 14:49 ` Bernhard Bitsch
2025-03-24 14:41 ` Bernhard Bitsch
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4d7fda4f-0de9-4a77-99b1-6276b161f68a@ipfire.org \
--to=bbitsch@ipfire.org \
--cc=development@lists.ipfire.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox