#!/bin/sh

echo "KES for Mac 11.2.1 - Patch B"
echo "Patch script v. 2.4"

KAV_DIR="/Library/Application Support/Kaspersky Lab/KAV"
KAV_BINARIES_DIR="$KAV_DIR/Binaries"
KAV_DATA_DIR="$KAV_DIR/Data"
KAV_APP_PKG="$KAV_DATA_DIR/kav_app.tar.gz"
KAV_AGENT_PKG="$KAV_DATA_DIR/kav_agent.tar.gz"
DRIVERS_PKG_DIR="$KAV_DATA_DIR"
DRIVERS_CACHE_DIR="$KAV_DIR/Bases/Cache"
BASES_KLAVA_DIR="$KAV_DIR/Bases/KLAVA"
KAV_AGENT_APP_PATH="$KAV_DIR/Applications/Kaspersky Anti-Virus Agent.app"
KAV_AGENT_WATCHPATH="$KAV_DIR/kickstart_gui"
LAUNCHAGENT_DIR="/Library/LaunchAgents"
LAUNCHAGENT_KAV_PLIST="$LAUNCHAGENT_DIR/com.kaspersky.kav.gui.plist"
LAUNCHAGENT_APP_PLIST="$LAUNCHAGENT_DIR/com.kaspersky.kav.app.plist"
KAV_KICKSTART_DIR_APP="$KAV_DIR"/kickstart_app
DEFAULT_KAVAPP_PATH="/Applications/Kaspersky Anti-Virus For Mac.app"
LOC_TGZ="$KAV_DATA_DIR/loc.tar.gz"
LOC_DIR="$KAV_DIR/Loc"
CONFIG_XML_CHANGES_TMP="/tmp/kav_config_xml_changes"
KAV_UNINSTALLER_PKG="$KAV_DATA_DIR/kav_uninstaller.tar.gz"
KAV_UNINSTALLER_APP_PATH="$KAV_DIR/Applications/Kaspersky Uninstaller.app"

UPDATE_CFG_SCRIPT="$KAV_BINARIES_DIR/update_cfg.pl"
UPDATE_CFG_TARGET="$KAV_BINARIES_DIR/config.xml"
UPDATE_CFGPDKESM_TARGET_X86="$KAV_BINARIES_DIR/configpdk_x86_64.esm"
UPDATE_CFGPDKESM_TARGET_ARM="$KAV_BINARIES_DIR/configpdk_arm64.esm"

KAV_SETTINGS_DB_PATH="$KAV_DATA_DIR/settings.kvdb"

get_environment_key()
{
	/usr/bin/xmllint --xpath "//propertiesmap/key[@name=\"environment\"]/tSTRING[@name=\"$1\"]/text()" "$UPDATE_CFG_TARGET"
}

get_last_patch_deployment()
{
	/usr/bin/xmllint --xpath "//propertiesmap/key[@name=\"Timestamps\"]/tDWORD[@name=\"LastPatchDeployment\"]/text()" "$UPDATE_CFG_TARGET"
}

stop_kav_app()
{
	local KAVAPP_RECORD=$(ps -axwo pid,command | grep -v grep | grep "Contents/MacOS/kav_app")
	local KAVPID=$(/bin/echo -n "$KAVAPP_RECORD" | awk '{print $1}')
	if [ "$KAVPID" != "" ]
	then
		RELAUNCH_KAVAPP_PATH=$(/bin/echo -n "$KAVAPP_RECORD" | sed 's/[ ]*'"$KAVPID"'[ ]*\(.*\.app\).*/\1/')
		kill -s KILL "$KAVPID"
	fi
}

stop_kav_agent()
{
	local KAVPID=$(ps -axwo pid,command | grep -v grep | grep "Contents/MacOS/kav_agent" | awk '{print $1}')
	if [ "$KAVPID" != "" ]
	then
		kill -s KILL $KAVPID
		RESTART_KAVAGENT=1
	fi
}

deploy_launch_agent()
{
    [[ ! -f "${KAV_DATA_DIR}/com.kaspersky.kav.app.plist" ]] && return 0
    cp -rfv "${KAV_DATA_DIR}/com.kaspersky.kav.app.plist" "${LAUNCHAGENT_APP_PLIST}"
        [ $? != 0 ] && echo "error: fail to copy com.kaspersky.kav.app.plist to ${LAUNCHAGENT_APP_PLIST}"
    
    chown root:wheel ${LAUNCHAGENT_APP_PLIST}

    echo "Creating ${KAV_KICKSTART_DIR_APP} kickstart app directory"
    mkdir -pv "${KAV_KICKSTART_DIR_APP}"
        [ $? != 0 ] && echo "error: failed to create ${KAV_KICKSTART_DIR_APP}"

    chmod 0777 "${KAV_KICKSTART_DIR_APP}"

    who | awk '{print $1}' | uniq | while read _USER; do
        sudo su - "$_USER" -c "launchctl load -w \"${LAUNCHAGENT_APP_PLIST}\""
    done

    echo "finish deploy launch agent"

    return 0
}

version_less_than()
{
    local LEFT_MAJOR=`echo "$1" | awk -F"." '{printf "%d\n", $1}'`
    local LEFT_MINOR=`echo "$1" | awk -F"." '{printf "%d\n", $2}'`

    local RIGHT_MAJOR=`echo "$2" | awk -F"." '{printf "%d\n", $1}'`
    local RIGHT_MINOR=`echo "$2" | awk -F"." '{printf "%d\n", $2}'`

    [ "$LEFT_MAJOR" -lt "$RIGHT_MAJOR" ] && return 1
    [ "$LEFT_MAJOR" -gt "$RIGHT_MAJOR" ] && return 0

    [ "$LEFT_MINOR" -lt "$RIGHT_MINOR" ] && return 1
    
    return 0
}

if [ "$1" != "OnHotfixInstalled" ]; then
    if [ -f "$UPDATE_CFG_SCRIPT" ]
    then
    	echo ""
    	echo "Stopping application..."
    	stop_kav_app

    	echo ""
    	echo "Stopping possibly respawned application..."
    	stop_kav_app
    fi

    if [ -e "$LOC_TGZ" ]
    then
        LOC_EXTRACTION_TEMP_PATH=$(mktemp -d)
        echo ""
        echo "Extracting $LOC_TGZ into $LOC_EXTRACTION_TEMP_PATH"
        /usr/bin/tar -xzvf "$LOC_TGZ" -C "$LOC_EXTRACTION_TEMP_PATH"
        echo "Extracted: "
        ls -la "$LOC_EXTRACTION_TEMP_PATH"

        echo ""
        echo "Deploying localizations..."
        echo "Locales:"
        ls -al "$LOC_EXTRACTION_TEMP_PATH/Loc"

        echo "Copy locales to product"
        for LOC in $(ls "$LOC_EXTRACTION_TEMP_PATH/Loc")
        do
            if [ -d "$LOC_DIR"/"$LOC" ]
            then
                cp -Rfv "$LOC_EXTRACTION_TEMP_PATH/Loc"/"$LOC"/ "$LOC_DIR"/"$LOC"
            fi
        done
    fi

    if [ "$KAV_APP_PKG" != "" ]
    then
        LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)
        KAV_APP_PKG_TIMESTAMP=$(stat -f "%m" "$KAV_APP_PKG")
        echo "kav app pkg timestamp: $KAV_APP_PKG_TIMESTAMP, last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"

        if [[ (-e "$KAV_APP_PKG") && ($KAV_APP_PKG_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]]; then
            KAV_APP_EXTRACTION_TEMP_PATH=$(mktemp -d)
            echo ""
            echo "Extracting $KAV_APP_PKG into $KAV_APP_EXTRACTION_TEMP_PATH"
            /usr/bin/tar -xzvf "$KAV_APP_PKG" -C "$KAV_APP_EXTRACTION_TEMP_PATH"
            echo "Extracted: "
            ls -la "$KAV_APP_EXTRACTION_TEMP_PATH"

    		echo ""
    		echo "Deploying application resources..."

            KAVAPP_PATH="$DEFAULT_KAVAPP_PATH"

            KAV_APP_CUR_RES_TEMP_PATH=$(mktemp -d)
            echo ""
            echo "Saving current app resources to ${KAV_APP_CUR_RES_TEMP_PATH}"
            cp -rfv "${KAVAPP_PATH}/Contents/Resources" "${KAV_APP_CUR_RES_TEMP_PATH}"

            echo ""
            echo "Deleting current app"
            rm -rfv "${KAVAPP_PATH}"

            echo ""
            echo "Moving ${KAV_APP_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus For Mac.app to ${KAVAPP_PATH}"
            cp -rvf "${KAV_APP_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus For Mac.app" "${KAVAPP_PATH}"

            echo ""
            echo "Updating app resources"
                    
            echo ""
            echo "Deleting ${KAVAPP_PATH}/Contents/Resources"
            rm -rfv "${KAVAPP_PATH}/Contents/Resources"

            echo ""
            echo "Moving ${KAV_APP_CUR_RES_TEMP_PATH}/Resources to ${KAVAPP_PATH}/Contents"
            mv "${KAV_APP_CUR_RES_TEMP_PATH}/Resources" "${KAVAPP_PATH}/Contents"

            echo ""
            echo "Copying new resources to app"
            cp -Rfv "${KAV_APP_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus For Mac.app/Contents/Resources/"* "${KAVAPP_PATH}/Contents/Resources"

            touch "$KAVAPP_PATH"

    		echo ""
    		echo "Stopping application..."
    		stop_kav_app
    	fi
    else
        echo ""
        echo "KAV app pkg path is empty"
    fi

    if [ "$KAV_AGENT_PKG" != "" ]
    then
        LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)
        KAV_AGENT_PKG_TIMESTAMP=$(stat -f "%m" "$KAV_AGENT_PKG")
        echo "kav app pkg timestamp: $KAV_AGENT_PKG_TIMESTAMP, last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"

        if [[ (-e "$KAV_AGENT_PKG") && ($KAV_AGENT_PKG_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    	then
            KAV_AGENT_EXTRACTION_TEMP_PATH=$(mktemp -d)
    		echo ""
    		echo "Extracting agent resources to $KAV_AGENT_EXTRACTION_TEMP_PATH..."
    		/usr/bin/tar -xzvf "$KAV_AGENT_PKG" -C "$KAV_AGENT_EXTRACTION_TEMP_PATH"
            echo "Extracted: "
            ls -la "$KAV_AGENT_EXTRACTION_TEMP_PATH"

            echo ""
            echo "Deploying agent resources..."

            KAV_AGENT_CUR_RES_TEMP_PATH=$(mktemp -d)
            echo ""
            echo "Saving current agent resources to ${KAV_AGENT_CUR_RES_TEMP_PATH}"
            cp -rfv "${KAV_AGENT_APP_PATH}/Contents/Resources" "${KAV_AGENT_CUR_RES_TEMP_PATH}"

            echo ""
            echo "Deleting current agent"
            rm -rfv "${KAV_AGENT_APP_PATH}"

            echo ""
            echo "Moving ${KAV_AGENT_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus Agent.app to ${KAV_DIR}/Applications"
            cp -rvf "${KAV_AGENT_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus Agent.app" "${KAV_DIR}/Applications"

            echo ""
            echo "Updating agent resources"

            echo ""
            echo "Deleting ${KAV_DIR}/Applications/Kaspersky Anti-Virus Agent.app/Contents/Resources"
            rm -rfv "${KAV_DIR}/Applications/Kaspersky Anti-Virus Agent.app/Contents/Resources"

            echo ""
            echo "Moving ${KAV_AGENT_CUR_RES_TEMP_PATH}/Resources to ${KAV_AGENT_APP_PATH}/Contents"
            mv "${KAV_AGENT_CUR_RES_TEMP_PATH}/Resources" "${KAV_AGENT_APP_PATH}/Contents"

            echo ""
            echo "Copying new resources to agent"
            cp -Rfv "${KAV_AGENT_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus Agent.app/Contents/Resources/"* "${KAV_AGENT_APP_PATH}/Contents/Resources"

            touch "${KAV_AGENT_APP_PATH}"

    		echo ""
    		echo "Stopping agent..."
    		stop_kav_agent

    		if [ "$RESTART_KAVAGENT" == "1" ]
    		then
    			AGENTPID=$(ps -axwo pid,command | grep -v grep | grep "Contents/MacOS/kav_agent" | awk '{print $1}')
    			if [ "$AGENTPID" == "" ]
    			then
    				echo ""
    				echo "Restarting agent..."
    				LOGINWINDOW_RECORDS=$(ps -axwo pid,uid,command | grep -v grep | grep loginwindow)
    				for RECORD in "$LOGINWINDOW_RECORDS"
    				do
    					LOGINWINDOW_PID=$(/bin/echo -n "$RECORD" | awk '{print $1}')
    					LOGINWINDOW_UID=$(/bin/echo -n "$RECORD" | awk '{print $2}')
    					echo "Loading launch agent for uid $LOGINWINDOW_UID..."
    					launchctl asuser "$LOGINWINDOW_UID" launchctl load "$LAUNCHAGENT_KAV_PLIST"
    				done
    				echo "Kickstarting agent..."
    				touch "$KAV_AGENT_WATCHPATH"
    			fi
    		fi
    	fi
    else
        echo ""
        echo "KAV agent pkg path is empty"
    fi

    if [ "$KAV_UNINSTALLER_PKG" != "" ]
    then
        LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)
        KAV_UNINSTALLER_PKG_TIMESTAMP=$(stat -f "%m" "$KAV_UNINSTALLER_PKG")
        echo "kav uninstaller pkg timestamp: $KAV_UNINSTALLER_PKG_TIMESTAMP, last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"

        if [[ (-e "$KAV_UNINSTALLER_PKG") && ($KAV_UNINSTALLER_PKG_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
        then
            KAV_UNINSTALLER_EXTRACTION_TEMP_PATH=$(mktemp -d)
            echo ""
            echo "Extracting uninstaller resources to $KAV_UNINSTALLER_EXTRACTION_TEMP_PATH..."
            tar -xzvf "$KAV_UNINSTALLER_PKG" -C "$KAV_UNINSTALLER_EXTRACTION_TEMP_PATH"
            echo "Extracted: "
            ls -la "$KAV_UNINSTALLER_EXTRACTION_TEMP_PATH"

            echo ""
            echo "Deploying uninstaller resources..."

            echo ""
            echo "Deleting current uninstaller"
            rm -rfv "${KAV_UNINSTALLER_APP_PATH}"

            echo ""
            echo "Moving ${KAV_UNINSTALLER_EXTRACTION_TEMP_PATH}/Kaspersky Uninstaller.app to ${KAV_DIR}/Applications"
            cp -rvf "${KAV_UNINSTALLER_EXTRACTION_TEMP_PATH}/Kaspersky Uninstaller.app" "${KAV_DIR}/Applications"

            touch "$KAV_UNINSTALLER_APP_PATH"
        fi
    else
        echo ""
        echo "KAV uninstaller pkg path is empty"
    fi


    SYSCTRLD_PID=$(ps -axwo pid,command | grep -v grep | grep "${DEFAULT_KAVAPP_PATH}/Contents/MacOS/sysextctrld.app/Contents/MacOS/sysextctrld" | awk '{print $1}')
    if [ "${SYSCTRLD_PID}" != "" ]
    then
        echo "System extension controller pid: ${SYSCTRLD_PID}"
        kill -s TERM "${SYSCTRLD_PID}"
    else
        echo "warning: Process sysextctrld not found"
    fi
else
    LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)

    deploy_launch_agent
    
    echo ""
    echo "Last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"
fi

split_driver_version()
{
    local MAJOR=$(echo $1 | sed -n "s/\([0-9]*\).*/\1/p")
    local MINOR=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\).*/\2/p")
    local BUGFIX=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/p")
    local STAGE=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\([a-z]*\).*/\4/p")
    local BUILD=$(echo $1 | sed -n "s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\([a-z]*\)\([0-9]*\)/\5/p")
    echo "$MAJOR $MINOR $BUGFIX $STAGE $BUILD"
}

get_driver_version_component()
{
    echo "$1" | cut -f $2 -d " "
}

get_driver_version_stage_priority()
{
    local PRIORITIZED_LIST=$(echo ":d"; echo ":a"; echo ":b"; echo ":fc"; echo ":")
    echo "$PRIORITIZED_LIST" | grep -n "^:$1" | sed "s/\([0-9]*\).*/\1/"
}

compare_driver_versions()
{
    V1=$(split_driver_version $1)
    V2=$(split_driver_version $3)

    N1=$(echo "$V1" | awk '{ print NF }')
    N2=$(echo "$V2" | awk '{ print NF }')

    local N
    if [ $N1 -gt $N2 ]; then
        N=$N1
    else
        N=$N2
    fi

    for i in `seq 1 $N`; do
	local NUMBER1=$(get_driver_version_component "$V1" $i);
	local NUMBER2=$(get_driver_version_component "$V2" $i);

	if [ $i -eq 4 ]; then
	    NUMBER1=$(get_driver_version_stage_priority ${NUMBER1})
	    NUMBER2=$(get_driver_version_stage_priority ${NUMBER2})
        fi

	if [ ${NUMBER1:=0} -ne ${NUMBER2:=0} ]; then
	    [ ${NUMBER1:=0} $2 ${NUMBER2:=0} ]
	    return
	fi
    done

    [ 0 $2 0 ]
}

update_driver()
{
    [ ! -f "$5/$3" ] && echo "No $5/$3 file" && return 1

    DRIVER_REFERENCES_PATH="/Library/Application Support/Kaspersky Lab/Shared/$1.references"
    DRIVER_REFERENCES_LEGACY_PATH="$4/$1.kext/Contents/.References.plist"
    if [ "$4" == "/Library/Extensions" ] && [ -f "$DRIVER_REFERENCES_LEGACY_PATH" ] && [ ! -f "$DRIVER_REFERENCES_PATH" ]; then
	DRIVER_REFERENCES_DIR=$(dirname "$DRIVER_REFERENCES_PATH")
	mkdir -p "$DRIVER_REFERENCES_DIR"
	mv "$DRIVER_REFERENCES_LEGACY_PATH" "$DRIVER_REFERENCES_PATH" || return 1
    fi

    if [ "$4" == "/System/Library/Extensions" ] && [ -f "$DRIVER_REFERENCES_LEGACY_PATH" ]; then
	rm -rvf "$DRIVER_REFERENCES_LEGACY_PATH"
    fi

    DRIVER_PATH="$4/$1.kext"
    if [ -d "$DRIVER_PATH" ]; then
        INSTALLED_DRIVER_VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$DRIVER_PATH/Contents/Info.plist")
        echo "Installed driver version: ${INSTALLED_DRIVER_VERSION}"
        compare_driver_versions $2 -gt $INSTALLED_DRIVER_VERSION || return 1
    fi

    echo "Deploy new driver"

    rm -rvf "$DRIVER_PATH"
    /usr/bin/tar -xzvf "$5/$3" -C "$4"
    chown -R root:wheel "$DRIVER_PATH"
    echo "Driver $1 updated to version $2"
}

chmod -R o+r "/Library/Application Support/Kaspersky Lab/KAV/Bases/"

echo "Deleting personal certificates"
rm -rfv /Library/Caches/com.kaspersky.kav/PersonalCertificates/*

echo "Deleting kav crash logs"
rm -rfv /Library/Logs/DiagnosticReports/kav_*
echo "Deleting kav_app crash logs"
rm -rfv ~/Library/Logs/DiagnosticReports/kav_app*
echo "Deleting kav_agent crash logs"
rm -rfv ~/Library/Logs/DiagnosticReports/kav_agent*
