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

#include "scanviewer.h"
#include "klamav.h"
#include "freshklam.h"
#include "directorylist.h"
#include "dbviewer.h"
#include "collectiondb.h"

#include <config.h>
#include "klamavconfig.h"


#include <klocale.h>
#include <kiconloader.h>
#include <kmenubar.h>
#include <kstatusbar.h>
#include <kio/netaccess.h>
#include <knotifyclient.h>
#include <kprocio.h>
#include <qlayout.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <ksystemtray.h>
#include <kprogress.h>

#include <qtimer.h>
#include <qpushbutton.h>
#include <qcolor.h>
#include <qtooltip.h> //QToolTip::palette()

static int counter = 0;

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

    scanInProgress = TRUE;    
    multiScan = FALSE;    
    
    //QGridLayout *layout = new QGridLayout(this, 6, 3, 10, 4);
    layout = new QGridLayout(this, 6, 3, 10, 4);
    layout->setColStretch(0, 10);
    layout->addColSpacing(1, 10);
    layout->setColStretch(1, 0);
    layout->setColStretch(2, 1);
    layout->addRowSpacing(1, 10);
    layout->setRowStretch(1, 0);
    layout->setRowStretch(2, 10);
    layout->addRowSpacing(4, 10);
    layout->setRowStretch(4, 0);
    
    
    
    resultview = new QListView(this);
    resultview->setShowSortIndicator(true);

    QFontMetrics rb_fm(resultview->fontMetrics());
    //resultview->setMinimumSize(rb_fm.width("0")*55,
    //            rb_fm.lineSpacing()*15);
    resultview->addColumn( i18n( "Name of File" ),(resultview->width()/3));
        resultview->addColumn( i18n( "Name of Problem Found" ),(resultview->width()/3));
    resultview->addColumn( i18n( "Status" ),(resultview->width()/3));
    resultview->setResizeMode(QListView::AllColumns);
    resultview->setSelectionMode( QListView::Extended );
    resultview->setAllColumnsShowFocus(true);
    layout->addMultiCellWidget(resultview, 2, 2, 0, 2);

    connect( resultview, SIGNAL(onItem ( QListViewItem * )),
        SLOT(slotOnItem ( QListViewItem * )));
    connect( resultview, SIGNAL(onViewport (  )),
        SLOT(slotOffItem ( )));

    menu = new QPopupMenu( resultview );

        connect(resultview, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ), 
        this, SLOT( slotRMB( QListViewItem *, const QPoint &, int ) ) );
        
    status_frame = new QFrame(this);
    status_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    QBoxLayout *status_layout = new QHBoxLayout(status_frame, 2);
    

    status_label = new QLabel("", status_frame);
    status_layout->addWidget(status_label, 10);
    
    //matches_label = new QLabel(status_frame);
    //QFontMetrics ml_fm(matches_label->fontMetrics());
    //matches_label->setFixedWidth(ml_fm.width(i18n("9999 viruseses/errors found")));
    //matches_label->setFixedHeight(ml_fm.lineSpacing());
    //status_layout->addWidget(matches_label, 0);
    
    
    status_layout->activate();
    status_frame->adjustSize();
    status_frame->setMinimumSize(status_frame->size());
    layout->addMultiCellWidget(status_frame, 3, 3, 0, 2);

    status2_frame = new QFrame(this);
    status2_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    status2_layout = new QHBoxLayout(status2_frame, 2);
    
    status2_label = new QLabel(i18n("Files scanned: 0"), status2_frame);
    status2_layout->addWidget(status2_label, 10);
    status2_label->hide();

    prog = new KProgress(status2_frame);
    progosd = new K3bJobProgressOSD();
    progosd->setText("Scanning..");
    progosd->readSettings(KGlobal::config());

    status2_layout->addWidget(prog, 10);
    prog->adjustSize();
    prog->hide();
    progosd->hide();

     scan_time = new QPushButton( status2_frame );
    scan_time->setText(i18n("Calculating Scan Time... (Click To By-Pass)"));
    status2_layout->addWidget(scan_time,10);
     scan_time->adjustSize();
    scan_time->show();

    //status_frame->setPaletteBackgroundColor(QColor::Yellow);
    connect( scan_time, SIGNAL(clicked()),
        SLOT(slotCancelScanTime()) );



    matches2_label = new QLabel(status2_frame);
    QFontMetrics ml_fm2(matches2_label->fontMetrics());
    matches2_label->setFixedWidth(ml_fm2.width(i18n("9999 viruseses/problems found")));
    matches2_label->setFixedHeight(ml_fm2.lineSpacing());
    status2_layout->addWidget(matches2_label, 0);
    
    QToolTip::add(matches2_label, i18n("cf. 'Flanderseses' - Homer Simpson. This childish joke will be removed when KlamAV is more mature."));

    status2_layout->activate();
    status2_frame->adjustSize();
    status2_frame->setMinimumSize(status2_frame->size());

    layout->addMultiCellWidget(status2_frame, 4, 4, 0, 2);

        
    layout->activate();


}

ScanViewer::~ScanViewer()
{

    scanCancelled = TRUE;

    if ((childproc) && (scanInProgress)){
        delete childproc;
        childproc = 0;
    }
}



void ScanViewer::processOutput()
{
    int pos;
    QString item2;

    if (!(childproc))
        return;

    if ((showProgress) && prog->isHidden()){
        status2_label->hide();
        scan_time->hide();
        prog->show();
        progosd->show();
    }


    //buf.replace("//","/"); // don't know why they're getting two slashes
    while ((childproc) && ((pos = (childproc->readln(item2,true))) != -1)) {
            //item2 = (buf.section('\n',j,j)).stripWhiteSpace();
            item2 = item2.stripWhiteSpace();
            int fnameStartPoint = 0;
            int fnameEndPoint = item2.findRev(":");
            QString tmpFName = item2.mid(fnameStartPoint,(fnameEndPoint - fnameStartPoint));

            if ((pos = (item2.find(" FOUND"))) != -1){
            //if ((pos = buf.section('\n',j,j).find("FOUND")) != -1){
                QString tmpVirusName = item2.mid((fnameEndPoint+1),(item2.length() - (fnameEndPoint+1)));
                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-zzz ap"));

                if ((tmpVirusName.find("FOUND")) != -1){
                    tmpVirusName.replace("FOUND","");
                    QListViewItem* tm = new QListViewItem( resultview, tmpFName, tmpVirusName.stripWhiteSpace(),"Loose");
                    tm->setPixmap( 0, SmallIcon("klamav") );
                    //resultview->insertItem(buf.section('\n',j,j));
                    QuarantineList.append(tmpFName+":"+tmpVirusName+suffix);
                CollectionDB::instance()->insertEvent("Virus Found",tmpVirusName,tmpFName);

                }
                filesscanned++;
                if (!(showProgress))
                    status2_label->setText(i18n("Files scanned: %1").arg(filesscanned));
                
            //}else if ((pos = buf.section('\n',j,j).find("ERROR:")) != -1){
            }else if ((pos = (item2.find("ERROR:"))) != -1){
                QString tmpVirusName = item2.mid((fnameEndPoint+1),(item2.length() - (fnameEndPoint+1)));
                new QListViewItem( resultview, tmpFName, tmpVirusName.stripWhiteSpace(),"Not a Virus");
                //resultview->insertItem(buf.section('\n',j,j));
                CollectionDB::instance()->insertEvent("Error Found",tmpVirusName,tmpFName);

                errorsEncountered = TRUE;
                filesscanned++;
                if (!(showProgress))
                    status2_label->setText(i18n("Files scanned: %1").arg(filesscanned));
            //}else if ((pos = buf.section('\n',j,j).find("Scanning ")) != -1){
            }else if ((pos = (item2.find("Scanning"))) != -1){
                if (status_label->palette() != QToolTip::palette())
                    status_label->setText(item2);
            //}else if ((pos = buf.section('\n',j,j).find(": OK")) != -1){
            }else if ((pos = (item2.find(": OK"))) != -1){
                filesscanned++;
                if (!(showProgress))
                    status2_label->setText(i18n("Files scanned: %1").arg(filesscanned));

            //}else if ((pos = buf.section('\n',j,j).find(": Access denied")) != -1){
            }else if ((pos = (item2.find(": Access denied"))) != -1){
                filesscanned++;
                if (!(showProgress))
                    status2_label->setText(i18n("Files scanned: %1").arg(filesscanned));
                KNotifyClient::event(kmain->_tray->winId(),"ScanAccessDenied", QString("Can't scan %1 "
                    "- Access Denied!").arg(tmpFName));
                CollectionDB::instance()->insertEvent("Error Found","Access Denied",tmpFName);
            //}else if ((pos = buf.section('\n',j,j).find(": Can't open")) != -1){
    
            }else if ((pos = (item2.find(": Can't open"))) != -1){
                //status2_label->setText(i18n("Files scanned: %1").arg(++filesscanned));
                filesscanned++;
                if (!(showProgress))
                    status2_label->setText(i18n("Files scanned: %1").arg(filesscanned));
                KNotifyClient::event(kmain->_tray->winId(),"ScanAccessDenied", QString("Can't scan %1 "
                   "- Access Denied!").arg(tmpFName));
                CollectionDB::instance()->insertEvent("Error Found","Access Denied",tmpFName);
            }else if ((pos = (item2.find(": Empty file"))) != -1){
                //status2_label->setText(i18n("Files scanned: %1").arg(++filesscanned));
                filesscanned++;
                if (!(showProgress))
                        status2_label->setText(i18n("Files scanned: %1").arg(filesscanned));
            //KNotifyClient::event(kmain->_tray->winId(),"ScanAccessDenied", QString("Can't scan %1 "
            //            "- Empty File!").arg(tmpFName));
                CollectionDB::instance()->insertEvent("Error Found","Empty File",tmpFName);
            }
            item2 = "";
    }

    QString str;
    str.setNum(resultview->childCount());

    str += i18n(" viruseses/problems found");
    matches2_label->setText(str);

    if (showProgress){
        prog->setProgress (filesscanned);
        progosd->setProgress ((int)(100 * (float)filesscanned/cnt));
    }


}


void ScanViewer::slotScan(const QStringList & filepattern, int mode, bool recursive, bool dcopscan)
{

    //KMessageBox::information (this, filepattern);    
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    
    if(( args->isSet( "scanthis" ) ) || (dcopscan)) {
        calculateTime = FALSE;
        showProgress = FALSE;
        scan_time->hide();
        status2_label->show();

    }else{
        calculateTime = TRUE;
        showProgress = TRUE;
        scan_time->show();
        status2_label->hide();
    }

    scanCancelled = FALSE;
    scanInProgress = FALSE;

    m_mode = mode;
    m_filepattern = filepattern;
    m_recursive = recursive;


    //kdDebug() << "m_filepattern *" << m_filepattern << "*" << endl;

    prog->hide();
    progosd->hide();


    matches2_label->setText("");
    status_label->setText( i18n("Preparing To Scan ") + m_filepattern.join(" "));
    status2_label->setText(i18n("Files scanned:")+" 0");
    prog->setProgress(0);
    //progosd->setProgress(0);

    kdDebug() << filepattern << endl;
    QStringList tmpfilepattern = filepattern;

    cnt = 0;
    //QStringList temp = QStringList::split(" ", tmpfilepattern.replace("\"",""));
    //kdDebug() << temp << endl;
    if (calculateTime){
        for ( QStringList::Iterator it = tmpfilepattern.begin(); it != tmpfilepattern.end(); ++it ){
            QDir d( QString((*it).latin1()).stripWhiteSpace() );
            kdDebug() << "dir " << QString((*it).latin1()).stripWhiteSpace() << endl;
            counter = 0;
            cnt = cnt + countFiles(d);
            if (scanCancelled)
            break;
        }
    }
    //kdDebug() << scanCancelled << endl;

    calculateTime = FALSE;
    if (scanCancelled)
        return;

    //kdDebug() << filepattern << endl;

    prog->setTotalSteps(cnt);
    kdDebug() << "COUNT" << cnt << endl;    

    config = KGlobal::config();

    slotClear();
    QuarantineList.clear();
    
    errorsEncountered = FALSE;
    filesscanned = 0;
    //status2_label->setText(i18n("Scan in Progress..."));

    QString db;

    if(!( args->isSet( "scanthis" ) ) )
        db = kmain->freshklam->getCurrentDBDir();
    else{
        config->setGroup("Freshklam");
        QStringList lastDownloadPaths = config->readListEntry("lastDownloadPaths");
        for (QStringList::Iterator ita = lastDownloadPaths.begin(); ita == lastDownloadPaths.begin() ; ita++){
            db = *ita;
        }
    }
    
    ////kdDebug() << "here 2" << endl;    
    QString dbpath;
    QString excludes;
    QString options;
    
    if (!(db.isEmpty()))
        dbpath = QString(" -d %1 ").arg(db);

    config->setGroup("Klamscan");
    
    if (config->readEntry("ExcludeQuarantine") == "Yes"){
        config->setGroup("Kuarantine");
        QStringList lastQuarLocations = config->readListEntry("KuarantineLocations");
        QString quarloc;
        for (QStringList::Iterator ita = lastQuarLocations.begin(); ita == lastQuarLocations.begin() ; ita++){
                quarloc = *ita;
        }
        excludes += QString(" --exclude=%1 ").arg(quarloc);
    }

    
    //if ((recursive_box->isChecked() && !(multiScan)) || (multi_recursive && multiScan))
    if (recursive)
        options += " -r ";

    //config->setGroup("Klamscan");


    if (KlamavConfig::noFilesToExtract() > 0)
        options += "--max-files=" + QString("%1").arg(KlamavConfig::noFilesToExtract()) + " ";

    if (KlamavConfig::mBsToExtract() > 0)
        options += "--max-space=" + QString("%1").arg(KlamavConfig::mBsToExtract()) + " ";
        
    if (KlamavConfig::compressionRatio() > 0)
        options += "--max-ratio=" + QString("%1").arg(KlamavConfig::compressionRatio()) + " ";

    if (KlamavConfig::recursionLevel() > 0)
        options += "--max-recursion=" + QString("%1").arg(KlamavConfig::recursionLevel()) + " ";


    //config->setGroup("Klamscan");
    if (KlamavConfig::virusLimitsExceeded())
        options += "--block-max ";

    if (KlamavConfig::virusEncrypted())
        options += "--block-encrypted ";

    if (!(KlamavConfig::scanMail()))
        options += "--no-mail ";

    if (!(KlamavConfig::scanHTML()))
        options += "--no-html ";
        
    if (!(KlamavConfig::scanPE()))
        options += "--no-pe ";

    if (!(KlamavConfig::scanMacros()))
        options += "--no-ole2 ";

    if (KlamavConfig::virusBroken())
        options += "--detect-broken ";


    if (KlamavConfig::scanZip()){
        options += "--unzip";
        if ((KlamavConfig::zipUsing()) != "")
            options += "="+(KlamavConfig::zipUsing())+" ";
        else
            options+=" ";
    }

    if (KlamavConfig::scanRar()){
        options += "--unrar";
        if ((KlamavConfig::rarUsing()) != "")
            options += "="+(KlamavConfig::rarUsing())+" ";
        else
            options+=" ";
    }
    
    if (KlamavConfig::scanArj()){
        options += "--unarj";
        if ((KlamavConfig::arjUsing()) != "")
            options += "="+(KlamavConfig::arjUsing())+" ";
        else
            options+=" ";
    }

    if (KlamavConfig::scanZoo()){
        options += "--unzoo";
        if ((KlamavConfig::zooUsing()) != "")
            options += "="+(KlamavConfig::zooUsing())+" ";
        else
            options+=" ";
    }
    
    if (KlamavConfig::scanLzh()){
        options += "--lha";
        if ((KlamavConfig::lzhUsing()) != "")
            options += "="+(KlamavConfig::lzhUsing())+" ";
        else
            options+=" ";
    }

    if (KlamavConfig::scanJar()){
        options += "--jar";
        if ((KlamavConfig::jarUsing()) != "")
            options += "="+(KlamavConfig::jarUsing())+" ";
        else
            options+=" ";
    }

    if (KlamavConfig::scanDeb()){
        options += "--deb";
        if ((KlamavConfig::debUsing()) != "")
            options += "="+(KlamavConfig::debUsing())+" ";
        else
            options+=" ";
    }

    if (KlamavConfig::scanTar()){
        options += "--tar";
        if ((KlamavConfig::tarUsing()) != "")
            options += "="+(KlamavConfig::tarUsing())+" ";
        else
            options+=" ";
    }

    if (KlamavConfig::scanTgz()){
        options += "--tgz";
        if ((KlamavConfig::tgzUsing()) != "")
            options += "="+(KlamavConfig::tgzUsing())+" ";
        else
            options+=" ";
    }

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

    *childproc << "clamscan -v ";
    *childproc << excludes << " ";
    *childproc << dbpath << " ";
    *childproc << options << " ";
    
    *childproc << "'" + m_filepattern.join("' '") + "'";


/*    connect( childproc, SIGNAL(processExited(KProcess *)),
        SLOT(childExited()) );
    connect( childproc, SIGNAL(receivedStdout(KProcess *, char *, int)),
        SLOT(receivedOutput(KProcess *, char *, int)) );
    childproc->start(KProcess::NotifyOnExit, KProcess::Stdout);*/

    connect( childproc, SIGNAL(readReady(KProcIO *)),
        SLOT(receivedOutput(KProcIO *)) );
    childproc->start(KProcIO::NotifyOnExit);
    connect( childproc, SIGNAL(processExited(KProcess *)),
            SLOT(childExited()) );

    scanInProgress = TRUE;

    menu->setEnabled(FALSE);


}


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


    if ((childproc) && (scanInProgress)){
        //processOutput();
        kdDebug() << "deleting childproc" << endl;
        delete childproc;
        childproc = 0;
        kdDebug() << "deleted childproc" << endl;
    }

    scanInProgress = FALSE;

    status_label->setText(i18n( "If viruses were found, you can right-click to quarantine selected files." ));
    menu->setEnabled(TRUE);
    //dir_combo->setEnabled(TRUE);

    scan_time->hide();
    prog->hide();
    progosd->hide();
    progosd->saveSettings(KGlobal::config());
    status2_label->show();

    multiScan = FALSE;
    calculateTime = FALSE;

    emit scanFinished(this);

}


void ScanViewer::slotCancel()
{

    scanCancelled = TRUE;
    finish();

    //status2_frame->adjustSize();
    status2_label->setText(i18n("Cancelled"));

    CollectionDB::instance()->insertEvent("Manual Scan",QString("Scan Cancelled"),m_filepattern.join(" "));

}


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

    int result;
    
    status2_label->setText( i18n("Scan Complete") );
    CollectionDB::instance()->insertEvent("Manual Scan",QString("Scan Complete"),m_filepattern.join(" "));

    if (status == 0){
        if (!(errorsEncountered))
            KNotifyClient::event(kmain->_tray->winId(),i18n( "ScanCompleteNoVirus" ), i18n( "Scan Complete - No Viruses Found!" ));
        else
            KNotifyClient::event(kmain->_tray->winId(),i18n( "ScanCompleteNoVirusButErrors" ), i18n( "Scan Complete - No Viruses Found But Some Errors Encountered!" ));

    }else if(status == 1){
        switch (m_mode) {
        case 0:
            progosd->setText("Problems found!");
            result = KMessageBox::warningContinueCancelList(this, i18n( "I'm going to quarantine this lot, you can restore them later if you want. If you don't want to quarantine, just press cancel."),QuarantineList,i18n( "Quarantine Infected Files" ),i18n( "Quarantine" ));
            switch (result) {
                case 2 :KNotifyClient::event(kmain->_tray->winId(),"ScanAccessDenied", QString("Suspicious Items Not "
                        "Quarantined!")); break;
                case 5 : Quarantine(); break;
            }
            break;
        case 1:
            Quarantine(); break;
        default:
            KMessageBox::information (this,i18n( "Scan Complete - Viruses Found!") );break;
    }
       }else if (status ==40){ KMessageBox::information (this,i18n( "Unknown option passed.") );

       }else if (status ==50){ KMessageBox::information (this,i18n( "Database initialization error.") );

       }else if (status ==52){ KMessageBox::information (this,i18n( "Not supported file type.") );

       }else if (status ==53){ KMessageBox::information (this,i18n( "Can't open directory.") );

       }else if (status ==54){ KMessageBox::information (this,i18n( "Can't open file. (ofm)") );

       }else if (status ==55){ KMessageBox::information (this,i18n( "Error reading file. (ofm)") );

       }else if (status ==56){ KMessageBox::information (this,i18n( "Can't stat input file / directory.") );

       }else if (status ==57){ KMessageBox::information (this,i18n( "Can't get absolute path name of current working directory." ));

       }else if (status ==58){ KMessageBox::information (this,i18n( "I/O error, please check your filesystem." ));

       }else if (status ==59){ KMessageBox::information (this,i18n( "Can't get information about current user from /etc/passwd.") );

       }else if (status ==60){ KMessageBox::information (this,i18n( "Can't get information about user 'clamav' (default name) from /etc/passwd.") );

       }else if (status ==61){ KMessageBox::information (this,i18n( "Can't fork.") );

       }else if (status ==63){ KMessageBox::information (this, i18n("Can't create temporary files/directories (check permissions)."));

       }else if (status ==64){ KMessageBox::information (this, i18n("Can't write to temporary directory (please specify another one)."));

       }else if (status ==70){ KMessageBox::information (this, i18n("Can't allocate and clear memory (calloc)."));

       }else if (status ==71){ KMessageBox::information (this, i18n("Can't allocate memory (malloc)."));

       }else if (status ==71){KMessageBox::information (this, i18n("Unspecified Error!"));
    }

    status2_label->setText( i18n("Files scanned: %1").arg(filesscanned) );

    finish();

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

}


void ScanViewer::receivedOutput(KProcIO *)
{
    //buf += QCString(buffer, buflen+1);
    processOutput();
       //childproc->ackRead();

}


void ScanViewer::slotClear()
{
    //finish();
    resultview->clear();

//    status2_label->setText(i18n("Ready"));
    matches2_label->setText(i18n("0 viruseses/problems found"));

}


// void  ScanViewer::setDirName(QString dir){
// //    dir_combo->setEditText(dir);
//     dir_combo->setCurrentText(dir);
// }

void  ScanViewer::Quarantine(){
    
    //config = KGlobal::config();
    config->setGroup("Kuarantine");
    //lastQuarItems = config->readListEntry("KuarantineItems");
    QStringList lastQuarLocations = config->readListEntry("KuarantineLocations");
    
    QString quarloc;
    for (QStringList::Iterator it = lastQuarLocations.begin(); it == lastQuarLocations.begin() ; it++){
            quarloc = *it;
    }
        
    //Get Items for this location
    
    lastQuarItems = config->readListEntry(QString("Items %1").arg(quarloc));
    
    
    for (QStringList::Iterator it = QuarantineList.begin(); it != QuarantineList.end(); it++ ){
        if (lastQuarItems.contains(*it) != 0) {
            lastQuarItems.remove(*it);
        }
        QString item2 = (*it).stripWhiteSpace();
        ////kdDebug() << item2 << endl;
        int fnameStartPoint = 0;
        int dtStartPoint = item2.findRev(":");
        int fnameEndPoint = item2.findRev(":", (signed int)-((item2.length() - dtStartPoint)+1));
        ////kdDebug() << QString("%1").arg((signed int)-((item2.length() - dtStartPoint)+1)) << endl;
        ////kdDebug() << QString("%1").arg(dtStartPoint) << endl;
        ////kdDebug() << QString("%1").arg(fnameEndPoint) << endl;
        QString fname = item2.mid(fnameStartPoint,(fnameEndPoint - fnameStartPoint));
        QString itemName = item2.mid((fnameEndPoint+1),((dtStartPoint+1) - (fnameEndPoint+2)));
        QString when = item2.mid((dtStartPoint+1),(item2.length() - (dtStartPoint+1)));
        ////kdDebug() << fname << endl;
        ////kdDebug() << itemName << endl;
        ////kdDebug() << when << endl;
        if (!(fname.isEmpty())){
            QStringList tokens = QStringList::split ( "/", fname, FALSE );
            QString qname = tokens.last();
            qname.prepend("/");
            qname.prepend(quarloc);
            qname.append(":"+when);
            /*
            QString suCommand=QString("mv -f '%1' '%2'").arg(fname).arg(qname);
            KProcIO *proc = new KProcIO();
            proc->setUseShell(TRUE);
            *proc<<suCommand;
            
            proc->start(KProcIO::NotifyOnExit);
            */
            if (KIO::NetAccess::file_move(fname,qname)){
                if (lastQuarItems.contains(item2))
                    lastQuarItems.remove(item2);
                lastQuarItems.prepend(item2);
                (resultview->findItem(fname,0))->setText(2,"Quarantined");
                    (resultview->findItem(fname,0))->setPixmap( 0, SmallIcon("klamavbw") );
                chmod((const char *)qname,0400);
        CollectionDB::instance()->insertEvent("Quarantine",QString("Quarantined"),fname);

            }else{
                KMessageBox::information (this,i18n("<p>There was a problem quarantining <b>%1</b>. Check your diskspace, the permissions on your quarantine location and whether a file with the same name already exists in the quarantine. </p>").arg(fname));
            }

            
        }
    }
    config->writeEntry(QString("Items %1").arg(quarloc), lastQuarItems);
    config->sync();
    
    //kmain->kuarantine->refresh();



}

void ScanViewer::slotRMB( QListViewItem* Item, const QPoint & point, int )
{

    if( Item ){
    QPixmap gicon;
    QPixmap vicon;
    QPixmap vlicon;
    QPixmap ticon;

        QString iconPath = locate("cache", KMimeType::favIconForURL("http://www.viruspool.net")+".png");
        if ( iconPath.isEmpty() )
          vicon = SmallIcon("find");
        else
          vicon = QPixmap( iconPath );

        iconPath = locate("cache", KMimeType::favIconForURL("http://www.google.com")+".png");
        if ( iconPath.isEmpty() )
          gicon = SmallIcon("find");
        else
          gicon = QPixmap( iconPath );

        iconPath = locate("cache", KMimeType::favIconForURL("http://www.trendmicro.com")+".png");
        if ( iconPath.isEmpty() )
          ticon = SmallIcon("find");
        else
          ticon = QPixmap( iconPath );

        iconPath = locate("cache", KMimeType::favIconForURL("http://www.viruslist.com")+".png");
        if ( iconPath.isEmpty() )
          vlicon = SmallIcon("find");
        else
          vlicon = QPixmap( iconPath );

    menu->clear();
        menu->insertItem( "Quarantine Selected", this,SLOT(slotQuarantineSelected()) );
        menu->insertItem( vlicon,i18n("Search for %1 with VirusList").arg(Item->text(1)), this, SLOT(slotVirusList()) );

        menu->insertItem( vicon,i18n("Search for %1 with VirusPool").arg(Item->text(1)), this, SLOT(slotVirusPool()) );
        menu->insertItem( ticon,i18n("Search for %1 with Trend Micro").arg(Item->text(1)), this, SLOT(slotTrendMicro()) );

        menu->insertItem( gicon,i18n("Search for %1 with Google").arg(Item->text(1)), this, SLOT(slotGoogle()) );
        menu->popup( point );
     }
}

void ScanViewer::slotQuarantineSelected()
{

           QPtrList<QListViewItem> list;
    QListViewItemIterator it( resultview, QListViewItemIterator::Selected );
    
    QuarantineList = "";
        while ( it.current() ) {
        QListViewItem* tItem = it.current();
        
        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"));

        QuarantineList.append(tItem->text(0)+":"+tItem->text(1)+suffix);
        ++it;
    }

    Quarantine();
}



void ScanViewer::slotGoogle()
{
    QString name = resultview->currentItem()->text(1);
    kmain->klamdb->slotExternal(name, "Google");
}

void ScanViewer::slotVirusPool()
{
    QString name = resultview->currentItem()->text(1);
    kmain->klamdb->slotExternal(name, "VirusPool");
}

void ScanViewer::slotTrendMicro()
{
    QString name = resultview->currentItem()->text(1);
    kmain->klamdb->slotExternal(name, "TrendMicro");
}

void ScanViewer::slotVirusList()
{
    QString name = resultview->currentItem()->text(1);
    kmain->klamdb->slotExternal(name, "VirusList");
}

void ScanViewer::slotStartAgain()
{
    calculateTime = TRUE;
    emit scanStartingAgain(this);
    slotScan(m_filepattern, m_mode, m_recursive,false);
    

}

bool ScanViewer::scanGoingOn()
{
    return (scanInProgress || calculateTime);
}

void ScanViewer::slotCancelScanTime()
{
    calculateTime = FALSE;
    showProgress = FALSE;
    status2_label->show();
    scan_time->hide();

}


// void ScanViewer::startProgress()
// {
// 
//     cnt = 0;
//     //kdDebug() << "m_filepattern" << m_filepattern << endl;
//     QDir d( m_filepattern );
// //    int num = countFiles(d);
// //     if (countFiles(d) > 0)
// //        //kdDebug() << "count" << num << endl;
// 
//     progress = new KProgressDialog (this, "progress", i18n( "Loading .." ), i18n( "Loading..." ), true);
//     progress->setAllowCancel(false);
//     prog = progress->progressBar();
//     progress->setLabel(i18n( "Loading lots and lots and lots of virus information" ));
//     //int cnt = countFiles(d);
//     prog->setTotalSteps(countFiles(d));
//     //kdDebug() << "COUNT" << countFiles(d) << endl;    
// 
// }

int ScanViewer::countFiles( QDir & root)
{

    kapp->processEvents();

    if (!(calculateTime) || (scanCancelled)){
//         kapp->processEvents();
        return 0;
    }
    QStringList entries = root.entryList( QDir::Dirs | QDir::Files | QDir::Hidden);

    
    ////kdDebug() << "count" << counter << endl;    
    for (QStringList::size_type j = 0; j < entries.size(); j++ )
    {
        QString entry = entries[j];

        if( entry == "." || entry == "..")
            continue;
        

        QFileInfo fi(root, entry );
        entry = fi.absFilePath();
        entry = QDir::convertSeparators(entry);

        if ((fi.isFile()) && !(fi.isSymLink())){
            counter++;
        }else if ((fi.isDir()) && !(fi.isSymLink())){
            QDir temp(entry);
            countFiles(temp);
        }
    }
    return counter;
}

void ScanViewer::startProgressDialog( const QString & text )
{
    //if ( progressDialog )
    //    delete progressDialog;

    progressDialog = new KProgressDialog( this, "progress_dialog", QString::null, text, false );

    progressDialog->setAllowCancel( true );
    progressDialog->showCancelButton( true );
    progressDialog->setPlainCaption( i18n( "Please Wait" ) );

    progressDialog->progressBar()->setTotalSteps( 0 );
    progressDialog->progressBar()->setPercentageVisible( false );

    progressDialog->setMinimumDuration( 500 );
    progressDialog->show();

    timer = new QTimer( this );
    connect( timer, SIGNAL( timeout() ), this, SLOT( slotProg() ) );

    timer->start( 200, FALSE );
}

void ScanViewer::slotProg()
{

    if (progressDialog)
        progressDialog->progressBar()->setProgress(progressDialog->progressBar()->progress() + 4 );
}

void ScanViewer::slotOnItem( QListViewItem * lineitem)
{


    status_label->setPalette(QToolTip::palette());

    QString problem = lineitem->text(1).stripWhiteSpace();
    QString message = problem + " is probably a virus. Right-click and select a service to research it.";

    QString path( lineitem->text(0).stripWhiteSpace() );
    QString file = path.section( '/', -1 );

    if ((problem.contains("ExceededFile")) ||
       (problem == "Archive.ExceededRecursionLimit") ||
       (problem == "Oversized.Zip") ||
       (problem == "Oversized.RAR"))
        message = problem +": " + i18n("Attempts to scan ") + file + i18n(" resulted in exceeding a limit you set in 'Archive Limits'.");
    else if (problem == "ClamAV-Test-File")
        message = problem +": "  + file + i18n(" contains the ClamAV test signature. It's not a virus.");
    else if (problem == "Broken.Executable")
        message = problem +": " + file + i18n(" is a damaged exectuable. Some viruses use this to conceal themselves.");
    else if (problem == "Suspect.zip")
        message = problem +": " + file + i18n(" has a form of zip compression sometimes used by viruses.");
    else if (problem == "Encrypted.zip")
        message = problem +": " + file + i18n(" is an encrypted zip file.");
    else if (problem == "Encrypted.RAR")
        message = problem +": " + file + i18n(" is an encrypted RAR file.");
    else if (problem == "Exploit.Zip.ModifiedHeaders")
        message = problem +": " + file + i18n(" is mis-formatted in a way sometimes used by viruses.");


     status_label->setText( message);
    
}

void ScanViewer::slotOffItem( )
{

    status_label->unsetPalette();
    status_label->setText(i18n("Hover over each entry for more info. Right-click on entries for more options."));

}
#include "scanviewer.moc"
