Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions src/ui/conf/confrulemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#include <util/conf/confutil.h>
#include <util/dateutil.h>

#include "confmanager.h"

using namespace Fort;

namespace {
Expand Down Expand Up @@ -140,6 +138,20 @@ const char *const sqlUpdateRuleName = "UPDATE rule SET name = ?2 WHERE rule_id =

const char *const sqlUpdateRuleEnabled = "UPDATE rule SET enabled = ?2 WHERE rule_id = ?1;";

const char *const sqlSelectRuleIdDpendentApps =
"SELECT CASE "
" WHEN name IS NOT NULL AND name != '' THEN name "
" ELSE path "
"END AS display_name "
"FROM app WHERE rule_id = ?1 "
"ORDER BY lower(display_name);";

const char *const sqlSelectRuleIdDpendentRules =
"SELECT r.name, r.rule_type FROM rule r "
"JOIN rule_set rs ON rs.rule_id = r.rule_id "
"WHERE rs.sub_rule_id = ?1 "
"ORDER BY r.rule_type, lower(r.name);";

bool driverWriteRules(ConfBuffer &confBuf, bool onlyFlags = false)
{
if (confBuf.hasError()) {
Expand Down Expand Up @@ -415,6 +427,30 @@ bool ConfRuleManager::updateRuleEnabled(quint16 ruleId, bool enabled)
return ok;
}

ConfRuleManager::RuleDependentsInfo ConfRuleManager::getRuleDependentsInfo(quint16 ruleId, Rule::RuleType ruleType) const
{
RuleDependentsInfo depsInfo;
SqliteStmt stmt;

if (ruleType == Rule::AppRule &&
DbQuery(sqliteDb()).sql(sqlSelectRuleIdDpendentApps).vars({ ruleId }).prepare(stmt)) {
while (stmt.step() == SqliteStmt::StepRow) {
depsInfo.appNames << stmt.columnText(0);
}
}

if (ruleType == Rule::PresetRule &&
DbQuery(sqliteDb()).sql(sqlSelectRuleIdDpendentRules).vars({ ruleId }).prepare(stmt)) {
while (stmt.step() == SqliteStmt::StepRow) {
QString name = stmt.columnText(0);
auto type = static_cast<Rule::RuleType>(stmt.columnInt(1));
depsInfo.ruleNamesByType[type] << name;
}
}

return depsInfo;
}

bool ConfRuleManager::walkRules(
WalkRulesArgs &wra, const std::function<walkRulesCallback> &func) const
{
Expand Down
10 changes: 10 additions & 0 deletions src/ui/conf/confrulemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "confmanagerbase.h"

class ConfRuleManager : public ConfManagerBase, public ConfRulesWalker, public IocService

Check warning on line 13 in src/ui/conf/confrulemanager.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Class has 36 methods, which is greater than the 35 authorized. Split it into smaller classes.

See more on https://sonarcloud.io/project/issues?id=tnodir_fort&issues=AZ2j7qoyIF1tYcto5zKN&open=AZ2j7qoyIF1tYcto5zKN&pullRequest=735
{
Q_OBJECT

Expand All @@ -33,6 +33,16 @@
virtual bool updateRuleName(quint16 ruleId, const QString &ruleName);
virtual bool updateRuleEnabled(quint16 ruleId, bool enabled);

struct RuleDependentsInfo {
QStringList appNames;
QMap<Rule::RuleType, QStringList> ruleNamesByType;

bool isEmpty() const {
return appNames.isEmpty() && ruleNamesByType.isEmpty();
}
};
RuleDependentsInfo getRuleDependentsInfo(quint16 ruleId, Rule::RuleType ruleType) const;

bool walkRules(WalkRulesArgs &wra, const std::function<walkRulesCallback> &func) const override;

static void walkRulesMapByStmt(WalkRulesArgs &wra, SqliteStmt &stmt);
Expand Down
50 changes: 48 additions & 2 deletions src/ui/conf/confzonemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#include <util/conf/confutil.h>
#include <util/dateutil.h>

#include "confmanager.h"

using namespace Fort;

namespace {
Expand Down Expand Up @@ -61,6 +59,24 @@ const char *const sqlUpdateZoneName = "UPDATE zone SET name = ?2 WHERE zone_id =

const char *const sqlUpdateZoneEnabled = "UPDATE zone SET enabled = ?2 WHERE zone_id = ?1;";

const char *const sqlSelectZoneIdDpendentAddressGroupIds =
"SELECT addr_group_id FROM address_group "
"WHERE (include_zones & ?1) <> 0 OR (exclude_zones & ?1) <> 0 "
"ORDER BY addr_group_id;";

const char *const sqlSelectZoneIdDpendentApps =
"SELECT CASE "
" WHEN name IS NOT NULL AND name != '' THEN name "
" ELSE path "
"END AS display_name FROM app "
"WHERE (accept_zones & ?1) <> 0 OR (reject_zones & ?1) <> 0 "
"ORDER BY lower(display_name);";

const char *const sqlSelectZoneIdDpendentRules =
"SELECT name, rule_type FROM rule "
"WHERE (accept_zones & ?1) <> 0 OR (reject_zones & ?1) <> 0 "
"ORDER BY rule_type, lower(name);";

const char *const sqlUpdateZoneResult =
"UPDATE zone"
" SET address_count = ?2, text_checksum = ?3, bin_checksum = ?4,"
Expand Down Expand Up @@ -243,6 +259,36 @@ bool ConfZoneManager::updateZoneEnabled(quint8 zoneId, bool enabled)
return ok;
}

ConfZoneManager::ZoneDependentsInfo ConfZoneManager::getZoneDependentsInfo(quint8 zoneId) const
{
ZoneDependentsInfo depsInfo;
SqliteStmt stmt;

const quint32 zoneBit = (quint32(1) << (zoneId - 1));

if (DbQuery(sqliteDb()).sql(sqlSelectZoneIdDpendentAddressGroupIds).vars({ zoneBit }).prepare(stmt)) {
while (stmt.step() == SqliteStmt::StepRow) {
depsInfo.addressGroupIds << stmt.columnInt(0);
}
}

if (DbQuery(sqliteDb()).sql(sqlSelectZoneIdDpendentApps).vars({ zoneBit }).prepare(stmt)) {
while (stmt.step() == SqliteStmt::StepRow) {
depsInfo.appNames << stmt.columnText(0);
}
}

if (DbQuery(sqliteDb()).sql(sqlSelectZoneIdDpendentRules).vars({ zoneBit }).prepare(stmt)) {
while (stmt.step() == SqliteStmt::StepRow) {
QString name = stmt.columnText(0);
auto type = static_cast<Rule::RuleType>(stmt.columnInt(1));
depsInfo.ruleNamesByType[type] << name;
}
}

return depsInfo;
}

bool ConfZoneManager::updateZoneResult(const Zone &zone)
{
bool ok = false;
Expand Down
12 changes: 12 additions & 0 deletions src/ui/conf/confzonemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <QHash>
#include <QObject>

#include <conf/rule.h>
#include <util/classhelpers.h>
#include <util/ioc/iocservice.h>

Expand All @@ -27,6 +28,17 @@ class ConfZoneManager : public ConfManagerBase, public IocService
virtual bool updateZoneName(quint8 zoneId, const QString &zoneName);
virtual bool updateZoneEnabled(quint8 zoneId, bool enabled);

struct ZoneDependentsInfo {
QList<int> addressGroupIds;
QStringList appNames;
QMap<Rule::RuleType, QStringList> ruleNamesByType;

bool isEmpty() const {
return appNames.isEmpty() && addressGroupIds.isEmpty() && ruleNamesByType.isEmpty();
}
};
ZoneDependentsInfo getZoneDependentsInfo(quint8 zoneId) const;

bool updateZoneResult(const Zone &zone);

void updateDriverZones(quint32 zonesMask, quint32 enabledMask, quint32 dataSize,
Expand Down
54 changes: 54 additions & 0 deletions src/ui/form/rule/ruleswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
#include <QVBoxLayout>

#include <conf/confmanager.h>
#include <conf/confrulemanager.h>
#include <form/controls/controlutil.h>
#include <form/controls/treeview.h>
#include <form/dialog/dialogutil.h>
#include <fortglobal.h>
#include <manager/windowmanager.h>
#include <model/rulelistmodel.h>
#include <user/iniuser.h>
#include <util/conf/confutil.h>
#include <util/iconcache.h>
#include <util/window/widgetwindowstatewatcher.h>

Expand Down Expand Up @@ -96,6 +98,7 @@ void RulesWindow::retranslateUi()
m_actAddRule->setText(tr("Add"));
m_actEditRule->setText(tr("Edit"));
m_actRemoveRule->setText(tr("Remove"));
m_actShowRuleUsage->setText(tr("Show Usage"));
m_editSearch->setPlaceholderText(tr("Search") + " /");

ruleListModel()->refresh();
Expand Down Expand Up @@ -160,12 +163,18 @@ QLayout *RulesWindow::setupHeader()
m_actRemoveRule = editMenu->addAction(IconCache::icon(":/icons/delete.png"), QString());
m_actRemoveRule->setShortcut(Qt::Key_Delete);

editMenu->addSeparator();

m_actShowRuleUsage = editMenu->addAction(IconCache::icon(":/icons/information.png"), QString());
m_actShowRuleUsage->setShortcut(Qt::Key_Exclam);

connect(m_actAddRule, &QAction::triggered, this, &RulesWindow::addNewRule);
connect(m_actEditRule, &QAction::triggered, this, &RulesWindow::editSelectedRule);
connect(m_actRemoveRule, &QAction::triggered, this, [&] {
windowManager()->showConfirmBox(
[&] { deleteSelectedRule(); }, tr("Are you sure to remove selected rule?"));
});
connect(m_actShowRuleUsage, &QAction::triggered, this, &RulesWindow::showRuleUsage);

m_btEdit = ControlUtil::createButton(":/icons/pencil.png");
m_btEdit->setMenu(editMenu);
Expand Down Expand Up @@ -252,6 +261,13 @@ void RulesWindow::setupTreeRulesChanged()
const bool isRuleSelected = RuleListModel::isIndexRule(ruleIndex);
m_actEditRule->setEnabled(isRuleSelected);
m_actRemoveRule->setEnabled(isRuleSelected);

bool isRuleSelectedNonGlobal = isRuleSelected;
if (isRuleSelected) {
const auto ruleType = RuleListModel::indexRuleType(ruleIndex);
isRuleSelectedNonGlobal = ruleType == Rule::AppRule || ruleType == Rule::PresetRule;
}
m_actShowRuleUsage->setEnabled(isRuleSelectedNonGlobal);
};

refreshTreeRulesChanged();
Expand Down Expand Up @@ -371,6 +387,44 @@ void RulesWindow::deleteSelectedRule()
ctrl()->deleteRule(ruleRow.ruleId);
}

void RulesWindow::showRuleUsage() const
{
const auto ruleIndex = ruleListCurrentIndex();
if (!RuleListModel::isIndexRule(ruleIndex))
return;
//get rule row
const auto &ruleRow = ruleListModel()->ruleRowAt(ruleIndex);
if (ruleRow.isNull())
return;

//dependents
ConfRuleManager::RuleDependentsInfo depsInfo = confRuleManager()->getRuleDependentsInfo(
ruleRow.ruleId, ruleRow.ruleType);

if (depsInfo.isEmpty()) {
QString msg;
if (ruleRow.ruleType == Rule::AppRule) {
msg = tr("This rule is currently not in use by any programs.");
} else if (ruleRow.ruleType == Rule::PresetRule) {
msg = tr("This rule is currently not in use by any other rules.");
} else {
msg = tr("This rule is currently not in use.");
}
windowManager()->showInfoBox(msg, tr("Rule Usage"));
return;
}

QStringList output;
const QString itemPrefix = "<span style='white-space: normal;'>&nbsp;&nbsp;";
const QString itemSuffix = "</span>";

const auto usageInAppRule = ConfUtil::formatUsageInAppRule(depsInfo.appNames, depsInfo.ruleNamesByType,
itemPrefix, itemSuffix);
output << usageInAppRule;

windowManager()->showInfoBox(output.join("<br>").trimmed(), tr("Rule Usage"));
}

QModelIndex RulesWindow::ruleListCurrentIndex() const
{
return m_ruleListView->currentIndex();
Expand Down
3 changes: 3 additions & 0 deletions src/ui/form/rule/ruleswindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class RulesWindow : public FormWindow

void deleteSelectedRule();

void showRuleUsage() const;

QModelIndex ruleListCurrentIndex() const;

private:
Expand All @@ -77,6 +79,7 @@ class RulesWindow : public FormWindow
QAction *m_actAddRule = nullptr;
QAction *m_actEditRule = nullptr;
QAction *m_actRemoveRule = nullptr;
QAction *m_actShowRuleUsage = nullptr;
QLineEdit *m_editSearch = nullptr;
QToolButton *m_btOptions = nullptr;
QPushButton *m_btMenu = nullptr;
Expand Down
51 changes: 51 additions & 0 deletions src/ui/form/zone/zoneswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
#include <QVBoxLayout>

#include <conf/confmanager.h>
#include <conf/confzonemanager.h>
#include <form/controls/controlutil.h>
#include <form/controls/tableview.h>
#include <form/dialog/dialogutil.h>
#include <fortglobal.h>
#include <manager/windowmanager.h>
#include <model/rulelistmodel.h>
#include <model/zonelistmodel.h>
#include <task/taskinfozonedownloader.h>
#include <task/taskmanager.h>
Expand Down Expand Up @@ -82,6 +84,7 @@ void ZonesWindow::retranslateUi()
m_actAddZone->setText(tr("Add"));
m_actEditZone->setText(tr("Edit"));
m_actRemoveZone->setText(tr("Remove"));
m_actShowZoneUsage->setText(tr("Show Usage"));
m_btSaveAsText->setText(tr("Save As Text"));
m_btUpdateZones->setText(tr("Update Zones"));

Expand Down Expand Up @@ -132,12 +135,18 @@ QLayout *ZonesWindow::setupHeader()
m_actRemoveZone = editMenu->addAction(IconCache::icon(":/icons/delete.png"), QString());
m_actRemoveZone->setShortcut(Qt::Key_Delete);

editMenu->addSeparator();

m_actShowZoneUsage = editMenu->addAction(IconCache::icon(":/icons/information.png"), QString());
m_actShowZoneUsage->setShortcut(Qt::Key_Exclam);

connect(m_actAddZone, &QAction::triggered, this, &ZonesWindow::addNewZone);
connect(m_actEditZone, &QAction::triggered, this, &ZonesWindow::editSelectedZone);
connect(m_actRemoveZone, &QAction::triggered, this, [&] {
windowManager()->showConfirmBox(
[&] { deleteSelectedZone(); }, tr("Are you sure to remove selected zone?"));
});
connect(m_actShowZoneUsage, &QAction::triggered, this, &ZonesWindow::showZoneUsage);

m_btEdit = ControlUtil::createButton(":/icons/pencil.png");
m_btEdit->setMenu(editMenu);
Expand Down Expand Up @@ -218,6 +227,7 @@ void ZonesWindow::setupTableZonesChanged()
const bool zoneSelected = (zoneIndex >= 0);
m_actEditZone->setEnabled(zoneSelected);
m_actRemoveZone->setEnabled(zoneSelected);
m_actShowZoneUsage->setEnabled(zoneSelected);
m_btSaveAsText->setEnabled(zoneSelected);
};

Expand Down Expand Up @@ -283,6 +293,47 @@ void ZonesWindow::deleteSelectedZone()
deleteZone(zoneListCurrentIndex());
}

void ZonesWindow::showZoneUsage() const
{
const auto zoneIndex = zoneListCurrentIndex();
if (zoneIndex < 0)
return;
//get zone row
const auto &zoneRow = zoneListModel()->zoneRowAt(zoneIndex);
if (zoneRow.isNull())
return;

//dependents
ConfZoneManager::ZoneDependentsInfo depsInfo = confZoneManager()->getZoneDependentsInfo(zoneRow.zoneId);

if (depsInfo.isEmpty()) {
windowManager()->showInfoBox(tr("This zone is currently not in use."), tr("Zone Usage"));
return;
}

QStringList output;
const QString itemPrefix = "<span style='white-space: normal;'>&nbsp;&nbsp;";
const QString itemSuffix = "</span>";

if (!depsInfo.addressGroupIds.isEmpty()) {
output << "<b>" + tr("In Address Groups").toHtmlEscaped() + "</b>";
for (const int &addressGroupId : std::as_const(depsInfo.addressGroupIds)) {
QString addressGroupName;
if (addressGroupId == 1) { addressGroupName = tr("Local Network Addresses"); }
else if (addressGroupId == 2) { addressGroupName = tr("Block Addresses"); }
else { addressGroupName = tr("Address Group ID %1").arg(addressGroupId); }
output << itemPrefix + addressGroupName.toHtmlEscaped() + itemSuffix;
}
output << "";
}

const auto usageInAppRule = ConfUtil::formatUsageInAppRule(depsInfo.appNames, depsInfo.ruleNamesByType,
itemPrefix, itemSuffix);
output << usageInAppRule;

windowManager()->showInfoBox(output.join("<br>").trimmed(), tr("Zone Usage"));
}

void ZonesWindow::downloadZones()
{
taskManager()->runTask(TaskInfo::ZoneDownloader);
Expand Down
Loading