From f448a58184c32439f325883414b9983fa24e6fc7 Mon Sep 17 00:00:00 2001 From: CZECHIA-COM Date: Tue, 24 Feb 2026 17:58:58 +0100 Subject: [PATCH] Update dns_czechia.sh fix(dnsapi): make dns_czechia.sh shellcheck/shfmt clean --- dnsapi/dns_czechia.sh | 103 ++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/dnsapi/dns_czechia.sh b/dnsapi/dns_czechia.sh index 3166e4b7..6fba9bd0 100644 --- a/dnsapi/dns_czechia.sh +++ b/dnsapi/dns_czechia.sh @@ -11,7 +11,7 @@ # Required env: # CZ_AuthorizationToken (saved to account.conf for automatic renewals) # CZ_Zones zone(s) separated by comma/space, e.g. "example.com" or "example.com,example.net" -# For SAN/wildcard, the plugin picks the longest matching zone suffix per-domain. +# For SAN/wildcard, the plugin picks the longest matching zone suffix per-domain. # # Optional env (can be saved): # CZ_TTL (default 3600) @@ -24,15 +24,17 @@ dns_czechia_add() { txtvalue="$2" _info "Czechia DNS add TXT for $fulldomain" - _czechia_load_conf || return 1 zone="$(_czechia_pick_zone "$fulldomain")" || return 1 host="$(_czechia_rel_host "$fulldomain" "$zone")" || return 1 - url="$CZ_API_BASE/api/DNS/$zone/TXT" body="$(_czechia_build_body "$host" "$txtvalue")" + _info "Czechia zone: $zone" + _info "Czechia API URL: $url" + _info "Czechia hostName: $host" + _czechia_api_request "POST" "$url" "$body" } @@ -41,44 +43,44 @@ dns_czechia_rm() { txtvalue="$2" _info "Czechia DNS remove TXT for $fulldomain" - _czechia_load_conf || return 1 zone="$(_czechia_pick_zone "$fulldomain")" || return 1 host="$(_czechia_rel_host "$fulldomain" "$zone")" || return 1 - url="$CZ_API_BASE/api/DNS/$zone/TXT" body="$(_czechia_build_body "$host" "$txtvalue")" + _info "Czechia zone: $zone" + _info "Czechia API URL: $url" + _info "Czechia hostName: $host" + _czechia_api_request "DELETE" "$url" "$body" } -#################### Internal helpers #################### - _czechia_load_conf() { - CZ_AuthorizationToken="${CZ_AuthorizationToken:-$(_readaccountconf_mutable CZ_AuthorizationToken)}" - if [ -z "$CZ_AuthorizationToken" ]; then _err "CZ_AuthorizationToken is missing." + _err "Export it first: export CZ_AuthorizationToken=\"...\"" return 1 fi - _saveaccountconf_mutable CZ_AuthorizationToken "$CZ_AuthorizationToken" CZ_Zones="${CZ_Zones:-$(_readaccountconf_mutable CZ_Zones)}" CZ_TTL="${CZ_TTL:-$(_readaccountconf_mutable CZ_TTL)}" CZ_PublishZone="${CZ_PublishZone:-$(_readaccountconf_mutable CZ_PublishZone)}" CZ_API_BASE="${CZ_API_BASE:-$(_readaccountconf_mutable CZ_API_BASE)}" + CZ_CURL_TIMEOUT="${CZ_CURL_TIMEOUT:-$(_readaccountconf_mutable CZ_CURL_TIMEOUT)}" if [ -z "$CZ_Zones" ]; then - _err "CZ_Zones is required." + _err "CZ_Zones is required (apex zone), e.g. \"example.com\" or \"example.com,example.net\"" return 1 fi [ -z "$CZ_TTL" ] && CZ_TTL="3600" [ -z "$CZ_PublishZone" ] && CZ_PublishZone="1" [ -z "$CZ_API_BASE" ] && CZ_API_BASE="https://api.czechia.com" + [ -z "$CZ_CURL_TIMEOUT" ] && CZ_CURL_TIMEOUT="30" CZ_Zones="$(_czechia_norm_zonelist "$CZ_Zones")" CZ_API_BASE="$(printf "%s" "$CZ_API_BASE" | sed 's:/*$::')" @@ -87,91 +89,102 @@ _czechia_load_conf() { _saveaccountconf_mutable CZ_TTL "$CZ_TTL" _saveaccountconf_mutable CZ_PublishZone "$CZ_PublishZone" _saveaccountconf_mutable CZ_API_BASE "$CZ_API_BASE" + _saveaccountconf_mutable CZ_CURL_TIMEOUT "$CZ_CURL_TIMEOUT" return 0 } _czechia_norm_zonelist() { + # Normalize comma/space separated list to a single comma-separated list + # - lowercased + # - trimmed + # - trailing dots removed + # - empty entries dropped in="$1" [ -z "$in" ] && return 0 - in="$(printf "%s" "$in" | tr 'A-Z' 'a-z')" + in="$(_lower_case "$in")" printf "%s" "$in" | tr ' ' ',' | tr -s ',' | - sed 's/[\t\r\n]//g; s/\.$//; s/^,//; s/,$//' + sed 's/[\t\r\n]//g; s/\.$//; s/^,//; s/,$//; s/,,*/,/g' } _czechia_pick_zone() { fulldomain="$1" - fd="$(printf "%s" "$fulldomain" | tr 'A-Z' 'a-z' | sed 's/\.$//')" + fd="$(_lower_case "$fulldomain")" + fd="$(printf "%s" "$fd" | sed 's/\.$//')" best="" bestlen=0 oldifs="$IFS" IFS=',' - for z in $CZ_Zones; do z="$(printf "%s" "$z" | sed 's/^ *//; s/ *$//; s/\.$//')" + [ -z "$z" ] && continue case "$fd" in - "$z" | *".$z") - if [ "${#z}" -gt "$bestlen" ]; then - best="$z" - bestlen=${#z} - fi - ;; + "$z" | *".$z") + if [ "${#z}" -gt "$bestlen" ]; then + best="$z" + bestlen=${#z} + fi + ;; esac done - IFS="$oldifs" if [ -z "$best" ]; then - _err "No matching zone found for $fd" + _err "No matching zone for '$fd'. Set CZ_Zones to include the apex zone for this domain." return 1 fi printf "%s" "$best" + return 0 } _czechia_rel_host() { fulldomain="$1" zone="$2" - fd="$(printf "%s" "$fulldomain" | tr 'A-Z' 'a-z' | sed 's/\.$//')" - z="$(printf "%s" "$zone" | tr 'A-Z' 'a-z' | sed 's/\.$//')" + fd="$(_lower_case "$fulldomain")" + fd="$(printf "%s" "$fd" | sed 's/\.$//')" + + z="$(_lower_case "$zone")" + z="$(printf "%s" "$z" | sed 's/\.$//')" if [ "$fd" = "$z" ]; then - printf "@" + printf "%s" "@" return 0 fi suffix=".$z" - case "$fd" in - *"$suffix") - rel="${fd%"$suffix"}" - [ -z "$rel" ] && rel="@" - printf "%s" "$rel" - return 0 - ;; + *"$suffix") + rel="${fd%"$suffix"}" + [ -z "$rel" ] && rel="@" + printf "%s" "$rel" + return 0 + ;; esac - _err "Domain $fd is not under zone $z" + _err "fulldomain '$fd' is not under zone '$z'" return 1 } _czechia_build_body() { host="$1" txt="$2" + txt_escaped="$(_czechia_json_escape "$txt")" + printf "%s" "{\"hostName\":\"$host\",\"text\":\"$txt_escaped\",\"ttl\":$CZ_TTL,\"publishZone\":$CZ_PublishZone}" +} - txt_escaped="$(printf "%s" "$txt" | sed 's/\\/\\\\/g; s/"/\\"/g')" - - printf '{"hostName":"%s","text":"%s","ttl":%s,"publishZone":%s}' \ - "$host" "$txt_escaped" "$CZ_TTL" "$CZ_PublishZone" +_czechia_json_escape() { + # Minimal JSON escaping for TXT value (backslash + quote) + printf "%s" "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' } _czechia_api_request() { @@ -181,15 +194,19 @@ _czechia_api_request() { export _H1="authorizationToken: $CZ_AuthorizationToken" export _H2="Content-Type: application/json" + export _CURL_TIMEOUT="$CZ_CURL_TIMEOUT" + + _info "Czechia request: $method $url" + _debug2 "Czechia body: $body" - response="$(_post "$body" "$url" "" "$method" "application/json")" - ret="$?" + resp="$(_post "$body" "$url" "" "$method" "application/json")" + post_ret="$?" - if [ "$ret" != "0" ]; then - _err "Czechia API call failed." + if [ "$post_ret" -ne 0 ]; then + _err "Czechia API call failed (ret=$post_ret). Response: ${resp:-}" return 1 fi - _debug2 "Response: $response" + _debug2 "Czechia response: ${resp:-}" return 0 }