#!/bin/sh

. $(dirname $0)/nod32upd.conf

log()
# :
# $1 -> hist -    
# $2 -> std -   ( /),    
#	stdNoLF ->  ( /),   
#	noDate ->  /,    
#       noDateNoLF ->  /    
# $3 -> ,    
{
  LOGDATE=`date +'%Y-%m-%d %T'`

  if [ "$1" = "hist" ]; then
    echo $LOGDATE $3 >> $HIST #    
  fi

  if [ $DelStr = "1" ] && [ ! "$3" == "\033[2K" ]; then 
    echo -e -n "\r\033[2K"  #    
    DelStr=0
  fi

  case $2 in
    std) 	#   ( /)   
       if [ "$3" == "\033[2K" ]; then 
         sed -i '$ d' $LOG
         DelStr=1
       else
         echo -e "$3"
         echo -e $LOGDATE "$3" >> $LOG
       fi
    ;;
    stdNoLF) 	#   ( /)   
       if [ "$3" == "\033[2K" ]; then 
	 sed -i '$ d' $LOG
         DelStr=1
       else
         echo -n -e "$3"
         echo -n -e $LOGDATE "$3" >> $LOG
       fi
    ;;
    noDate) 	#   ,    
       if [ "$3" == "\033[2K" ]; then 
         sed -i '$ d' $LOG
         DelStr=1
       else
         echo -e "$3"
         echo -e "$3" >> $LOG
       fi
    ;;
    noDateNoLF) #   ,   
       if [ "$3" == "\033[2K" ]; then 
         sed -i '$ d' $LOG
         DelStr=1
       else          
         echo -n -e "$3"
         echo -n -e "$3" >> $LOG
       fi
    ;;
  esac
} # log

trace_error() {
# :
# $1 - fatal -  ,   
  echo $STATUS_ERROR > $STATUS_F

  if [ "$1" = "fatal" ]; then
    log hist std "Fatal! $LOG_ERROR"
    clear_tmp
    logger -t nod32upd "Aborted! $LOG_ERROR"
    log noHist std "Script was aborted"

    #           
    DATE=$(date +'%y-%m-%d_%H%M')
    log noHist std "Log saved to nod32upd_ERR_$DATE.log"
    cp -f $LOG "$WEB_ROOT/nod32upd_ERR_$DATE.log"

    pid_file clear
    exit
  else
    log hist std "$LOG_ERROR"
    logger -t nod32upd "$LOG_ERROR"
  fi
} # trace_error

pid_file() {
# :
# $1 -> clear -  -
if [ "$1" = "clear" ]; then
  rm -f /opt/var/run/nod32upd.pid     #  -
else 
  if [ ! -f "/opt/var/run/nod32upd.pid" ]; then
    echo $$ > /opt/var/run/nod32upd.pid
  else
    logger -t nod32upd "NOD32 base updater start failed"
    log hist stdNoLF "NOD32 base updater start failed"
    echo , already is running.
    echo If you are sure that process is not started, use argument -f
    exit
  fi
fi
} # pid_file

unpack_file() {
  mv -f update.ver update.rar
  unrar x -y -inul update.rar
  if [ ! -f "update.ver" ]; then
    cp -f -p update.rar update.ver
  fi
  rm -f update.rar
} # unpack_file

clear_tmp() {
  log noHist stdNoLF "Temporary folder clearing..."
  cd $WEB_ROOT/$AVBASE_DIR/tmp 2>/dev/null
  rm -f update.rar
  rm -f update.ver
  rm -r -f $WEB_ROOT/$AVBASE_DIR/tmp
  #     
  mv $WEB_ROOT/$AVBASE_DIR/update.tmp $WEB_ROOT/$AVBASE_DIR/update.ver 2>/dev/null
  log noHist noDate "> Complete"
} # clear_tmp

dl_keys() {
  USER=''
  PASS=''

  if [ -z "$keys" ]; then   		#    ,  
     if [ -f "$KEYS_F" ]; then 		#     ,   
       keys=$(cat $KEYS_F)		#       
     fi
  fi

  if [ -z "$HTMLs_list" ] && [ -z "$keys" ]; then
    #       ,   
    LOG_ERROR="HTMLs_list incorrect, need editing the config file"
    STATUS_ERROR="HTMLs_list incorrect, need editing the config file"
    trace_error fatal
  fi
   
  until [ -z "$HTMLs_list" ] && [ -z "$keys" ]; do
  #            .
    if [ -z "$keys" ]; then
      #         
      KEYS_HTML=$(echo "$HTMLs_list" | sed 's/,.*//') 		#   
      HTMLs_list=$(echo "$HTMLs_list" | sed -n 's/[^,]*,//p') 	#     
      #   .
      log noHist stdNoLF "Downloading webpage from $(echo $KEYS_HTML | sed 's:[^//]*\//::' | sed 's:/.*::')..."
      wget -O $WEB_ROOT/keys.html -o $WEB_ROOT/keys.html.log -U 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050511' --timeout=30 --waitretry=5 --tries=5 --no-check-certificate $KEYS_HTML
      if [ $? != 0 ]; then
        log noHist noDate "> Failed"
        if [ -z $HTMLs_list ]; then
          rm -f $WEB_ROOT/$AVBASE_DIR/update.new
          LOG_ERROR="Error downloading webpage with keys list"
          STATUS_ERROR="Error downloading webpage with keys list"
          trace_error fatal   	#           
        else          
          continue		#     
        fi
      fi
      log noHist noDate "> Success"

      #   
      log noHist stdNoLF "Parsing keys list from webpage..."
      keys=$(cat $WEB_ROOT/keys.html | iconv -c -f cp1251 | sed 's/<[^<>]*>/\n/g' | sed 's/&[^&;]*;/\n/g' | sed -n 's/username:/&/Igp;s/password:/&/Igp' | sed 's/ //g' | sed '/xxx/d')
      if [ ! -z "$keys" ]; then
        log noHist noDate "> Success"
      else
        log noHist noDate "> Keys not found"
      fi
    fi

    until [ -z "$keys" ]; do 	#      
      log noHist stdNoLF "Getting USER/PASS from list..."
      USER=$(echo "$keys"|sed '/^username:*/I!d; s///;q')  #    username  password
      PASS=$(echo "$keys"|sed '/^password:*/I!d; s///;q')
      keys=$(echo "$keys"|sed '1,/^password:*/Id') 	   #       
      if [ -z $USER ] || [ -z $PASS ]; then
        log noHist noDate "> Not Found" 	#       ,
        break					#         
      else        
        log noHist noDate "> Success"
        log noHist std "Username: $USER"
        log noHist std "Password: $PASS"
        echo $USER|tr -d '\015'  > $KEY_F 	#   ,     
        echo $PASS|tr -d '\015' >> $KEY_F 	
        echo "$keys" > $KEYS_F			#     
        break 2                                 #      
      fi
    done # [ -z "$keys" ]

  done  # [ -z "$HTMLs_list" ]

  if [ -z $USER ] || [ -z $PASS ]; then
    #           USER/PASS,   
    LOG_ERROR="USER/PASS not found, need editing HTMLs_list in the config file"
    STATUS_ERROR="USER/PASS not found, need editing HTMLs_list in the config file"
    rm -f $KEY_F
    trace_error fatal
  fi
}  # dl_keys

load_username() {
  #         
  log noHist stdNoLF "Loading USER/PASS from $(basename $KEY_F)..."
  USER=$(cat $KEY_F|sed -n '1,1p')
  PASS=$(cat $KEY_F|sed -n '2,2p')
  if [ -z $USER ] || [ -z $PASS ]; then
    log noHist noDate "> Failed."
    dl_keys
  else
    log noHist noDate "> Success"
    log noHist std "Username: $USER"
    log noHist std "Password: $PASS"
  fi
} # load_username

dl_file() {
# :
# $1 - "fatal" -       !
# $2 -   
# $3 -   
# $4 -      (  , 
#        ,         
  Size=""
  ExitCode=6
  DownNow=1

  while [ $ExitCode = "6" ]; do
    log noHist stdNoLF "$2" 	#  
    if [ ! -z $4 ]; then 	#    ,     
      fLocalSize=0
      if [ -f $WEB_ROOT/$AVBASE_DIR/$(basename $3) ]; then        
        fLocalSize=$(stat -c %s $WEB_ROOT/$AVBASE_DIR/$(basename $3))	#           
      fi
      if [ "$4" == "$fLocalSize" ]; then
        log noHist noDateNoLF "> Identically"  	#    ,   
        log noHist noDateNoLF "\033[2K" 	#       
        DownNow=0
        ExitCode=0
      else
        log noHist noDateNoLF "Downloading..."
        DownNow=1
      fi
    fi

    if [ "$DownNow" == "1" ]; then
      wget --http-user=$USER --http-passwd=$PASS -U 'ESS Update (Windows; U; 32bit; VDB 13362; BPC 4.2.64.12; OS: 5.1.2600 SP 3.0 NT; TDB 13362; CH 0.0; LNG 1033; x32c; UPD AUTOSELECT; APP ess; BEO 1; CPU 5964; ASP 0.0; FW 0.1; PX 1; PUA 0)' -N -nv -o $WEB_ROOT/$AVBASE_DIR/tmp/wget.log --cache=off --timeout=15 --waitretry=3 --tries=3 --no-check-certificate "$3"
      ExitCode=$?
      case $ExitCode in
        0 ) 
          #  
          Size=$(cat $WEB_ROOT/$AVBASE_DIR/tmp/wget.log | sed 's/[^\[]*\[//' | sed 's/\/.*$//' )  
          if [ -z $Size ]; then 
            #    -    
            log noHist noDate "> New file not found"
          else
            Size=$(expr $Size / 1024)"."$(expr $Size % 1024) 		#    (/ 1024)
            Size=$(echo $Size | xargs printf '%.*f\n' 2 | sed 's/,/./') 	#   2   
            log noHist noDate "> Success ($Size Kb)"
          fi
        ;;
        1 ) log noHist noDate "> Generic error code" ;;
        3 ) log noHist noDate "> File I/O error" ;;
        4 ) log noHist noDate "> Network failure" ;;
        6 ) log noHist noDate "> Authorization failed" ;;   
        7 ) log noHist noDate "> Protocol errors" ;;
        8 ) log noHist noDate "> Server issued an error response" ;;
      esac

      if [ ! "$ExitCode" = "0" ]; then  #    
        if [ "$ExitCode" = "6" ]; then  #      -   
          dl_keys
        else #  ,   
          LOG_ERROR="Download error $(basename $3)"
          STATUS_ERROR="Download error $(basename $3)"
          if [ "$1" = "fatal" ]; then  #   ->    
            rm -f $WEB_ROOT/$AVBASE_DIR/update.new
            trace_error fatal
#          else 
#            trace_error nofatal
          fi
          break
        fi
      fi
    fi # DownNow
  done  # while ExitCode = 6
return $ExitCode
} # dl_file

# ---------------------------- MAIN START -------------------------------------
DelStr=0

rm -f $LOG

for i in $@; do    #    
  if [ "$i" = "-f" ]; then
    pid_file clear
  fi
done

pid_file

log noHist std "Start NOD32 base updater ver $VER. PID: $$"

for i in $@; do   #  
  case "$i" in
    "-h"|"--help" ) log noHist std "Usage arguments:"
       log noHist std "-c|--check  Force virus database check"
       log noHist std "-n|--new    Clean start of the script (remove database, archive and additional files)"
       log noHist std "-f          Force script startup"
       pid_file clear
       exit
    ;;
    "-c"|"--check" ) #    
      log noHist std "Force virus database check"
      rm $WEB_ROOT/$AVBASE_DIR/update.ver 2>/dev/null
    ;;    
    "-n"|"--new" ) #   
      log noHist stdNoLF "Clearing base file..."
      rm $WEB_ROOT/$AVBASE_DIR/*.* 2>/dev/null
      rm $WEB_ROOT/$AVBASE_DIR/tmp 2>/dev/null
      log noHist noDate "> Complete"
      log noHist stdNoLF "Clearing archive file..."
      rm $WEB_ROOT/base.tar 2>/dev/null
      log noHist noDate "> Complete"
      log noHist stdNoLF "Clearing additional file..."
      rm -f $KEY_F
      rm -f $KEYS_F
      rm -f $SERV_F
      rm -f $STATUS_F
      rm -f $VER_F
      log noHist noDate "> Complete"
    ;;
  esac
done

log noHist stdNoLF "Local base"
LOCALBASE=""

if [ -f $WEB_ROOT/$AVBASE_DIR/update.ver ]; then
  #   update.ver  ,      
  localver=$(cat $WEB_ROOT/$AVBASE_DIR/update.ver | sed '1,/ENGINE2/ d' | sed '/^version=*/!d; s///;q' | tr -d '\015')
fi

if [ -z "$localver" ]; then 
  log nohist noDate ": Version is unknown, checking local database"
  rm -f $WEB_ROOT/$AVBASE_DIR/update.ver
  rm -f $VER_F
else
  log nohist noDate ": $localver"
fi

if [ -f "$KEY_F" ]; then #      ?
  load_username #      
else 
  dl_keys #   -     
fi

echo Updating... > $STATUS_F

#       
mv $WEB_ROOT/$AVBASE_DIR/update.ver $WEB_ROOT/$AVBASE_DIR/update.tmp 2>/dev/null

mkdir -p $WEB_ROOT/$AVBASE_DIR
mkdir -p $WEB_ROOT/$AVBASE_DIR/tmp
cd $WEB_ROOT/$AVBASE_DIR/tmp

#       14 
find $(dirname $SERV_F) -name $(basename $SERV_F) -mtime +14 -type f -delete
SERVERS=""

if [ -f $SERV_F ]; then  #      
  log noHist stdNoLF "Reading list of servers from $(basename $SERV_F)..."
  SERVERS=$(cat $SERV_F|sort -R)
  if [ -z "$SERVERS" ]; then
    log noHist std "> Empty, download list"
  else
    log noHist noDate "> Success"
  fi
fi

if [ -z "$SERVERS" ]; then  #    ,   
  dl_file fatal "Downloading update.ver from $(echo $SERVER | sed 's:[^//]*\//::')..." $SERVER/$DIR/update.ver
  unpack_file
  log noHist stdNoLF "Parsing list of servers from update.ver..."
  grep Other= update.ver|sed s/Other=//|sed s/,/'\n'/g|sed s/^.*@//|sed s:/$DIR/::|sed '/update.eset.com/d'|sort -R > $SERV_F
  SERVERS=$(cat $SERV_F)

  if [ -n "$SERVERS" ]; then
    log noHist noDate "> Success"
  else 
    log noHist noDate "> Failed"
    LOG_ERROR="List of servers download error"
    STATUS_ERROR="List of servers download error"    
    trace_error fatal
  fi 
fi

rm -f update.ver

for UPDSERVER in $SERVERS; do   #    
  dl_file nofatal "Downloading update.ver from $(echo $UPDSERVER | sed 's:[^//]*\//::')..." $UPDSERVER/$DIR/update.ver
  if [ $? = 0 ]; then 
    unpack_file
    #       
    remotever=$(cat update.ver | sed '1,/ENGINE2/ d' | sed '/^version=*/!d; s///;q' | tr -d '\015')
    if [ ! "$remotever" == "$localver" ]; then  #    ,    
      log noHist std "New virus base found: $remotever"
      # parsing update.ver -----------------------------------------------------------------------------
      IFS='['
      for section in `cat update.ver|sed '1s/\[//;s/^ *//'|grep -v '^#'|grep -v '^$'`; do
        SectionName=$(echo $section|sed -n 1p|sed 's/..$//')
        case "$SectionName" in
          # ,    , 
          HOSTS) ;;
          W10UPGRADE*) ;;
          CONTINUOUS_*) ;;
          MAILSERVER*) ;;
          HIPS*) ;;
          PROTOSCAN*) ;;
          PARENTAL*) ;;
          HORUS*) ;;
          IRIS*) ;;
          DB*) ;;
          * )
            #         - 
            eval $(echo $section|tr -d "\r"|grep 'file='|sed 's/ *=/=/;s/= */=/')
    	    #   ENGINE,    
            if [ ! -z $(echo $section|grep '^ENGINE2]') ]; then
              version=$(echo $section|sed '/^version=*/!d; s///;q'|tr -d '\015')
            fi
            cd $WEB_ROOT/$AVBASE_DIR
            #   
            fServerSize=$(echo $section|sed '/^size=*/!d; s///;q'|tr -d '\015')
            fLocalSize=0
            if [ -f $WEB_ROOT/$AVBASE_DIR/$(basename $file) ]; then        
              fLocalSize=$(stat -c %s $WEB_ROOT/$AVBASE_DIR/$(basename $file))	  #           
              fLocalSize=$(expr $fLocalSize / 1024)"."$(expr $fLocalSize % 1024)	  #    (/ 1024)
              fLocalSize=$(echo $fLocalSize | xargs printf '%.*f\n' 2 | sed 's/,/./') #   2   
            fi
            dl_file fatal "Checking $(basename $file) ($fLocalSize Kb)... " $UPDSERVER$file $fServerSize
            #      update.ver
            echo [$(echo $section|sed 's/file=.*\//file=/') >> $WEB_ROOT/$AVBASE_DIR/update.new  ## ]
            cd $WEB_ROOT/$AVBASE_DIR/tmp
          ;;
        esac
      done   # for section
      IFS=' '
      # .new file to .ver & set new file date
      cd $WEB_ROOT/$AVBASE_DIR
      if [ -f "update.new" ]; then
        mv -f update.new update.tmp
        touch -am -r ./tmp/update.ver update.tmp
        log noHist std "New update.ver created success"
        break
      fi
      cd $WEB_ROOT/$AVBASE_DIR/tmp
    else 
      log noHist std "New version virus database not found on server"
      break
    fi #   
  fi #  
done # for UPDSERVER

# ----------------------------------------------------------------------------------------------------
clear_tmp
cd $WEB_ROOT
rm -f $WEB_ROOT/keys.ht*

echo Ok > $STATUS_F   #  

if [ "$PACKED" == "yes" ]; then
  if [ -n "$version" ] || [ ! -f "base.tar" ]; then 
    #        
    log noHist stdNoLF "Creating packed database..."
    tar cf base.tar $AVBASE_DIR/*
    if [ $? -eq 0 ]; then
      log noHist noDate "> Success"
    else 
      log noHist noDate "> Failed"
      LOG_ERROR="Error reate packed database"
      trace_error nofatal
    fi
  fi
fi

if [ -n "$version" ]; then
  #  
  echo $version > $VER_F
  logger -t nod32upd "Virus database updated success, ver: $version"
  log hist std "Virus database updated success, ver: $version"
else 
  #   
  echo $localver > $VER_F
  logger -t nod32upd "No virus database update, local ver: $localver"
  log hist std "No virus database update, local ver: $localver"
fi

log nohist std "NOD32 base updater ver $VER completed"

pid_file clear
