mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-24 12:17:26 +01:00
1223 lines
37 KiB
C++
1223 lines
37 KiB
C++
/*
|
|
|
|
Firewall Builder
|
|
|
|
Copyright (C) 2008 NetCitadel, LLC
|
|
|
|
Author: Vadim Kurland vadim@fwbuilder.org
|
|
|
|
$Id$
|
|
|
|
This program is free software which we release under the GNU General Public
|
|
License. You may redistribute and/or modify this program under the terms
|
|
of that license as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
To get a copy of the GNU General Public License, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
#include "../../config.h"
|
|
#include "global.h"
|
|
#include "utils.h"
|
|
#include "utils_no_qt.h"
|
|
|
|
#include "instDialog.h"
|
|
#include "FirewallInstaller.h"
|
|
#include "FWBSettings.h"
|
|
#include "FWWindow.h"
|
|
#include "InstallFirewallViewItem.h"
|
|
#include "instOptionsDialog.h"
|
|
#include "instBatchOptionsDialog.h"
|
|
|
|
#include <qcheckbox.h>
|
|
#include <qlineedit.h>
|
|
#include <qtextedit.h>
|
|
#include <qtimer.h>
|
|
#include <qfiledialog.h>
|
|
#include <qpushbutton.h>
|
|
#include <qlabel.h>
|
|
#include <qprogressbar.h>
|
|
#include <qprocess.h>
|
|
#include <qapplication.h>
|
|
#include <qeventloop.h>
|
|
#include <qfile.h>
|
|
#include <qdir.h>
|
|
#include <qmessagebox.h>
|
|
#include <qspinbox.h>
|
|
#include <qgroupbox.h>
|
|
#include <qcolor.h>
|
|
#include <qtablewidget.h>
|
|
#include <qtextcodec.h>
|
|
#include <qfileinfo.h>
|
|
#include <qtextstream.h>
|
|
#include <qpixmapcache.h>
|
|
|
|
#include <QPixmap>
|
|
#include <QDateTime>
|
|
#include <QTableWidget>
|
|
#include <QTableWidgetItem>
|
|
#include <QTreeWidgetItemIterator>
|
|
#include <QTextBlockFormat>
|
|
#include <QBrush>
|
|
#include <QTextFormat>
|
|
#include <QtDebug>
|
|
|
|
#include "fwbuilder/Resources.h"
|
|
#include "fwbuilder/FWObjectDatabase.h"
|
|
#include "fwbuilder/Firewall.h"
|
|
#include "fwbuilder/Cluster.h"
|
|
#include "fwbuilder/XMLTools.h"
|
|
#include "fwbuilder/Interface.h"
|
|
#include "fwbuilder/Management.h"
|
|
#include "fwbuilder/StateSyncClusterGroup.h"
|
|
|
|
#ifndef _WIN32
|
|
# include <unistd.h> // for access(2) and getdomainname
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
using namespace libfwbuilder;
|
|
|
|
void instDialog::enableStopButton()
|
|
{
|
|
currentStopButton->setText(tr("Stop"));
|
|
currentStopButton->setEnabled(true);
|
|
}
|
|
|
|
void instDialog::disableStopButton()
|
|
{
|
|
currentStopButton->setEnabled(false);
|
|
}
|
|
|
|
bool instDialog::checkIfNeedToCompile(Firewall *fw)
|
|
{
|
|
return (fw->needsCompile() && reqFirewalls.empty() && !fw->getInactive()) ||
|
|
(!onlySelected && !reqFirewalls.empty() && reqFirewalls.find(fw)!=reqFirewalls.end() ||
|
|
(onlySelected && fw->needsCompile() && !fw->getInactive()) );
|
|
}
|
|
|
|
bool instDialog::checkIfNeedToInstall(Firewall *fw)
|
|
{
|
|
return ((fw->needsInstall() && reqFirewalls.empty() && !fw->getInactive()) ||
|
|
(!reqFirewalls.empty() && reqFirewalls.find(fw)!=reqFirewalls.end()));
|
|
}
|
|
|
|
QTreeWidgetItem* instDialog::createTreeItem(QTreeWidgetItem* parent,
|
|
Firewall *fw)
|
|
{
|
|
QTreeWidgetItem* item;
|
|
QStringList sl;
|
|
sl.push_back(fw->getName().c_str());
|
|
|
|
if (parent)
|
|
item = new QTreeWidgetItem(parent, sl);
|
|
else
|
|
item = new QTreeWidgetItem(sl);
|
|
|
|
QString icn_filename = (":/Icons/" + fw->getTypeName() + "/icon").c_str();
|
|
QPixmap pm;
|
|
if ( ! QPixmapCache::find(icn_filename, pm))
|
|
{
|
|
pm.load(icn_filename);
|
|
QPixmapCache::insert(icn_filename, pm);
|
|
}
|
|
item->setIcon(0, QIcon(pm));
|
|
|
|
item->setData(0, Qt::UserRole, QVariant(fw->getId()));
|
|
|
|
// Mark cluster members
|
|
// If parent!=NULL, new tree item corresponds to the cluster member
|
|
item->setData(1, Qt::UserRole, QVariant(parent!=NULL));
|
|
|
|
// it is useful to know how many members does this cluster have. If this is
|
|
// not a cluster, store 0
|
|
list<Firewall*> members;
|
|
if (Cluster::isA(fw))
|
|
Cluster::cast(fw)->getMembersList(members);
|
|
int num_members = members.size();
|
|
|
|
item->setData(2, Qt::UserRole, QVariant(num_members));
|
|
|
|
item->setCheckState(COMPILE_CHECKBOX_COLUMN, checkIfNeedToCompile(fw)?Qt::Checked:Qt::Unchecked);
|
|
if (!compile_only)
|
|
item->setCheckState(INSTALL_CHECKBOX_COLUMN, checkIfNeedToInstall(fw)?Qt::Checked:Qt::Unchecked);
|
|
|
|
return item;
|
|
}
|
|
|
|
void instDialog::setFlags(QTreeWidgetItem* item)
|
|
{
|
|
int obj_id = item->data(0, Qt::UserRole).toInt();
|
|
Firewall *fw = Firewall::cast(project->db()->findInIndex(obj_id));
|
|
QTreeWidgetItem* parent = item->parent();
|
|
|
|
time_t lm = fw->getInt("lastModified");
|
|
time_t lc = fw->getInt("lastCompiled");
|
|
time_t li = fw->getInt("lastInstalled");
|
|
QDateTime dt;
|
|
|
|
// need to skip the secondary cluster members if platform only
|
|
// allows installations on the primary (e.g. PIX). Note that
|
|
// platform attribute must be the same in the cluster and member
|
|
// firewalls objects. See #998
|
|
|
|
string platform = fw->getStr("platform");
|
|
bool install_only_on_primary_member = Resources::getTargetCapabilityBool(
|
|
platform, "install_only_on_primary");
|
|
|
|
Cluster *cluster = NULL;
|
|
FWObject *master_interface = NULL;
|
|
|
|
if (parent)
|
|
{
|
|
int obj_id = parent->data(0, Qt::UserRole).toInt();
|
|
cluster = Cluster::cast(project->db()->findInIndex(obj_id));
|
|
if (cluster)
|
|
{
|
|
FWObject *state_sync_group =
|
|
cluster->getFirstByType(StateSyncClusterGroup::TYPENAME);
|
|
string master_id = state_sync_group->getStr("master_iface");
|
|
for (FWObjectTypedChildIterator grp_it =
|
|
state_sync_group->findByType(FWObjectReference::TYPENAME);
|
|
grp_it != grp_it.end(); ++grp_it)
|
|
{
|
|
FWObject *iface = FWObjectReference::getObject(*grp_it);
|
|
if (FWObjectDatabase::getStringId(iface->getId()) == master_id)
|
|
{
|
|
master_interface = iface;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Real firewalls get checkbox for install
|
|
if (Firewall::isA(fw) && ! compile_only)
|
|
{
|
|
bool checked = false;
|
|
checked = checkIfNeedToInstall(fw);
|
|
if (cluster)
|
|
{
|
|
// override if checkIfNeedToCompile() is true for the
|
|
// parent cluster.
|
|
if (checkIfNeedToCompile(cluster))
|
|
{
|
|
checked = true;
|
|
}
|
|
}
|
|
item->setCheckState(INSTALL_CHECKBOX_COLUMN,
|
|
checked?Qt::Checked:Qt::Unchecked);
|
|
|
|
// If this platform requires installation only on
|
|
// the master, disable and uncheck checkbox for the standby.
|
|
if (install_only_on_primary_member && master_interface != NULL)
|
|
{
|
|
QString txt = item->text(0);
|
|
if (master_interface->isChildOf(fw))
|
|
{
|
|
// Master
|
|
item->setText(0, QString("%1 (master)").arg(txt));
|
|
} else
|
|
{
|
|
// Standby
|
|
item->setText(0, QString("%1 (standby)").arg(txt));
|
|
item->setCheckState(INSTALL_CHECKBOX_COLUMN, Qt::Unchecked);
|
|
item->setFlags(0);
|
|
}
|
|
}
|
|
|
|
if (cluster==NULL)
|
|
{
|
|
// we are adding firewall that is not cluster member, it
|
|
// needs "compile" checkbox
|
|
checked = checkIfNeedToCompile(fw);
|
|
item->setCheckState(COMPILE_CHECKBOX_COLUMN,
|
|
checked?Qt::Checked:Qt::Unchecked);
|
|
}
|
|
}
|
|
|
|
int num_members = 0;
|
|
// Clusters only get checkbox for compile, and only if they have members.
|
|
if (Cluster::isA(fw))
|
|
{
|
|
list<Firewall*> members;
|
|
Cluster::cast(fw)->getMembersList(members);
|
|
num_members = members.size();
|
|
if (num_members)
|
|
{
|
|
bool checked = checkIfNeedToCompile(fw);
|
|
// if any of the member firewalls are in reqFirewalls, re-check
|
|
// if we need to compile the cluster. checkIfNeedToCompile()
|
|
// uses different condition if reqFirewalls is not empty.
|
|
for (list<Firewall*>::iterator it=members.begin(); it!=members.end(); ++it)
|
|
{
|
|
if (reqFirewalls.find(*it)!=reqFirewalls.end() &&
|
|
fw->needsCompile() && !fw->getInactive())
|
|
checked = true;
|
|
}
|
|
item->setCheckState(COMPILE_CHECKBOX_COLUMN,
|
|
checked?Qt::Checked:Qt::Unchecked);
|
|
}
|
|
}
|
|
|
|
dt.setTime_t(lm);
|
|
item->setText(LAST_MODIFIED_COLUMN, (lm)?dt.toString():QString("Never"));
|
|
|
|
dt.setTime_t(lc);
|
|
item->setText(LAST_COMPILED_COLUMN, (lc)?dt.toString():QString("Never"));
|
|
|
|
dt.setTime_t(li);
|
|
item->setText(LAST_INSTALLED_COLUMN, (li)?dt.toString():QString("Never"));
|
|
}
|
|
|
|
/*
|
|
* The following color and font manipulations are subject to QT bug
|
|
* http://trolltech.no/developer/task-tracker/index_html?method=entry&id=212207
|
|
*
|
|
* This requires QT 4.4.1 or 4.3
|
|
*/
|
|
void instDialog::setSuccessState(QTreeWidgetItem *item)
|
|
{
|
|
QBrush b = item->foreground(1);
|
|
b.setColor(Qt::darkGreen);
|
|
item->setForeground(1,b);
|
|
item->setForeground(0,b);
|
|
|
|
QFont f = item->font(1);
|
|
f.setBold(true);
|
|
item->setFont(1,f);
|
|
item->setFont(0,f);
|
|
}
|
|
|
|
void instDialog::setFailureState(QTreeWidgetItem *item)
|
|
{
|
|
QBrush b = item->foreground(1);
|
|
b.setColor(Qt::darkRed);
|
|
item->setForeground(1,b);
|
|
item->setForeground(0,b);
|
|
|
|
QFont f = item->font(1);
|
|
f.setBold(true);
|
|
item->setFont(1,f);
|
|
item->setFont(0,f);
|
|
}
|
|
|
|
void instDialog::setErrorState(QTreeWidgetItem *item)
|
|
{
|
|
QBrush b = item->foreground(1);
|
|
b.setColor(Qt::darkRed);
|
|
item->setForeground(1,b);
|
|
item->setForeground(0,b);
|
|
|
|
QFont f = item->font(1);
|
|
f.setBold(true);
|
|
item->setFont(1,f);
|
|
item->setFont(0,f);
|
|
}
|
|
|
|
void instDialog::setInProcessState(QTreeWidgetItem *item)
|
|
{
|
|
QBrush b = item->foreground(1);
|
|
b.setColor(Qt::black);
|
|
item->setForeground(1,b);
|
|
item->setForeground(0,b);
|
|
|
|
QFont f = item->font(1);
|
|
f.setBold(true);
|
|
item->setFont(1,f);
|
|
item->setFont(0,f);
|
|
}
|
|
|
|
void instDialog::opSuccess(Firewall *fw)
|
|
{
|
|
opListMapping[(fw)->getId()]->setText(1,tr("Success"));
|
|
setSuccessState(opListMapping[(fw)->getId()]);
|
|
currentLabel->setText("");
|
|
}
|
|
|
|
void instDialog::opError(Firewall *fw)
|
|
{
|
|
opListMapping[(fw)->getId()]->setText(1, tr("Error"));
|
|
setErrorState(opListMapping[(fw)->getId()]);
|
|
currentLabel->setText("");
|
|
}
|
|
|
|
void instDialog::opCancelled(Firewall *fw)
|
|
{
|
|
opListMapping[(fw)->getId()]->setText(1, tr("Cancelled"));
|
|
setErrorState(opListMapping[(fw)->getId()]);
|
|
currentLabel->setText("");
|
|
}
|
|
|
|
void instDialog::nextClicked()
|
|
{
|
|
if (nextRelevant( currentPage() ) > -1)
|
|
showPage(nextRelevant( currentPage() ));
|
|
}
|
|
|
|
void instDialog::backClicked()
|
|
{
|
|
if (previousRelevant( currentPage() ) > -1)
|
|
showPage(previousRelevant( currentPage() ));
|
|
}
|
|
|
|
void instDialog::prepareInstConf(Firewall *)
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::prepareInstConf");
|
|
}
|
|
|
|
void instDialog::storeInstallerOptions()
|
|
{
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/savediff",cnf.save_diff);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/saveStandby",cnf.saveStandby);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/dryrun" ,cnf.dry_run);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/quiet", cnf.quiet);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/verbose", cnf.verbose);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/stripComments",
|
|
cnf.stripComments);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/compressScript",
|
|
cnf.compressScript);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/copyFWB", cnf.copyFWB);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/testRun", cnf.testRun);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/rollback", cnf.rollback);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/rollbackTime",
|
|
cnf.rollbackTime);
|
|
st->setValue(SETTINGS_PATH_PREFIX"/Installer/canceRollbackIfSuccess",
|
|
cnf.cancelRollbackIfSuccess);
|
|
}
|
|
|
|
void instDialog::summary()
|
|
{
|
|
QStringList str;
|
|
|
|
str.append(QObject::tr("Summary:"));
|
|
str.append(QObject::tr("* Running as user : %1").arg(user_name));
|
|
str.append(QObject::tr("* Firewall name : %1")
|
|
.arg(QString::fromUtf8(cnf.fwobj->getName().c_str())));
|
|
str.append(QObject::tr("* Installer uses user name : %1").arg(cnf.user));
|
|
str.append(QObject::tr("* Management address : %1").arg(cnf.maddr));
|
|
str.append(QObject::tr("* Platform : %1")
|
|
.arg(cnf.fwobj->getStr("platform").c_str()));
|
|
str.append(QObject::tr("* Host OS : %1")
|
|
.arg(cnf.fwobj->getStr("host_OS").c_str()));
|
|
str.append(QObject::tr("* Loading configuration from file %1")
|
|
.arg(cnf.fwbfile));
|
|
|
|
if (cnf.save_diff)
|
|
str.append(QObject::tr("* Configuration diff will be saved in file %1").
|
|
arg(cnf.diff_file));
|
|
|
|
if (cnf.dry_run)
|
|
str.append(QObject::tr("* Commands will not be executed on the firewall"));
|
|
|
|
str.append("");
|
|
|
|
QTextCursor cursor = currentLog->textCursor();
|
|
cursor.insertBlock();
|
|
cursor.insertText(str.join("\n"), highlight_format);
|
|
}
|
|
|
|
void instDialog::fillCompileSelectList()
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::fillCompileSelectList");
|
|
|
|
Firewall *fw;
|
|
Cluster *cl;
|
|
QDateTime dt;
|
|
|
|
if (fwbdebug && reqFirewalls.empty())
|
|
qDebug("instDialog::fillCompileSelectList reqFirewalls is empty");
|
|
|
|
creatingTable = true;
|
|
|
|
list<Firewall*> working_list_of_firewalls = firewalls;
|
|
|
|
for (list<Cluster *>::iterator i=clusters.begin(); i!=clusters.end(); ++i)
|
|
{
|
|
cl = *i;
|
|
|
|
QTreeWidgetItem* cluster_item = createTreeItem(NULL, cl);
|
|
m_dialog->selectTable->addTopLevelItem(cluster_item);
|
|
|
|
list<Firewall*> members;
|
|
cl->getMembersList(members);
|
|
|
|
for (list<Firewall*>::iterator member=members.begin();
|
|
member!=members.end(); ++member)
|
|
{
|
|
QTreeWidgetItem *itm = createTreeItem(cluster_item, *member);
|
|
working_list_of_firewalls.remove(*member);
|
|
}
|
|
cluster_item->setExpanded(true);
|
|
}
|
|
|
|
for (list<Firewall *>::iterator i=working_list_of_firewalls.begin();
|
|
i!=working_list_of_firewalls.end(); ++i)
|
|
{
|
|
fw = *i;
|
|
QTreeWidgetItem* fw_item = createTreeItem(NULL, fw);
|
|
m_dialog->selectTable->addTopLevelItem(fw_item);
|
|
}
|
|
|
|
QTreeWidgetItemIterator it(m_dialog->selectTable);
|
|
while (*it)
|
|
{
|
|
setFlags(*it);
|
|
++it;
|
|
}
|
|
|
|
creatingTable = false;
|
|
|
|
for (int i=0; i<m_dialog->selectTable->columnCount(); i++)
|
|
m_dialog->selectTable->resizeColumnToContents(i);
|
|
|
|
setNextEnabled(0, tableHasCheckedItems());
|
|
|
|
//m_dialog->selectTable->resizeRowsToContents();
|
|
}
|
|
|
|
void instDialog::displayCommand(const QStringList &args)
|
|
{
|
|
QStringList a1 = args;
|
|
|
|
for (QStringList::iterator i=a1.begin(); i!=a1.end(); i++)
|
|
{
|
|
if ( (*i)=="-pw" )
|
|
{
|
|
i++;
|
|
*i = "XXXXXX";
|
|
break;
|
|
}
|
|
}
|
|
QString s=a1.join(" ");
|
|
addToLog( tr("Running command '%1'\n").arg(s) );
|
|
}
|
|
|
|
void instDialog::updateProgressBar(int n, bool setsize)
|
|
{
|
|
if (fwbdebug)
|
|
qDebug("instDialog::updateProgressBar n=%d setsize=%d",n,setsize);
|
|
|
|
if (setsize) currentProgressBar->setMaximum(n);
|
|
else
|
|
currentProgressBar->setValue(currentProgressBar->maximum()-n);
|
|
}
|
|
|
|
void instDialog::finishClicked()
|
|
{
|
|
finished = true;
|
|
accept();
|
|
}
|
|
|
|
/* user clicked 'Cancel' */
|
|
void instDialog::cancelClicked()
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::cancelClicked()");
|
|
finished = true;
|
|
|
|
if (proc.state() == QProcess::Running)
|
|
{
|
|
rejectDialogFlag = true;
|
|
proc.kill();
|
|
}
|
|
|
|
if (installer != NULL)
|
|
{
|
|
if (fwbdebug)
|
|
qDebug() << "instDialog::cancelClicked killing installer";
|
|
installer->terminate();
|
|
delete installer;
|
|
installer = NULL;
|
|
}
|
|
|
|
QDialog::reject();
|
|
}
|
|
|
|
|
|
void instDialog::showEvent( QShowEvent *ev)
|
|
{
|
|
st->restoreGeometry(this, QRect(200,100,780,500) );
|
|
QDialog::showEvent(ev);
|
|
}
|
|
|
|
void instDialog::hideEvent( QHideEvent *ev)
|
|
{
|
|
st->saveGeometry(this);
|
|
QDialog::hideEvent(ev);
|
|
}
|
|
|
|
void instDialog::saveLog()
|
|
{
|
|
QString dir;
|
|
if (currentLog==NULL) return;
|
|
dir=st->getWDir();
|
|
if (dir.isEmpty()) dir=st->getOpenFileDir();
|
|
if (dir.isEmpty()) dir="~";
|
|
|
|
/*
|
|
* We use QTextEdit::append to add lines to the log buffer, each
|
|
append creates a new paragraph so QTextEdit::text returns only
|
|
contents of the last paragraph. Need to reassemble the whole text
|
|
adding text from each paragraph separately.
|
|
*/
|
|
QString logText;
|
|
logText = currentLog->toPlainText();
|
|
//logText = currentLog->toHtml();
|
|
|
|
QString s = QFileDialog::getSaveFileName(
|
|
this,
|
|
"Choose a file",
|
|
dir,
|
|
"Text file (*.txt)");
|
|
|
|
if (fwbdebug)
|
|
qDebug( "Saving log to file %s", s.toAscii().constData() );
|
|
|
|
if (!s.isEmpty())
|
|
{
|
|
if (!s.endsWith(".txt"))
|
|
{
|
|
s+=".txt";
|
|
}
|
|
|
|
QFile f(s);
|
|
if (f.open( QIODevice::WriteOnly ))
|
|
{
|
|
QTextStream str( &f );
|
|
str << logText;
|
|
f.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Adds one line of text to the log
|
|
*
|
|
*/
|
|
void instDialog::addToLog(const QString &line)
|
|
{
|
|
// if (fwbdebug)
|
|
// qDebug("instDialog::addToLog: '%s'", line.toLatin1().constData());
|
|
|
|
if (line.isEmpty()) return;
|
|
|
|
if (currentLog)
|
|
{
|
|
QString txt = line.trimmed();
|
|
|
|
QTextCharFormat format = normal_format;
|
|
|
|
list<QRegExp>::const_iterator it;
|
|
for (it=error_re.begin(); it!=error_re.end(); ++it)
|
|
{
|
|
if ((*it).indexIn(txt) != -1)
|
|
{
|
|
format = error_format;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (it=warning_re.begin(); it!=warning_re.end(); ++it)
|
|
{
|
|
if ((*it).indexIn(txt) != -1)
|
|
{
|
|
format = warning_format;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* See sourceforge bug https://sourceforge.net/tracker/?func=detail&aid=2847263&group_id=5314&atid=1070394
|
|
*
|
|
* QTextEditor::insertHtml() becomes incrementally slow as the
|
|
* amount of text already in the QTextEditor
|
|
* increases. Compiling ~10 firewalls with few dozen rules
|
|
* each slows the output to a crawl on Windows. Keeping each
|
|
* line in a separate block makes it much faster.
|
|
*/
|
|
|
|
txt = line;
|
|
while (!txt.isEmpty() && (txt.endsWith("\n") || txt.endsWith("\r")))
|
|
txt.chop(1);
|
|
|
|
if (format == error_format || format == warning_format )
|
|
format.setAnchorHref(txt);
|
|
|
|
QTextCursor cursor = currentLog->textCursor();
|
|
cursor.insertBlock();
|
|
cursor.insertText(txt, format);
|
|
|
|
//m_dialog->procLogDisplayList->addItem(txt);
|
|
|
|
currentLog->ensureCursorVisible();
|
|
|
|
qApp->processEvents();
|
|
}
|
|
}
|
|
|
|
void instDialog::interpretLogLine(const QString &line)
|
|
{
|
|
if (fwbdebug)
|
|
qDebug("instDialog::interpretLogLine %s", line.toAscii().constData() );
|
|
|
|
QStringList words = line.trimmed().split(" ");
|
|
|
|
if (fwbdebug)
|
|
{
|
|
for (int i=0; i<words.size(); ++i)
|
|
qDebug("instDialog::interpretLogLine words[%d]='%s'",
|
|
i, words[i].toAscii().constData());
|
|
}
|
|
|
|
if (words.first().indexOf("rule")>=0)
|
|
{
|
|
bool ok;
|
|
processedRules = words[1].toInt(&ok);
|
|
if (ok)
|
|
currentProgressBar->setValue(processedRules);
|
|
|
|
if (fwbdebug)
|
|
qDebug("instDialog::interpretLogLine set progress bar current=%d",
|
|
processedRules);
|
|
} else
|
|
{
|
|
if (words.first().indexOf("processing")>=0)
|
|
{
|
|
currentProgressBar->reset();
|
|
bool ok;
|
|
int totalRules = words[1].toInt(&ok);
|
|
if (ok)
|
|
currentProgressBar->setMaximum(totalRules);
|
|
processedRules = 0;
|
|
|
|
if (fwbdebug)
|
|
qDebug("instDialog::interpretLogLine set progress bar max=%d",
|
|
totalRules);
|
|
} else
|
|
{
|
|
if (words.first().indexOf("Compiling")>=0)
|
|
{
|
|
//currentLabel->setText(line.trimmed());
|
|
currentProgressBar->reset();
|
|
} else
|
|
{
|
|
if (line.indexOf("Compiled successfully")>=0)
|
|
{
|
|
//currentLabel->setText(line.trimmed());
|
|
currentProgressBar->setValue(currentProgressBar->maximum());
|
|
if (fwbdebug)
|
|
qDebug("instDialog::interpretLogLine set progress "
|
|
"bar to max");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents,1);
|
|
}
|
|
|
|
void instDialog::readFromStdout()
|
|
{
|
|
char buf[2048];
|
|
int read_status = 0;
|
|
while ((read_status = proc.readLine(buf, sizeof(buf)))>0)
|
|
{
|
|
if (fwbdebug)
|
|
{
|
|
qDebug("instDialog::readFromStdout: read_status=%d buf=%s",
|
|
read_status, buf);
|
|
}
|
|
addToLog(buf);
|
|
interpretLogLine(buf);
|
|
}
|
|
}
|
|
|
|
void instDialog::selectAllFirewalls()
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::selectAllFirewalls");
|
|
setSelectStateAll(INSTALL_CHECKBOX_COLUMN, Qt::Checked);
|
|
setSelectStateAll(COMPILE_CHECKBOX_COLUMN, Qt::Checked);
|
|
tableItemChanged(NULL, 0);
|
|
}
|
|
|
|
void instDialog::deselectAllFirewalls()
|
|
{
|
|
setSelectStateAll(INSTALL_CHECKBOX_COLUMN, Qt::Unchecked);
|
|
setSelectStateAll(COMPILE_CHECKBOX_COLUMN, Qt::Unchecked);
|
|
tableItemChanged(NULL, 0);
|
|
}
|
|
|
|
void instDialog::setSelectStateAll(int column, Qt::CheckState select)
|
|
{
|
|
QTreeWidgetItemIterator it(m_dialog->selectTable);
|
|
while (*it)
|
|
{
|
|
int obj_id = (*it)->data(0, Qt::UserRole).toInt();
|
|
FWObject *o = project->db()->findInIndex(obj_id);
|
|
bool cluster_member = (*it)->data(1, Qt::UserRole).toBool();
|
|
int num_members = (*it)->data(2, Qt::UserRole).toInt();
|
|
|
|
Qt::ItemFlags flags = (*it)->flags();
|
|
if ((flags & Qt::ItemIsUserCheckable) != 0)
|
|
{
|
|
// firewalls only get checkboxes for install,
|
|
if (column == INSTALL_CHECKBOX_COLUMN && Firewall::isA(o))
|
|
(*it)->setCheckState(column, select);
|
|
|
|
// Cluster gets checkbox for compile.
|
|
// Cluster should never get a checkbox if it has no members.
|
|
// Firewall that is not a cluster member gets compile checkbox
|
|
if ((column == COMPILE_CHECKBOX_COLUMN && Cluster::isA(o) && num_members) ||
|
|
(Firewall::isA(o) && !cluster_member))
|
|
(*it)->setCheckState(column, select);
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
|
|
void instDialog::fillCompileOpList()
|
|
{
|
|
compile_fw_list.clear();
|
|
QTreeWidgetItemIterator it(m_dialog->selectTable);
|
|
while (*it)
|
|
{
|
|
if ((*it)->checkState(COMPILE_CHECKBOX_COLUMN))
|
|
{
|
|
int obj_id = (*it)->data(0, Qt::UserRole).toInt();
|
|
FWObject *o = project->db()->findInIndex(obj_id);
|
|
compile_fw_list.push_back(Firewall::cast(o));
|
|
}
|
|
++it;
|
|
}
|
|
compile_list_initial_size = compile_fw_list.size();
|
|
}
|
|
|
|
void instDialog::fillCompileUIList()
|
|
{
|
|
m_dialog->fwWorkList->clear();
|
|
opListMapping.clear();
|
|
|
|
Firewall * f;
|
|
InstallFirewallViewItem * item;
|
|
list<Firewall*>::iterator i;
|
|
for(i=compile_fw_list.begin(); i!=compile_fw_list.end(); ++i)
|
|
{
|
|
f = (*i);
|
|
item = new InstallFirewallViewItem(
|
|
NULL,//m_dialog->fwWorkList,
|
|
QString::fromUtf8(f->getName().c_str()),
|
|
false);
|
|
|
|
item->setData(0, Qt::UserRole, QVariant(f->getId()));
|
|
m_dialog->fwWorkList->insertTopLevelItem(0, item);
|
|
|
|
opListMapping[f->getId()] = item;
|
|
}
|
|
|
|
m_dialog->fwWorkList->resizeColumnToContents(0);
|
|
m_dialog->fwWorkList->sortByColumn(0, Qt::AscendingOrder);
|
|
}
|
|
|
|
void instDialog::fillInstallOpList()
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::fillInstallOpList");
|
|
install_fw_list.clear();
|
|
QTreeWidgetItemIterator it(m_dialog->selectTable);
|
|
while (*it)
|
|
{
|
|
if ((*it)->checkState(INSTALL_CHECKBOX_COLUMN))
|
|
{
|
|
int obj_id = (*it)->data(0, Qt::UserRole).toInt();
|
|
FWObject *o = project->db()->findInIndex(obj_id);
|
|
install_fw_list.push_back(Firewall::cast(o));
|
|
if (fwbdebug)
|
|
qDebug("fillInstallOpList: Install requested for %s", o->getName().c_str());
|
|
}
|
|
++it;
|
|
}
|
|
install_list_initial_size = install_fw_list.size();
|
|
}
|
|
|
|
void instDialog::fillInstallUIList()
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::fillInstallUIList");
|
|
m_dialog->fwWorkList->clear();
|
|
opListMapping.clear();
|
|
|
|
Firewall * f;
|
|
InstallFirewallViewItem * item;
|
|
list<Firewall*>::iterator i;
|
|
for(i=install_fw_list.begin(); i!=install_fw_list.end(); ++i)
|
|
{
|
|
f=(*i);
|
|
item = new InstallFirewallViewItem(
|
|
NULL,
|
|
QString::fromUtf8(f->getName().c_str()),
|
|
false);
|
|
|
|
m_dialog->fwWorkList->insertTopLevelItem(0, item);
|
|
opListMapping[f->getId()] = item;
|
|
}
|
|
m_dialog->fwWorkList->resizeColumnToContents(0);
|
|
m_dialog->fwWorkList->sortByColumn(0, Qt::AscendingOrder);
|
|
}
|
|
|
|
void instDialog::findFirewallInCompileLog(QTreeWidgetItem* item)
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::findFirewallInCompileLog");
|
|
|
|
m_dialog->detailMCframe->show();
|
|
qApp->processEvents();
|
|
QString fw_name = item->text(0);
|
|
|
|
m_dialog->procLogDisplay->moveCursor( QTextCursor::End );
|
|
m_dialog->procLogDisplay->find(currentSearchString +
|
|
fw_name,
|
|
QTextDocument::FindWholeWords |
|
|
QTextDocument::FindCaseSensitively |
|
|
QTextDocument::FindBackward);
|
|
}
|
|
|
|
void instDialog::tableItemChanged(QTreeWidgetItem*, int)
|
|
{
|
|
if (!creatingTable)
|
|
setNextEnabled(0, tableHasCheckedItems());
|
|
}
|
|
|
|
bool instDialog::tableHasCheckedItems()
|
|
{
|
|
QTreeWidgetItemIterator it(m_dialog->selectTable);
|
|
while (*it)
|
|
{
|
|
if ((*it)->checkState(COMPILE_CHECKBOX_COLUMN) ||
|
|
(*it)->checkState(INSTALL_CHECKBOX_COLUMN))
|
|
return true;
|
|
++it;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void instDialog::clearReqFirewalls()
|
|
{
|
|
reqFirewalls.clear();
|
|
}
|
|
|
|
void instDialog::addReqFirewall(Firewall *f)
|
|
{
|
|
reqFirewalls.insert(f);
|
|
}
|
|
|
|
/*
|
|
* getInstOptions() fills attributes of the cnf object
|
|
*/
|
|
bool instDialog::getInstOptions(Firewall *fw)
|
|
{
|
|
cnf.fwobj = fw;
|
|
|
|
readInstallerOptionsFromSettings();
|
|
readInstallerOptionsFromFirewallObject(fw);
|
|
|
|
if (m_dialog->batchInstall->isChecked() && batch_inst_opt_dlg)
|
|
{
|
|
// in batch install mode we use the same dialog to fill cnf
|
|
// without showing it to the user again
|
|
readInstallerOptionsFromDialog(fw, batch_inst_opt_dlg);
|
|
} else
|
|
{
|
|
// In non-batch mode installer options from the dialog
|
|
// overwrite options set in the fw object itself.
|
|
instOptionsDialog *inst_opt_dlg = new instOptionsDialog(this, &cnf);
|
|
if (inst_opt_dlg->exec()==QDialog::Rejected)
|
|
{
|
|
delete inst_opt_dlg;
|
|
return false;
|
|
}
|
|
readInstallerOptionsFromDialog(fw, inst_opt_dlg);
|
|
}
|
|
|
|
return verifyManagementAddress();
|
|
}
|
|
|
|
/*
|
|
* getBatchInstOptions() fills attributes of the cnf object for batch install
|
|
*/
|
|
bool instDialog::getBatchInstOptions(Firewall *first_fw)
|
|
{
|
|
cnf.fwobj = first_fw; // NULL;
|
|
|
|
readInstallerOptionsFromSettings();
|
|
readInstallerOptionsFromFirewallObject(first_fw);
|
|
|
|
if (batch_inst_opt_dlg != NULL) delete batch_inst_opt_dlg;
|
|
|
|
batch_inst_opt_dlg = new instBatchOptionsDialog(this, &cnf);
|
|
|
|
if (batch_inst_opt_dlg->exec()==QDialog::Rejected)
|
|
{
|
|
stopProcessFlag = true;
|
|
this->m_dialog->finishButton->setEnabled(true);
|
|
foreach(Firewall *fw, this->install_fw_list)
|
|
this->opCancelled(fw);
|
|
return false;
|
|
}
|
|
// clear aternative address in the dialog
|
|
batch_inst_opt_dlg->m_dialog->altAddress->setText("");
|
|
readInstallerOptionsFromDialog(NULL, batch_inst_opt_dlg);
|
|
|
|
if (fwbdebug)
|
|
qDebug() << "instDialog::getBatchInstOptions(): cnf.user=" << cnf.user;
|
|
|
|
return verifyManagementAddress();
|
|
}
|
|
|
|
void instDialog::readInstallerOptionsFromSettings()
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::readInstallerOptionsFromSettings");
|
|
|
|
fwb_prompt="--**--**--";
|
|
|
|
cnf.batchInstall = m_dialog->batchInstall->isChecked();
|
|
|
|
cnf.save_diff = st->value(SETTINGS_PATH_PREFIX"/Installer/savediff").toBool();
|
|
cnf.saveStandby = st->value(SETTINGS_PATH_PREFIX"/Installer/saveStandby").toBool();
|
|
cnf.dry_run = st->value(SETTINGS_PATH_PREFIX"/Installer/dryrun").toBool();
|
|
cnf.quiet = st->value(SETTINGS_PATH_PREFIX"/Installer/quiet").toBool();
|
|
cnf.verbose = st->value(SETTINGS_PATH_PREFIX"/Installer/verbose" ).toBool();
|
|
cnf.stripComments = st->value(SETTINGS_PATH_PREFIX"/Installer/stripComments").toBool();
|
|
cnf.compressScript = st->value(SETTINGS_PATH_PREFIX"/Installer/compressScript").toBool();
|
|
cnf.copyFWB = st->value(SETTINGS_PATH_PREFIX"/Installer/copyFWB").toBool();
|
|
cnf.testRun = st->value(SETTINGS_PATH_PREFIX"/Installer/testRun").toBool();
|
|
cnf.rollback = st->value(SETTINGS_PATH_PREFIX"/Installer/rollback").toBool();
|
|
cnf.rollbackTime = st->value(SETTINGS_PATH_PREFIX"/Installer/rollbackTime").toInt();
|
|
cnf.cancelRollbackIfSuccess =
|
|
st->value(SETTINGS_PATH_PREFIX"/Installer/canceRollbackIfSuccess").toBool();
|
|
}
|
|
|
|
void instDialog::readInstallerOptionsFromFirewallObject(Firewall *fw)
|
|
{
|
|
FWOptions *fwopt = NULL;
|
|
if (fw)
|
|
{
|
|
fwopt = fw->getOptionsObject();
|
|
|
|
string platform = cnf.fwobj->getStr("platform");
|
|
string host_OS = cnf.fwobj->getStr("host_OS");
|
|
|
|
cnf.user = fwopt->getStr("admUser").c_str();
|
|
QString aaddr = fwopt->getStr("altAddress").c_str();
|
|
if (!aaddr.isEmpty()) cnf.maddr = aaddr;
|
|
else
|
|
{
|
|
// Note that Host::getManagementAddress() scans interfaces and
|
|
// finds one marked as "management" and takes its address.
|
|
// It does not use Management child object.
|
|
const InetAddr *mgmt_addr = cnf.fwobj->getManagementAddress();
|
|
if (mgmt_addr)
|
|
cnf.maddr = mgmt_addr->toString().c_str();
|
|
else
|
|
cnf.maddr = "";
|
|
}
|
|
/*
|
|
* if user requested test run, store firewall script in a temp
|
|
* file. Always store it in a temp file on linksys
|
|
*/
|
|
QString s;
|
|
|
|
/* user_can_change_install_dir */
|
|
bool uccid = Resources::getTargetOptionBool(
|
|
host_OS, "user_can_change_install_dir");
|
|
|
|
if (uccid) s = fwopt->getStr("firewall_dir").c_str();
|
|
|
|
if (s.isEmpty()) s = Resources::getTargetOptionStr(
|
|
host_OS, "activation/fwdir").c_str();
|
|
|
|
cnf.fwdir = s;
|
|
|
|
cnf.script = FirewallInstaller::getGeneratedFileFullPath(fw);
|
|
cnf.remote_script = ""; // filled in FirewallInstaller::readManifest()
|
|
cnf.fwbfile = project->db()->getFileName().c_str();
|
|
cnf.wdir = getFileDir( project->getRCS()->getFileName() );
|
|
cnf.diff_file = QString(cnf.fwobj->getName().c_str())+".diff";
|
|
cnf.diff_pgm = Resources::platform_res[platform]->
|
|
getResourceStr("/FWBuilderResources/Target/diff").c_str();
|
|
cnf.diff_pgm = getPathToBinary(
|
|
cnf.diff_pgm.toAscii().constData()).c_str();
|
|
#ifdef _WIN32
|
|
cnf.diff_pgm = cnf.diff_pgm + ".exe";
|
|
#endif
|
|
cnf.sshArgs = fwopt->getStr("sshArgs").c_str();
|
|
cnf.scpArgs = fwopt->getStr("scpArgs").c_str();
|
|
cnf.useSCPForCisco = fwopt->getBool("use_scp");
|
|
|
|
cnf.activationCmd = fwopt->getStr("activationCmd").c_str();
|
|
|
|
if (fwbdebug)
|
|
{
|
|
qDebug("platform: %s", platform.c_str());
|
|
qDebug("host_OS: %s", host_OS.c_str());
|
|
qDebug("user_can_change_install_dir=%d", uccid);
|
|
qDebug("firewall_dir='%s'", fwopt->getStr("firewall_dir").c_str());
|
|
qDebug("management address: %s", cnf.maddr.toAscii().constData());
|
|
qDebug("cnf.fwdir='%s'", cnf.fwdir.toAscii().constData());
|
|
qDebug("activationCmd='%s'", cnf.activationCmd.toAscii().constData());
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void instDialog::readInstallerOptionsFromDialog(Firewall *fw,
|
|
instOptionsDialog *dlg)
|
|
{
|
|
if (fwbdebug) qDebug("instDialog::readInstallerOptionsFromDialog");
|
|
|
|
cnf.fwobj = fw;
|
|
QString adm_user;
|
|
|
|
FWOptions *fwopt = NULL;
|
|
if (fw)
|
|
{
|
|
fwopt = cnf.fwobj->getOptionsObject();
|
|
adm_user = fwopt->getStr("admUser").c_str();
|
|
}
|
|
|
|
cnf.dry_run = dlg->m_dialog->test->isChecked();
|
|
cnf.backup_file = dlg->m_dialog->backupConfigFile->text();
|
|
cnf.backup = !cnf.backup_file.isEmpty();
|
|
cnf.save_diff = dlg->m_dialog->saveDiff->isChecked();
|
|
cnf.saveStandby = dlg->m_dialog->saveStandby->isChecked();
|
|
|
|
/* Alternative address:
|
|
- first, check dialog. User could have overriden it using dialog
|
|
- then check firewall options, user could have set it in the "Install"
|
|
tab of firewall settings dialog
|
|
- last, if all overrides are empty, take it from the management interface
|
|
*/
|
|
|
|
QString aaddr = dlg->m_dialog->altAddress->text();
|
|
if (!aaddr.isEmpty())
|
|
{
|
|
/* alternative address can also be putty session name. In any case,
|
|
* leave it up to ssh to resolve it and signal an error if it can't be
|
|
* resolved ( Putty session name does not have to be in DNS at all ).
|
|
*/
|
|
cnf.maddr = aaddr;
|
|
if (fwbdebug)
|
|
qDebug("alternative addr %s", aaddr.toAscii().constData());
|
|
}
|
|
|
|
// user name set in the dialog overrides that set in the fw object
|
|
// But the dialog user name input field can be left blank, in which
|
|
// case we use the one configured in the object
|
|
if (!adm_user.isEmpty()) cnf.user = adm_user;
|
|
if (!dlg->m_dialog->uname->text().isEmpty())
|
|
cnf.user = dlg->m_dialog->uname->text();
|
|
|
|
cnf.pwd = dlg->m_dialog->pwd->text();
|
|
cnf.epwd = dlg->m_dialog->epwd->text();
|
|
cnf.quiet = dlg->m_dialog->quiet->isChecked();
|
|
cnf.verbose = dlg->m_dialog->verbose->isChecked();
|
|
cnf.stripComments = dlg->m_dialog->stripComments->isChecked();
|
|
cnf.compressScript= dlg->m_dialog->compressScript->isChecked();
|
|
cnf.copyFWB = dlg->m_dialog->copyFWB->isChecked();
|
|
cnf.testRun = dlg->m_dialog->testRun->isChecked();
|
|
cnf.rollback = dlg->m_dialog->rollback->isChecked();
|
|
cnf.rollbackTime = dlg->m_dialog->rollbackTime->value();
|
|
cnf.cancelRollbackIfSuccess =
|
|
dlg->m_dialog->cancelRollbackIfSuccess->isChecked();
|
|
|
|
dlg->savePassword();
|
|
storeInstallerOptions();
|
|
}
|
|
|
|
bool instDialog::verifyManagementAddress()
|
|
{
|
|
/* check for a common error when none or multiple interfaces are marked as
|
|
* 'management'
|
|
*/
|
|
if (cnf.fwobj)
|
|
{
|
|
int nmi = 0;
|
|
list<FWObject*> ll = cnf.fwobj->getByTypeDeep(Interface::TYPENAME);
|
|
for (FWObject::iterator i=ll.begin(); i!=ll.end(); i++)
|
|
{
|
|
Interface *intf = Interface::cast( *i );
|
|
if (intf->isManagement()) nmi++;
|
|
}
|
|
if (nmi>1)
|
|
{
|
|
QString err = QObject::tr("Only one interface of the firewall '%1' "
|
|
"must be marked as management interface.\n")
|
|
.arg(QString::fromUtf8(cnf.fwobj->getName().c_str()));
|
|
|
|
QMessageBox::critical(this, "Firewall Builder", err,
|
|
tr("&Continue") );
|
|
addToLog(err);
|
|
return false;
|
|
}
|
|
if (nmi==0)
|
|
{
|
|
QString err = QObject::tr("One of the interfaces of the firewall '%1' "
|
|
"must be marked as management interface.\n")
|
|
.arg(QString::fromUtf8(cnf.fwobj->getName().c_str()));
|
|
|
|
QMessageBox::critical(this, "Firewall Builder", err,
|
|
tr("&Continue") );
|
|
addToLog(err);
|
|
return false;
|
|
}
|
|
if (cnf.maddr == "" ||
|
|
cnf.maddr == QString(InetAddr::getAny().toString().c_str()))
|
|
{
|
|
QString err = QObject::tr("Management interface does not have IP address, "
|
|
"can not communicate with the firewall.\n");
|
|
|
|
QMessageBox::critical(this, "Firewall Builder", err,
|
|
tr("&Continue") );
|
|
addToLog(err);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void instDialog::logItemClicked(QUrl data)
|
|
{
|
|
QStringList parts = data.toString().split(':');
|
|
if (parts[0] == "Error") return;
|
|
if (parts.size()<3)
|
|
{
|
|
if(fwbdebug)
|
|
cout << "Wrong error message clicked" << endl;
|
|
return;
|
|
}
|
|
emit activateRule(project, parts[0], parts[1], parts[2].toInt());
|
|
}
|
|
|
|
void instDialog::closeEvent(QCloseEvent *event)
|
|
{
|
|
if (fwbdebug) qDebug() << "instDialog::closeEvent";
|
|
if (proc.state() == QProcess::Running)
|
|
{
|
|
if (fwbdebug)
|
|
qDebug() << "instDialog::closeEvent killing process";
|
|
proc.kill();
|
|
}
|
|
if (installer != NULL)
|
|
{
|
|
if (fwbdebug)
|
|
qDebug() << "instDialog::closeEvent killing installer";
|
|
installer->terminate();
|
|
delete installer;
|
|
installer = NULL;
|
|
}
|
|
}
|