You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
klamav/src/klamscan.cpp

485 lines
14 KiB

/*
* Copyright (C) 2004 Robert Hogan <robert at roberthogan dot net>
*/
#include "klamscan.h"
#include "klamav.h"
#include "klamd.h"
#include "klamscanoptions.h"
#include "schedule.h"
#include "directorylist.h"
#include "tabwidget.h"
#include "scanviewer.h"
#include "collectiondb.h"
#include <config.h>
#include <kiconloader.h>
#include <kstatusbar.h>
#include <kdebug.h>
#include <ksystemtray.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include <qtooltip.h>
#include <qtoolbutton.h>
#include <dcopclient.h>
#include <qdir.h>
#include <kprogress.h>
#include <dcopref.h>
#include <dcopclient.h>
using namespace KlamAV;
Klamscan::Klamscan(QWidget *parent, const char *name)
: QWidget(parent, name), DCOPObject( "DCOPKlamscan" )
{
/* scanInProgress = FALSE;
multiScan = FALSE; */
setDefaults();
QBoxLayout *top = new QVBoxLayout(this,10,10);
tabBrowser = new TabWidget(this);
tabBrowser->setMargin(5);
top->addWidget(tabBrowser);
/* dblayout->addMultiCellWidget( tabBrowser, 0, 1, 1, 1 );*/
//QGridLayout *layout = new QGridLayout(this, 6, 3, 10, 4);
QWidget* privateLayoutWidget2 = new QWidget( this, "dblayout" );
QGridLayout *layout = new QGridLayout(privateLayoutWidget2, 6, 6, 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);
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
QLabel *combo_label = new QLabel(i18n("When a virus is found:"), privateLayoutWidget2);
//combo_label->setFixedSize(combo_label->sizeHint());
layout->addWidget(combo_label,0,0);
combo_label->adjustSize();
check_combo = new QComboBox(false, privateLayoutWidget2);
check_combo->insertItem( i18n( "Ask me" ) );
check_combo->insertItem( i18n( "Quarantine file" ) );
check_combo->insertItem( i18n( "Just report" ) );
check_combo->adjustSize();
//check_combo->setFixedSize(check_combo->size());
layout->addWidget(check_combo,0,1);
recursive_box = new QCheckBox(i18n("&Scan Folders Recursively"), privateLayoutWidget2);
recursive_box->setMinimumWidth(recursive_box->sizeHint().width());
recursive_box->setChecked(true);
// dir_layout2->addSpacing(10);
layout->addWidget(recursive_box,0,3);
QToolTip::add( recursive_box, i18n( "Scan all directories under the specified path." ) );
QToolButton* schedule = new QToolButton( privateLayoutWidget2,"play" );
schedule->setIconSet( SmallIconSet( "xclock" ) );
schedule->setTextLabel(i18n( "Schedule" ));
schedule->setTextPosition(QToolButton::Right);
schedule->setUsesTextLabel(true);
schedule->adjustSize();
layout->addWidget(schedule,0,4);
connect( schedule, SIGNAL(clicked()),
SLOT(slotSchedule()) );
QToolButton* adv_options = new QToolButton( privateLayoutWidget2,"play" );
adv_options->setIconSet( SmallIconSet( "configure" ) );
adv_options->setTextLabel(i18n("Options"));
adv_options->setTextPosition(QToolButton::Right);
adv_options->setUsesTextLabel(true);
layout->addWidget(adv_options,0,5);
//adv_options->setFixedSize(adv_options->sizeHint());
adv_options->adjustSize();
connect( adv_options, SIGNAL(clicked()),
SLOT(slotAdvOptions()) );
setup = new CollectionSetup( privateLayoutWidget2, recursive_box->isChecked() );
layout->addMultiCellWidget(setup, 1, 6,0,6);
connect( recursive_box, SIGNAL(toggled(bool)),setup,
SLOT(slotRecursiveToggled(bool)) );
QHBox* controls = new QHBox(tabBrowser);
//controls->setSpacing(5);
controls->setMargin(2);
play = new QToolButton( controls,"play" );
play->setIconSet( SmallIconSet( "player_play" ) );
play->setTextLabel(i18n( "Scan" ));
play->setTextPosition(QToolButton::Right);
play->setUsesTextLabel(true);
play->adjustSize();
play->setFixedHeight(play->height() - 1);
stop = new QToolButton( controls,"stop" );
stop->setIconSet( SmallIconSet( "player_stop" ) );
stop->setTextLabel(i18n( "Stop" ));
stop->setTextPosition(QToolButton::Right);
stop->setUsesTextLabel(true);
stop->adjustSize();
stop->setFixedHeight(stop->height() - 1);
m_tabsClose = new QToolButton( controls,"tab_remove" );
m_tabsClose->setIconSet( SmallIconSet( "tab_remove" ) );
m_tabsClose->setTextLabel(i18n( "Close" ));
m_tabsClose->setTextPosition(QToolButton::Right);
m_tabsClose->setUsesTextLabel(true);
m_tabsClose->adjustSize();
m_tabsClose->setFixedHeight(m_tabsClose->height() - 1);
connect( play, SIGNAL( clicked() ), this,
SLOT( slotStartAgain() ) );
connect( stop, SIGNAL( clicked() ), this,
SLOT( slotStopScanning() ) );
connect( m_tabsClose, SIGNAL( clicked() ), this,
SLOT( slotRemoveTab() ) );
controls->adjustSize();
tabBrowser->setCornerWidget( controls, TopRight );
////kdDebug() << "pos: " << controls->pos() << endl;
//controls->move(controls->pos());
tabBrowser->addTab(privateLayoutWidget2, i18n( "Launcher"));
layout->activate();
connect(tabBrowser, SIGNAL(currentChanged(QWidget *)),this,
SLOT(slotManageButtons(QWidget *)) );
// Register with DCOP
if ( !kapp->dcopClient()->isRegistered() ) {
kapp->dcopClient()->registerAs( "dcopklamscan" );
kapp->dcopClient()->setDefaultObject( objId() );
}
if( args->isSet( "scanthis" ) ) {
slotScan();
}
}
Klamscan::~Klamscan()
{
}
void Klamscan::slotScan()
{
ScanViewer* homepage = new ScanViewer(this, "page");
connect( homepage, SIGNAL( scanFinished(QWidget *) ), this,
SLOT( slotManageButtons(QWidget *) ) );
connect( homepage, SIGNAL( scanStartingAgain(QWidget *) ), this,
SLOT( slotManageButtons(QWidget *) ) );
kmain->_tray->setPixmap(KSystemTray::loadIcon("klamav_scanning"));
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 ap"));
tabBrowser->addTab(homepage,suffix);
tabBrowser->setCurrentPage(tabBrowser->count() - 1);
//return;
QStringList filepattern;
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
if( args->isSet( "scanthis" ) ) {
listOfUrlsToScan.clear();
for( int i = 0; i < args->count(); i++ ) {
//KMessageBox::information (this,QString(args->arg(i)));
filepattern.append(args->arg(i));
listOfUrlsToScan.prepend(QString(args->arg(i)));
}
prevdir = listOfUrlsToScan.first();
}else{
filepattern = pruneSelectedDirs();
}
//kdDebug() << filepattern << endl;
CollectionDB::instance()->insertEvent("Manual Scan",QString("Commencing Scan"),filepattern.join(" "));
homepage->slotScan(filepattern, check_combo->currentItem(),setup->recursive(),false);
}
void Klamscan::slotAdvOptions(){
/* KlamscanOptions *dialog = new KlamscanOptions( this, "settings");
dialog->show();
dialog->raise();
dialog->setActiveWindow();*/
kmain->slotConfigKlamav( "Archive Limits" );
}
void Klamscan::slotSchedule(){
QStringList filepattern = pruneSelectedDirs();
if (filepattern.isEmpty()){
KMessageBox::error(this, i18n( "Please select something to scan!") );
return;
}
Schedule *dialog = new Schedule( this, filepattern, "settings");
dialog->show();
dialog->raise();
dialog->setActiveWindow();
}
void Klamscan::setDefaults(){
config = KGlobal::config();
config->setGroup("ScanPaths");
config->setGroup("Klamscan");
if ((config->readEntry("NoFilesToExtract")).isEmpty())
config->writeEntry("NoFilesToExtract","500");
if ((config->readEntry("RecursionLevel")).isEmpty())
config->writeEntry("RecursionLevel","8");
// if ((config->readEntry("MBsToExtract")).isEmpty())
// config->writeEntry("MBsToExtract","10M");
//
// if ((config->readEntry("CompressionRatio")).isEmpty())
// config->writeEntry("CompressionRatio","250");
if ((config->readEntry("MaxFileSize")).isEmpty())
config->writeEntry("MaxFileSize","25M");
if ((config->readEntry("MaxScanSize")).isEmpty())
config->writeEntry("MaxScanSize","25M");
// if ((config->readEntry("VirusLimitsExceeded")).isEmpty())
// config->writeEntry("VirusLimitsExceeded", "Yes");
if ((config->readEntry("VirusEncrypted")).isEmpty())
config->writeEntry("VirusEncrypted", "Yes");
if ((config->readEntry("ScanMail")).isEmpty())
config->writeEntry("ScanMail", "Yes");
if ((config->readEntry("ScanPE")).isEmpty())
config->writeEntry("ScanPE", "Yes");
if ((config->readEntry("ScanOle")).isEmpty())
config->writeEntry("ScanOle", "Yes");
if ((config->readEntry("ScanHTML")).isEmpty())
config->writeEntry("ScanHTML", "Yes");
if ((config->readEntry("VirusBroken")).isEmpty())
config->writeEntry("VirusBroken", "Yes");
if ((config->readEntry("ExcludeQuarantine")).isEmpty())
config->writeEntry("ExcludeQuarantine", "Yes");
if ((config->readEntry("ScanMail")).isEmpty())
config->writeEntry("ScanMail", "Yes");
config->sync();
}
void Klamscan::scanURLs(const QString &urls)
{
setActiveWindow();
raise();
kmain->tab->setCurrentPage(0);
QString tmpurls = urls;
//urlsToScan = urlsToScan.replace("*"," ");
urlsToScan = QStringList::split("*", tmpurls);
//for ( QStringList::Iterator it = temp.begin(); it != temp.end(); ++it )
// (*it).sprintf("\"%s\"", (*it).latin1());
//urlsToScan = temp;
ScanViewer* homepage = new ScanViewer(this, "page");
connect( homepage, SIGNAL( scanFinished(QWidget *) ), this,
SLOT( slotManageButtons(QWidget *) ) );
connect( homepage, SIGNAL( scanStartingAgain(QWidget *) ), this,
SLOT( slotManageButtons(QWidget *) ) );
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 ap"));
tabBrowser->addTab(homepage,suffix);
tabBrowser->setCurrentPage(tabBrowser->count() - 1);
CollectionDB::instance()->insertEvent("Manual Scan",QString("Commencing Scan"),urlsToScan.join(" "));
homepage->slotScan(urlsToScan, check_combo->currentItem(),setup->recursive(),true);
}
void Klamscan::slotStopScanning(){
if (kmain->klamd->isKlamdAlive())
kmain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_enabled"));
else
kmain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));
////kdDebug() << tabBrowser->currentPage()->name() << endl;
ScanViewer* cur = static_cast<ScanViewer*>(tabBrowser->currentPage());
cur->slotCancel();
}
void Klamscan::slotStartAgain(){
////kdDebug() << tabBrowser->currentPage()->name() << endl;
if (tabBrowser->currentPageIndex() != 0){
ScanViewer* cur = static_cast<ScanViewer*>(tabBrowser->currentPage());
cur->slotStartAgain();
}else
slotScan();
//slotManageButtons(tabBrowser->currentPage());
}
void Klamscan::slotRemoveTab(){
if (kmain->klamd->isKlamdAlive())
kmain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_enabled"));
else
kmain->_tray->setPixmap(KSystemTray::loadIcon("klamav_on_acc_disabled"));
////kdDebug() << tabBrowser->currentPage()->name() << endl;
if (tabBrowser->currentPageIndex() != 0){
slotStopScanning();
tabBrowser->removePage(tabBrowser->currentPage());
}
}
void Klamscan::slotManageButtons(QWidget * current){
ScanViewer* cur = static_cast<ScanViewer*>(current);
if (tabBrowser->currentPageIndex() == 0){
play->setEnabled(true);
stop->setEnabled(false);
m_tabsClose->setEnabled(false);
return;
}
if (cur->scanGoingOn()){
play->setEnabled(false);
stop->setEnabled(true);
}else{
play->setEnabled(true);
stop->setEnabled(false);
}
m_tabsClose->setEnabled(true);
}
QStringList Klamscan::pruneSelectedDirs(){
//This gets rid of redundant sub-directories from the list of dirs to be scanned.
QStringList filepattern;
QStringList listOfUrlsToScan = setup->dirs();
listOfUrlsToScan.sort();
QString prev;
QStringList prevdirs;
for (QStringList::Iterator it = listOfUrlsToScan.begin(); it != listOfUrlsToScan.end(); it++ ){
//kdDebug() << "dir: " << (*it) << endl;
(*it) = (*it).stripWhiteSpace() + "/";
if (prevdirs.isEmpty()){
//kdDebug() << (*it) << endl;
filepattern.append(*it);
prevdirs.append((*it));
}else{
filepattern.append(*it);
bool shouldappend = true;
for (QStringList::Iterator it2 = prevdirs.begin(); it2 != prevdirs.end(); it2++ ){
if ((*it).contains(*it2)){
//kdDebug() << (*it) << endl;
filepattern.remove((*it));
shouldappend = false;
break;
}
}
if (shouldappend)
prevdirs.append((*it));
}
}
return filepattern;
}
#include "klamscan.moc"