#!/bin/sh

set -eu

NGINX_CONFIG=/etc/nginx/conf.d/dav-ext-autopkgtest.conf
DOCUMENT_ROOT=/var/lib/nginx/dav-ext-autopkgtest
TEST_URL=http://127.0.0.1:18080
HEADERS="${AUTOPKGTEST_TMP}/webdav.headers"
BODY="${AUTOPKGTEST_TMP}/webdav.body"

cleanup()
{
    rm -f "${NGINX_CONFIG}" "${DOCUMENT_ROOT}/foo" \
        "${DOCUMENT_ROOT}/locked"
    rmdir "${DOCUMENT_ROOT}" 2>/dev/null || :
    invoke-rc.d nginx reload >/dev/null 2>&1 || :
}

trap cleanup EXIT

diagnostics()
{
    if [ -f "${HEADERS}" ]; then
        echo "=== response headers ==="
        sed 's/\r$//' "${HEADERS}"
    fi
    if [ -f "${BODY}" ]; then
        echo "=== response body ==="
        cat "${BODY}"
    fi
    echo "=== journalctl ==="
    journalctl -n all -xu nginx.service || :
    echo "=== error.log ==="
    if [ -f /var/log/nginx/error.log ]; then
        cat /var/log/nginx/error.log
    else
        echo "/var/log/nginx/error.log not found"
    fi
}

fail()
{
    echo "FAILED: $*" >&2
    diagnostics
    exit 1
}

request()
{
    method="$1"
    url="$2"
    shift 2

    status="$(curl --silent --show-error --max-time 60 \
        --retry 10 --retry-connrefused --retry-delay 1 \
        --request "${method}" "$@" \
        --dump-header "${HEADERS}" --output "${BODY}" \
        --write-out '%{http_code}' "${url}")" ||
        fail "${method} ${url} request failed"
}

install -d -o www-data -g www-data -m 0755 "${DOCUMENT_ROOT}"
printf '%s' 'foo' > "${DOCUMENT_ROOT}/foo"

cat > "${NGINX_CONFIG}" <<'EOF'
dav_ext_lock_zone zone=dav_ext_autopkgtest:1m timeout=60s;

server {
    listen 127.0.0.1:18080;
    server_name localhost;

    root /var/lib/nginx/dav-ext-autopkgtest;

    location / {
        dav_methods PUT DELETE MKCOL COPY MOVE;
        dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
        dav_ext_lock zone=dav_ext_autopkgtest;
    }
}
EOF

nginx -t || fail "nginx configuration test"
invoke-rc.d nginx restart || fail "nginx restart"

request OPTIONS "${TEST_URL}/"
[ "${status}" = 200 ] || fail "OPTIONS returned HTTP ${status}, expected 200"
grep -Eiq '^DAV:[[:space:]]*2[[:space:]]*\r?$' "${HEADERS}" ||
    fail "OPTIONS response lacks DAV: 2"
grep -Eiq '^Allow:.*PROPFIND.*OPTIONS.*LOCK.*UNLOCK' "${HEADERS}" ||
    fail "OPTIONS response does not advertise all supported methods"
echo "OPTIONS returned the expected DAV and Allow headers ... OK"

request PROPFIND "${TEST_URL}/foo" \
    --header 'Depth: 0' \
    --header 'Content-Type: application/xml' \
    --data-binary '<?xml version="1.0"?><D:propfind xmlns:D="DAV:"><D:allprop/></D:propfind>'
[ "${status}" = 207 ] || fail "PROPFIND returned HTTP ${status}, expected 207"
grep -Fq '<D:displayname>foo</D:displayname>' "${BODY}" ||
    fail "PROPFIND response lacks the file display name"
grep -Fq '<D:getcontentlength>3</D:getcontentlength>' "${BODY}" ||
    fail "PROPFIND response lacks the expected file size"
echo "PROPFIND returned metadata for the test file ... OK"

request LOCK "${TEST_URL}/locked" --header 'Depth: 0'
[ "${status}" = 201 ] || fail "LOCK returned HTTP ${status}, expected 201"
lock_token="$(awk '
    tolower($1) == "lock-token:" {
        sub(/\r$/, "", $2)
        print $2
    }
' "${HEADERS}")"
[ -n "${lock_token}" ] || fail "LOCK response lacks a lock token"
[ -f "${DOCUMENT_ROOT}/locked" ] || fail "LOCK did not create the resource"
echo "LOCK created the resource and returned a lock token ... OK"

request PUT "${TEST_URL}/locked" --data-binary 'blocked'
[ "${status}" = 423 ] ||
    fail "PUT without the lock token returned HTTP ${status}, expected 423"
echo "LOCK prevented a PUT without the lock token ... OK"

request UNLOCK "${TEST_URL}/locked" --header "Lock-Token: ${lock_token}"
[ "${status}" = 204 ] || fail "UNLOCK returned HTTP ${status}, expected 204"

request PUT "${TEST_URL}/locked" --data-binary 'updated'
[ "${status}" = 204 ] ||
    fail "PUT after UNLOCK returned HTTP ${status}, expected 204"
grep -Fqx 'updated' "${DOCUMENT_ROOT}/locked" ||
    fail "PUT after UNLOCK did not update the resource"
echo "UNLOCK released the resource for subsequent writes ... OK"

echo "WebDAV method tests ... OK"
