diff options
author | Mavridis Philippe <mavridisf@gmail.com> | 2021-01-13 19:26:24 +0200 |
---|---|---|
committer | Mavridis Philippe <mavridisf@gmail.com> | 2021-01-13 19:26:24 +0200 |
commit | 8c20dc919f7d54eb48fb60f39ba5e1d466a70763 (patch) | |
tree | 44d89f278d5dd066603e5ab9c0b270bc8eb4ad51 /src/kuarantine.cpp | |
download | klamav-8c20dc919f7d54eb48fb60f39ba5e1d466a70763.tar.gz klamav-8c20dc919f7d54eb48fb60f39ba5e1d466a70763.zip |
Initial commit
Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
Diffstat (limited to 'src/kuarantine.cpp')
-rw-r--r-- | src/kuarantine.cpp | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/src/kuarantine.cpp b/src/kuarantine.cpp new file mode 100644 index 0000000..27e4ea0 --- /dev/null +++ b/src/kuarantine.cpp @@ -0,0 +1,707 @@ +/* + * 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" |