/*
 * Copyright (C) 2004 Robert Hogan <robert at roberthogan dot net>
 */
#include <config.h>


#include "kuarantine.h"
#include "dbviewer.h"
#include "klamav.h"


#include <klocale.h>
#include <kiconloader.h>
#include <kmenubar.h>
#include <kstatusbar.h>
#include <kkeydialog.h>
#include <kio/netaccess.h>
#include <kfiledialog.h>



#include <kbuttonbox.h>
#include <kurlrequester.h>
#include <kurlcompletion.h>
#include <kcombobox.h>
#include <qlayout.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>


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

    config = KGlobal::config();
    config->setGroup("Kuarantine");
    lastQuarLocations = config->readListEntry("KuarantineLocations");

    //kdDebug() << "in quarantine " << endl;    
    if (lastQuarLocations.isEmpty()){
        createQuarDir();
     }else{
        for (QStringList::Iterator it = lastQuarLocations.begin(); it == lastQuarLocations.begin(); it++ )
        quarloc = *it;
        if (!(KIO::NetAccess::exists(quarloc,TRUE,NULL))){
            KMessageBox::information (this,i18n( "Your current quarantine location ('%1') no longer exists. I'm going to attempt to create a new one.").arg(quarloc));
            createQuarDir();
        }
    }
        

        
    //Get Items for this location

    lastQuarItems = config->readListEntry(QString("Items %1").arg(quarloc));

    if (lastQuarItems.isEmpty()){
        config->writeEntry(QString("Items %1").arg(quarloc), "");
        lastQuarItems = config->readListEntry(QString("Items %1").arg(quarloc));
    }
    
    //Get History for this location

    lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));

    if (lastHistoryItems.isEmpty()){
        config->writeEntry(QString("History %1").arg(quarloc), "");
        config->sync();
        lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));
    }
    
    //Create GUI    

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

    QGroupBox *group = new QGroupBox(i18n("Quarantine Location"), this);
    vbox->addWidget(group);

    QGridLayout *layout = new QGridLayout( group, 9, 3, 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,2);
    QHBoxLayout *dir_layout = new QHBoxLayout(hlp, KDialog::spacingHint() );

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


    // anders: KDE is an amazing tool:)
    dir_combo = new KURLRequester( new KComboBox(true, hlp), hlp, "dir combo" );
    dir_combo->completionObject()->setMode(KURLCompletion::DirCompletion);

    dir_combo->comboBox()->insertStringList(lastQuarLocations);
    dir_combo->setMode( KFile::Directory|KFile::LocalOnly );
    dir_layout->addWidget(dir_combo);
    dir_label->setBuddy(dir_combo);
    
    connect( dir_combo, SIGNAL(urlSelected(const QString &)),
        SLOT(updateLastQuarLocations()) );
    connect( dir_combo, SIGNAL(textChanged(const QString &)),
        SLOT(updateLastQuarLocations()) );



    QGroupBox *group2 = new QGroupBox(i18n("Contents Of Quarantine"), this);
    vbox->addWidget(group2);

    QGridLayout *layout2 = new QGridLayout( group2, 9, 3, KDialog::spacingHint(),
            KDialog::spacingHint(), "layout2");
    layout2->addRowSpacing(0, group2->fontMetrics().height());
    layout2->setColStretch(0, 1);
    layout2->setColStretch(1, 1);

    QWidget *hlp2 = new QWidget( group2 );
    layout2->addMultiCellWidget(hlp2, 1,1, 0,2);
    QHBoxLayout *dir_layout2 = new QHBoxLayout(hlp2, KDialog::spacingHint() );


//     currentbox = new QListBox(hlp2);
//     QFontMetrics rb_fm(currentbox->fontMetrics());
//     currentbox->setMinimumSize(rb_fm.width("0")*25,
//                 rb_fm.lineSpacing()*8);
//     dir_layout2->addWidget(currentbox);

    currentbox = new QListView(hlp2);
        currentbox->setShowSortIndicator(true);
    
    QFontMetrics rb_fm(currentbox->fontMetrics());
    //currentbox->setMinimumSize(rb_fm.width("0")*55,
    //            rb_fm.lineSpacing()*15);
    //kdDebug() << ((currentbox->width())/3) << endl;
    currentbox->addColumn( i18n( "Name of File" ),0);
        currentbox->addColumn( i18n( "Name of Virus Found" ),0);
    currentbox->addColumn( i18n( "Date Quarantined" ),0);
    currentbox->setResizeMode(QListView::AllColumns);
    currentbox->setSelectionMode( QListView::Extended );
    currentbox->setAllColumnsShowFocus(true);

    qmenu = new QPopupMenu( currentbox );

        connect(currentbox, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ), 
        this, SLOT( slotRMB( QListViewItem *, const QPoint &, int ) ) );

    dir_layout2->addWidget(currentbox);
    
    //layout->addMultiCellWidget(currentbox);

    refresh();

    KButtonBox *actionbox = new KButtonBox(hlp2, Qt::Vertical);
    actionbox->addStretch();
    refresh_button = actionbox->addButton(i18n("&Refresh"));
    refresh_button->setDefault(true);
    search_button = actionbox->addButton(i18n("&Restore"));
    search_button->setDefault(true);
    cancel_button = actionbox->addButton(i18n("&Delete"));
    actionbox->addStretch();
        actionbox->adjustSize();
    actionbox->layout();

    dir_layout2->addWidget(actionbox);


    connect( refresh_button, SIGNAL(clicked()),
        SLOT(refresh()) );

    connect( search_button, SIGNAL(clicked()),
        SLOT(slotSearch()) );
    connect( cancel_button, SIGNAL(clicked()),
        SLOT(slotCancel()) );



    QGroupBox *group3 = new QGroupBox(i18n("Quarantine History"), this);
    vbox->addWidget(group3);

    QGridLayout *layout3 = new QGridLayout( group3, 9, 2, KDialog::spacingHint(),
            KDialog::spacingHint(), "layout3");
    layout3->addRowSpacing(0, group3->fontMetrics().height());
    layout3->setColStretch(0, 1);
    layout3->setColStretch(1, 1);

    QWidget *hlp3 = new QWidget( group3 );
    layout3->addMultiCellWidget(hlp3, 1,1, 0,2);
    QHBoxLayout *dir_layout3 = new QHBoxLayout(hlp3, KDialog::spacingHint() );


//     historybox = new QListBox(hlp3);
//     QFontMetrics rb_fm3(historybox->fontMetrics());
//     historybox->setMinimumSize(rb_fm3.width("0")*25,
//                 rb_fm3.lineSpacing()*8);
//     dir_layout3->addWidget(historybox);

    historybox = new QListView(hlp3);
        historybox->setShowSortIndicator(true);

    QFontMetrics rb_fm2(historybox->fontMetrics());
    //historybox->setMinimumSize(rb_fm2.width("0")*55,
    //            rb_fm2.lineSpacing()*15);
    historybox->addColumn( i18n( "Name of File" ),(historybox->width()));
        historybox->addColumn( i18n( "Name of Virus Found" ),(historybox->width()));
    historybox->addColumn( i18n( "Date Quarantined" ),(historybox->width()));
    historybox->setResizeMode(QListView::AllColumns);
    historybox->setSelectionMode( QListView::Extended );
    historybox->setAllColumnsShowFocus(true);

    hmenu = new QPopupMenu( historybox );

        connect(historybox, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ), 
        this, SLOT( slotRMB( QListViewItem *, const QPoint &, int ) ) );

    dir_layout3->addWidget(historybox);
    //layout->addMultiCellWidget(historybox, 2, 2, 0, 2);

    KButtonBox *actionbox3 = new KButtonBox(hlp3, Qt::Vertical);
    actionbox3->addStretch();
    search_button3 = actionbox3->addButton(i18n("&Clear All"));
    search_button3->setDefault(true);
    cancel_button3 = actionbox3->addButton(i18n("&Delete"));
    cancel_button3->setEnabled(true);
    actionbox3->addStretch();
    actionbox3->layout();

    dir_layout3->addWidget(actionbox3);

    refreshhistory();

    connect( search_button3, SIGNAL(clicked()),
        SLOT(slotClearHistory()) );
    connect( cancel_button3, SIGNAL(clicked()),
        SLOT(slotDeleteHistory()) );

    
    
}

Kuarantine::~Kuarantine()
{
}

void Kuarantine::refresh()
{


    QStringList obsoleteQuarItems;
    config = KGlobal::config();
    config->setGroup("Kuarantine");
    lastQuarItems = config->readListEntry(QString("Items %1").arg(quarloc));
    
    if (!(KIO::NetAccess::exists(quarloc,TRUE,NULL))){
        KMessageBox::information (this,i18n("Your current quarantine location ('%1') no longer exists. I'm going to attempt to create a new one.").arg(quarloc));
        createQuarDir();
    }else{

        currentbox->clear();
        for (QStringList::Iterator it = lastQuarItems.begin(); it != lastQuarItems.end(); it++ ){
                
                QString fname = getFileName(*it);    
                QString itemname = getVirusName(*it);
                QString when = getWhen(*it);
                
                QStringList tokens = QStringList::split ( "/", fname, FALSE );
                QString qname = tokens.last();
                
                qname.prepend("/");
                qname.prepend(quarloc);
                qname.append(":"+when);
                //kdDebug() << qname << endl;
                if (KIO::NetAccess::exists(qname,TRUE,NULL)){
                    //currentbox->insertItem(*it);
                    new QListViewItem( currentbox, fname, itemname,when);
                }else{
                    //kdDebug() << qname << "doesna exist" << endl;
                    obsoleteQuarItems.append(*it);
                }
        }
    
        for (QStringList::Iterator it = obsoleteQuarItems.begin(); it != obsoleteQuarItems.end(); it++ )
            lastQuarItems.remove(*it);
        
        config->writeEntry(QString("Items %1").arg(quarloc), lastQuarItems);
    }
    config->sync();

}

void Kuarantine::refreshhistory()
{
    config = KGlobal::config();
    config->setGroup("Kuarantine");
    lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));

    historybox->clear();
    for (QStringList::Iterator it = lastHistoryItems.begin(); it != lastHistoryItems.end(); it++ ){
            QString fname = getFileName(*it);    
            QString itemname = getVirusName(*it);
            QString when = getWhen(*it);

            new QListViewItem( historybox, fname, itemname,when);
    }
}

void Kuarantine::load()
{
    QString target;
    // the below code is what you should normally do.  in this
    // example case, we want the url to our own.  you probably
    // want to use this code instead for your app

        currentbox->clear();
    for (QStringList::Iterator it = lastQuarItems.begin(); it != lastQuarItems.end(); it++ ){
            QString fname = getFileName(*it);    
            QString itemname = getVirusName(*it);
            QString when = getWhen(*it);

            new QListViewItem( currentbox, fname, itemname,when);
    }
}



void Kuarantine::slotSearch()
{
    //if (!(currentbox->selectedItem()))
    //    return;

    QPtrList<QListViewItem> list;

    QListViewItemIterator it( currentbox, QListViewItemIterator::Selected );
    
        while ( it.current() ) {

        QListViewItem* tItem = it.current();
        config = KGlobal::config();
        config->setGroup("Kuarantine");
        lastQuarItems = config->readListEntry(QString("Items %1").arg(quarloc));
        lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));
    
        QString fname = tItem->text(0);
    
        QStringList tokens = QStringList::split ( "/", fname, FALSE );
        QString qname = tokens.last();
        qname.prepend("/");
        qname.prepend(quarloc);
        qname.append(":"+tItem->text(2));
        
        if (KIO::NetAccess::file_move(qname,fname)){
            lastQuarItems.remove(tItem->text(0)+":"+tItem->text(1)+":"+tItem->text(2));
            
            //currentbox->takeItem(currentbox->currentItem());
            list.prepend( it.current() );
            
            config->writeEntry(QString("Items %1").arg(quarloc), lastQuarItems);
            config->sync();
        }else{
            KMessageBox::information (this,i18n("<p>There was a problem restoring <b>%1</b>. Check your diskspace, the permissions on the location you are restoring to, and whether a file with the same name already exists in that location. </p>").arg(fname));
        }
            ++it;
    }

for( QListViewItem *item = list.first(); item; item = list.next() )
{
    delete item;
}


}


void Kuarantine::updateLastQuarLocations()
{


    config = KGlobal::config();
    config->setGroup("Kuarantine");
    lastQuarLocations = config->readListEntry("KuarantineLocations");
    
    if (lastQuarLocations.contains(dir_combo->url()) == 0) {
        dir_combo->comboBox()->insertItem(dir_combo->url(), 0);
        lastQuarLocations.prepend(dir_combo->url());
        if (lastQuarLocations.count() > 10) {
            lastQuarLocations.remove(lastQuarLocations.fromLast());
            dir_combo->comboBox()->removeItem(dir_combo->comboBox()->count() - 1);
        }
    }else{
        
        lastQuarLocations.remove(dir_combo->url());
        lastQuarLocations.prepend(dir_combo->url());
    }
    config->writeEntry("KuarantineLocations", lastQuarLocations);
    config->sync();
    quarloc = dir_combo->url();
    
    refresh();
    refreshhistory();
}


void Kuarantine::slotCancel()
{

    //if (!(currentbox->selectedItem()))
    //    return;
    QPtrList<QListViewItem> list;

    QListViewItemIterator it( currentbox, QListViewItemIterator::Selected );
    
        while ( it.current() ) {
            
        //QListViewItem* tItem = ( *it );
        //if (tItem->isSelected()){
            config = KGlobal::config();
            config->setGroup("Kuarantine");
            lastQuarItems = config->readListEntry(QString("Items %1").arg(quarloc));
            lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));
            
            QString QuarLocation = dir_combo->url();
        
        
        
            //QStringList tokens = QStringList::split ( ":", ( it.current() )->text(), FALSE );
            QString fname = ( it.current() )->text(0);
            QString itemname = ( it.current() )->text(1);
            QString when = ( it.current() )->text(2);
            
            QStringList tokens = QStringList::split ( "/", fname, FALSE );
            QString qname = tokens.last();
            qname.prepend("/");
            qname.prepend(QuarLocation);
            qname.append(":"+( it.current() )->text(2));
            
            if (KIO::NetAccess::del(qname,NULL)){
        
                lastQuarItems.remove(( it.current() )->text(0)+":"+( it.current() )->text(1)+":"+( it.current() )->text(2));
                lastHistoryItems.prepend(( it.current() )->text(0)+":"+( it.current() )->text(1)+":"+( it.current() )->text(2));
        
                new QListViewItem( historybox, fname, itemname,when);
            
                //historybox->inser( it.current() )(( it.current() )->text());
                //currentbox->takeItem(( it.current() ));
                list.prepend( it.current() );
            }else{
                KMessageBox::information (this,i18n( "There was a problem deleting the file. Is there a problem with the permissions on the quarantine folder? " ));
            }
        //}
            ++it;
    }

    for( QListViewItem *item = list.first(); item; item = list.next() )
    {
        delete item;
    }
    
    config->writeEntry(QString("Items %1").arg(quarloc), lastQuarItems);
    config->writeEntry(QString("History %1").arg(quarloc), lastHistoryItems);
    config->sync();

    
}





void Kuarantine::slotClearHistory()
{

    historybox->clear();
    config = KGlobal::config();
    config->setGroup("Kuarantine");
    lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));

    if (lastHistoryItems.isEmpty())
        return;

    lastHistoryItems.clear();

     config->writeEntry(QString("History %1").arg(quarloc), lastHistoryItems);
     config->sync();



}

void Kuarantine::slotDeleteHistory()
{

    //if (!(historybox->selectedItem()))
    //    return;

    //QListViewItem* tItem = historybox->selectedItem();

    config->setGroup("Kuarantine");
    lastHistoryItems = config->readListEntry(QString("History %1").arg(quarloc));

           QPtrList<QListViewItem> list;

    QListViewItemIterator it( historybox, QListViewItemIterator::Selected );
    
        while ( it.current() ) {

        lastHistoryItems.remove(( it.current() )->text(0)+":"+( it.current() )->text(1)+":"+( it.current() )->text(2));
        //historybox->takeItem(historybox->curren( it.current() )());
        list.prepend( it.current() );
        ++it;
    }
    
    for( QListViewItem *item = list.first(); item; item = list.next() )
    {
        delete item;

    }
    config->writeEntry(QString("History %1").arg(quarloc), lastHistoryItems);
    config->sync();

}


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

void  Kuarantine::createQuarDir(){

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

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

    if (ok){
        quarloc = QString("%1").arg(path);
        lastQuarLocations.append( QString("%1").arg(path));
        config = KGlobal::config();
        config->setGroup("Kuarantine");
        config->writeEntry("KuarantineLocations", lastQuarLocations);
        config->sync();
        lastQuarLocations = config->readListEntry("KuarantineLocations");
        
    }
    
    KMessageBox::information (this,QString(ok ? i18n( "Your default quarantine 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 quarantine directory by your self." )).arg(path));
    
}

QString Kuarantine::getFileName(QString entry){

    int fnameStartPoint = 0;
    int dtStartPoint = entry.findRev(":");
    int fnameEndPoint = entry.findRev(":", (signed int)-((entry.length() - dtStartPoint)+1));
    QString fname = entry.mid(fnameStartPoint,(fnameEndPoint - fnameStartPoint));
    
    //kdDebug() << fname << endl;
    
    return fname;    
    
}

QString Kuarantine::getVirusName(QString entry){

    int dtStartPoint = entry.findRev(":");
    int fnameEndPoint = entry.findRev(":", (signed int)-((entry.length() - dtStartPoint)+1));
    
    QString itemName = entry.mid((fnameEndPoint+1),((dtStartPoint+1) - (fnameEndPoint+2)));
    
    //kdDebug() << itemName << endl;
    
    return itemName.stripWhiteSpace();    
    
}

QString Kuarantine::getWhen(QString entry){

    int dtStartPoint = entry.findRev(":");
    
    QString when = entry.mid((dtStartPoint+1),(entry.length() - (dtStartPoint+1)));
    
    //kdDebug() << when << endl;
    
    return when;    
    
}

void Kuarantine::slotRMB( QListViewItem* Item, const QPoint & point, int )
{
    if( Item ){
    
    QPixmap gicon;
    QPixmap vicon;
    QPixmap ticon;
        QPixmap vlicon;

        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 );


    if (Item->listView() == currentbox){
        qmenu->clear();
        qmenu->insertItem( vlicon,i18n("Search for %1 with VirusList").arg(Item->text(1)), this, SLOT(slotVirusListCurrent()) );
        qmenu->insertItem( vicon,i18n("Search for %1 with VirusPool").arg(Item->text(1)), this, SLOT(slotVirusPoolCurrent()) );
        qmenu->insertItem( ticon,i18n("Search for %1 with Trend Micro").arg(Item->text(1)), this, SLOT(slotTrendMicroCurrent()) );
        qmenu->insertItem( gicon,i18n("Search for %1 with Google").arg(Item->text(1)), this, SLOT(slotGoogleCurrent()) );
    
        qmenu->popup( point );
    }else if (Item->listView() == historybox){
        hmenu->clear();
        hmenu->insertItem( vicon,i18n("Search for %1 with VirusPool").arg(Item->text(1)), this, SLOT(slotVirusPoolHistory()) );
        hmenu->insertItem( vicon,i18n("Search for %1 with VirusList").arg(Item->text(1)), this, SLOT(slotVirusListHistory()) );
        hmenu->insertItem( ticon,i18n("Search for %1 with Trend Micro").arg(Item->text(1)), this, SLOT(slotTrendMicroHistory()) );
        hmenu->insertItem( gicon,i18n("Search for %1 with Google").arg(Item->text(1)), this, SLOT(slotGoogleHistory()) );
    
        hmenu->popup( point );
    }
    }
}

void Kuarantine::slotVirusPoolCurrent()
{
    QString name = currentbox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name,"VirusPool");
}

void Kuarantine::slotVirusListCurrent()
{
    QString name = currentbox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name,"VirusList");
}

void Kuarantine::slotGoogleCurrent()
{
    QString name = currentbox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name,"Google");
}

void Kuarantine::slotTrendMicroCurrent()
{
    QString name = currentbox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name, "TrendMicro");
}


void Kuarantine::slotVirusPoolHistory()
{
    QString name = historybox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name,"VirusPool");
}

void Kuarantine::slotVirusListHistory()
{
    QString name = historybox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name,"VirusList");
}

void Kuarantine::slotGoogleHistory()
{
    QString name = historybox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name,"Google");
}

void Kuarantine::slotTrendMicroHistory()
{
    QString name = historybox->currentItem()->text(1);
    kmain->klamdb->slotExternal(name, "TrendMicro");
}

#include "kuarantine.moc"
