# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:sw=4:ts=4:sts=4
PortSystem          1.0
name                adblock2privoxy
version             2.3.1
revision            0
categories          www haskell
maintainers         {ieee.org:s.t.smith @essandess} openmaintainer
license             GPL-3
description         Convert adblock config files to privoxy format
long_description    {*}${description}. \
                    AdBlock Plus browser plugin has great block list \
                    files provided by big community, but it is client \
                    software and cannot work on a server as proxy. \
                    Privoxy proxy has good potential to block ads at \
                    server side, but it experiences acute shortage of \
                    updated block lists.  This software converts \
                    adblock lists to privoxy config files format. \
                    Almost all adblock features are supported \
                    including block/unblock requests (on privoxy) all \
                    syntax features are supported except for regex \
                    templates matching host name hide/unhide page \
                    elements (via CSS) all syntax features are \
                    supported all block request options except for \
                    outdated ones: Supported: script, image, \
                    stylesheet, object, xmlhttprequest, \
                    object-subrequest, subdocument, document, \
                    elemhide, other, popup, third-party, domain=..., \
                    match-case, donottrack.
homepage            https://github.com/essandess/adblock2privoxy
checksums           rmd160  4c85ac78e0bbf94523114fd865eb65737db89b66 \
                    sha256  8a6113404ad8254da885c8f0f7cb837f136d5ef4baf9d8b25ee14e6c0a47d0be \
                    size    44273
depends_lib-append  port:zlib
depends_run-append  port:bash \
                    port:nginx \
                    port:privoxy \
                    port:wget
depends_skip_archcheck \
                    privoxy
variant initialize_always \
    description {Always initialize all configuration files. Intended\
        for development and troubleshooting only. Working deployments\
        must disable this variant to prevent configuration files\
        being overwritten at the next upgrade. Existing configuration\
        files are not overwritten by default.} {
    pre-fetch {
        ui_warn \
            "All configuration files will be initialized because\
            the variant +initialize_always is set. Please disable\
            this variant for working deployments."
    }
}
# use domain or ip with port, e.g. 127.0.0.1:8119
set adblock2privoxy_css_server \
                    127.0.0.1:8119
# relative paths to ${prefix}
set ab2p_datadir    share/${name}
    
post-extract {
    # Fix for cabal data-files hardcoded path in binary
    # See:
    # https://github.com/commercialhaskell/stack/issues/848
    # https://github.com/commercialhaskell/stack/issues/4857
    # https://github.com/haskell/cabal/issues/462
    # https://github.com/haskell/cabal/issues/3586
    xinstall -m 0644 -W ${worksrcpath} \
                    ${filespath}/Paths_NAME.hs ./src/Paths_${name}.hs
    reinplace "s|@PREFIX@|${prefix}|g" \
                    ${worksrcpath}/src/Paths_${name}.hs
    reinplace "s|@NAME@|${name}|g" \
                    ${worksrcpath}/src/Paths_${name}.hs
    reinplace -E "s|(Version\[\[:space:\]\]+)\\\[\[\[:digit:\]\]+(,\[\[:digit:\]\]+){1,4}\\\]|\\1\[[join [split ${version} .] ,]\]|" \
                    ${worksrcpath}/src/Paths_${name}.hs
}
variant stack \
    description {Use stack to build.} {}
if { [variant_isset "stack"] } {
    PortGroup       haskell_stack 1.0
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/${name}/templates
        # cabal's data-files datadir: ${name}_datadir from Paths_${name}.hs
        fs-traverse f ${worksrcpath}/.stack-work {
            if { [string match "ab2p.system.*" [file tail ${f}]] } {
                xinstall -m 0644 ${f} \
                    ${destroot}${prefix}/share/${name}/templates
            }
        }
    }
} else {
    PortGroup       haskell_cabal 1.0
    build.target-append \
                    --allow-newer
    
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/${name}/templates
        foreach f [glob ${worksrcpath}/templates/ab2p.system.*] {
            xinstall -m 0644 ${f} \
                    ${destroot}${prefix}/share/${name}/templates
        }
    }
}
post-destroot {
    xinstall -m 0644 -W ${worksrcpath} \
        man/man1/${name}.1 \
        ${destroot}${prefix}/share/man/man1
    xinstall -d \
        ${destroot}${prefix}/etc/${name} \
        ${destroot}${prefix}/etc/${name}/bin \
        ${destroot}${prefix}/etc/${name}/css \
        ${destroot}${prefix}/etc/${name}/privoxy
    xinstall -m 0755 -W ${filespath} \
        adblock2privoxy_initialize.sh \
        ${destroot}${prefix}/etc/${name}/bin
    reinplace "s|@PREFIX@|${prefix}|g" \
        ${destroot}${prefix}/etc/${name}/bin/adblock2privoxy_initialize.sh
    xinstall -m 0644 -W ${filespath} \
        adblock2privoxy_blocklist.txt \
        ${destroot}${prefix}/etc/${name}/adblock2privoxy_blocklist.txt.macports
    xinstall -m 0644 -W ${filespath} \
        nginx.conf \
        ${destroot}${prefix}/etc/${name}/nginx.conf.macports
    xinstall -m 0644 -W ${filespath} \
        default.html \
        ${destroot}${prefix}/etc/${name}/css/default.html.macports
    reinplace "s|@PREFIX@|${prefix}|g" \
        ${destroot}${prefix}/etc/${name}/nginx.conf.macports
}
set tls_ca_dir      ${prefix}/etc/${name}/ca.macports
set tls_cert_dir    ${prefix}/etc/${name}/certs
set optional_proxy  http://localhost:8080
set proxy_message \
        "Startupitem configured to use a proxy. Please set the
environment variables http_proxy and https_proxy and
install this port variant a sudo command that sets
these variables, e.g.:
\tsudo -E port install ${name} +proxy_settings
\tsudo env http_proxy=${optional_proxy} port install ${name} +proxy_settings
or edit the startupitem:
\t${prefix}/etc/${startupitem.location}/org.macports.${name}/org.macports.${name}.plist
to change the proxy settings and reload the port."
variant proxy_settings \
    description {Include proxy settings in the startupitem plist.} {
    # Note: `sudo launchctl setenv` is no longer functional on macOS Ventura+
    notes-append ${proxy_message}
    post-activate {
        if { [info exists ::env(http_proxy)] } {
            set http_proxy $env(http_proxy)
        } else {
            set http_proxy ${optional_proxy}
        }
        if { [info exists ::env(https_proxy)] } {
            set https_proxy $env(https_proxy)
        } else {
            set https_proxy ${http_proxy}
        }
        # org.macports.adblock2privoxy
        reinplace \
            "s|^ProgramArguments|EnvironmentVariables\\
\\
	http_proxy\\
	${http_proxy}\\
	https_proxy\\
	${https_proxy}\\
\\
&|" \
        ${prefix}/etc/${startupitem.location}/org.macports.${name}/org.macports.${name}.plist
        ui_msg "${proxy_message}
The startupitem is configured to use the proxy settings:
\thttp_proxy=${http_proxy}
\thttps_proxy=${https_proxy}
"
    }
}
variant https_inspection \
    description {HTTPS CSS Server for use with 'privoxy +https_inspection'.} {
    depends_build-append \
                    port:sf-pwgen
    depends_lib-append \
                    path:bin/openssl:openssl
    # random 4-word-based passphrase
    proc correct_horse_battery_staple {} {
        # ignore errors from sf-pwgen if the password is shorter than requested
        set passphrase \
            [join [exec sh -c "sf-pwgen \
                --algorithm memorable --count 2 --length 16 \
                    2>/dev/null || true"] -]
        # set random passphrase if sf-pwgen's is too short for some reason
        if {[string length ${passphrase}] < 20} {
            set passphrase \
                [exec sh -c "openssl rand -base64 23 2>/dev/null \
                    | sed 's|=*\$||' || true"]
        }
        return ${passphrase}
    }
    post-destroot {
        # TLS Root CA configuration
        xinstall -m 0770 -d ${destroot}${tls_cert_dir}
        xinstall -m 0700 -d ${destroot}${tls_ca_dir}
        destroot.keepdirs-append \
                    ${destroot}${tls_cert_dir}
        xinstall -m 0644 -W ${filespath} \
                    openssl.cnf \
                    ${destroot}${tls_ca_dir}/openssl.cnf.macports
    }
    pre-activate {
        if { [file exists ${tls_ca_dir}] } {
            delete  ${tls_ca_dir}.previous
            move    ${tls_ca_dir} \
                    ${tls_ca_dir}.previous
        }
    }
    post-activate {
        foreach f [list \
            ${tls_ca_dir}/openssl.cnf \
            ] {
            if { [variant_isset "initialize_always"]
                 && [file exists ${f}]
                } {
                delete ${f}.previous
                move \
                    ${f} \
                    ${f}.previous
            }
            if { [variant_isset "initialize_always"]
                || ![file exists ${f}]
                } {
                if { [file isfile ${f}.macports] } {
                    xinstall -m 0644 \
                        ${f}.macports \
                        ${f}
                }
            }
        }
        # CA passphrase
        # generate a strong password, use for openssl -passin and -passout
        set tls_ca_passphrase \
            [correct_horse_battery_staple]
        set tls_ca_passphrase_fd \
            [open ${tls_ca_dir}/passphrase.txt w 0600]
        # -passin or -passout
        puts ${tls_ca_passphrase_fd} \
            ${tls_ca_passphrase}
        # -passout
        puts ${tls_ca_passphrase_fd} \
            ${tls_ca_passphrase}
        close ${tls_ca_passphrase_fd}
        # create the root CA
        system -W ${tls_ca_dir} \
            "sh < serial
            # CA encrypted key
            # EC
            openssl genpkey -out ca.key.pem -algorithm EC \\
                -pkeyopt ec_paramgen_curve:P-384 -aes256 \\
                -pass file:passphrase.txt
            # RSA
            # openssl genpkey -out ca.key.pem -algorithm RSA \\
            #     -pkeyopt rsa_keygen_bits:2048 -aes256 \\
            #     -passout file:passphrase.txt
            chmod go-rw ca.key.pem
            # CA certificate
            openssl req -config openssl.cnf \\
                -new -x509 -days 1460 -sha384 \\
                -extensions v3_ca \\
                -out ca.cert.pem -key ca.key.pem \\
                -passin file:passphrase.txt -batch
            # CA certificate openssl self-verification
            openssl verify -CAfile ca.cert.pem ca.cert.pem
            # Convert to .cer DER and .p12 for other uses
            openssl x509 -outform der -in ca.cert.pem -out ca.cer
            # https://github.com/essandess/macports-ports/pull/new/privoxy
            openssl pkcs12 -legacy -export -out ca.p12 \\
                -inkey ca.key.pem -in ca.cert.pem \\
                -passin file:passphrase.txt \\
                -passout file:passphrase.txt
            # verify .p12 passphrase
            openssl pkcs12 -legacy -noout -in ca.p12 -passin file:passphrase.txt
            # Server certificates
            # Server certificate encrypted key and decrypted key
            openssl genpkey -out adblock2privoxy-nginx.key.pem \
                -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -aes256 \
                -pass file:passphrase.txt
            openssl ec -in adblock2privoxy-nginx.key.pem \
               -passin file:passphrase.txt \
               -out adblock2privoxy-nginx.key.pem.decrypted
            chmod go-rwx adblock2privoxy-nginx.key.pem.decrypted
            # Server certificate CSR
            openssl req -config openssl.cnf -new -sha384 \
                 -key adblock2privoxy-nginx.key.pem \
                 -passin file:passphrase.txt \
                 -out adblock2privoxy-nginx.csr.pem -batch
            # Server certificate (825 days maximum validity)
            # https://support.apple.com/en-us/HT210176
            openssl ca -config openssl.cnf -days 825 -notext -md sha384 \
                -extensions server_cert -in adblock2privoxy-nginx.csr.pem \
                -out adblock2privoxy-nginx.cert.pem \
                -passin file:passphrase.txt \
                -subj '/CN=adblock2privoxy-nginx' -batch
            # Server certificate chain of trust
            cat adblock2privoxy-nginx.cert.pem ca.cert.pem \
                > adblock2privoxy-nginx.chain.pem
            # Server certificate and chain validity
            openssl verify -CAfile ca.cert.pem adblock2privoxy-nginx.cert.pem
            openssl verify -CAfile ca.cert.pem adblock2privoxy-nginx.chain.pem
ADBLOCK2PRIVOXY_PKI
"
        if { ![file exists ${tls_cert_dir}/adblock2privoxy-nginx.cert.pem]
            || ![file exists ${tls_cert_dir}/adblock2privoxy-nginx.key.pem.decrypted]
            } {
            xinstall -m 0664 \
                    ${tls_ca_dir}/ca.cert.pem \
                    ${tls_cert_dir}
            xinstall -m 0664 \
                    ${tls_ca_dir}/ca.key.pem \
                    ${tls_cert_dir}
            xinstall -m 0600 \
                    ${tls_ca_dir}/passphrase.txt \
                    ${tls_cert_dir}
            xinstall -m 0664 \
                    ${tls_ca_dir}/adblock2privoxy-nginx.cert.pem \
                    ${tls_cert_dir}
            xinstall -m 0664 \
                    ${tls_ca_dir}/adblock2privoxy-nginx.chain.pem \
                    ${tls_cert_dir}
            xinstall -m 0664 \
                    ${tls_ca_dir}/adblock2privoxy-nginx.key.pem \
                    ${tls_cert_dir}
            xinstall -m 0600 \
                    ${tls_ca_dir}/adblock2privoxy-nginx.key.pem.decrypted \
                    ${tls_cert_dir}
        }
        if { ![file exists ${tls_cert_dir}/dhparam.pem]
            } {
            system -W ${tls_ca_dir} \
                "sh </dev/null 2>&1; \
                    then echo 'WONT_EXPIRE'; \
                    else echo 'WILL_EXPIRE'; fi"]
        if {[string trim ${ab2p_cert_valid}] ne {WONT_EXPIRE}} {
            ui_warn "Certificate ${tls_cert_dir}/adblock2privoxy-nginx.cert.pem expired or will expire within 30 days."
        }
    }
    notes-append \
       "Configure adblock2privoxy PKI by creating a\
        certificate from e.g. Privoxy's certificate authority (CA). As sudo:
        # Example, more likely use ${prefix}/etc/privoxy/CA
        cp -R ${prefix}/etc/privoxy/ca.macports ca.adblock2privoxy \\
          && cd ca.adblock2privoxy
        cp ${tls_cert_dir}/openssl.cnf .
        # edit openssl.cnf for your local organizationName, commonName, etc.
        # initialize
        touch index.txt
        echo 1000 > serial
        # Server certificates
        # Server certificate encrypted key and decrypted key
        openssl genpkey -out adblock2privoxy-nginx.key.pem \\
            -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -aes256 \\
            -pass file:passphrase.txt
        openssl ec -in adblock2privoxy-nginx.key.pem \\
           -passin file:passphrase.txt \\
           -out adblock2privoxy-nginx.key.pem.decrypted
        chmod go-rwx adblock2privoxy-nginx.key.pem.decrypted
        # Server certificate CSR
        openssl req -config openssl.cnf -new -sha384 \\
             -key adblock2privoxy-nginx.key.pem \\
             -passin file:passphrase.txt \\
             -out adblock2privoxy-nginx.csr.pem -batch
        # Server certificate (825 days maximum validity)
        # https://support.apple.com/en-us/HT210176
        openssl ca -config openssl.cnf -days 825 -notext -md sha384 \\
            -extensions server_cert -in adblock2privoxy-nginx.csr.pem \\
            -out adblock2privoxy-nginx.cert.pem \\
            -passin file:passphrase.txt \\
            -subj '/CN=adblock2privoxy-nginx' -batch
        # Server certificate chain of trust
        cat adblock2privoxy-nginx.cert.pem ca.cert.pem \\
            > adblock2privoxy-nginx.chain.pem
        # Server certificate and chain validity
        openssl verify -CAfile ca.cert.pem adblock2privoxy-nginx.cert.pem
        openssl verify -CAfile ca.cert.pem adblock2privoxy-nginx.chain.pem
        # Install the adblock2privoxy PKI
        cp -p ca.key.pem ca.cert.pem passphrase.txt \\
            adblock2privoxy-nginx.cert.pem adblock2privoxy-nginx.chain.pem \\
            adblock2privoxy-nginx.key.pem \\
            adblock2privoxy-nginx.key.pem.decrypted \\
            ${tls_cert_dir}
"
}
default_variants-append \
                    +https_inspection
# default: empty flag
set ab2p_use_http_flag \
                    {}
if { ![variant_isset "https_inspection"] } {
    set ab2p_use_http_flag \
                    {-u}
}
startupitem.create  yes
startupitems \
    name            ${name} \
    init [list      "if \[ -f \"\${prefix}/etc/adblock2privoxy/ADBLOCK2PRIVOXY.env\" ]; then" \
                    "\tset -a" \
                    "\t. <(grep -E -o -e '^\[\[:alnum:]_]+=\[^\[:space:]\;]+\$' \"${prefix}/etc/adblock2privoxy/ADBLOCK2PRIVOXY.env\" | grep -E -v '^\[\[:space:]]*(#|\$)|\\\$\\(|`')" \
                    "\tset +a" \
                    "fi" \
                    "ADBLOCK2PRIVOXY_CSS_SERVER=\"\${ADBLOCK2PRIVOXY_CSS_SERVER:-${adblock2privoxy_css_server}}\"" \
    ] \
    start [list     "( IFS=\$'\\n' ADBLOCK2PRIVOXY_BLOCKLIST=(\$(grep -v -e '^ *#' < \"\${prefix}/etc/${name}/adblock2privoxy_blocklist.txt\" \\" \
                    "\t| while read -r t; do if \"\${prefix}/bin/wget\" --max-redirect=0 -S --spider \"\${t}\" 2>&1 | grep -q 'HTTP/1.1 200 OK'; then echo \"\${t}\"; fi done)); \\" \
                    "/bin/test -f \"\${prefix}/etc/adblock2privoxy/privoxy/ab2p.task\" \\" \
                    "&& \"\${prefix}/bin/adblock2privoxy\" -t \"\${prefix}/etc/adblock2privoxy/privoxy/ab2p.task\" \\" \
                    "|| \"\${prefix}/bin/adblock2privoxy\" -p \"\${prefix}/etc/adblock2privoxy/privoxy\" \\" \
                    "\t-w \"\${prefix}/etc/adblock2privoxy/css\" \\" \
                    "\t-d \"\${ADBLOCK2PRIVOXY_CSS_SERVER}\" ${ab2p_use_http_flag} \\" \
                    "\t\"\${ADBLOCK2PRIVOXY_BLOCKLIST\[@]}\" \\" \
                    ") && \"\${prefix}/bin/port\" reload privoxy" \
    ] \
    stop            "\"/usr/bin/kill -SIGUSR1 \\\"\$(/usr/bin/pgrep -u root ${name})\\\" 2>/dev/null\"" \
    pidfile         none
startupitems-append \
    name            ${name}-nginx \
    init            "pidfile=\"\${prefix}/var/run/nginx/nginx-adblock2privoxy.pid\"" \
    start [list     "\"\${prefix}/sbin/nginx\" \\" \
                    "\t-c \\" \
                    "\t\"\${prefix}/etc/${name}/nginx.conf\" \\" \
                    "\t-g \"daemon off;\"" \
    ] \
    stop [list      "if \[ -f \"\${pidfile}\" \]; then" \
                    "\t/usr/bin/kill \"\$(cat \"\${pidfile}\")\" \\" \
                    "\t\t&& /bin/rm -f \"\${pidfile}\" ;" \
                    "else" \
                    "\t/usr/bin/kill -SIGUSR1 \"\$(/usr/bin/pgrep -u root nginx)\" 2>/dev/null ;" \
                    "fi" \
    ]
post-destroot {
    # org.macports.adblock2privoxy
    reinplace -E \
        "1s|^(#!\[\[:space:]]*)/bin/sh|\\1/usr/bin/env bash|" \
        ${destroot}${prefix}/etc/${startupitem.location}/org.macports.${name}/${name}.wrapper
    reinplace \
        "s|^ProgramArguments|StartCalendarInterval\\
	\\
		\\
			Weekday\\
			7\\
			Hour\\
			1\\
			Minute\\
			30\\
		\\
	\\
	StandardErrorPath\\
	${prefix}/var/log/${name}.log\\
	StandardOutPath\\
	${prefix}/var/log/${name}.log\\
&|" \
        ${destroot}${prefix}/etc/${startupitem.location}/org.macports.${name}/org.macports.${name}.plist
}
post-activate {
    foreach f [list \
        ${prefix}/etc/${name}/adblock2privoxy_blocklist.txt \
        ${prefix}/etc/${name}/nginx.conf \
        ${prefix}/etc/${name}/css/default.html \
        ] {
        if { [variant_isset "initialize_always"]
             && [file exists ${f}]
            } {
            delete ${f}.previous
            move \
                ${f} \
                ${f}.previous
        }
        if { [variant_isset "initialize_always"]
             || ![file exists ${f}]
            } {
            if { [file isfile ${f}.macports] } {
                xinstall -m 0644 \
                    ${f}.macports \
                    ${f}
            }
        }
    }
}
notes "\
After initial installation, it is necessary to kickstart this launch daemon,\
which does not run at load:
  sudo launchctl kickstart -k system/org.macports.adblock2privoxy
The blocklist URLs are specified in the file\
${prefix}/etc/${name}/adblock2privoxy_blocklist.txt.
Example production run:
  adblock2privoxy -p ${prefix}/etc/adblock2privoxy/privoxy \\
    -w ${prefix}/etc/adblock2privoxy/css -d ${adblock2privoxy_css_server} \\
    \$(< ${prefix}/etc/${name}/adblock2privoxy_blocklist.txt)
Update run:
  adblock2privoxy -t ${prefix}/etc/adblock2privoxy/privoxy/ab2p.task
The CSS web server domain name or IP address is specified by the\
environment variable ADBLOCK2PRIVOXY_CSS_SERVER (with default value):
  ADBLOCK2PRIVOXY_CSS_SERVER=${adblock2privoxy_css_server}
To change this or site-specific environment variables, set them in the\
optional file
  ${prefix}/etc/adblock2privoxy/ADBLOCK2PRIVOXY.env
Please note that the macOS command `launchctl setenv` is now prohibited by SIP.
"
if { [variant_isset "initialize_always"] } {
    if {[exists notes]} {
        # leave a blank line after the existing notes
        notes-append ""
    }
    notes-append \
        "The variant +initialize_always is set, which initializes\
        all configuration files. Please disable this variant for\
        working deployments."
}