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


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

#include <tdelocale.h>
#include <tdeio/netaccess.h>


#include <tdeaction.h>

#include <tqcheckbox.h>
#include <kbuttonbox.h>
#include <kurlrequester.h>
#include <kurlcompletion.h>
#include <kcombobox.h>
#include <tqlayout.h>
#include <tdemessagebox.h>
#include <klineedit.h>
#include <tdetempfile.h>
#include <ksystemtray.h>
#include <ktar.h>
#include <kprogress.h>
#include <kprocio.h>
#include <knotifyclient.h>
#include <tdeapplication.h>
#include <dcopclient.h>
#include <kuser.h>

#include <tqtimer.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
};


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

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

//    MetaDB* updater = new MetaDB();
//    updater->update();



    tdemain->firstDownload = false;
    checkingDirectly = false;


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

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


    //Data Directory Widget


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

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


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

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


    TQWidget *hlp = new TQWidget( group );
    layout->addMultiCellWidget(hlp, 1,1, 0,1);
    TQHBoxLayout *dir_layout = new TQHBoxLayout(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 );

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

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


    TQGridLayout *proxy_layout = new TQGridLayout( 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
    TQWidget *proxy_hlp = new TQWidget( proxy_group );

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

    TQLabel *proxy_dir_label = new TQLabel(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);

    TQLabel *proxy_port_label = new TQLabel(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);


    TQLabel *proxy_user_label = new TQLabel(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);

    TQLabel *proxy_pass_label = new TQLabel(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


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


    TQGridLayout *daemon_layout = new TQGridLayout( 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);


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

    TQHBoxLayout *daemon_check_layout = new TQHBoxLayout(daemonhlp, KDialog::spacingHint() );
    daemon_box = new TQCheckBox(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 TQComboBox(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);



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



    KButtonBox *actionbox = new KButtonBox(this, TQt::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();

    TQFrame *status_frame = new TQFrame(this);
    status_frame->setFrameStyle(TQFrame::Panel | TQFrame::Sunken);
    TQBoxLayout *status_layout = new TQHBoxLayout(status_frame, 2);

    status_label = new TQLabel(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();


}

Freshklam::~Freshklam()
{

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

}

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

    while (( (pos = buf.find('\n')) != -1) || ( (pos = buf.find(']')) != -1))
    {
        TQString item = buf.left(pos);
        TQDate today = TQDate::currentDate();
        TQTime now = TQTime::currentTime();
        TQString suffix = TQString("%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);
    }

    // Notifications
    // -> Database updated
    if ((pos = item2.find("daily.cvd updated")) != -1 || (pos = item2.find("daily.cld updated")) != -1 ){
	CollectionDB::instance()->insertEvent("Updates","Daily Database Updated",dir_combo->url());
        KNotifyClient::event(tdemain->_tray->winId(), i18n("Updating Virues Databases..."), i18n("Updated Daily DB (1 out of 3)."));
        updateMailClient();
    }

    if ((pos = item2.find("main.cvd updated")) != -1 || (pos = item2.find("main.cld updated")) != -1 ){
        KNotifyClient::event(tdemain->_tray->winId(), i18n("Updating Virues Databases..."), i18n("Updated Main DB (2 out of 3)."));
    }

    if ((pos = item2.find("bytecode.cvd updated")) != -1 || (pos = item2.find("bytecode.cld updated")) != -1 ){
        KNotifyClient::event(tdemain->_tray->winId(), i18n("Updating Virues Databases..."), i18n("Updated Bytecode DB (3 out of 3)."));
    }

    // -> Database already up to date
    if ((pos = item2.find("daily.cvd database is up to date")) != -1 || (pos = item2.find("daily.cld database is up to date")) != -1){
        KNotifyClient::event(tdemain->_tray->winId(), i18n("Database is Up To Date"), i18n("Daily DB Up To Date (1 out of 3)."));
        updateMailClient();
    }

    if ((pos = item2.find("main.cvd database is up to date")) != -1 || (pos = item2.find("main.cld database is up to date")) != -1){
        KNotifyClient::event(tdemain->_tray->winId(), i18n("Database is Up To Date"), i18n("Main DB Up To Date (2 out of 3)."));
    }

    if ((pos = item2.find("bytecode.cvd database is up to date")) != -1 || (pos = item2.find("bytecode.cld database is up to date")) != -1){
        KNotifyClient::event(tdemain->_tray->winId(), i18n("Database is Up To Date"), i18n("Bytecode DB Up To Date (3 out of 3)."));
    }


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

    	tdemain->_tray->setPixmap(KSystemTray::loadIcon("klamav_update_required"));
        pos2 = item2.find('\n',pos);
        TQString version = item2.mid((pos+20),pos2 - (pos+20)).stripWhiteSpace();

        KNotifyClient::event(tdemain->_tray->winId(), i18n("ClamAV Outdated!"), i18n(TQString("Your copy of ClamAV is out of date! Please Upgrade to ClamAV %1!").arg(version).latin1()));
    }


}


void Freshklam::slotSearch()
{

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

    TQString filepattern = dir_combo->url();

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

    status_label->setText(i18n("Beginning Update..."));


    childproc = new KShellProcess();
    TQString command = "freshclam --stdout ";

    TQString 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;
    }

    writeConf();
    command += " --config-file=";
    command += tempFileName;

    disableInputs();


    *childproc << command;

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

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

    connect( childproc, SIGNAL(processExited(TDEProcess *)),
        SLOT(childExited()) );
    connect( childproc, SIGNAL(receivedStdout(TDEProcess *, char *, int)),
        SLOT(receivedOutput(TDEProcess *, char *, int)) );

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

}

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

    enableInputs();
    tdemain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));

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

    CollectionDB::instance()->insertEvent("Updates","Virus Database Updated",dir_combo->url());
    KNotifyClient::event(tdemain->_tray->winId(), i18n("Update Finished"), i18n("Virus Databases updated successfully."));

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

    //updateMetaDB();

}

void Freshklam::updateMetaDB()
{

    TQDate latestDate = TQDate::fromString(CollectionDB::instance()->latestMetaDBDate(),TQt::ISODate);
    TQDate today = TQDate::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 (TDEApplication::kApplication()->mainWidget()) {
            winid = TDEApplication::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();


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

    int result;
    int numfilters = nooffilters.toInt();
    nooffilters = numfilters;
    for (int j=0; j != numfilters; j++ ){
        TQVariant numb = j;
        TQString filtername=TQString("Filter #%1").arg(numb.toString());
        mailconfig->setGroup(filtername);
        TQString binary = mailconfig->readEntry("action-args-0");
        if (binary.find("klammail") != -1){
            TQString pathonly = binary.section(" ",2,2);
            if (pathonly == dir_combo->url())
                break;
            if (binary.find(" " + dir_combo->url() + " ") == -1){


                TQString 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'. "),TQString("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",TQString("klammail -d %1").arg(dir_combo->url()));
                    mailconfig->sync();
                    break;

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

    delete mailconfig;

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


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

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


void  Freshklam::setDirName(TQString 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();

    TQTextStream &ts = *(tf.textStream());

    ts << "DatabaseMirror database.clamav.net" << "\n";
    ts << "DNSDatabaseInfo current.cvd.clamav.net" << "\n";
    ts << "Foreground True" << "\n";
    if ( (proxyIP->hasAcceptableInput()) && (!(proxyIP->text().isEmpty()))) {
        ts << TQString("HTTPProxyServer %1").arg(proxyIP->text()) << "\n";
        if ( proxyPort->hasAcceptableInput() ) {
            ts << TQString("HTTPProxyPort %1").arg(proxyPort->text()) << "\n";
        }
        if ( proxyUser->hasAcceptableInput() && ! proxyUser->text().isEmpty() ) {
            ts << TQString("HTTPProxyUsername %1").arg(proxyUser->text()) << "\n";
            if ( proxyPass->hasAcceptableInput() ) {
               ts << TQString("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);
    }

    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 = TDEGlobal::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());

    config->sync();
}

bool  Freshklam::killPID(){

    TQFile inf(pidFileName);
    if (!inf.open(IO_ReadOnly))
        return false;
    TQTextStream is(&inf);
    TQString 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()))
        TDEIO::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);
}

TQString  Freshklam::getCurrentDBDir(){
    unsigned int ret= 0;
    unsigned int no = 0;
    struct cl_engine *engine = NULL;
    TQStringList lastDownloadPaths;
    TQString dbdir;
    TQString db;

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


    if (dbdir != dir_combo->url()){
        /* load all available databases from default directory */
        ret = cl_load(dir_combo->url().ascii(), engine, &no, CL_DB_STDOPT);
        //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(){

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

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

    if (ok){
        config->setGroup("Freshklam");
        config->writeEntry("lastDownloadPaths", lastDownloadPaths);
        config->sync();
        lastDownloadPaths = config->readListEntry("lastDownloadPaths");

    }

    KMessageBox::information (this,TQString(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 :
                    tdemain->firstDownload = true;
                    break;

                }
    }
}


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

}


void Freshklam::enableAutoUpdates()
{

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

}

void
Freshklam::getCurrentVersionOfClamAV( )
{

        ////kdDebug() << "version clamav" << endl;
	TQString suCommand=TQString("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(TDEProcess *)),
			SLOT(versionExited()) );

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

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

void Freshklam::readVersionLine(KProcIO *)
{
	TQString 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("/");
			TQString currentClamAVVersion = lineout.mid(StartPoint,(EndPoint - StartPoint));
                        currentClamAVVersion = currentClamAVVersion.stripWhiteSpace();
			KlamavConfig::setClamAVVersion(currentClamAVVersion);
            KlamavConfig::writeConfig();
                        ////kdDebug() << currentClamAVVersion << endl;
		}
   	}
	versionproc->ackRead();

	lineout = "";

}

#include "freshklam.moc"
