/*
 * Copyright (C) 2004 Robert Hogan <robert at roberthogan dot net>
 */


#include "freshklam.h"
#include "klamav.h"
#include "klamd.h"
#include "collectiondb.h"
/*#include "gmanedb.h"*/
#include "klamavconfig.h"

#include <klocale.h>
#include <kio/netaccess.h>


#include <kaction.h>

#include <qcheckbox.h>
#include <kbuttonbox.h>
#include <kurlrequester.h>
#include <kurlcompletion.h>
#include <kcombobox.h>
#include <qlayout.h>
#include <kmessagebox.h>
#include <klineedit.h>
#include <ktempfile.h>
#include <ksystemtray.h>
#include <ktar.h>
#include <kprogress.h>
#include <kprocio.h>
#include <knotifyclient.h>
#include <dom/html_misc.h>
#include <kapplication.h>
#include <dcopclient.h>
#include <kuser.h>

#include <qtimer.h>

#include <clamav.h>
#include "version.h"

#include <stdlib.h>
    
const char *check_desc[] = {
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
    "10",
    "11",
    "12",
    "13",
    "14",
    "15",
    "16",
    "17",
    "18",
    "19",
    "20",
    "21",
    "22",
    "23",
    "24",
    "48",
    0
};


QString readymessage = i18n("KlamAV ") + KLAMAV_VERSION + i18n(" - Ready");

Freshklam::Freshklam(QWidget *parent, const char *name)
    : QWidget(parent, name)
{

//    MetaDB* updater = new MetaDB();
//    updater->update();
    updater = new KlamavUpdate(this);
    connect( updater,   SIGNAL( getCurrentVersionOfClamAV() ), SLOT( getCurrentVersionOfClamAV() ) );
    connect( updater,   SIGNAL( toggleUpgradeButtons(bool) ), SLOT( toggleUpgradeButtons(bool) ) );



    kmain->firstDownload = false;
    checkingDirectly = false;
    

    freshklamAlive = FALSE;
    config = KGlobal::config();
    config->setGroup("Freshklam");
    lastDownloadPaths = config->readListEntry("lastDownloadPaths");
    getCurrentVersionOfClamAV( );

    if ((lastDownloadPaths.isEmpty()) || (!(KIO::NetAccess::exists(QString((*lastDownloadPaths.begin())),TRUE,NULL)))){
        createDBDir();
    }
    QString proxyIPText = config->readEntry("ProxyIP");
    QString proxyPortText = config->readEntry("ProxyPort");
    QString proxyUserText = config->readEntry("ProxyUser");
    QString proxyPassText = config->readEntry("ProxyPass");


    //Data Directory Widget


    QVBoxLayout *vbox = new QVBoxLayout(this, KDialog::marginHint(),
            KDialog::spacingHint(), "vbox");

    //Proxy Widget
    QGroupBox *software_group = new QGroupBox(i18n("Software Updates"), this);
    vbox->addWidget(software_group);


    QGridLayout *software_layout = new QGridLayout( software_group, 5, 2, KDialog::spacingHint(),
            KDialog::spacingHint(), "software_layout");
    software_layout->addRowSpacing(0, software_group->fontMetrics().height());
    software_layout->setColStretch(0, 1);
    software_layout->setColStretch(1, 1);


    //Dazuko
    QWidget *dazuko_hlp = new QWidget( software_group );
    software_layout->addMultiCellWidget(dazuko_hlp, 1,2, 0,2);
    QGridLayout *dazuko_dir_layout = new QGridLayout(dazuko_hlp,2,2, KDialog::spacingHint() );


    clamav_box = new QCheckBox(i18n("Update ClamAV Automatically"), dazuko_hlp);
    clamav_box->setMinimumWidth(clamav_box->sizeHint().width());
    dazuko_dir_layout->addWidget(clamav_box,0,0);

    klamav_box = new QCheckBox(i18n("Update KlamAV Automatically"), dazuko_hlp);
    klamav_box->setMinimumWidth(klamav_box->sizeHint().width());
    dazuko_dir_layout->addWidget(klamav_box,0,1);



    clamav_options = new QPushButton (i18n( "Upgrade ClamAV Now" ), dazuko_hlp);
    dazuko_dir_layout->addWidget(clamav_options,1,0);
    clamav_options->setFixedSize(clamav_options->sizeHint());
    connect( clamav_options, SIGNAL( clicked() ), this,
		SLOT( checkForNewClamAVNow() ) );

    klamav_options = new QPushButton (i18n( "Upgrade KlamAV Now" ), dazuko_hlp);
    dazuko_dir_layout->addWidget(klamav_options,1,1);
    klamav_options->setFixedSize(klamav_options->sizeHint());
    connect( klamav_options, SIGNAL( clicked() ), this,
		SLOT( checkForNewKlamAVNow() ) );






    //Virus Database Directory
    QGroupBox *group = new QGroupBox(i18n("Virus Database Directory"), this);
    vbox->addWidget(group);
    

    QGridLayout *layout = new QGridLayout( group, 9, 2, KDialog::spacingHint(),
            KDialog::spacingHint(), "layout");

    layout->addRowSpacing(0, group->fontMetrics().height());
    layout->setColStretch(0, 1);
    layout->setColStretch(1, 1);


    QWidget *hlp = new QWidget( group );
    layout->addMultiCellWidget(hlp, 1,1, 0,1);
    QHBoxLayout *dir_layout = new QHBoxLayout(hlp,KDialog::spacingHint() );
    dir_combo = new KURLRequester( new KComboBox(true, this), hlp, "dir combo" );
    dir_combo->completionObject()->setMode(KURLCompletion::DirCompletion);
    dir_combo->comboBox()->insertStringList(lastDownloadPaths);
    dir_combo->setMode( KFile::Directory|KFile::LocalOnly );

    QLabel *dir_label = new QLabel(i18n("Directory:"), hlp);
    dir_label->setFixedSize(dir_label->sizeHint());
    dir_layout->addWidget(dir_label);
    dir_layout->addWidget(dir_combo);

    //Proxy Widget
    QGroupBox *proxy_group = new QGroupBox(i18n("Proxy for Database Updates"), this);
    vbox->addWidget(proxy_group);


    QGridLayout *proxy_layout = new QGridLayout( proxy_group, 2, 5, KDialog::spacingHint(),
            KDialog::spacingHint(), "proxy_layout");
    proxy_layout->addRowSpacing(0, proxy_group->fontMetrics().height());
    proxy_layout->setColStretch(0, 1);
    proxy_layout->setColStretch(1, 1);

    //IP Address & Port
    QWidget *proxy_hlp = new QWidget( proxy_group );

    proxy_layout->addMultiCellWidget(proxy_hlp, 1,2, 0,2);
    QGridLayout *proxy_dir_layout = new QGridLayout(proxy_hlp, 2,4,KDialog::spacingHint() );

    QLabel *proxy_dir_label = new QLabel(i18n("IP Address:"), proxy_hlp);
    //proxy_dir_label->setFixedSize(proxy_dir_label->sizeHint());
    proxy_dir_layout->addWidget(proxy_dir_label,0,0);
    proxyIP = new KLineEdit(proxy_hlp);
    proxy_dir_layout->addWidget(proxyIP,0,1);
    proxyIP->setText(proxyIPText);
    
    QLabel *proxy_port_label = new QLabel(i18n("Port:"), proxy_hlp);
    //proxy_port_label->setFixedSize(proxy_port_label->sizeHint());
    proxy_dir_layout->addWidget(proxy_port_label,0,3);
    proxyPort = new KLineEdit(proxy_hlp);
    proxy_dir_layout->addWidget(proxyPort,0,4);
    proxyPort->setText(proxyPortText);
    

    QLabel *proxy_user_label = new QLabel(i18n("User:"), proxy_hlp);
    //proxy_user_label->setFixedSize(proxy_user_label->sizeHint());
    proxy_dir_layout->addWidget(proxy_user_label,1,0);
    proxyUser = new KLineEdit(proxy_hlp);
    proxy_dir_layout->addWidget(proxyUser,1,1);
    proxyUser->setText(proxyUserText);
    
    QLabel *proxy_pass_label = new QLabel(i18n("Password:"), proxy_hlp);
    //proxy_pass_label->setFixedSize(proxy_pass_label->sizeHint());
    proxy_dir_layout->addWidget(proxy_pass_label,1,3);
    proxyPass = new KLineEdit(proxy_hlp);
    proxy_dir_layout->addWidget(proxyPass,1,4);
    proxyPass->setText(proxyPassText);
    
    //Daemon Widget


    QGroupBox *daemon_group = new QGroupBox(i18n("Database AutoUpdate Settings"), this);
    vbox->addWidget(daemon_group);


    QGridLayout *daemon_layout = new QGridLayout( daemon_group, 5, 4, KDialog::spacingHint(),
            KDialog::spacingHint(), "daemon_layout");
    daemon_layout->addRowSpacing(0, daemon_group->fontMetrics().height());
    daemon_layout->addRowSpacing(1, daemon_group->fontMetrics().height());
    //daemon_layout->setColStretch(0, 1);
    //daemon_layout->setColStretch(1, 1);


    QWidget *daemonhlp = new QWidget( daemon_group );
    daemon_layout->addMultiCellWidget(daemonhlp, 1,1, 0,1);

    QHBoxLayout *daemon_check_layout = new QHBoxLayout(daemonhlp, KDialog::spacingHint() );
    daemon_box = new QCheckBox(i18n("Update Virus Database Automatically"), daemonhlp);
    daemon_box->setMinimumWidth(daemon_box->sizeHint().width());

    daemon_check_layout->addSpacing(10);
    daemon_check_layout->addWidget(daemon_box);


    check_combo = new QComboBox(false, daemonhlp);
    check_combo->insertStrList(check_desc);
    if (!(config->readEntry("NoOfUpdates").isEmpty()))
        check_combo->setCurrentText(config->readEntry("NoOfUpdates"));
    check_combo->adjustSize();
    //check_combo->setFixedSize(check_combo->size());
    daemon_check_layout->addWidget(check_combo);


    
    QLabel *combo_label = new QLabel(i18n("Times a Day"), daemonhlp);
    //combo_label->setFixedSize(combo_label->sizeHint());
    daemon_check_layout->addWidget(combo_label);



    KButtonBox *actionbox = new KButtonBox(this, Qt::Horizontal);
    vbox->addWidget(actionbox, 2, 0);
    actionbox->addStretch();
    search_button = actionbox->addButton(i18n("&Update Now"));
    search_button->setDefault(true);
    cancel_button = actionbox->addButton(i18n("Cancel"));
    cancel_button->setEnabled(false);
    actionbox->addStretch();
    actionbox->layout();

    QFrame *status_frame = new QFrame(this);
    status_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    QBoxLayout *status_layout = new QHBoxLayout(status_frame, 2);

    status_label = new QLabel(readymessage, status_frame);
    status_layout->addWidget(status_label, 10);

    status_layout->activate();
    status_frame->adjustSize();
    status_frame->setMinimumSize(status_frame->size());
     vbox->addWidget(status_frame);



    initCheckBoxes();


    checkInternet();
}

Freshklam::~Freshklam()
{
    
    if (daemon_box->isChecked()){
        killPID();
    }
    if (!(tempFileName.isEmpty()))
        KIO::NetAccess::del(tempFileName,NULL);

}

void Freshklam::processOutput()
{
    int pos;
    int pos2;
    QString item2;

    while (( (pos = buf.find('\n')) != -1) || ( (pos = buf.find(']')) != -1))
    {
        QString item = buf.left(pos);
        QDate today = QDate::currentDate();
        QTime now = QTime::currentTime();
        QString suffix = QString("%1 %2")
        .arg(today.toString("ddd MMMM d yyyy"))
        .arg(now.toString("hh:mm:ss ap : "));

        if (!item.isEmpty()){
            if ( (pos2 = buf.find('[')) != -1)
                item +=']';
                status_label->setText(suffix + item);
            item2 += item;
            item2 += '\n';
        }
        buf = buf.right(buf.length()-pos-1);
    }

    if ((pos = item2.find("ERROR")) != -1){
        pos2 = item2.find('\n',pos);
        errorMessage = item2.mid(pos,pos2);
    }

    if ((pos = item2.find("Database updated")) != -1){
	   CollectionDB::instance()->insertEvent("Updates","Database Updated",dir_combo->url());
        KNotifyClient::event(kmain->_tray->winId(),"UpdatedDatabase", "Virus Database Updated.");
        updateMailClient();
    }

    if ((pos = item2.find("daily.cvd is up to date")) != -1){
	   CollectionDB::instance()->insertEvent("Updates","Database Already Up To Date",dir_combo->url());
        KNotifyClient::event(kmain->_tray->winId(),"DatabaseUpToDate", "Virus Database Up To Date.");
        updateMailClient();
    }


    if ((pos = item2.find("Recommended version:")) != -1){

        pos2 = item2.find('\n',pos);
        QString version = item2.mid((pos+20),pos2 - (pos+20)).stripWhiteSpace();

        if ((clamav_box->isChecked())){
    
            int result = KMessageBox::warningContinueCancel(this, i18n( "It looks like your version of the ClamAV engine is out of date! ClamAV-%1 is the most recent version of ClamAV available. Would you like to KlamAV to download and compile it for you?").arg(version),i18n( "Download and Install ClamAV-%1" ).arg(version),i18n( "Download and Install ClamAV-%1" ).arg(version));
        
            switch (result) {
                case 2 : 
                    break;
                case 5 : 
                    updater->downloadComponent("clamav",version,"tar.gz");
            }
        }else if (!(clamav_box->isChecked()))
            KNotifyClient::event(kmain->_tray->winId(),"ClamAVOutDated", QString("Your copy of ClamAV is out of date! Please Upgrade to ClamAV %1!").arg(version));
    }


}


void Freshklam::slotSearch()
{

    search_button->setEnabled(false);
    cancel_button->setEnabled(true);

    QString filepattern = dir_combo->url();
    
    CollectionDB::instance()->insertEvent("Updates","Commencing DB Update", filepattern);

    status_label->setText(i18n("Beginning Update..."));
    
    
    childproc = new KShellProcess();
    QString command = "freshclam --stdout ";
    
    QString user = KUser().loginName();
    command += " --user=" + user + " ";

    if (!(filepattern.isEmpty())){
        command += " --datadir=";
        command += filepattern;
    }
    
    if (daemon_box->isChecked()){
        command += " -d -c ";
        command += check_combo->currentText();
        KTempFile tf;
        if ( tf.status() != 0 ) {
            tf.close();
            //delete tf;
            KMessageBox::information (this,i18n( "There was an error creating a temp file!") );
            return;
        }
        pidFileName = tf.name();
        command += " -p ";
        command += pidFileName;
        freshklamAlive = TRUE;
    }
    
    if (!(KApplication::kApplication()->isRestored())){

        if (kmain->klamd->isKlamdAlive()){
            QString klamdconf = kmain->klamd->getKlamdConfFile();
            ////kdDebug() << klamdconf << endl;
            command += " --daemon-notify=";
            command += klamdconf;
        }        
    }
        
    writeConf();
    command += " --config-file=";
    command += tempFileName;
    
    disableInputs();
    

    *childproc << command;
    
    //kdDebug() << command << endl;

    childproc->start(KProcess::NotifyOnExit, KProcess::Stdout);

    connect( childproc, SIGNAL(processExited(KProcess *)),
        SLOT(childExited()) );
    connect( childproc, SIGNAL(receivedStdout(KProcess *, char *, int)),
        SLOT(receivedOutput(KProcess *, char *, int)) );
    
    if (kmain->klamd->isKlamdAlive())
        kmain->_tray->setPixmap(KSystemTray::loadIcon("klamavdl"));    
    else
        kmain->_tray->setPixmap(KSystemTray::loadIcon("klamavbwdl"));    

    kmain->EnableFreshklam->setEnabled(FALSE);
    kmain->DisableFreshklam->setEnabled(TRUE);

}

void Freshklam::finish()
{
    search_button->setEnabled(true);
    cancel_button->setEnabled(false);

    enableInputs();
    if (kmain->klamd->isKlamdAlive())
        kmain->_tray->setPixmap(KSystemTray::loadIcon("klamav"));    
    else
        kmain->_tray->setPixmap(KSystemTray::loadIcon("klamavbw"));    

    buf += '\n';
    processOutput();
    delete childproc;
    childproc = 0;
    freshklamAlive = FALSE;
    if (!(tempFileName.isEmpty()))
        KIO::NetAccess::del(tempFileName,NULL);

    kmain->EnableFreshklam->setEnabled(TRUE);
    kmain->DisableFreshklam->setEnabled(FALSE);

    //updateMetaDB();

}

void Freshklam::updateMetaDB()
{

    QDate latestDate = QDate::fromString(CollectionDB::instance()->latestMetaDBDate(),Qt::ISODate);
    QDate today = QDate::currentDate();
    kdDebug() << latestDate << " " << today << endl;

    if (latestDate.daysTo(today) > 31){
/*           MetaDB* updater = new MetaDB();
           updater->update();*/
    }

}

void Freshklam::slotCancel()
{
    finish();
    
    if (daemon_box->isChecked()){
        if (!(killPID()))
            KMessageBox::information (this,i18n( "There was a problem killing the update process!") );
    }

    status_label->setText(i18n("Canceled"));
    CollectionDB::instance()->insertEvent("Updates","Database Update Cancelled", dir_combo->url());

}

void Freshklam::processDied()
{
    
    KMessageBox::information (this,i18n( "Update Process died unexpectedly! Did you kill it manually?" ));

    status_label->setText(i18n("Update Process Died Unexpectedly!"));

    CollectionDB::instance()->insertEvent("Updates","Database Update Process Died Unexpectedly",dir_combo->url());

}


void Freshklam::childExited()
{
    int status = childproc->exitStatus();

/*       int winid = 0;
        if (KApplication::kApplication()->mainWidget()) {
            winid = KApplication::kApplication()->mainWidget()->winId();
        }*/
    finish();
    
    if (daemon_box->isChecked()){
    //KMessageBox::information (this,"Update Running in Background!", "Auto-Update","Don't Show Again");
        processDied();
        return;
    }
    

    if (status == 0){
        //updateMailClient();
    }else if (status == 1){
        //KMessageBox::information (this,"No Update Required - Database already up to date!");
        //updateMailClient();
    }else if (status == 40)
    KMessageBox::information (this, i18n("Unknown option passed."));
    else if (status == 50)
    KMessageBox::information (this, i18n("Can't change directory."));
    else if (status == 51)
    KMessageBox::information (this, i18n("Can't check MD5 sum."));
    else if (status == 52)
    KMessageBox::information (this, i18n("Connection (network) problem."));
    else if (status == 53)
    KMessageBox::information (this, i18n("Can't unlink a file."));
    else if (status == 54)
    KMessageBox::information (this, i18n("MD5 or digital signature verification error."));
    else if (status == 55)
    KMessageBox::information (this, i18n("Error reading file."));
    else if (status == 56)
    KMessageBox::information (this, i18n("Config file error."));
    else if (status == 57)
    KMessageBox::information (this, i18n("Can't create a new file."));
    else if (status == 58)
    KMessageBox::information (this, i18n("Can't read database from remote server."));
    else if (status == 59)
    KMessageBox::information (this, i18n("Mirrors are not fully synchronized (try again later)."));
    else if (status == 60)
    KMessageBox::information (this, i18n("Can't get information about clamav user from /etc/passwd."));
    else if (status == 61)
    KMessageBox::information (this, i18n("Can't drop privileges."));
    else
    KMessageBox::information (this, i18n("Warning - Unknown Error!"));

    if (errorMessage != "")
        KMessageBox::information (this,errorMessage);
    errorMessage = "";
    status_label->setText( readymessage );

    //if (status != 0)
          //matches_label->setText("");

}

void Freshklam::updateMailClient()

{


    config->setGroup("Freshklam");
    
    if (lastDownloadPaths.contains(dir_combo->/*currentText*/url()) == 0) {
    dir_combo->comboBox()->insertItem(dir_combo->/*currentText*/url(), 0);
    lastDownloadPaths.prepend(dir_combo->/*currentText*/url());
        if (lastDownloadPaths.count() > 10) {
            lastDownloadPaths.remove(lastDownloadPaths.fromLast());
            dir_combo->comboBox()->removeItem(dir_combo->comboBox()->count() - 1);
        }
    }else{
        
        lastDownloadPaths.remove(dir_combo->url());
        lastDownloadPaths.prepend(dir_combo->url());
    }
    config->writeEntry("lastDownloadPaths", lastDownloadPaths);
    
    config->writeEntry("ProxyIP", proxyIP->text());
    config->writeEntry("ProxyPort", proxyPort->text());
    config->writeEntry("ProxyUser", proxyUser->text());
    config->writeEntry("ProxyPass", proxyPass->text());
    
    //KMessageBox::information (this,proxyIP->text());
    config->sync();

    
    KConfig* mailconfig = new KConfig("kmailrc");
    mailconfig->setGroup("General");
    QVariant nooffilters = mailconfig->readEntry("filters");

    int result;    
    int numfilters = nooffilters.toInt();
    nooffilters = numfilters;
    for (int j=0; j != numfilters; j++ ){
        QVariant numb = j;
        QString filtername=QString("Filter #%1").arg(numb.toString());
        mailconfig->setGroup(filtername);
        QString binary = mailconfig->readEntry("action-args-0");
        if (binary.find("klammail") != -1){
            QString pathonly = binary.section(" ",2,2);
            if (pathonly == dir_combo->url())
                break;
            if (binary.find(" " + dir_combo->url() + " ") == -1){
                
                
                QString path = getenv("HOME");
                result = KMessageBox::warningContinueCancelList(this, i18n( "Since you have changed the database location, KlamAV needs to change the parameters used for mail scanning in KMail. The change is displayed below. If you have KMail open you will need to close it now so that the change can take effect. If you want to make the change manually just click 'Cancel'. "),QString("New filter command: klammail -d %1").arg(dir_combo->url()),i18n( "Update KMail Filters" ),i18n( "Update" ));
                switch (result) {
                    case 2 : KMessageBox::information (this,"KMail has not been updated with the new database location.");  break;
                    case 5 :
                    mailconfig->writeEntry("action-args-0",QString("klammail -d %1").arg(dir_combo->url()));
                    mailconfig->sync();
                    break;

                }
                break;
            }
        }
    }
    //KMessageBox::information (this,"Database Update Complete!");

    delete mailconfig;

}
void Freshklam::receivedOutput(KProcess */*proc*/, char *buffer, int buflen)
{
    //kdDebug() << buffer << endl;
    buf += QCString(buffer, buflen+1);
    processOutput();
}


void Freshklam::slotClear()
{
    finish();
    resultbox->clear();

    status_label->setText(i18n("Ready"));
    matches_label->setText("");
}


void  Freshklam::setDirName(QString dir){
//    dir_combo->setEditText(dir);
    dir_combo->setURL(dir);
}

void Freshklam::writeConf()
{
    KTempFile tf;
    if ( tf.status() != 0 ) {
        tf.close();
        //delete tf;
        KMessageBox::information (this,i18n( "KMFilterActionWithCommand: Could not create temp file!" ));
        return;
    }
    
    
    
    //tf->setAutoDelete(TRUE);
    tempFileName = tf.name();
    
    QTextStream &ts = *(tf.textStream());

    ts << "DatabaseMirror database.clamav.net" << "\n";
    ts << "DNSDatabaseInfo current.cvd.clamav.net" << "\n";
    ts << "Foreground" << "\n";
    if ( (proxyIP->hasAcceptableInput()) && (!(proxyIP->text().isEmpty()))) {
        ts << QString("HTTPProxyServer %1").arg(proxyIP->text()) << "\n";
        if ( proxyPort->hasAcceptableInput() ) {
            ts << QString("HTTPProxyPort %1").arg(proxyPort->text()) << "\n";
        }
        if ( proxyUser->hasAcceptableInput() && ! proxyUser->text().isEmpty() ) {
            ts << QString("HTTPProxyUsername %1").arg(proxyUser->text()) << "\n";
            if ( proxyPass->hasAcceptableInput() ) {
               ts << QString("HTTPProxyPassword %1").arg(proxyPass->text()) << "\n";
            }
        }
    } 
    else
       return;
}


void  Freshklam::initCheckBoxes(){

    if ((config->readEntry("AutoUpdate")) == "Yes"){
        daemon_box->setChecked(true);
        check_combo->setEnabled(true);
    }else{
        daemon_box->setChecked(false);
        check_combo->setEnabled(false);
    }

    if ((config->readEntry("AutoUpdateClamAV")) == "Yes"){
        clamav_box->setChecked(true);
    }else{
        clamav_box->setChecked(false);
    }

    if ((config->readEntry("AutoUpdateKlamAV")) == "Yes"){
        klamav_box->setChecked(true);
    }else{
        klamav_box->setChecked(false);
    }

    connect( clamav_box, SIGNAL(toggled(bool)), SLOT(handleChecks()) );
    connect( klamav_box, SIGNAL(toggled(bool)), SLOT(handleChecks()) );
    connect( daemon_box, SIGNAL(toggled(bool)), SLOT(handleChecks()) );
    connect( check_combo, SIGNAL(activated(int)), SLOT(handleChecks()) );

    if (daemon_box->isChecked())
        slotSearch();

}

void  Freshklam::handleChecks(){


    config = KGlobal::config();
    config->setGroup("Freshklam");
    if (daemon_box->isChecked()){
        config->writeEntry("AutoUpdate","Yes");
        check_combo->setEnabled(true);
    }else{
        config->writeEntry("AutoUpdate","No");
        check_combo->setEnabled(false);
    }
    config->writeEntry("NoOfUpdates", check_combo->currentText());

    if (clamav_box->isChecked()){
        config->writeEntry("AutoUpdateClamAV","Yes");
    }else{
        config->writeEntry("AutoUpdateClamAV","No");
    }

    if (klamav_box->isChecked()){
        config->writeEntry("AutoUpdateKlamAV","Yes");
    }else{
        config->writeEntry("AutoUpdateKlamAV","No");
    }
 
    config->sync();
}

bool  Freshklam::killPID(){
    
    QFile inf(pidFileName);
    if (!inf.open(IO_ReadOnly))
        return false;
    QTextStream is(&inf);
    QString line;
    while (!is.eof())
        line = is.readLine();
    inf.close();

    ////kdDebug() << line << endl;
    if (!(line.isEmpty()))
        kill(line.toInt(), SIGKILL);
    else
        return false;
    if (!(pidFileName.isEmpty()))
        KIO::NetAccess::del(pidFileName,NULL);

    return true;
}

void  Freshklam::disableInputs(){

    dir_combo->setEnabled(false);
    daemon_box->setEnabled(false);
    check_combo->setEnabled(false);
    proxyIP->setEnabled(false);
    proxyUser->setEnabled(false);
    proxyPort->setEnabled(false);
    proxyPass->setEnabled(false);
}

void  Freshklam::enableInputs(){

    dir_combo->setEnabled(true);
    daemon_box->setEnabled(true);
    if (daemon_box->isChecked())
        check_combo->setEnabled(true);
    else
        check_combo->setEnabled(false);
    proxyIP->setEnabled(true);
    proxyUser->setEnabled(true);
    proxyPort->setEnabled(true);
    proxyPass->setEnabled(true);
}

QString  Freshklam::getCurrentDBDir(){
        unsigned int ret= 0;
    unsigned int no = 0;
        struct cl_node *root = NULL;
    QStringList lastDownloadPaths;
    QString dbdir;
    QString db;

    config = KGlobal::config();
    config->setGroup("Freshklam");
    lastDownloadPaths = config->readListEntry("lastDownloadPaths");
    for (QStringList::Iterator ita = lastDownloadPaths.begin(); ita == lastDownloadPaths.begin() ; ita++){
            dbdir = *ita;
    }
    

    if (dbdir != dir_combo->url()){
        ret = cl_loaddbdir((const char *)dir_combo->url(), &root, &no);
        ////kdDebug() << "ret " << ret << endl;
        if (no == 0){
            db = dbdir;
        }else{
            db = dir_combo->url();
            lastDownloadPaths.prepend(dir_combo->url());
            config->writeEntry("lastDownloadPaths", lastDownloadPaths);
            config->sync();
        }

    }else
        db = dbdir;
    
    return db;


}

void  Freshklam::createDBDir(){

    QString path = getenv("HOME");
    bool ok = true;
    // directory exist?
    path += "/.klamav";
    QDir klamavdir(path);
    if (!klamavdir.exists() && !klamavdir.mkdir(path))
        ok = false;

    path += "/database";
    if (ok)
    {
        QDir klamavqdir(path);
        if (!klamavqdir.exists() && !klamavqdir.mkdir(path))
            ok = false;
        else
            chmod((const char *)path,0700);
    }

    if (ok){
        lastDownloadPaths.prepend( QString("%1").arg(path));
        config = KGlobal::config();
        config->setGroup("Freshklam");
        config->writeEntry("lastDownloadPaths", lastDownloadPaths);
        config->sync();
        lastDownloadPaths = config->readListEntry("lastDownloadPaths");
        
    }
    
    KMessageBox::information (this,QString(ok ? i18n( "Your Virus Database location has been set up as '%1'. You can change this to something else if you want to." ) : i18n( "I cannot create the directory '%1' for you. Something is wrong with your HOME or klamav directory. You have to adjust your Virus Database directory by your self." )).arg(path));

    if (ok){
        int result = KMessageBox::warningContinueCancel(this, i18n( "Would you like to download the latest Virus Database to your new database location now? (You can do this later manually if you want.)"),i18n( "Download Virus Database" ),i18n( "Download" ));
            switch (result) {
                case 2 : KMessageBox::information (this,i18n( "You should update the database manually at your earliest convenience.") );  break;
                case 5 : 
                    kmain->firstDownload = true;
                    break;

                }
    }
}


bool  Freshklam::isFreshklamAlive(){
    if (freshklamAlive)
        return true;
    return false;

}


void Freshklam::enableAutoUpdates()
{

        config = KGlobal::config();
        config->writeEntry("AutoUpdate","Yes");
        config->sync();
        daemon_box->setChecked(true);
        check_combo->setEnabled(true);
	slotSearch();

}

void Freshklam::checkForNewClamAVNow()
{

    updater->checkForNewClamAVDirectly();
}

void Freshklam::checkForNewKlamAVNow()
{

    updater->checkForNewKlamAVDirectly();
}

void
Freshklam::checkInternet() //SLOT
{

    m_url.setHost( "prdownloads.sourceforge.net" ); 
    if ( !m_url.port() ) m_url.setPort( 80 );

    connect( &m_resolver,   SIGNAL( finished( KResolverResults ) ), SLOT( resolved( KResolverResults ) ) );
    connectToHost();
}

void
Freshklam::connectToHost() //SLOT
{

        ////kdDebug() << m_url.host() << endl;

        m_resolver.setNodeName( m_url.host() );
        m_resolver.setFamily( KResolver::InetFamily );
        m_resolver.start();

}


void
Freshklam::resolved( KResolverResults result) // SLOT
{

    if ((!( result.error() != KResolver::NoError || result.isEmpty() )) 
       && klamav_box->isChecked()){
    	updater->checkForNewKlamAV();
    }else
        kdDebug() << "network error or not set to check for new klamav" << endl;
}


void
Freshklam::getCurrentVersionOfClamAV( )
{

        ////kdDebug() << "version clamav" << endl;
	QString suCommand=QString("clamscan -V");

	versionproc = new KProcIO();
	versionproc->setUseShell(TRUE);
	versionproc->setUsePty (KProcIO::Stdout,TRUE);

	*versionproc<<suCommand;
	
	connect( versionproc, SIGNAL(readReady(KProcIO *)),
		SLOT(readVersionLine(KProcIO *)) );
	connect( versionproc, SIGNAL(processExited(KProcess *)),
			SLOT(versionExited()) );

	versionproc->start(KProcIO::NotifyOnExit);
    versionproc->closeWhenDone();
}

void Freshklam::versionExited()
{
    kdDebug() << "deleting versionproc" << endl;
    delete versionproc;
}

void Freshklam::readVersionLine(KProcIO *)
{
	QString lineout = "";
	int pos;
	
	if ((pos = (versionproc->readln(lineout))) != -1) {
		if ((pos = (lineout.find("ClamAV"))) != -1){
			lineout = lineout.stripWhiteSpace();
			int StartPoint = (lineout.find("ClamAV") + 6);
			int EndPoint = lineout.find("/");
			QString currentClamAVVersion = lineout.mid(StartPoint,(EndPoint - StartPoint));
                        currentClamAVVersion = currentClamAVVersion.stripWhiteSpace();
			KlamavConfig::setClamAVVersion(currentClamAVVersion);
                        ////kdDebug() << currentClamAVVersion << endl;
		}
   	}
	versionproc->ackRead();

	lineout = "";

}

void Freshklam::toggleUpgradeButtons(bool state)
{

    klamav_options->setEnabled(state);
    clamav_options->setEnabled(state);


}

#include "freshklam.moc"
