#!/bin/sh

PATCH_NAME="Kaspersky for Mac 27.0 - Patch A"

KAV_DIR="/Library/Application Support/Kaspersky Lab/KAV"
KAV_BINARIES_DIR="$KAV_DIR/Binaries"
KAVD_BINARIES_TAR="$KAV_BINARIES_DIR/binaries.tar.gz"
KAV_DATA_DIR="$KAV_DIR/Data"
KAV_APP_PKG="$KAV_DATA_DIR/kav_app.tar.gz"
KAV_AGENT_TAR="$KAV_DATA_DIR/kav_agent.tar.gz"
KAV_UPDATE_TAR="$KAV_DATA_DIR/kav_update.tar.gz"
KAV_CONFIGPDK_TAR="$KAV_DATA_DIR/configpdk.tar.gz"
KAV_UNINSTALLER_TAR="$KAV_DATA_DIR/kav_uninstaller.tar.gz"
KAV_AGENT_APP_PATH="$KAV_DIR/Applications/Kaspersky Anti-Virus Agent.app"
KAV_UPDATE_APP_PATH="$KAV_DIR/Applications/Kaspersky Anti-Virus Update.app"
KAV_UNINSTALLER_APP_PATH="$KAV_DIR/Applications/Kaspersky Uninstaller.app"
KAV_AGENT_WATCHPATH="$KAV_DIR/kickstart_agent"
LAUNCHAGENT_DIR="/Library/LaunchAgents"
LAUNCHAGENT_KAV_ID="com.kaspersky.kav.agent"
KAV_AGENT_PLIST="$LAUNCHAGENT_KAV_ID.plist"
KAV_AGENT_PLIST_BACKUP_DIR="$KAV_DIR"
KAVAPP_PATH="/Applications/Kaspersky Anti-Virus For Mac.app"
LOC_TGZ="$KAV_DATA_DIR/loc.tar.gz"
LOC_DIR="$KAV_DIR/Loc"
DOC_TGZ="$KAV_DATA_DIR/doc.tar.gz"
DOC_DIR="$KAV_DIR/Doc"
DATA_TGZ="$KAV_DATA_DIR/data.tar.gz"
CONFIG_XML_CHANGES_TMP="$KAV_BINARIES_DIR/kav_config_xml_changes.v2"
CONFIG_XML="$KAV_BINARIES_DIR/config.xml"


install_log()
{
    logger -p 'install.warning' "Kaspersky.patch[$$] $@"
}

log()
{
    echo "`date '+%Y-%m-%d %H:%M:%S'` $@"
    install_log "$@"
}

log "${PATCH_NAME}"
log "${PATCH_VER}"

decrypt_file()
{
    local src="$1"
    local dst="$2"

    log "Decrypting '$src' '$dst'"

    openssl enc -d -aes-256-cbc -in "${src}" -out "${dst}" -md sha256 -k pass
}

get_decrypted_fname()
{
    basename "${1}"
}

get_value_by_xpath()
{

    /usr/bin/xmllint --xpath "$1" "$CONFIG_XML" 2>/dev/null
}

does_xpath_exist()
{


    /usr/bin/xmllint --xpath "$1" "$CONFIG_XML" 1>/dev/null 2>/dev/null
    [ $? -eq 0 ] && echo 1 || echo 0
}

get_environment_key()
{
    get_value_by_xpath "//propertiesmap/key[@name=\"environment\"]/tSTRING[@name=\"$1\"]/text()"
}

get_last_patch_deployment()
{
    get_value_by_xpath "//propertiesmap/key[@name=\"Timestamps\"]/tDWORD[@name=\"LastPatchDeployment\"]/text()"
}

stop_kav_app()
{
    local pids=$(/bin/ps -axwo pid,command | /usr/bin/grep -v grep | /usr/bin/grep "Contents/MacOS/kav_app" | /usr/bin/awk '{print $1}')
    if [ "$pids" != "" ] ; then
        local oldIFS="$IFS"
        IFS=$'\n'
        for pid in `echo "$pids"`
        do
            log "Stopping kav_app with pid=$pid"
            /bin/kill -s KILL $pid
        done
        IFS="$oldIFS"
    fi
}

unload_agents()
{
    log "Disable and stop agents in launchctl ..."
    local records=$(/bin/ps -axwo uid,command | /usr/bin/grep -v grep | /usr/bin/grep loginwindow)
    if [ "$records" != "" ] ; then
        local oldIFS="$IFS"
        IFS=$'\n'
        for rec in `echo "$records"`
        do
            local uid=$(/bin/echo -n "$rec" | /usr/bin/awk '{print $1}')
            local target="gui/$uid/$LAUNCHAGENT_KAV_ID"


            if [ "$uid" == "0" ] ; then
                log "Skip disabling agent when no user is logged on"
                continue
            fi

            /bin/launchctl disable "$target"
            log "Disabling agent for uid $uid finished with rc=$?"

            /bin/launchctl bootout "$target"
            log "bootout agent for uid $uid finished with rc=$?"
        done
        IFS="$oldIFS"
    fi




    local counter=20
    while [ $counter -gt 0 ] ; do
        local uids=$(/bin/ps -axwo uid,command | /usr/bin/grep -v grep | /usr/bin/grep "Contents/MacOS/kav_agent" | /usr/bin/awk '{print $1}')
        if [ -z "$uids" ] ; then
            log "No agents to stop"
            break
        fi

        log "Wait for stopping agent for uids = $uids ... "
        sleep 0.25
        ((counter-=1))
    done

    [ $counter -gt 0 ] && return 0

    log "Unable to stop all agents."
    return 1
}

do_killall()
{
    local app_name="$1"

    local pids=$(/bin/ps -axwo pid,command | /usr/bin/grep -v grep | /usr/bin/grep "Contents/MacOS/$app_name" | /usr/bin/awk '{print $1}')
    if [ "$pids" != "" ] ; then
        local oldIFS="$IFS"
        IFS=$'\n'
        for pid in `echo "$pids"`
        do
            log "Stopping '$app_name' with pid=$pid"
            /bin/kill -s KILL $pid
        done
        IFS="$oldIFS"
    fi
}

kill_kav_apps()
{
    do_killall "kav_app"
}

kill_agents()
{
    do_killall "kav_agent"
}

disable_kav_agents()
{
    unload_agents && return 0


    log "Kill agents and try to unload again"
    kill_agents

    unload_agents
}

enable_kav_agents()
{
    local plist_path="$LAUNCHAGENT_DIR/$KAV_AGENT_PLIST"

    log "Restarting agents..."
    local records=$(/bin/ps -axwo uid,command | /usr/bin/grep -v grep | /usr/bin/grep loginwindow)
    if [ "$records" != "" ] ; then
        local oldIFS="$IFS"
        IFS=$'\n'
        for rec in `echo "$records"`
        do
            local uid=$(/bin/echo -n "$rec" | /usr/bin/awk '{print $1}')


            if [ "$uid" == "0" ] ; then
                log "Skip starting agent when no user is logged on"
                continue
            fi

            /bin/launchctl enable "gui/$uid/$LAUNCHAGENT_KAV_ID"
            log "Enabling agent for uid=$uid with rc=$?"

            /bin/launchctl asuser "$uid" /bin/launchctl list | /usr/bin/grep -q "$LAUNCHAGENT_KAV_ID"
            if [ $? -eq 0 ] ; then
                log "Starting already loaded agent for uid $uid ..."
                /bin/launchctl asuser "$uid" /bin/launchctl start "$LAUNCHAGENT_KAV_ID" \
                    || log "Unable to start agent $LAUNCHAGENT_KAV_ID"
            else
                log "Loading agent for uid $uid ..."
                /bin/launchctl bootstrap "gui/$uid" "$plist_path" \
                    || log "Unable to load agent $plist_path"
            fi
        done
        IFS="$oldIFS"
    fi
    log "Kickstarting agent..."
    /usr/bin/touch "$KAV_AGENT_WATCHPATH"
}

extract_bundle_tar()
{
    local TAR_PATH="$1"
    local BUNDLE_PATH="$2"
    local BUNDLE_NAME="$3"
    local BUNDLE_DESTINATION_PATH="$4"
    local MATCHED_ARCHIVE="$5"

    if [ ! -f "${TAR_PATH}" ]; then
        log "No ${TAR_PATH} tar, skip ${BUNDLE_NAME} extraction"
        return 0
    fi

    local TAR_TIMESTAMP=$(/usr/bin/stat -f "%m" "$TAR_PATH")
    local LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)
    log "${TAR_PATH} timestamp: $TAR_TIMESTAMP, last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"

    if [[ (-e "${TAR_PATH}") && ($TAR_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    then
        local ENC_SRC_PATH="${TAR_PATH}"

        log "Decrypting $ENC_SRC_PATH ..."
        local DECRYPTED_TEMP_DIR=$(mktemp -d)
        local DECRYPTED_FNANE=$(get_decrypted_fname "${ENC_SRC_PATH}")
        local DECRYPTED_FULL_PATH="${DECRYPTED_TEMP_DIR}/${DECRYPTED_FNANE}"
        decrypt_file "${ENC_SRC_PATH}" "${DECRYPTED_FULL_PATH}" || return 1

        local EXTRACTION_TEMP_PATH=$(mktemp -d)

        log "Extracting ${BUNDLE_NAME} resources to $EXTRACTION_TEMP_PATH..."
        /usr/bin/tar -xzvf "${DECRYPTED_FULL_PATH}" -C "${EXTRACTION_TEMP_PATH}"
        log "Extracted: "
        /bin/ls -la "$EXTRACTION_TEMP_PATH"

        log "Deploying ${BUNDLE_NAME} resources..."

        if [ -f "$EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" ]; then
            local CURRENT_BUNDLE_EXTRACTION_TEMP_PATH=$(mktemp -d)
            log "Extracting application resources from $MATCHED_ARCHIVE to $CURRENT_BUNDLE_EXTRACTION_TEMP_PATH..."
            /usr/bin/tar -xzvf "$EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" -C "$CURRENT_BUNDLE_EXTRACTION_TEMP_PATH"

            local CURRENT_BUNDLE_RESOURSES_TEMP_PATH=$(mktemp -d)

            log "Saving current bundle resources to ${CURRENT_BUNDLE_RESOURSES_TEMP_PATH}"
            /bin/cp -rfv "${BUNDLE_PATH}/Contents/Resources" "${CURRENT_BUNDLE_RESOURSES_TEMP_PATH}"

            log "Deleting current bundle"
            /bin/rm -rfv "${BUNDLE_PATH}"

            log "Copying ${CURRENT_BUNDLE_EXTRACTION_TEMP_PATH}/${BUNDLE_NAME} to ${BUNDLE_DESTINATION_PATH}"
            /bin/cp -rvf "${CURRENT_BUNDLE_EXTRACTION_TEMP_PATH}/${BUNDLE_NAME}" "${BUNDLE_DESTINATION_PATH}"

            log "Deleting ${BUNDLE_PATH}/Contents/Resources"
            /bin/rm -rfv "${BUNDLE_PATH}/Contents/Resources"

            log "Moving ${CURRENT_BUNDLE_RESOURSES_TEMP_PATH}/Resources to ${BUNDLE_PATH}/Contents"
            /bin/mv "${CURRENT_BUNDLE_RESOURSES_TEMP_PATH}/Resources" "${BUNDLE_PATH}/Contents"

            log "Copying new resources to ${BUNDLE_PATH}/Contents/Resources"
            /bin/cp -Rfv "${CURRENT_BUNDLE_EXTRACTION_TEMP_PATH}/${BUNDLE_NAME}/Contents/Resources/"* "${BUNDLE_PATH}/Contents/Resources"

            /usr/bin/touch "$BUNDLE_PATH"
        else
            log "No matched archive in $EXTRACTION_TEMP_PATH, do not apply patch for $BUNDLE_PATH"
        fi
    fi

    return 0
}

add_value_to_config_changes_file()
{
    local KEY="$1"
    local VALUE="$2"


    local PATTERN="$3"


    local PATH_TO_NODE="$4"


    local TYPE="$5"

    if [ "$TYPE" != "tBOOL" -a "$TYPE" != "tDWORD" ];
    then
        TYPE="tSTRING"
    fi

    local DO_UPDATE=0
    if [ "$PATTERN" = '*' ]; then
        DO_UPDATE=1
        log "Update forcibly because of pattern '*' with '${KEY}' in path '${PATH_TO_NODE}'"
    else

        local SEARCH_RESULT=$(/usr/bin/grep "${PATTERN}" "$CONFIG_XML")
        if [ -z "$SEARCH_RESULT" ]; then
            DO_UPDATE=1
        fi
    fi
    
    if [ $DO_UPDATE -eq 1 ]; then
        log "Updating in node '${PATH_TO_NODE}'  ${KEY} value to ${VALUE} with type ${TYPE}"
        /usr/bin/touch "$CONFIG_XML_CHANGES_TMP"
        /bin/echo "${PATH_TO_NODE} ${KEY} ${VALUE} ${TYPE}" >> "$CONFIG_XML_CHANGES_TMP"
    else
        log "Skip updating ${KEY} value"
    fi

    return 0
}

add_env_value_to_update()
{
    add_value_to_config_changes_file "$1" "$2" "$3" "environment"
}

patch_loc()
{
    LOC_TGZ_TIMESTAMP=$(/usr/bin/stat -f "%m" "$LOC_TGZ")
    log "loc timestamp: $LOC_TGZ_TIMESTAMP"
    if [[ -e "$LOC_TGZ" && ($LOC_TGZ_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    then
        LOC_EXTRACTION_TEMP_PATH=$(mktemp -d)
        log "Extracting $LOC_TGZ into $LOC_EXTRACTION_TEMP_PATH"
        /usr/bin/tar -xzvf "$LOC_TGZ" -C "$LOC_EXTRACTION_TEMP_PATH"
        log "Extracted: "
        /bin/ls -la "$LOC_EXTRACTION_TEMP_PATH"

        log "Deploying localizations..."
        if [ -f "$LOC_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" ]; then
            CURRENT_LOC_EXTRACTION_TEMP_PATH=$(mktemp -d)
            log "Extracting application resources from $MATCHED_ARCHIVE to $CURRENT_LOC_EXTRACTION_TEMP_PATH..."
            /usr/bin/tar -xzvf "$LOC_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" -C "$CURRENT_LOC_EXTRACTION_TEMP_PATH"
            /bin/cp -Rfv "$CURRENT_LOC_EXTRACTION_TEMP_PATH"/ "$LOC_DIR"
        else
            log "No matched archive in $LOC_EXTRACTION_TEMP_PATH, do not apply patch for $LOC_DIR"
        fi
    else
        log "Skip extracting loc.tar.gz"
    fi
}

patch_doc()
{
    DOC_TGZ_TIMESTAMP=$(/usr/bin/stat -f "%m" "$DOC_TGZ")
    log "doc.tar.gz timestamp: $DOC_TGZ_TIMESTAMP"
    if [[ -e "$DOC_TGZ" && ($DOC_TGZ_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    then
        DOC_EXTRACTION_TEMP_PATH=$(mktemp -d)

        log "Extracting $DOC_TGZ into $DOC_EXTRACTION_TEMP_PATH"
        /usr/bin/tar -xzvf "$DOC_TGZ" -C "$DOC_EXTRACTION_TEMP_PATH"
        log "Extracted: "
        /bin/ls -la "$DOC_EXTRACTION_TEMP_PATH"

        log "Deploying docs..."
        if [ -f "$DOC_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" ]; then
            CURRENT_DOC_EXTRACTION_TEMP_PATH=$(mktemp -d)
            log "Extracting application resources from $MATCHED_ARCHIVE to $CURRENT_DOC_EXTRACTION_TEMP_PATH..."
            /usr/bin/tar -xzvf "$DOC_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" -C "$CURRENT_DOC_EXTRACTION_TEMP_PATH"
            /bin/cp -Rfv "$CURRENT_DOC_EXTRACTION_TEMP_PATH"/ "$DOC_DIR"
        else
            log "No matched archive in $DOC_EXTRACTION_TEMP_PATH, do not apply patch for $DOC_DIR"
        fi
    else
        log "Skip extracting doc.tar.gz"
    fi
}

patch_data()
{
    local TGZ_TIMESTAMP=$(/usr/bin/stat -f "%m" "$DATA_TGZ")
    log "data.tar.gz timestamp: $TGZ_TIMESTAMP"
    if [[ -e "$DATA_TGZ" && ($TGZ_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    then
        local EXTRACTION_TEMP_PATH=$(mktemp -d)

        log "Extracting $DATA_TGZ into $EXTRACTION_TEMP_PATH"
        /usr/bin/tar -xzvf "$DATA_TGZ" -C "$EXTRACTION_TEMP_PATH"
        log "Extracted: "
        /bin/ls -FRla "$EXTRACTION_TEMP_PATH"

        log "Deploying ..."
        /bin/cp -rvf "$EXTRACTION_TEMP_PATH"/* "$KAV_DATA_DIR"
        /bin/rm -rf "$EXTRACTION_TEMP_PATH"
    else
        log "Skip extracting data.tar.gz"
    fi
}

patch_binaries()
{
    BINARIES_TGZ_TIMESTAMP=$(/usr/bin/stat -f "%m" "$KAVD_BINARIES_TAR")
    log "binaries.tar.gz timestamp: $BINARIES_TGZ_TIMESTAMP"
    
    if [[ -e "$KAVD_BINARIES_TAR" && ($BINARIES_TGZ_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    then
        local EXTRACTION_TEMP_PATH=$(mktemp -d)

        log "Extracting $KAVD_BINARIES_TAR to $EXTRACTION_TEMP_PATH ..."
        /usr/bin/tar -xzvf "$KAVD_BINARIES_TAR" -C "$EXTRACTION_TEMP_PATH" --no-same-owner
        /bin/mv -fv "$EXTRACTION_TEMP_PATH"/* "$KAV_BINARIES_DIR"
        /bin/rm -rf "$EXTRACTION_TEMP_PATH"
    else
        log "Skip extracting binaries.tar.gz"
    fi
}

patch_kav_app()
{
    KAV_APP_PKG_TIMESTAMP=$(/usr/bin/stat -f "%m" "$KAV_APP_PKG")
    log "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

        local ENC_SRC_PATH="${KAV_APP_PKG}"

        log "Decrypting $ENC_SRC_PATH ..."
        local DECRYPTED_TEMP_DIR=$(mktemp -d)
        local DECRYPTED_FNANE=$(get_decrypted_fname "${ENC_SRC_PATH}")
        local DECRYPTED_FULL_PATH="${DECRYPTED_TEMP_DIR}/${DECRYPTED_FNANE}"
        decrypt_file "${ENC_SRC_PATH}" "${DECRYPTED_FULL_PATH}" || return 1

        KAV_APP_EXTRACTION_TEMP_PATH=$(mktemp -d)

        log "Extracting $DECRYPTED_FULL_PATH into $KAV_APP_EXTRACTION_TEMP_PATH"
        /usr/bin/tar -xzvf "$DECRYPTED_FULL_PATH" -C "$KAV_APP_EXTRACTION_TEMP_PATH"
        log "Extracted: "
        /bin/ls -la "$KAV_APP_EXTRACTION_TEMP_PATH"

        log "Deploying application resources..."

        if [ -f "$KAV_APP_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" ]; then
            CURRENT_KAV_APP_EXTRACTION_TEMP_PATH=$(mktemp -d)
            log "Extracting application resources from $MATCHED_ARCHIVE to $CURRENT_KAV_APP_EXTRACTION_TEMP_PATH..."
            /usr/bin/tar -xzvf "$KAV_APP_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" -C "$CURRENT_KAV_APP_EXTRACTION_TEMP_PATH"

            KAV_APP_CUR_CONTENTS_TEMP_PATH=$(mktemp -d)
            log "Saving current app embedded.provisionprofile to ${KAV_APP_CUR_CONTENTS_TEMP_PATH}"
            /bin/cp -fv "${KAVAPP_PATH}/Contents/embedded.provisionprofile" "${KAV_APP_CUR_CONTENTS_TEMP_PATH}"

            KAV_APP_CUR_RES_TEMP_PATH=$(mktemp -d)

            log "Saving current app resources to ${KAV_APP_CUR_RES_TEMP_PATH}"
            /bin/cp -rfv "${KAVAPP_PATH}/Contents/Resources" "${KAV_APP_CUR_RES_TEMP_PATH}"

            KAV_APP_SAFARI_EXT_CUR_RES_TEMP_PATH=$(mktemp -d)

            log "Saving current safari extension resources to ${KAV_APP_SAFARI_EXT_CUR_RES_TEMP_PATH}"
            /bin/cp -rfv "${KAVAPP_PATH}/Contents/PlugIns/KasperskySecurity.appex/Contents/Resources" "${KAV_APP_SAFARI_EXT_CUR_RES_TEMP_PATH}"


            log "Deleting current app binary"
            /bin/rm -v "${KAVAPP_PATH}/Contents/MacOS/kav_app"

            log "Stopping application..."
            stop_kav_app

            log "Deleting current app bundle"
            /bin/rm -rfv "${KAVAPP_PATH}"

            KAV_APP_PARENT_DIR="${KAVAPP_PATH}"
            log "Moving ${CURRENT_KAV_APP_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus For Mac.app to ${KAV_APP_PARENT_DIR}"
            /bin/cp -rvf "${CURRENT_KAV_APP_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus For Mac.app" "${KAV_APP_PARENT_DIR}"

            log "Updating app resources"

            log "Deleting ${KAVAPP_PATH}/Contents/Resources"
            /bin/rm -rfv "${KAVAPP_PATH}/Contents/Resources"
            
            log "Moving ${KAV_APP_CUR_CONTENTS_TEMP_PATH}/embedded.provisionprofile to ${KAVAPP_PATH}/Contents"
            mv "${KAV_APP_CUR_CONTENTS_TEMP_PATH}/embedded.provisionprofile" "${KAVAPP_PATH}/Contents"

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

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

            log "Updating safari extension resources"

            log "Deleting ${KAVAPP_PATH}/Contents/PlugIns/KasperskySecurity.appex/Contents/Resources"
            /bin/rm -rfv "${KAVAPP_PATH}/Contents/PlugIns/KasperskySecurity.appex/Contents/Resources"

            log "Moving ${KAV_APP_SAFARI_EXT_CUR_RES_TEMP_PATH}/Resources to ${KAVAPP_PATH}/Contents/PlugIns/KasperskySecurity.appex/Contents"
            mv "${KAV_APP_SAFARI_EXT_CUR_RES_TEMP_PATH}/Resources" "${KAVAPP_PATH}/Contents/PlugIns/KasperskySecurity.appex/Contents"

            log "Copying new resources to app"
            /bin/cp -Rfv "${CURRENT_KAV_APP_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus For Mac.app/Contents/PlugIns/KasperskySecurity.appex/Contents/Resources/"* "${KAVAPP_PATH}/Contents/PlugIns/KasperskySecurity.appex/Contents/Resources"

            /usr/bin/touch "$KAVAPP_PATH"


            log "Lock \"$KAVAPP_PATH\"..."
            chflags -v uchg "$KAVAPP_PATH"
            if [ $? != 0 ]
            then
                log "Failed to change flags of \"$KAVAPP_PATH\""
                return 1
            else
                log "Flags of \"$KAVAPP_PATH\" changed successfully"
            fi
        else
            log "No matched archive in $KAV_APP_EXTRACTION_TEMP_PATH, do not apply patch for $KAVAPP_PATH"
        fi
    fi
}

patch_kav_agent()
{
    KAV_AGENT_PKG_TIMESTAMP=$(/usr/bin/stat -f "%m" "$KAV_AGENT_TAR")
    log "kav app pkg timestamp: $KAV_AGENT_PKG_TIMESTAMP, last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"

    if [[ (-e "$KAV_AGENT_TAR") && ($KAV_AGENT_PKG_TIMESTAMP > $LAST_PATCH_DEPLOYMENT_TIMESTAMP) ]];
    then

        local ENC_SRC_PATH="${KAV_AGENT_TAR}"

        log "Decrypting $ENC_SRC_PATH ..."
        local DECRYPTED_TEMP_DIR=$(mktemp -d)
        local DECRYPTED_FNANE=$(get_decrypted_fname "${ENC_SRC_PATH}")
        local DECRYPTED_FULL_PATH="${DECRYPTED_TEMP_DIR}/${DECRYPTED_FNANE}"
        decrypt_file "${ENC_SRC_PATH}" "${DECRYPTED_FULL_PATH}" || return 1


        KAV_AGENT_EXTRACTION_TEMP_PATH=$(mktemp -d)

        log "Extracting agent resources to $KAV_AGENT_EXTRACTION_TEMP_PATH..."
        /usr/bin/tar -xzvf "$DECRYPTED_FULL_PATH" -C "$KAV_AGENT_EXTRACTION_TEMP_PATH"
        log "Extracted: "
        /bin/ls -la "$KAV_AGENT_EXTRACTION_TEMP_PATH"

        log "Deploying agent resources..."

        if [ -f "$KAV_AGENT_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" ]; then
            CURRENT_KAV_AGENT_EXTRACTION_TEMP_PATH=$(mktemp -d)
            log "Extracting application resources from $MATCHED_ARCHIVE to $CURRENT_KAV_AGENT_EXTRACTION_TEMP_PATH..."
            /usr/bin/tar -xzvf "$KAV_AGENT_EXTRACTION_TEMP_PATH/$MATCHED_ARCHIVE" -C "$CURRENT_KAV_AGENT_EXTRACTION_TEMP_PATH"

            KAV_AGENT_CUR_RES_TEMP_PATH=$(mktemp -d)

            log "Saving current agent resources to ${KAV_AGENT_CUR_RES_TEMP_PATH}"
            /bin/cp -rfv "${KAV_AGENT_APP_PATH}/Contents/Resources" "${KAV_AGENT_CUR_RES_TEMP_PATH}"

            log "Deleting current agent"
            /bin/rm -rfv "${KAV_AGENT_APP_PATH}"

            log "Moving ${CURRENT_KAV_AGENT_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus Agent.app to ${KAV_DIR}/Applications"
            /bin/cp -rvf "${CURRENT_KAV_AGENT_EXTRACTION_TEMP_PATH}/Kaspersky Anti-Virus Agent.app" "${KAV_DIR}/Applications"

            log "Deleting ${KAV_AGENT_APP_PATH}/Contents/Resources"
            /bin/rm -rfv "${KAV_AGENT_APP_PATH}/Contents/Resources"

            log "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"

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

            /usr/bin/touch "${KAV_AGENT_APP_PATH}"
        else
            log "No matched archive in $KAV_AGENT_EXTRACTION_TEMP_PATH, do not apply patch for $KAV_AGENT_APP_PATH"
        fi
    fi
}

patch_updater()
{
    extract_bundle_tar "${KAV_UPDATE_TAR}" "${KAV_UPDATE_APP_PATH}" "Kaspersky Anti-Virus Update.app" "${KAV_DIR}/Applications" "${MATCHED_ARCHIVE}"
        [ $? != 0 ] && log "warning: failed to extract ${KAV_UPDATE_TAR}"
}

patch_uninstaller()
{
    extract_bundle_tar "${KAV_UNINSTALLER_TAR}" "${KAV_UNINSTALLER_APP_PATH}" "Kaspersky Uninstaller.app" "${KAV_DIR}/Applications" "${MATCHED_ARCHIVE}"
        [ $? != 0 ] && log "warning: failed to extract ${KAV_UNINSTALLER_TAR}"
}


update_existent_fields()
{









    log "update_existent_fields ..."
}


update_non_existent_fields()
{









    log "update_non_existent_fields ..."
}


update_existent_env_fields()
{




    log "update_existent_env_fields ..."
}


update_config_xml()
{
    log "Updating config.xml"


    update_existent_env_fields


    update_existent_fields
    update_non_existent_fields


    if [ -f "${CONFIG_XML_CHANGES_TMP}" ];
    then
        log "Printing $CONFIG_XML_CHANGES_TMP"
        /bin/cat "$CONFIG_XML_CHANGES_TMP"
    else
        log "No ${CONFIG_XML_CHANGES_TMP} file"
    fi
}


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

patch_configpdk()
{
    if [ ! -e "${KAV_CONFIGPDK_TAR}" ] ; then
        log "No configpdk. skipping."
        return 0
    fi

    log "Extracting configpdk to $KAV_BINARIES_DIR..."
    /usr/bin/tar -xzvf "$KAV_CONFIGPDK_TAR" -C "$KAV_BINARIES_DIR"

    log "Changing esm owner..."
    /usr/sbin/chown root:admin "$KAV_BINARIES_DIR"/configpdk_x86_64.esm
    /usr/sbin/chown root:admin "$KAV_BINARIES_DIR"/configpdk_arm64.esm
}

delete_old_stuff()
{
    log "Deleting personal certificates"
    /bin/rm -rfv /Library/Caches/com.kaspersky.kav/PersonalCertificates/*

    local CRASH_FILES_DIR="Library/Logs/DiagnosticReports"
    local BACKUP_DIR="/Library/Logs/Kaspersky Lab/DiagnosticReports.backup"
    USERS_DIR="/Users"

    mkdir -pv "$BACKUP_DIR" 

    log "Moving kav crash logs from /$CRASH_FILES_DIR  to '$BACKUP_DIR'"
    mv -vf "/$CRASH_FILES_DIR/"{Retired,}/kav* "$BACKUP_DIR/"
    mv -vf "/$CRASH_FILES_DIR/"{Retired,}/com.kaspersky.kav.sysext* "$BACKUP_DIR/"

    for USERHOME in $(ls "$USERS_DIR")
    do
        local USER_BACKUP_DIR="$BACKUP_DIR/$USERHOME"
        mkdir -pv "$USER_BACKUP_DIR"

        log "Moving kav crash logs from '$USERS_DIR/$USERHOME/$CRASH_FILES_DIR' to '$USER_BACKUP_DIR'"
        mv -vf "$USERS_DIR/$USERHOME/$CRASH_FILES_DIR/"{Retired,}/kav_app* "$USER_BACKUP_DIR" 
        mv -vf "$USERS_DIR/$USERHOME/$CRASH_FILES_DIR/"{Retired,}/kav_agent* "$USER_BACKUP_DIR"
        mv -vf "$USERS_DIR/$USERHOME/$CRASH_FILES_DIR/"{Retired,}/kavd* "$USER_BACKUP_DIR"
        mv -vf "$USERS_DIR/$USERHOME/$CRASH_FILES_DIR/"{Retired,}/KasperskySecurity* "$USER_BACKUP_DIR"
    done
}

drop_obsolete_bins()
{
    log "drop_obsolete_bins() ..."

    pushd "$KAV_BINARIES_DIR"
        [ $? != 0 ] && return 1

        rm -fv "libksnmock_http2server.dylib" 
        rm -fv "libksn_mock_metainfo.dylib" 

    popd
}

get_product_region_raw()
{
    local region=""

    for tmp in $(seq 1 1)
    do

        region=$(get_environment_key "ProductRegionRaw")
        if [ -n  "$region" ] ; then
            break
        fi


        region=$(get_environment_key "ProductRegion")
    done

    echo "$region"
}

if [ "$1" != "OnHotfixInstalled" ]; then
    PRODUCT_TYPE=$(get_environment_key "ProductType")
    log "ProductType:      $PRODUCT_TYPE"

    PRODUCT_REGION_RAW=$(get_product_region_raw)
    log "ProductRegionRaw:    $PRODUCT_REGION_RAW"

    MATCHED_ARCHIVE="${PRODUCT_REGION_RAW}".tar.gz
    log "Matched archive:  $MATCHED_ARCHIVE"

    LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)
    log "Last patch deployment timestamp:  $LAST_PATCH_DEPLOYMENT_TIMESTAMP"

    patch_loc
    patch_doc

    log "Disable agents..."
    disable_kav_agents

    log "Stopping kav_apps..."
    kill_kav_apps

    drop_obsolete_bins

    patch_data

    patch_binaries
    patch_kav_app
    patch_kav_agent

    log "Enable agents..."
    enable_kav_agents

    patch_updater
    patch_uninstaller

    update_config_xml
    stop_sysextctrld

    patch_configpdk
else
    LAST_PATCH_DEPLOYMENT_TIMESTAMP=$(get_last_patch_deployment)

    log "Last path deployment timestamp: $LAST_PATCH_DEPLOYMENT_TIMESTAMP"
fi

delete_old_stuff

log "Finished."
