#!/bin/sh

po_domain="alterator-drweb"
alterator_api_version=1
 
set -f

. alterator-sh-functions
. shell-quote


service=/etc/init.d/drwebd
monitor=/etc/init.d/drweb-monitor
crontab=/etc/cron.d/drweb-update
drwebd_enable=/etc/drweb/drwebd.enable
monitor_enable=/etc/drweb/drweb-monitor.enable
cron=/etc/init.d/crond
keyfile=/opt/drweb/drweb32.key
quarantine=/var/drweb/infected/def/
cache_dir=/var/cache/alterator/drweb
DRWEB_QCONTROL=/opt/drweb/drweb-qcontrol
DRWEBDC=/opt/drweb/drwebdc

reset_cache()
{
  rm -rf -- "$cache_dir"
  mkdir -p -- "$cache_dir"
}

status_service()
{
    local statusstring="`_ "Dr.Web not installed."`"
    [ -e /etc/init.d/drwebd ] && statusstring=$($service status)
    local infected="0"
    [ -e "$DRWEB_QCONTROL" ] && infected=$("$DRWEB_QCONTROL" --timeout=5 --stat def/% | sed '/WARN\|ERROR/d' | wc -l)

    echo "$(/sbin/chkconfig --list drwebd)" | grep -v -q ":on"; write_bool_param daemon "$?"

    if [ -f "$crontab" ];then
	grep -q "^#" "$crontab"; write_bool_param enable_updates "$?"
	get_cron
    fi
    
    write_string_param cur_status "$statusstring"
    write_string_param quarantine_status "$infected"
    
    if [ -e /var/drweb/updates/timestamp ]; then
	write_string_param update_date "$(date +"%d.%m.%Y" -r /var/drweb/updates/timestamp)"
	write_string_param update_time "$(date +"%H:%M" -r /var/drweb/updates/timestamp)"
    else
	write_string_param update_date "__.__.__"
	write_string_param update_time "__:__"
	
    fi
    

}

init_pager()
{
    write_string_param per_page "50"
    write_string_param total $(find /var/drweb/infected/def/drweb/ -name *.envelope| wc -l)
}

init_selector()
{
    write_enum_item "25" "`_ "25 lines"`"
    write_enum_item "50" "`_ "50 lines"`"
    write_enum_item "100" "`_ "100 lines"`"
    write_enum_item "150" "`_ "150 lines"`"
    write_enum_item "200" "`_ "200 lines"`"
}

setstatus_daemon()
{
	local status=$1; shift
	if test_bool "$in_status"; then
    	    echo -e "ENABLE=1" > $drwebd_enable
    	    echo -e "ENABLE=1" > $monitor_enable
    	    $service "$status"
    	    $monitor "$status"
    	    chkconfig drwebd on
    	    chkconfig drweb-monitor on
        else
    	    $service "$status"
    	    $monitor "$status"
    	    chkconfig drwebd off
    	    chkconfig drweb-monitor off
    	    echo -e "ENABLE=0" > $drwebd_enable
    	    echo -e "ENABLE=0" > $monitor_enable
        fi
	local statusstring=$($service status)
	write_string_param cur_status "$statusstring"
}

get_cron()
{
	cat $crontab | ( read M H d m w;
	    [ "$M" == "*/30" -a "$H" == "*" ] && write_string_param update_period "30"
	    [ "$M" == "5" -a "$H" == "*" ] && write_string_param update_period "60"
	    [ "$M" == "10" -a "$H" == "*/2" ] && write_string_param update_period "120"
	    [ "$M" == "15" -a "$H" == "*/3" ] && write_string_param update_period "180"
	    [ "$M" == "20" -a "$H" == "*/4" ] && write_string_param update_period "240"
	    [ "$M" == "25" -a "$H" == "*/8" ] && write_string_param update_period "480"
	)
	
}

set_cron()
{
        timestring=""
        case "$in_time" in
    	    30)
    		timestring="*/30 * * * *"
    	    ;;
    	    60)
    		timestring="5 * * * *"
    	    ;;
    	    120)
    		timestring="10 */2 * * *"
    	    ;;
    	    180)
    		timestring="15 */3 * * *"
    	    ;;
    	    240)
    		timestring="20 */4 * * *"
    	    ;;
    	    480)
    	        timestring="25 */8 * * *"
    	    ;;
    	    *)
    		timestring="*/30 * * * *"
    	    ;;
    	esac
	echo -e "$timestring\tdrweb\t/opt/drweb/update.pl" > $crontab
	
	$cron reload
}

enable_cron()
{
    local status=$1; shift
    echo "Set cron $status" >&2
    if [ "$status" == "yes" ];then
	sed -e "/^#.*update\.pl$/s/^#//g" -i "$crontab"
    else
	sed -e "/^[^#].*update\.pl$/s/.*/#&/g" -i "$crontab" 
    fi
    
    $cron reload
}

read_key() 
{
    local key=$1; shift
    if [ -e "$key" ]; then
        for i in Version Applications Created Expires SubscriptionExpires; do
    	grep "$i" "$key" | 
	    while IFS='=' read param value; do
	        write_string_param "$param" "$(echo "$value"|sed -e "s/,/, /g")"
	        if [ "$param" == "SubscriptionExpires" ];then
	    	    test_expiration "$value"
	        fi
	    done
	done
    else
        for i in Version Applications Created Expires SubscriptionExpires; do
	        write_string_param "$i" ""
	done
        write_string_param "Alert" "`_ "Key: /opt/drweb/drweb32.key not found..."`"
    fi
}

test_expiration()
{
    local res=""
    local cur=$(date +%s)
    local test=$(date +%s -d "$1")
    [ "$cur" -gt "$test" ] && res="`_ "Expired !!!"`"
    
    write_string_param "Alert" "$res"
}

drop_key()
{
    rm -f $cache_dir/drweb32.key
}

new_key()
{
    cp -f "$keyfile" "$keyfile.old"
    cp -f "$in_key_file" $cache_dir/drweb32.key
    read_key "$in_key_file"
}

write_key()
{
    cp -f $cache_dir/drweb32.key "$keyfile"
    chmod 755 "$keyfile"
    chown root.root "$keyfile"
    reset_cache 
    $service restart
    $monitor restart
}

##########################
test_file() 
{
    local file=
    if [ -f "$in_file" ];then
	file="$in_file"
    else
	file=$(find /var/drweb/infected/def/ -name $(basename $in_file))
    fi
    
    	q_from=$(grep "^From:" "$file" | sed -e s/^From:[[:space:]]//g | sed -e s/.*\<//g | sed -e s/\>//g)
	q_to=$(grep "^To:" "$file" | sed -e s/^To:[[:space:]]//g | sed -e s/.*\<//g | sed -e s/\>//g)
	q_date="$(grep "^Date:" "$file" | cut -f2 -d ':')"
	q_subj=$(grep "^Subject:" "$file" | cut -f2 -d ':')
	
	write_string_param "q_file" "$file"
	write_string_param "q_from" "$q_from"
	write_string_param "q_to" "$q_to"
	write_string_param "q_date" "$q_date"
	write_string_param "q_subj" "$q_subj"
	write_string_param "q_reason" "Dr.Web report whill be added after many tests."

}

release_file()
{
    local file=`basename $in_file`
    "$DRWEB_QCONTROL" --send --remove def/%/$file
}

f_list()
{
    "$DRWEB_QCONTROL" --stat def/% | \
    while read _ file _; do
	write_enum_item "$file" "$(basename $file)"
    done
}

q_list()
{
    if [ "$in_start" -le 0 ];then
	f=1
    else
	f="$in_start"
    fi
    t=$(($f + $in_size -1))

    "$DRWEB_QCONTROL" --stat def/% | sed -n -e "$f,$t p" |\
    while read _ file _ from _ to _ date time; do
	write_table_item  \
    		name $(basename $file) \
    		q_from "$from" \
    		q_to "$to" \
    		q_date "$date $time"
    done
}

delete_filelist() 
{
    local IFS=';'
    for file in $in_qfiles; do
	"$DRWEB_QCONTROL" --remove def/%/$file
    done
}

rm_file()
{ 
    local file=`basename $in_file`
    "$DRWEB_QCONTROL" --remove def/%/$file
}

scan(){
    local file=
    if [ -f "$in_file" ];then
	file="$in_file"
    else
	file=$(find /var/drweb/infected/def/ -name $(basename $in_file))
    fi

    msg="$("$DRWEBDC" -u /var/drweb/run/.daemon -rvqx -f "$file" |
    sed -e 's/----- Dr.Web found viruses list begin -----/\n/g'|
    sed -e 's/----- Dr\.Web found viruses list end -----//g'|
    sed -e 's/[[:space:]]/\n/g'|
    sed -e 's/virus(es)\:/virus(es)\:\n/g'
    )"
    write_error "$msg"
}

read_samba_shares()
{
    if grep -qs '^[[:blank:]]*vfs objects = smb_spider' /etc/samba/smb.conf; then
        write_bool_param 'enable_samba' 'yes'
    else
        write_bool_param 'enable_samba' 'no'
    fi
}

write_samba_shares()
{
    local enabled="$1"

    if test_bool "$enabled"; then
        grep -qs '^[[:blank:]]*vfs objects = smb_spider' /etc/samba/smb.conf && return
        sed -i -r '/^\[(global|netlogon)\]/ !{/^\[.+\]/a \\tvfs objects = smb_spider
}' /etc/samba/smb.conf
    else
        sed -i '/^[[:blank:]]*vfs objects = smb_spider/d' /etc/samba/smb.conf
    fi

    service smb condrestart
}

reset_cache 
# Workaround for drweb-qcontrol bug:
# if maild is not running it creates /var/log/drweb/maild.log file
# with current user ownership (root in this case). Maild can't
# access this file afterward. So create this file and set
# owner drweb:drweb.
if [ ! -f /var/log/drweb/maild.log ]; then
	touch /var/log/drweb/maild.log
	chown drweb:drweb /var/log/drweb/maild.log
fi

on_message()
{
        case "$in_action" in
               list)
                      case "$in__objects" in
                    	 qlist)
                    	    q_list
                         ;;
                    	 flist)
                    	    f_list
                         ;;
                         selector)
                            init_selector
                         ;;
                         *)
                         ;;
                      esac
                         ;;
               read)
                      case "$in__objects" in
                         crontab) 
                            get_cron
                         ;;
                         status)
                            status_service
                            read_samba_shares
                         ;;
                         key)
                            read_key "$keyfile" 
                         ;;
                         newkey)
                            [ -f "$cache_dir/drweb32.key" ] && read_key "$cache_dir/drweb32.key"
                         ;;
                         file)
                            [ -z "$in_file" ] || test_file "$in_file"
                         ;;
                         pager)
                            init_pager
                         ;;
                         installed) 
                            [ -e /opt/drweb/drwebd ] && write_bool_param 'installed' 'yes' || write_bool_param 'installed' 'no'
                         ;;
                         drwebsambainstalled)
                            [ -e /etc/drweb/smb_spider.conf ] && write_bool_param 'drwebsambainstalled' 'yes' ||
                                write_bool_param 'drwebsambainstalled' 'no'
                         ;;
                         *)
                         ;;
                      esac
                      ;;
                write)
                      case "$in__objects" in
                         status)
                            [ -z "$in_status" ] || setstatus_service "$in_status"
                         ;;
                         daemon)
                            if test_bool "$in_status"; then
                            	setstatus_daemon "start"
                            else
                        	setstatus_daemon "stop"
                            fi
                         ;;
                         cron)
                            if test_bool "$in_cron"; then
                            	enable_cron "yes"
                            else
                        	enable_cron "no"
                            fi
                         ;;
                         update)
                            "$DRWEBDC" --update &
                         ;;
                         crontab)
                            [ -z "$in_time" ] || set_cron "$in_time"
                         ;;
                         newkey)
                            [ -f "$cache_dir/drweb32.key" ] && write_key
                         ;;
                         deliver_file)
                            [ -z "$in_file" ] || release_file "$in_file"
                         ;;
                         scan)
                            [ -z "$in_file" ] || scan "$in_file"
                         ;;
                         samba)
                            write_samba_shares "$in_enable_samba"
                         ;;
                         *)
                         ;;
                      esac
                    ;;
                new)
            	      case "$in__objects" in
            	        key)
            	    	    [ -z "$in_key_file" ] || new_key
            	        ;;
            	        *)
            	        ;;
            	      esac
                ;;
                delete)
            	      case "$in__objects" in
            	        newkey)
            	    	    drop_key
            	        ;;
            	        file)
            	    	    [ -z "$in_file" ] || rm_file "$in_file" 
            	        ;;
            	        filelist)
            	    	    [ -z "$in_qfiles" ] || delete_filelist "$in_qfiles"
            	        ;;
            	        *)
            	        ;;
            	      esac
                
                ;;
        esac
}
 
message_loop
