-
-
Save ChaosJohn/14cfcde4c3d659738919be149bd85d28 to your computer and use it in GitHub Desktop.
Download VMware Fusion Pro Without a Broadcom Account
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Download VMware Fusion for macOS without Broadcom account | |
# | |
# Use '-k' to keep the download file compressed, exiting after download. | |
# Use '-v VERSION' to specify desired version (13.0.0 or higher required). | |
BASE_URL="https://softwareupdate-prod.broadcom.com/cds/vmw-desktop" | |
CDN_MIRROR="softwareupdate-prod.broadcom.com:443:softwareupdate-prod.broadcom.com.cdn.cloudflare.net:443" | |
read -r -d '' XML_DATA << 'EOF' | |
<metalist> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.0.1/21139760/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.5.0/22583790/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.6.0/24238079/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.6.1/24319021/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.6.2/24409261/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.6.3/24585314/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.5.2/23775688/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.5.1/23298085/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.0.2/21581413/universal/core/</url> | |
</metadata> | |
<metadata> | |
<version>13.0.0</version> | |
<url>fusion/13.0.0/20802013/universal/core/</url> | |
</metadata> | |
</metalist> | |
EOF | |
KEEP_COMPRESSED=false | |
USER_VERSION="" | |
VERSION="" | |
BUILD="" | |
while getopts "kv:" opt; do | |
case $opt in | |
k) KEEP_COMPRESSED=true ;; | |
v) USER_VERSION=$OPTARG ;; | |
*) echo "Usage: $0 [-k] [-v VERSION]" >&2; exit 1 ;; | |
esac | |
done | |
requirements_check() { | |
command -v curl >/dev/null 2>&1 || { echo "Error: curl is required but not installed." >&2; exit 1; } | |
command -v grep >/dev/null 2>&1 || { echo "Error: grep is required but not installed." >&2; exit 1; } | |
command -v awk >/dev/null 2>&1 || { echo "Error: awk is required but not installed." >&2; exit 1; } | |
command -v sed >/dev/null 2>&1 || { echo "Error: sed is required but not installed." >&2; exit 1; } | |
command -v tar >/dev/null 2>&1 || { echo "Error: tar is required but not installed." >&2; exit 1; } | |
command -v sort >/dev/null 2>&1 || { echo "Error: sort is required but not installed." >&2; exit 1; } | |
command -v unzip >/dev/null 2>&1 || { echo "Error: unzip is required but not installed." >&2; exit 1; } | |
} | |
macos_requirements_check() { | |
(("${OSTYPE:6:2}" < 20)) && { echo "Warning: VMware Fusion v13.0.0+ requires macOS 11 or higher." >&2; return 1; } || return 0 | |
} | |
requirements_check | |
if sort --version 2>/dev/null | grep -q "GNU coreutils"; then | |
SORT_CMD="sort -V" | |
SORT_UNIQUE_CMD="sort -uV" | |
else | |
SORT_CMD="sort -t. -k1,1n -k2,2n -k3,3n -k4,4n" | |
SORT_UNIQUE_CMD="sort -t. -k1,1n -k2,2n -k3,3n -k4,4n -u" | |
fi | |
if [[ $(uname | tr '[:upper:]' '[:lower:]') != "darwin"* ]]; then | |
KEEP_COMPRESSED=true | |
echo "Warning: Not running on macOS. Keeping file compressed." >&2 | |
else | |
macos_requirements_check || { echo "Proceeding with download, but installation may fail due to macOS version." >&2; } | |
fi | |
version_gte() { | |
printf '%s\n%s\n' "$1" "$2" | eval "$SORT_CMD" | head -n 1 | grep -q "^$2$" | |
} | |
get_base_versions() { | |
echo "$XML_DATA" | awk ' | |
BEGIN {FS="[<>]"} | |
/<version>/ { | |
if ($3 ~ /^[0-9]+\.0\.0$/) { | |
print $3; | |
} | |
}' | eval "$SORT_UNIQUE_CMD" | |
} | |
get_full_versions_and_builds() { | |
local selected_base_major="$1" | |
local major_version_prefix=$(echo "$selected_base_major" | cut -d'.' -f1) | |
echo "$XML_DATA" | awk -v target_major="$major_version_prefix" ' | |
BEGIN { | |
in_metadata = 0; | |
current_version_tag = ""; | |
} | |
/<metadata>/ { in_metadata = 1; current_version_tag = ""; } | |
/<\/metadata>/ { in_metadata = 0; } | |
in_metadata && /<version>/ { | |
current_version_tag = $0; | |
gsub(/.*<version>|<\/version>.*/, "", current_version_tag); | |
} | |
in_metadata && /<url>/ { | |
url_tag=$0; | |
gsub(/.*<url>fusion\/|<\/url>.*/, "", url_tag); | |
split(url_tag, parts, "/"); | |
if (current_version_tag == target_major ".0.0" && parts[1] ~ "^" target_major "\\..*") { | |
print parts[1], parts[2]; | |
} | |
}' | eval "$SORT_UNIQUE_CMD" | |
} | |
get_specific_version_and_build() { | |
local target_version="$1" | |
local target_major_prefix=$(echo "$target_version" | cut -d'.' -f1) | |
echo "$XML_DATA" | awk -v target_ver="$target_version" -v target_major_prefix_awk="$target_major_prefix" ' | |
BEGIN { | |
FS="[<>]"; | |
current_version_tag_content = ""; | |
} | |
/<metadata>/ { current_version_tag_content = ""; } | |
/<version>/ { current_version_tag_content = $3; } | |
/<url>/ { | |
if (current_version_tag_content == target_major_prefix_awk ".0.0") { | |
split($3, url_parts, "/"); | |
full_version = url_parts[2]; | |
build_number = url_parts[3]; | |
if (full_version == target_ver) { | |
print full_version, build_number; | |
exit; | |
} | |
} | |
}' | |
} | |
check_url() { | |
local url=$1 | |
curl -s --head --connect-to "$CDN_MIRROR" "$url" | head -n 1 | grep "200" >/dev/null | |
} | |
if [[ -n "$USER_VERSION" ]]; then | |
version_gte "${USER_VERSION}" "13.0.0" || { echo "Error: Specified version ${USER_VERSION} is not supported. Fusion 13.0.0 or higher is required." >&2; exit 1; } | |
read -r VERSION BUILD <<< "$(get_specific_version_and_build "$USER_VERSION")" | |
[[ -z "$VERSION" || -z "$BUILD" ]] && { echo "Error: Version ${USER_VERSION} not found in the embedded XML data or URL format is unexpected." >&2; exit 1; } | |
else | |
#echo "Available base versions:" | |
#mapfile -t base_versions_array < <(get_base_versions) | |
#[[ ${#base_versions_array[@]} -eq 0 ]] && { echo "No base versions found in XML data. Exiting." >&2; exit 1; } | |
#PS3="Select a base version: " | |
#select base_version_selected in "${base_versions_array[@]}"; do | |
# [[ -n "$base_version_selected" ]] && break || echo "Invalid selection. Please try again." | |
#done | |
base_version_selected="13.0.0" | |
echo "Available versions for base version $base_version_selected:" | |
full_versions_builds_array=() | |
while IFS= read -r line; do | |
full_versions_builds_array+=("$line") | |
done < <(get_full_versions_and_builds "$base_version_selected") | |
[[ ${#full_versions_builds_array[@]} -eq 0 ]] && { echo "No full versions found for base version $base_version_selected. Exiting." >&2; exit 1; } | |
declare -a display_full_versions | |
for item in "${full_versions_builds_array[@]}"; do | |
display_full_versions+=("$(echo "$item" | awk '{print $1}')") | |
done | |
IFS=$'\n' sorted_display_full_versions=($(printf "%s\n" "${display_full_versions[@]}" | eval "$SORT_CMD")) | |
unset IFS | |
PS3="Select a full version: " | |
select full_version_selected in "${sorted_display_full_versions[@]}"; do | |
[[ -n "$full_version_selected" ]] && break || echo "Invalid selection. Please try again." | |
done | |
for item in "${full_versions_builds_array[@]}"; do | |
read -r ver build_num <<< "$item" | |
[[ "$ver" == "$full_version_selected" ]] && { BUILD="$build_num"; break; } | |
done | |
[[ -z "$BUILD" ]] && { echo "Error: Could not find build number for version '$full_version_selected'. This can happen if selection is invalid." >&2; exit 1; } | |
VERSION="$full_version_selected" | |
fi | |
echo "Selected version: $VERSION with build: $BUILD" | |
DOWNLOAD_URL="${BASE_URL}/fusion/${VERSION}/${BUILD}/universal/core/com.vmware.fusion.zip.tar" | |
DOWNLOAD_DIR="${HOME}/Downloads" | |
DOWNLOAD_FILE="${DOWNLOAD_DIR}/com.vmware.fusion-${VERSION}-${BUILD}.zip.tar" | |
UNZIP_DIR="${DOWNLOAD_DIR}/com.vmware.fusion-${VERSION}-${BUILD}" | |
APP_PATH="${UNZIP_DIR}/VMware Fusion.app" | |
echo "Downloading VMware Fusion v${VERSION} (${BUILD})..." | |
mkdir -p "${DOWNLOAD_DIR}" | |
check_url "$DOWNLOAD_URL" || { echo "Error: Installer file not found at $DOWNLOAD_URL even via CDN. Please check the version/build or XML data." >&2; exit 1; } | |
curl -k -q --progress-bar -f -o "${DOWNLOAD_FILE}" --connect-to "$CDN_MIRROR" "${DOWNLOAD_URL}" || { | |
echo "Error: Download failed for ${DOWNLOAD_URL}." >&2 | |
exit 1 | |
} | |
${KEEP_COMPRESSED} && { echo -e "\nFinished. Downloaded file location: ${DOWNLOAD_FILE}"; exit 0; } | |
echo "Extracting tar..." | |
mkdir -p "${UNZIP_DIR}" | |
tar -xf "${DOWNLOAD_FILE}" -C "${UNZIP_DIR}" || { | |
echo "Error: Extraction of tar file failed and may be corrupt." >&2 | |
echo "Downloaded file location: ${DOWNLOAD_FILE}" >&2 | |
rm -rf "${UNZIP_DIR}" | |
exit 1 | |
} | |
echo "Extracting zip..." | |
unzip -q "${UNZIP_DIR}/com.vmware.fusion.zip" "payload/VMware Fusion.app/*" -d "${UNZIP_DIR}" || { | |
echo "Error: Extraction of zip file failed and may be corrupt." >&2 | |
echo "Downloaded file location: ${DOWNLOAD_FILE}" >&2 | |
rm -rf "${UNZIP_DIR}" | |
exit 1 | |
} | |
echo "Cleaning up..." | |
mv "${UNZIP_DIR}/payload/VMware Fusion.app" "${APP_PATH}" | |
xattr -dr com.apple.quarantine "${APP_PATH}" &>/dev/null | |
rm -rf "${DOWNLOAD_FILE}" "${UNZIP_DIR}/com.vmware.fusion.zip" "${UNZIP_DIR}/descriptor.xml" "${UNZIP_DIR}/payload" 2>/dev/null | |
LICENSE_FILES=$(ls -1 "/Library/Preferences/VMware Fusion/license-fusion"* 2>/dev/null) | |
[[ -n "${LICENSE_FILES}" ]] && { | |
echo -e "\nNotice: Existing license file(s) found.\nDeletion is required if converting to \"Free for Personal Use\" model.\nTo remove:" >&2 | |
for LICENSE_FILE in ${LICENSE_FILES}; do | |
echo "sudo rm \"${LICENSE_FILE}\"" >&2 | |
done | |
} | |
echo -e "\nFinished. You can now move the app into the desired location.\nVMware Fusion.app location: ${APP_PATH}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment