#!/bin/sh
# Meshvirt Networking: write config.env (0600) from the install wizard
# answers. Runs on install and upgrade; on an upgrade without wizard answers
# the existing config.env is kept. Existing state (device identity) is never
# touched here.
# Meshvirt Networking: shared helpers for the DSM package scripts.
# Inlined into each script at packaging time in place of its "@include common"
# line (release/dist/synology/meshvirt_package.go); POSIX sh only.

PKGNAME="MeshvirtNetworking"
DEFAULT_SERVER_URL="https://mesh.meshvirt.io"

# meshvirt_pkgvar prints the directory holding state, config and logs.
meshvirt_pkgvar() {
    if [ "${SYNOPKG_DSM_VERSION_MAJOR:-7}" = "6" ]; then
        echo "/var/packages/${PKGNAME}/etc"
    elif [ -n "${SYNOPKG_PKGVAR}" ]; then
        echo "${SYNOPKG_PKGVAR}"
    else
        echo "/var/packages/${PKGNAME}/var"
    fi
}

# meshvirt_quote prints $1 single-quoted for a shell/env file.
meshvirt_quote() {
    printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"
}

# meshvirt_valid_url succeeds if $1 is https://host[:port][/path].
meshvirt_valid_url() {
    printf '%s' "$1" | grep -Eq '^https://[A-Za-z0-9.-]+(:[0-9]{1,5})?(/[^[:space:]?#]*)?$'
}

# meshvirt_valid_hostname succeeds if $1 is a DNS label.
meshvirt_valid_hostname() {
    printf '%s' "$1" | grep -Eq '^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?$'
}

# meshvirt_valid_code succeeds if $1 looks like a pre-auth key (8-512
# characters). The length is checked separately: bounds above RE_DUP_MAX
# (255) are rejected by BSD grep.
meshvirt_valid_code() {
    [ ${#1} -ge 8 ] && [ ${#1} -le 512 ] && printf '%s' "$1" | grep -Eq '^[A-Za-z0-9_.:+=/-]+$'
}

# meshvirt_has_net_caps DAEMON succeeds if DAEMON carries cap_net_admin.
# Uses getcap when DSM has it; otherwise the marker "meshvirt configure-host"
# writes after setcap, valid only while it is newer than the binary (an
# upgrade replaces the binary and drops its capabilities).
meshvirt_has_net_caps() {
    for g in /bin/getcap /usr/bin/getcap /sbin/getcap /usr/sbin/getcap; do
        if [ -x "$g" ]; then
            "$g" "$1" 2>/dev/null | grep -q "cap_net_admin"
            return $?
        fi
    done
    marker="$(meshvirt_pkgvar)/net-caps"
    [ -f "${marker}" ] && [ "${marker}" -nt "$1" ]
}

# meshvirt_log appends a line to the package log.
meshvirt_log() {
    echo "$(date '+%Y-%m-%dT%H:%M:%S%z') $*" >>"$(meshvirt_pkgvar)/meshvirt-package.log" 2>/dev/null
}

# meshvirt_notify shows $1 in DSM's result dialog (if DSM gave us a log
# file), the package log and stderr, without failing the operation.
meshvirt_notify() {
    [ -n "${SYNOPKG_TEMP_LOGFILE}" ] && echo "$1" >>"${SYNOPKG_TEMP_LOGFILE}"
    meshvirt_log "$1"
    echo "$1" >&2
}

# meshvirt_fail reports $1 to the DSM wizard and exits non-zero.
meshvirt_fail() {
    [ -n "${SYNOPKG_TEMP_LOGFILE}" ] && echo "$1" >"${SYNOPKG_TEMP_LOGFILE}"
    echo "$1" >&2
    exit 1
}

PKGVAR="$(meshvirt_pkgvar)"
CONFIG="${PKGVAR}/config.env"
umask 077
mkdir -p "${PKGVAR}"

write_config=""
if [ -n "${wizard_server_url+x}" ]; then
    # The install (or upgrade) wizard ran.
    url="${wizard_server_url:-${DEFAULT_SERVER_URL}}"
    host="${wizard_hostname:-}"
    write_config=1
elif [ ! -f "${CONFIG}" ]; then
    # No wizard and no earlier config: defaults (device name = NAS hostname).
    url="${DEFAULT_SERVER_URL}"
    host=""
    write_config=1
fi

if [ -n "${write_config}" ]; then
    meshvirt_valid_url "${url}" || meshvirt_fail "Server URL must start with https://."
    if [ -n "${host}" ] && ! meshvirt_valid_hostname "${host}"; then
        meshvirt_fail "Device name may use letters, digits and hyphens (up to 63 characters)."
    fi
    tmp="${CONFIG}.tmp.$$"
    {
        echo "# Meshvirt Networking package settings (written by postinst)."
        echo "MESHVIRT_SERVER_URL=$(meshvirt_quote "${url}")"
        echo "MESHVIRT_HOSTNAME=$(meshvirt_quote "${host}")"
    } >"${tmp}" && chmod 0600 "${tmp}" && mv -f "${tmp}" "${CONFIG}" \
        || meshvirt_fail "Could not write ${CONFIG}."
    meshvirt_log "postinst: wrote config.env (server ${url}, device name '${host:-<NAS hostname>}')"
fi

if [ -n "${wizard_enroll_code}" ]; then
    # Single-use code from https://enroll.meshvirt.io. start-stop-status uses
    # it once ("meshvirt up --auth-key=file:...") and deletes it on success.
    key="${PKGVAR}/enroll.key"
    rm -f "${key}" "${PKGVAR}/enroll.status"
    (umask 077 && printf '%s' "${wizard_enroll_code}" >"${key}") || meshvirt_fail "Could not store the enrollment code."
    chmod 0600 "${key}"
    meshvirt_log "postinst: enrollment code stored for first start"
fi

if [ "${SYNOPKG_DSM_VERSION_MAJOR}" = "6" ]; then
    chown -R meshvirt:meshvirt "${PKGVAR}" 2>/dev/null
fi
exit 0
