#!/bin/zsh
# Script Version: 12.4
# Description: Dyn DNS update script, checks token and updates DNS zone.

# Set variables
DIRECTORY="/var/www/ip/token"
LOG_FILE="/var/log/dynProxy.log"
TOKEN_DNS_ZONE_FILE="/etc/bind/tokendnszone.conf"
NSUPDATE_SERVER="127.0.0.1"
DEBUG=true

log() {
   local message="$1"
   echo "$(date '+%Y-%m-%dT%H:%M:%S.%6N'): $message" >> "$LOG_FILE"
   if $DEBUG; then echo "$message"; fi
}

log_debug() {
   if $DEBUG; then log "$1"; fi
}

# Output FastCGI headers
# These must be the first lines output by the script
echo "Content-Type: text/plain"
echo ""

log "Starting DNS update script."

# Extract the token and IP from the POST data
read -r post_data
log "Received POST data: $post_data"
TOKEN=$(echo "$post_data" | grep -oP '(?<=token=)[a-zA-Z0-9_-]+')
NEW_IP=$(echo "$post_data" | grep -oP '(?<=ip=)[0-9.]+')

if [ -z "$TOKEN" ]; then
   echo "Status: 400 Bad Request"
   echo "Missing token"
   log "Missing token"
   exit 1
fi

if [ -z "$NEW_IP" ]; then
   echo "Status: 400 Bad Request"
   echo "Missing IP"
   log "Missing IP in POST data"
   exit 1
fi

log "Token $TOKEN validated successfully."
log "New IP extracted from POST data: $NEW_IP"

TOKEN_FILE="${DIRECTORY}/${TOKEN}.txt"
if [ ! -f "$TOKEN_FILE" ]; then
   echo "Status: 403 Forbidden"
   echo "Token file not found"
   log "Token file not found for token $TOKEN"
   exit 1
fi

log "Token file found for token $TOKEN."

CLIENT_INFO=$(grep -m 1 "^$TOKEN," "$TOKEN_DNS_ZONE_FILE")
log_debug "CLIENT_INFO: $CLIENT_INFO"

if [ -z "$CLIENT_INFO" ]; then
   echo "Status: 403 Forbidden"
   echo "Token mapping not found in DNS zone configuration"
   log "Token mapping not found for token $TOKEN"
   exit 1
fi

log "Token mapping found for token $TOKEN."

DOMAIN=$(echo "$CLIENT_INFO" | cut -d',' -f2)
ZONE_FILE=$(echo "$CLIENT_INFO" | cut -d',' -f3)

if [ ! -f "$ZONE_FILE" ]; then
   echo "Status: 404 Not Found"
   echo "Zone file $ZONE_FILE not found"
   log "Zone file $ZONE_FILE not found for domain $DOMAIN"
   exit 1
fi

log "Zone file $ZONE_FILE found for domain $DOMAIN."

CURRENT_IP=$(cat "$TOKEN_FILE" | tr -d '[:space:]')
log "Current IP from token file: $CURRENT_IP"

SHORT_DOMAIN="${DOMAIN%%.*}"
ZONE_IP=$(awk -v origin="dynproxy.net." -v domain="$DOMAIN" '
   BEGIN {FS="[ \t]+"}
   $1 == substr(domain, 1, index(domain, ".") - 1) && $2 == "A" {print $3}
   $1 == domain && $2 == "A" {print $3}
' "$ZONE_FILE" | tr -d '[:space:]')

if [ -z "$ZONE_IP" ]; then
   log "Failed to extract ZONE_IP for domain $DOMAIN from zone file $ZONE_FILE. Ensure the A record exists."
   echo "Status: 500 Internal Server Error"
   echo "Failed to extract ZONE_IP for domain $DOMAIN"
   exit 1
fi

log "Extracted ZONE_IP for $DOMAIN: $ZONE_IP"

if [ "$NEW_IP" = "$ZONE_IP" ]; then
   echo "IP in zone file is already up-to-date. No update needed."
   log "IP for $DOMAIN is already up-to-date. No update needed."
   exit 0
fi

log "IP has changed for $DOMAIN. Proceeding with DNS update."

nsupdate_output=$(nsupdate <<EOF 2>&1
server $NSUPDATE_SERVER
zone ${DOMAIN#*.}
update delete $DOMAIN A
update add $DOMAIN 604800 A $NEW_IP
send
EOF
)

if [ $? -ne 0 ]; then
   echo "Status: 500 Internal Server Error"
   echo "Failed to update DNS for $DOMAIN"
   log "Failed to update DNS for $DOMAIN. nsupdate output: $nsupdate_output"
   exit 1
fi

log "DNS updated successfully for $DOMAIN to IP $NEW_IP"

echo "$NEW_IP" > "$TOKEN_FILE"
if [ $? -eq 0 ]; then
   log "Token file updated with new IP: $NEW_IP"
else
   log "Failed to update token file: $TOKEN_FILE"
fi

echo "IP updated successfully for $DOMAIN"