Artifact [d546c4b48d]

Artifact d546c4b48dfce80703e026590970cfac30222041:


     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
   100
   101
   102
   103
   104
   105
   106
   107
   108
   109
   110
   111
   112
   113
   114
   115
   116
   117
   118
   119
   120
#! /usr/bin/env bash

url="$1"
file="$2"
hash="$3"

if [ "${#}" != '3' ]; then
	echo 'Usage: download <url> <file> <hash>' >&2

	exit 1
fi

for tryDownloadProgram in wget curl; do
	tryDownloadProgramPath="$(which "${tryDownloadProgram}" 2>/dev/null)"

	if [ -z "${tryDownloadProgramPath}" ]; then
		continue
	fi

	if [ -x "${tryDownloadProgramPath}" ]; then
		downloadProgram="${tryDownloadProgram}"
		downloadProgramPath="${tryDownloadProgramPath}"

		break
	fi
done

case "${hash}" in
	????????????????????????????????????????)
		hashMethod='sha1'
		;;
	????????????????????????????????????????????????????????????????)
		hashMethod='sha256'
		;;
	-)
		hashMethod='null'
		;;
	*)
		echo "Unknown hash method for hash ${hash}" >&2

		exit 1
		;;
esac

function downloadFile() {
	local file urls
	local downloadProgramArgs
	local url
	local authoritativeURL

	file="$1"
	shift

	urls=("$@")

	authoritativeURL="${urls[@]: -1}"

	case "${downloadProgram}" in
		curl)
			downloadProgramArgs=(--header "X-Cache-URL: ${authoritativeURL}" --location --insecure --fail --output "${file}")
			;;
		wget)
			downloadProgramArgs=(--header="X-Cache-URL: ${authoritativeURL}" --no-check-certificate --output-document="${file}")
			;;
	esac

	for url in "${urls[@]}" __fail__; do
		rm -f "${file}"

		if [ "${url}" = '__fail__' ]; then
			return 1
		fi

		"${downloadProgram}" "${downloadProgramArgs[@]}" "${url}" && break
	done

	return 0
}

function verifyHash() {
	local file hash hashMethod
	local checkHash

	file="$1"
	hash="$2"
	hashMethod="$3"

	if [ "${hashMethod}" = 'null' ]; then
		return 0
	fi

	checkHash="$(openssl dgst "-${hashMethod}" "${file}" | sed 's@.*= *@@')"

	if [ "${checkHash}" = "${hash}" ]; then
		return 0
	fi

	echo "Hash (${hashMethod}) mismatch: Got: ${checkHash}; Expected: ${hash}" >&2

	return 1
}

rm -f "${file}.new" || exit 1

urls=("${url}")

if [ "${hashMethod}" != 'null' ]; then
	urls=(
		"http://hashcache.rkeene.org/${hashMethod}/${hash}"
		"${urls[@]}"
	)
fi

downloadFile "${file}.new" "${urls[@]}" || exit 1

verifyHash "${file}.new" "${hash}" "${hashMethod}" || exit 1

mv "${file}.new" "${file}" || exit 1

exit 0