/*
 * Copyright (C) 2004 Robert Hogan <robert at roberthogan dot net>
 *
 *  ClamAV DB code:
 *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>

 */

#include "dbviewer.h"
#include "klamav.h"
#include <clamav.h>
#include "pageviewer.h"
#include "tabwidget.h"
#include "freshklam.h"

#include <qheader.h>
#include <qlayout.h>
#include <qpopupmenu.h>

#include <ktoolbarbutton.h> //ctor
#include <ktempfile.h>
#include <ktempdir.h>
#include <klistviewsearchline.h>
#include <klistview.h>
#include <kprogress.h>

#include <dirent.h>
#include <zlib.h>

#include <klocale.h>
#include <kstandarddirs.h>
#include <kiconloader.h>

#define TAR_BLOCKSIZE 512
#define FILEBUFF 8192

int cli_untgz(int fd, const char *destdir);
int cli_rmdirs(const char *dirname);
int cli_strbcasestr(const char *haystack, const char *needle);
int cli_chomp(char *string);
char *cli_strtok(const char *line, int field, const char *delim);

using namespace KlamAV;
/*
 *  Constructs a KlamDB as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 *
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  TRUE to construct a modal dialog.
 */
KlamDB::KlamDB( QWidget* parent, const char* name, bool modal, WFlags fl )
    : QDialog( parent, name, modal, fl )
{
    if ( !name )
    setName( "KlamDB" );

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

    QWidget* privateLayoutWidget = new QWidget( this, "dblayout" );
    vbox->addWidget(privateLayoutWidget);

    dblayout = new QGridLayout( privateLayoutWidget, 1, 1, 2, 2, "dblayout"); 
    dblayout->setColStretch(1, 1);

    tabBrowser = new TabWidget(privateLayoutWidget);

    
    dblayout->addMultiCellWidget( tabBrowser, 0, 1, 1, 1 );
        
    KToolBarButton *button;
    KToolBar* searchToolBar = new KToolBar( privateLayoutWidget );
    searchToolBar->setMovingEnabled(false);
    searchToolBar->setFlat(true);
    searchToolBar->setIconSize( 16 );
    searchToolBar->setEnableContextMenu( false );

    button = new KToolBarButton( "locationbar_erase", 0, searchToolBar );

    VirusList = new KListView( privateLayoutWidget, "VirusList" );
    VirusList->addColumn( i18n( "All Known Viruses" ),150 );
/*    VirusList->setResizeMode(QListView::AllColumns);
    VirusList->setColumnWidthMode(0,QListView::Maximum);*/
    connect(VirusList, SIGNAL( doubleClicked( QListViewItem * , const QPoint &, int ) ),
                    this, SLOT(slotOpenTab(QListViewItem * , const QPoint &, int )) );

    menu = new QPopupMenu( VirusList );

    QPixmap gicon;
    QPixmap vicon;
    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 );

        menu->insertItem(vicon, i18n("Search in VirusList"), this,SLOT(slotVirusList()) );
        menu->insertItem(vicon, i18n("Search in VirusPool"), this,SLOT(slotVirusPool()) );
        menu->insertItem(ticon, i18n("Search with Trend Micro"), this,SLOT(slotTrendMicro()) );
        menu->insertItem(gicon, i18n("Search with Google"), this,SLOT(slotGoogle()) );

        connect(VirusList, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ), 
        this, SLOT( slotRMB( QListViewItem *, const QPoint &, int ) ) );
    
    kLineEdit1 = new KListViewSearchLine( (QWidget *)searchToolBar, VirusList,"klinedit1");
    QValueList<int> columns;
        columns.append(0);
    kLineEdit1->setSearchColumns(columns);
    kLineEdit1->setMaxLength(2);
    connect(button, SIGNAL( clicked() ),
                    kLineEdit1, SLOT(clear()) );

    dblayout->addWidget( searchToolBar, 0, 0 );
    
    dblayout->addWidget( VirusList, 1, 0 );
    

    languageChange();
    //resize( QSize(600, 480).expandedTo(minimumSizeHint()) );
    clearWState( WState_Polished );
    
    //listdir((const char *)QString("/home/robert/.klamav/database"));
    slotOpenHome();
}

/*
 *  Destroys the object and frees any allocated resources
 */
KlamDB::~KlamDB()
{
    // no need to delete child widgets, Qt does it all for us
}

/*
 *  Sets the strings of the subwidgets using the current
 *  language.
 */
void KlamDB::languageChange()
{
    setCaption( i18n( "Form1" ) );
    tabBrowser->changeTab( tab, i18n( "Info" ) );
    VirusList->header()->setLabel( 0, i18n( "All Known Viruses" ) );
    VirusList->clear();
    /*KListViewItem * item =*/ new KListViewItem( VirusList, 0 );
    //item->setText( 0, tr( "New Item" ) );

}

int KlamDB::listdb(const char *filename)
{
    FILE *fd, *tmpd;
//    char *buffer, *pt, *start, *dir, *tmp;
    char *buffer, *pt, *start;
    int line = 0, bytes;
    const char *tmpdir;

    if((fd = fopen(filename, "rb")) == NULL) {
    printf("!listdb(): Can't open file %s\n", filename);
    return -1;
    }

    if(!(buffer = (char *) malloc(FILEBUFF))) {
    printf("!listdb(): Can't allocate memory.\n");
    fclose(fd);
    return -1;
    }

    memset(buffer, 0, FILEBUFF);
    /* check for CVD file */
    fgets(buffer, 12, fd);
    rewind(fd);

    if(!strncmp(buffer, "ClamAV-VDB:", 11)) {

    fseek(fd, 512, SEEK_SET);

    tmpdir = getenv("TMPDIR");
    if(tmpdir == NULL)
#ifdef P_tmpdir
        tmpdir = P_tmpdir;
#else
        tmpdir = "/tmp";
#endif

    KTempDir* tf = new KTempDir();
    if ( tf->status() != 0 ) {
        delete tf;
        return -1;
    }
    //dir = tf.name();
    
    //kdDebug() << tf->name() << endl;
//     if(mkdir(tf->name(), 0700)) {
//         printf("!listdb(): Can't create temporary directory \n");
//         free(buffer);
//         fclose(fd);
//         return -1;
//     }

    /* FIXME: it seems there is some problem with current position indicator
    * after gzdopen() call in cli_untgz(). Temporarily we need this wrapper:
    */

    /* start */

/*    tmp = cli_gentemp(tmpdir);*/
    KTempFile* tn = new KTempFile(tf->name());
    //tn->close();
    //tn->unlink();

    //kdDebug() << tn->name() << endl;
    
    if((tmpd = fopen(tn->name(), "wb+")) == NULL) {
        printf("!listdb(): Can't create temporary file \n");
        delete tf;
        delete tn;
        free(buffer);
        fclose(fd);
        return -1;
    }

    while((bytes = fread(buffer, 1, FILEBUFF, fd)) > 0)
        fwrite(buffer, 1, bytes, tmpd);

    free(buffer);
    fclose(fd);

    fflush(tmpd);
    fseek(tmpd, 0L, SEEK_SET);

    if(cli_untgz(fileno(tmpd), tf->name())) {
        printf("!listdb(): Can't unpack CVD file.\n");
        cli_rmdirs(tf->name());
        delete tf;
        delete tn;
        fclose(tmpd);
        free(buffer);
        return -1;
    }

    fclose(tmpd);
    delete tn;
    /* wrapper end */

    /* list extracted directory */
    listdir(tf->name());

    cli_rmdirs(tf->name());
    delete tf;
    
    return 0;
    }

    if(cli_strbcasestr(filename, ".db") || cli_strbcasestr(filename, ".db2")) {
    /* old style database */

    while(fgets(buffer, FILEBUFF, fd)) {
        line++;
        pt = strchr(buffer, '=');
        if(!pt) {
        printf("!listdb(): Malformed pattern line %d (file %s).\n", line, filename);
        fclose(fd);
        free(buffer);
        return -1;
        }

        start = buffer;
        *pt = 0;

        if((pt = strstr(start, " (Clam)")))
        *pt = 0;

        //printf("%s\n", start);
        addVirusName(start);

    }

    } else if(cli_strbcasestr(filename, ".hdb")) {

    while(fgets(buffer, FILEBUFF, fd)) {
        line++;
        cli_chomp(buffer);
        start = cli_strtok(buffer, 2, ":");

        if(!start) {
        printf("!listdb(): Malformed pattern line %d (file %s).\n", line, filename);
        fclose(fd);
        free(buffer);
        return -1;
        }

        if((pt = strstr(start, " (Clam)")))
        *pt = 0;

        //printf("%s\n", start);
        addVirusName(start);
        free(start);
    }

    } else if(cli_strbcasestr(filename, ".ndb")) {

    while(fgets(buffer, FILEBUFF, fd)) {
        line++;
        cli_chomp(buffer);
        start = cli_strtok(buffer, 0, ":");

        if(!start) {
        printf("!listdb(): Malformed pattern line %d (file %s).\n", line, filename);
        fclose(fd);
        free(buffer);
        return -1;
        }

        if((pt = strstr(start, " (Clam)")))
        *pt = 0;

        //printf("%s\n", start);
        addVirusName(start);

        free(start);
    }
    }

    fclose(fd);
    free(buffer);
    return 0;
}

int KlamDB::listdir(const char *dirname)
{
    DIR *dd;
    struct dirent *dent;
    char *dbfile;


    if((dd = opendir(dirname)) == NULL) {
        printf("!Can't open directory %s\n", dirname);
        return -1;
    }

    while((dent = readdir(dd))) {
#ifndef C_INTERIX
    if(dent->d_ino)
#endif
    {
        if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
        (cli_strbcasestr(dent->d_name, ".db")  ||
         cli_strbcasestr(dent->d_name, ".db2") ||
         cli_strbcasestr(dent->d_name, ".hdb") ||
         cli_strbcasestr(dent->d_name, ".ndb") ||
         cli_strbcasestr(dent->d_name, ".cvd"))) {

        dbfile = (char *) calloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));

        if(!dbfile) {
            printf("!listdir(): Can't allocate memory.\n");
            closedir(dd);
            return -1;
        }
        sprintf(dbfile, "%s/%s", dirname, dent->d_name);

        if(listdb(dbfile)) {
            printf("!listdb(): error listing database %s\n", dbfile);
            free(dbfile);
            closedir(dd);
            return -1;
        }
        free(dbfile);
        }
    }
    }

    closedir(dd);
    return 0;
}

int KlamDB::checkdir(const char *dirname)
{
    DIR *dd;
    struct dirent *dent;


    if((dd = opendir(dirname)) == NULL) {
        printf("!Can't open directory %s\n", dirname);
        return -1;
    }

    int found = 0;
    while((dent = readdir(dd))) {
#ifndef C_INTERIX
    if(dent->d_ino)
#endif
    {
        if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
        (cli_strbcasestr(dent->d_name, ".db")  ||
         cli_strbcasestr(dent->d_name, ".db2") ||
         cli_strbcasestr(dent->d_name, ".hdb") ||
         cli_strbcasestr(dent->d_name, ".ndb") ||
         cli_strbcasestr(dent->d_name, ".cvd"))) {
        found = 1;
        }
    }
    }

    closedir(dd);
    
    if (!(found))
        return -1;
    return 0;
}

int cli_untgz(int fd, const char *destdir)
{
    char *fullname, osize[13], name[101], type;
    char block[TAR_BLOCKSIZE];
    int nbytes, nread, nwritten, in_block = 0;
    unsigned int size;
    FILE *outfile = NULL;
    gzFile *infile;

    printf("in cli_untgz()\n");

    if((infile = (gzFile*) gzdopen(fd, "rb")) == NULL) {
    printf("Can't gzdopen() descriptor %d\n", fd);
    return -1;
    }


    fullname = (char *) calloc(sizeof(char), strlen(destdir) + 100 + 5);

    while(1) {

    nread = gzread(infile, block, TAR_BLOCKSIZE);

    if(!in_block && nread == 0)
        break;

    if(nread != TAR_BLOCKSIZE) {
        printf("Incomplete block read.\n");
        free(fullname);
        gzclose(infile);
        return -1;
    }

    if(!in_block) {
        if (block[0] == '\0')  /* We're done */
        break;

        strncpy(name, block, 100);
        name[100] = '\0';
        strcpy(fullname, destdir);
        strcat(fullname, "/");
        strcat(fullname, name);
        printf("Unpacking %s\n",fullname);
        type = block[156];

        switch(type) {
        case '0':
        case '\0':
            break;
        case '5':
            printf("Directories in CVD are not supported.\n");
            free(fullname);
                gzclose(infile);
            return -1;
        default:
            printf("Unknown type flag %c.\n",type);
            free(fullname);
                gzclose(infile);
            return -1;
        }

        in_block = 1;

        if(outfile) {
        if(fclose(outfile)) {
            printf("Cannot close file %s.\n", fullname);
            free(fullname);
                gzclose(infile);
            return -1;
        }
        outfile = NULL;
        }

        if(!(outfile = fopen(fullname, "wb"))) {
        printf("Cannot create file %s.\n", fullname);
        free(fullname);
            gzclose(infile);
        return -1;
        }

        strncpy(osize, block + 124, 12);
        osize[12] = '\0';

        if((sscanf(osize, "%o", &size)) == 0) {
        printf("Invalid size in header.\n");
        free(fullname);
            gzclose(infile);
        fclose(outfile);
        return -1;
        }

    } else { /* write or continue writing file contents */
        nbytes = size > TAR_BLOCKSIZE ? TAR_BLOCKSIZE : size;
        nwritten = fwrite(block, 1, nbytes, outfile);

        if(nwritten != nbytes) {
        printf("Wrote %d instead of %d (%s).\n", nwritten, nbytes, fullname);
        free(fullname);
            gzclose(infile);
        return -1;
        }

        size -= nbytes;
        if(size == 0)
        in_block = 0;
    }
    }

    if(outfile)
    fclose(outfile);

    gzclose(infile);
    free(fullname);
    return 0;
}

int cli_rmdirs(const char *dirname)
{
    DIR *dd;
    struct dirent *dent;
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
    union {
        struct dirent d;
        char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
    } result;
#endif
    struct stat maind, statbuf;
    char *fname;


    chmod(dirname, 0700);
    if((dd = opendir(dirname)) != NULL) {
    while(stat(dirname, &maind) != -1) {
        if(!rmdir(dirname)) break;

#ifdef HAVE_READDIR_R_3
        while(!readdir_r(dd, &result.d, &dent) && dent) {
#elif defined(HAVE_READDIR_R_2)
        while((dent = (struct dirent *) readdir_r(dd, &result.d))) {
#else
        while((dent = readdir(dd))) {
#endif
#ifndef C_INTERIX
        if(dent->d_ino)
#endif
        {
            if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
            fname = (char *)calloc(strlen(dirname) + strlen(dent->d_name) + 2, sizeof(char));
            sprintf(fname, "%s/%s", dirname, dent->d_name);

            /* stat the file */
            if(lstat(fname, &statbuf) != -1) {
                if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
                if(rmdir(fname) == -1) { /* can't be deleted */
                    if(errno == EACCES) {
                    printf("Can't remove some temporary directories due to access problem.\n");
                    closedir(dd);
                    free(fname);
                    return 0;
                    }
                    cli_rmdirs(fname);
                }
                } else
                unlink(fname);
            }

            free(fname);
            }
        }
        }

        rewinddir(dd);

    }

    } else { 
    return 53;
    }

    closedir(dd);
    return 0;
}

int cli_strbcasestr(const char *haystack, const char *needle)
{
    char *pt = (char *) haystack;
    int i, j;

    i = strlen(haystack);
    j = strlen(needle);

    if(i < j)
    return 0;

    pt += i - j;

    return !strcasecmp(pt, needle);
}

/*
 * Remove trailing NL and CR characters from the end of the given string.
 * Return the new length of the string (ala strlen)
 */
int
cli_chomp(char *string)
{
    int l;

    if(string == NULL)
        return -1;

    l  = strlen(string);

    if(l == 0)
        return 0;

    --l;

    while((l >= 0) && ((string[l] == '\n') || (string[l] == '\r')))
        string[l--] = '\0';

    return l + 1;
}

/*
 * char *cli_strok(const char *line, int fieldno, char *delim)
 * Return a copy of field <fieldno> from the string <line>, where
 * fields are delimited by any char from <delim>, or NULL if <line>
 * doesn't have <fieldno> fields or not enough memory is available.
 * The caller has to free() the result afterwards.
 */
char *cli_strtok(const char *line, int fieldno, const char *delim)
{
    int counter = 0, i, j;
    char *buffer = NULL;


    /* step to arg # <fieldno> */
    for (i=0; line[i] && counter != fieldno; i++) {
    if (strchr(delim, line[i])) {
        counter++;
        while(line[i+1] && strchr(delim, line[i+1])) {
        i++;
        }
    }
    }
    if (!line[i]) {
    /* end of buffer before field reached */
    return NULL;
    }

    for (j=i; line[j]; j++) {
    if (strchr(delim, line[j])) {
        break;
    }
    }
    if (i == j) {
    return NULL;
    }
    buffer = (char *)malloc(j-i+1);
    if(!buffer)
    return NULL;
    strncpy(buffer, line+i, j-i);
    buffer[j-i] = '\0';

    return buffer;
}

void KlamDB::shouldIShow(QWidget * current)
{

    static struct cl_stat *dbstat=NULL;
    QString location;

    if ((current == this) && (!(loadinprogress))){
        QString db = kmain->freshklam->getCurrentDBDir();
    
        if (checkdir((const char *)db) == -1){
            kdDebug() << "returned -1" << endl;
            location = locate("data", "klamav/about/nodb.html");
            homepage->openURL(location);
    
            return;
        }


        if ( ((cl_statchkdir(dbstat) == 1) || (dbstat == NULL))) {
            location = locate("data", "klamav/about/wait.html");
            homepage->openURL(location);

                        loadinprogress = true;
            sigs = ( int )getSigNos();
            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" ));
            
            
            prog->setTotalSteps(sigs);
            
            //kdDebug() << prog->totalSteps() << endl;
            
            VirusList->hide();
            if (VirusList->childCount() > 0)
                VirusList->clear();
            count = 0;
            prog->setProgress (count);
            kapp->processEvents();

//             QString db = kmain->freshklam->getCurrentDBDir();

            listdir((const char *)db);

        
            prog->setProgress (sigs);
            
            VirusList->show();
            
            if(dbstat == NULL) {
                dbstat = (struct cl_stat *) malloc(sizeof(struct cl_stat));
            } else {
                cl_statfree(dbstat);
            }
            
            memset(dbstat, 0, sizeof(struct cl_stat));

            cl_statinidir((const char *)db, dbstat);
            
          
            loadinprogress = false;
            // Default english
            QString location = locate( "data", "klamav/about/main-" + KGlobal::locale()->language() + ".html" );
            if( location != QString::null )
                homepage->openURL( location );
            else
                homepage->openURL( locate("data", "klamav/about/main.html") );

        }
    }
}

void KlamDB::addVirusName(char *start)
{

    count++;
    
    kapp->processEvents();
    if ((count % 500) == 0){
        //progress->setLabel("Loading " + QString(start));
        progress->setLabel( i18n( "Loading ClamAV's Database of Virus Signatures") );
        prog->setProgress (count);
        kapp->processEvents();
    }
    new KListViewItem( VirusList, QString(start));
    kapp->processEvents();

}


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

    KConfig* config = KGlobal::config();
    config->setGroup("Freshklam");
    lastDownloadPaths = config->readListEntry("lastDownloadPaths");
    dbdir = lastDownloadPaths.first();


    ret = cl_loaddbdir((const char *)dbdir, &root, &no);
    //kdDebug() << "no " << no << endl;
    cl_free(root);
    return no;

}

void KlamDB::slotOpenTab(QListViewItem * item, const QPoint& , int )
{
    PageViewer* page = new PageViewer(this, "page");
    //connect( m_part, SIGNAL(signalSettingsChanged()), page, SLOT(slotPaletteOrFontChanged()));
    
    //connect( page, SIGNAL(setTabIcon(const QPixmap&)),
    //        this, SLOT(setTabIcon(const QPixmap&)));
    //connect( page, SIGNAL(setWindowCaption (const QString &)),
    //        this, SLOT(slotTabCaption (const QString &)) );
    connect( page, SIGNAL(urlClicked(const KURL &,bool)),
            this, SLOT(slotOpenTabPlain(const KURL &,bool)) );

    QString url = item->text(0);
    
    Frame *frame=new Frame(this, page, page->widget(), "VirusList : "+item->text(0));
    //connectFrame(frame);
    tabBrowser->addFrame(frame);

//    if(!background)
        tabBrowser->showPage(page->widget());
//    else
        setFocus();
    
    //if (m_tabs->count() > 1 && m_tabs->currentPageIndex() != 0)
//        m_tabsClose->setEnabled(true);
    page->openURL("http://www.viruslist.com/en/find?search_mode=virus&words="+url);
}

void KlamDB::slotOpenTabPlain(const KURL& url, bool background)
{
    PageViewer* page = new PageViewer(this, "page");
    //connect( m_part, SIGNAL(signalSettingsChanged()), page, SLOT(slotPaletteOrFontChanged()));
    
/*    connect( page, SIGNAL(setTabIcon(const QPixmap&)),
            this, SLOT(setTabIcon(const QPixmap&)));*/
    connect( page, SIGNAL(setWindowCaption (const QString &)),
            this, SLOT(slotTabCaption (const QString &)) );
    connect( page, SIGNAL(urlClicked(const KURL &,bool)),
            this, SLOT(slotOpenTabPlain(const KURL &,bool)) );

    Frame *frame=new Frame(this, page, page->widget(), i18n("Untitled"));
    //connectFrame(frame);
    tabBrowser->addFrame(frame);

    if(!background)
        tabBrowser->showPage(page->widget());
    else
        setFocus();
    
    //if (m_tabs->count() > 1 && m_tabs->currentPageIndex() != 0)
//        m_tabsClose->setEnabled(true);

    //kdDebug() << url << endl;
    page->openURL(url);
}

void KlamDB::slotTabCaption(const QString &caption)
{
    if (!caption.isEmpty())
    {
        PageViewer *pv=(PageViewer *)sender();
        tabBrowser->setTitle(caption, pv->widget());
        pv->slotSetCaption(caption);
    }
}

void KlamDB::slotOpenHome()
{
    homepage = new PageViewer(this, "page");
    
    Frame *frame=new Frame(this, homepage, homepage->widget(), "Home");
    //connectFrame(frame);
    tabBrowser->addFrame(frame);

//    if(!background)
        tabBrowser->showPage(homepage->widget());
//    else
        setFocus();
        
    QString location = locate( "data", "klamav/about/wait-" + KGlobal::locale()->language() + ".html" );
    if( location != QString::null )
       homepage->openURL( location );
    else
       homepage->openURL( locate("data", "klamav/about/wait.html") );
}

void KlamDB::slotRMB( QListViewItem* Item, const QPoint & point, int )
{
    if( Item )
        menu->popup( point );
}

void KlamDB::slotOpenPrefix(QString prefix, QString title,QString url)
{

    PageViewer* page = new PageViewer(this, "page");


    Frame *frame=new Frame(this, page, page->widget(), title+" : "+url);
    tabBrowser->addFrame(frame);

        tabBrowser->showPage(page->widget());
        setFocus();

    page->openURL(prefix+url);
}

void KlamDB::slotVirusPool()
{
    QString url = VirusList->selectedItem()->text(0);
    QString prefix = QString("http://www.viruspool.net/virus.cms?&name=");
    slotOpenPrefix(prefix,"VirusPool",url);
}

void KlamDB::slotVirusList()
{
    QString url = VirusList->selectedItem()->text(0);
    QString prefix = QString("http://www.viruslist.com/en/find?search_mode=virus&words=");
    slotOpenPrefix(prefix,"VirusList",url);
}

void KlamDB::slotGoogle()
{

    QString url = VirusList->selectedItem()->text(0);
    QString prefix = QString("http://www.google.com/search?ie=ISO-8859-1&q=");
    slotOpenPrefix(prefix,"Google",url);
}

void KlamDB::slotTrendMicro()
{

    QString url = VirusList->selectedItem()->text(0);
    QString prefix = QString("http://www.trendmicro.com/vinfo/virusencyclo/default2.asp?m=q&virus=");
    slotOpenPrefix(prefix,"TrendMicro",url);
}

void KlamDB::slotExternal(QString name,QString service)
{
    kmain->showVirusBrowser();
    shouldIShow(this);
    QString prefix;
    if (service == "VirusPool")
        prefix = QString("http://www.viruspool.net/virus.cms?&name=");
    else if (service == "Google")
        prefix = QString("http://www.google.com/search?ie=ISO-8859-1&q=");
        else if (service == "VirusList")
                prefix = QString("http://www.viruslist.com/en/find?search_mode=virus&words=");
    else
        prefix = QString("http://www.trendmicro.com/vinfo/virusencyclo/default2.asp?m=q&virus=");
    slotOpenPrefix(prefix,service,name);
}

#include "dbviewer.moc"
