mirror of
https://github.com/tnodir/fort
synced 2024-11-15 09:45:44 +00:00
UI: Add "Apply same rules to child processes" flag to App Groups & Programs
This commit is contained in:
parent
8f12e1b15d
commit
e9bf713319
@ -125,6 +125,7 @@ typedef struct fort_app_flags
|
||||
{
|
||||
UCHAR group_index;
|
||||
UCHAR use_group_perm : 1;
|
||||
UCHAR apply_child : 1;
|
||||
UCHAR blocked : 1;
|
||||
UCHAR alerted : 1;
|
||||
UCHAR is_new : 1;
|
||||
@ -148,6 +149,7 @@ typedef struct fort_app_entry
|
||||
|
||||
typedef struct fort_conf_group
|
||||
{
|
||||
UINT16 apply_child;
|
||||
UINT16 log_conn;
|
||||
UINT16 fragment_bits;
|
||||
|
||||
|
@ -7,6 +7,7 @@ AppGroup::AppGroup(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_edited(false),
|
||||
m_enabled(true),
|
||||
m_applyChild(false),
|
||||
m_logConn(true),
|
||||
m_fragmentPacket(false),
|
||||
m_periodEnabled(false),
|
||||
@ -23,6 +24,14 @@ void AppGroup::setEnabled(bool enabled)
|
||||
}
|
||||
}
|
||||
|
||||
void AppGroup::setApplyChild(bool on)
|
||||
{
|
||||
if (bool(m_applyChild) != on) {
|
||||
m_applyChild = on;
|
||||
setEdited(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AppGroup::setLogConn(bool on)
|
||||
{
|
||||
if (bool(m_logConn) != on) {
|
||||
@ -149,6 +158,7 @@ void AppGroup::copy(const AppGroup &o)
|
||||
m_edited = o.edited();
|
||||
|
||||
m_enabled = o.enabled();
|
||||
m_applyChild = o.applyChild();
|
||||
m_logConn = o.logConn();
|
||||
m_fragmentPacket = o.fragmentPacket();
|
||||
|
||||
@ -175,6 +185,7 @@ QVariant AppGroup::toVariant() const
|
||||
map["edited"] = edited();
|
||||
map["enabled"] = enabled();
|
||||
|
||||
map["applyChild"] = applyChild();
|
||||
map["logConn"] = logConn();
|
||||
map["fragmentPacket"] = fragmentPacket();
|
||||
|
||||
@ -203,6 +214,7 @@ void AppGroup::fromVariant(const QVariant &v)
|
||||
m_edited = map["edited"].toBool();
|
||||
m_enabled = map["enabled"].toBool();
|
||||
|
||||
m_applyChild = map["applyChild"].toBool();
|
||||
m_logConn = map["logConn"].toBool();
|
||||
m_fragmentPacket = map["fragmentPacket"].toBool();
|
||||
|
||||
|
@ -19,6 +19,9 @@ public:
|
||||
bool enabled() const { return m_enabled; }
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
bool applyChild() const { return m_applyChild; }
|
||||
void setApplyChild(bool on);
|
||||
|
||||
bool logConn() const { return m_logConn; }
|
||||
void setLogConn(bool on);
|
||||
|
||||
@ -74,6 +77,7 @@ private:
|
||||
bool m_edited : 1;
|
||||
bool m_enabled : 1;
|
||||
|
||||
bool m_applyChild : 1;
|
||||
bool m_logConn : 1;
|
||||
bool m_fragmentPacket : 1;
|
||||
|
||||
|
@ -34,7 +34,7 @@ Q_LOGGING_CATEGORY(CLOG_CONF_MANAGER, "conf")
|
||||
#define logWarning() qCWarning(CLOG_CONF_MANAGER, )
|
||||
#define logCritical() qCCritical(CLOG_CONF_MANAGER, )
|
||||
|
||||
#define DATABASE_USER_VERSION 10
|
||||
#define DATABASE_USER_VERSION 11
|
||||
|
||||
namespace {
|
||||
|
||||
@ -44,7 +44,7 @@ const char *const sqlSelectAddressGroups = "SELECT addr_group_id, include_all, e
|
||||
" FROM address_group"
|
||||
" ORDER BY order_index;";
|
||||
|
||||
const char *const sqlSelectAppGroups = "SELECT app_group_id, enabled, log_conn,"
|
||||
const char *const sqlSelectAppGroups = "SELECT app_group_id, enabled, apply_child, log_conn,"
|
||||
" fragment_packet, period_enabled,"
|
||||
" limit_in_enabled, limit_out_enabled,"
|
||||
" speed_limit_in, speed_limit_out,"
|
||||
@ -67,21 +67,22 @@ const char *const sqlUpdateAddressGroup = "UPDATE address_group"
|
||||
" WHERE addr_group_id = ?1;";
|
||||
|
||||
const char *const sqlInsertAppGroup =
|
||||
"INSERT INTO app_group(app_group_id, order_index, enabled, log_conn,"
|
||||
"INSERT INTO app_group(app_group_id, order_index, enabled,"
|
||||
" apply_child, log_conn,"
|
||||
" fragment_packet, period_enabled,"
|
||||
" limit_in_enabled, limit_out_enabled,"
|
||||
" speed_limit_in, speed_limit_out,"
|
||||
" name, block_text, allow_text,"
|
||||
" period_from, period_to)"
|
||||
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15);";
|
||||
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16);";
|
||||
|
||||
const char *const sqlUpdateAppGroup = "UPDATE app_group"
|
||||
" SET order_index = ?2, enabled = ?3, log_conn = ?4,"
|
||||
" fragment_packet = ?5, period_enabled = ?6,"
|
||||
" limit_in_enabled = ?7, limit_out_enabled = ?8,"
|
||||
" speed_limit_in = ?9, speed_limit_out = ?10,"
|
||||
" name = ?11, block_text = ?12, allow_text = ?13,"
|
||||
" period_from = ?14, period_to = ?15"
|
||||
" SET order_index = ?2, enabled = ?3, apply_child = ?4,"
|
||||
" log_conn = ?5, fragment_packet = ?6,"
|
||||
" period_enabled = ?7, limit_in_enabled = ?8,"
|
||||
" limit_out_enabled = ?9, speed_limit_in = ?10,"
|
||||
" speed_limit_out = ?11, name = ?12, block_text = ?13,"
|
||||
" allow_text = ?14, period_from = ?15, period_to = ?16"
|
||||
" WHERE app_group_id = ?1;";
|
||||
|
||||
const char *const sqlDeleteAppGroup = "DELETE FROM app_group"
|
||||
@ -107,6 +108,7 @@ const char *const sqlSelectAppById = "SELECT"
|
||||
" g.order_index as group_index,"
|
||||
" t.path,"
|
||||
" t.use_group_perm,"
|
||||
" t.apply_child,"
|
||||
" t.blocked"
|
||||
" FROM app t"
|
||||
" JOIN app_group g ON g.app_group_id = t.app_group_id"
|
||||
@ -116,6 +118,7 @@ const char *const sqlSelectApps = "SELECT"
|
||||
" g.order_index as group_index,"
|
||||
" t.path,"
|
||||
" t.use_group_perm,"
|
||||
" t.apply_child,"
|
||||
" t.blocked,"
|
||||
" (alert.app_id IS NOT NULL) as alerted"
|
||||
" FROM app t"
|
||||
@ -127,21 +130,22 @@ const char *const sqlSelectEndAppsCount = "SELECT COUNT(*) FROM app"
|
||||
" AND blocked = 0;";
|
||||
|
||||
const char *const sqlSelectEndedApps = "SELECT t.app_id, g.order_index as group_index,"
|
||||
" t.path, t.name, t.use_group_perm"
|
||||
" t.path, t.name, t.use_group_perm, t.apply_child"
|
||||
" FROM app t"
|
||||
" JOIN app_group g ON g.app_group_id = t.app_group_id"
|
||||
" WHERE end_time <= ?1 AND blocked = 0;";
|
||||
|
||||
const char *const sqlSelectAppIdByPath = "SELECT app_id FROM app WHERE path = ?1;";
|
||||
|
||||
const char *const sqlUpsertApp =
|
||||
"INSERT INTO app(app_group_id, path, name, use_group_perm, blocked,"
|
||||
" creat_time, end_time)"
|
||||
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7)"
|
||||
" ON CONFLICT(path) DO UPDATE"
|
||||
" SET app_group_id = ?1, name = ?3, use_group_perm = ?4, blocked = ?5,"
|
||||
" creat_time = ?6, end_time = ?7"
|
||||
" RETURNING app_id;";
|
||||
const char *const sqlUpsertApp = "INSERT INTO app(app_group_id, path, name,"
|
||||
" use_group_perm, apply_child, blocked,"
|
||||
" creat_time, end_time)"
|
||||
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)"
|
||||
" ON CONFLICT(path) DO UPDATE"
|
||||
" SET app_group_id = ?1, name = ?3,"
|
||||
" use_group_perm = ?4, apply_child = ?5, blocked = ?6,"
|
||||
" creat_time = ?7, end_time = ?8"
|
||||
" RETURNING app_id;";
|
||||
|
||||
const char *const sqlInsertAppAlert = "INSERT INTO app_alert(app_id) VALUES(?1);";
|
||||
|
||||
@ -151,7 +155,7 @@ const char *const sqlDeleteAppAlert = "DELETE FROM app_alert WHERE app_id = ?1;"
|
||||
|
||||
const char *const sqlUpdateApp = "UPDATE app"
|
||||
" SET app_group_id = ?2, name = ?3, use_group_perm = ?4,"
|
||||
" blocked = ?5, end_time = ?6"
|
||||
" apply_child = ?5, blocked = ?6, end_time = ?7"
|
||||
" WHERE app_id = ?1;";
|
||||
|
||||
const char *const sqlUpdateAppName = "UPDATE app SET name = ?2 WHERE app_id = ?1;";
|
||||
@ -283,18 +287,19 @@ bool loadAppGroups(SqliteDb *db, FirewallConf &conf)
|
||||
|
||||
appGroup->setId(stmt.columnInt64(0));
|
||||
appGroup->setEnabled(stmt.columnBool(1));
|
||||
appGroup->setLogConn(stmt.columnBool(2));
|
||||
appGroup->setFragmentPacket(stmt.columnBool(3));
|
||||
appGroup->setPeriodEnabled(stmt.columnBool(4));
|
||||
appGroup->setLimitInEnabled(stmt.columnBool(5));
|
||||
appGroup->setLimitOutEnabled(stmt.columnBool(6));
|
||||
appGroup->setSpeedLimitIn(quint32(stmt.columnInt(7)));
|
||||
appGroup->setSpeedLimitOut(quint32(stmt.columnInt(8)));
|
||||
appGroup->setName(stmt.columnText(9));
|
||||
appGroup->setBlockText(stmt.columnText(10));
|
||||
appGroup->setAllowText(stmt.columnText(11));
|
||||
appGroup->setPeriodFrom(stmt.columnText(12));
|
||||
appGroup->setPeriodTo(stmt.columnText(13));
|
||||
appGroup->setApplyChild(stmt.columnBool(2));
|
||||
appGroup->setLogConn(stmt.columnBool(3));
|
||||
appGroup->setFragmentPacket(stmt.columnBool(4));
|
||||
appGroup->setPeriodEnabled(stmt.columnBool(5));
|
||||
appGroup->setLimitInEnabled(stmt.columnBool(6));
|
||||
appGroup->setLimitOutEnabled(stmt.columnBool(7));
|
||||
appGroup->setSpeedLimitIn(quint32(stmt.columnInt(8)));
|
||||
appGroup->setSpeedLimitOut(quint32(stmt.columnInt(9)));
|
||||
appGroup->setName(stmt.columnText(10));
|
||||
appGroup->setBlockText(stmt.columnText(11));
|
||||
appGroup->setAllowText(stmt.columnText(12));
|
||||
appGroup->setPeriodFrom(stmt.columnText(13));
|
||||
appGroup->setPeriodTo(stmt.columnText(14));
|
||||
appGroup->setEdited(false);
|
||||
|
||||
conf.addAppGroup(appGroup);
|
||||
@ -311,10 +316,11 @@ bool saveAppGroup(SqliteDb *db, AppGroup *appGroup, int orderIndex)
|
||||
|
||||
const auto vars = QVariantList()
|
||||
<< (rowExists ? appGroup->id() : QVariant()) << orderIndex << appGroup->enabled()
|
||||
<< appGroup->logConn() << appGroup->fragmentPacket() << appGroup->periodEnabled()
|
||||
<< appGroup->limitInEnabled() << appGroup->limitOutEnabled() << appGroup->speedLimitIn()
|
||||
<< appGroup->speedLimitOut() << appGroup->name() << appGroup->blockText()
|
||||
<< appGroup->allowText() << appGroup->periodFrom() << appGroup->periodTo();
|
||||
<< appGroup->applyChild() << appGroup->logConn() << appGroup->fragmentPacket()
|
||||
<< appGroup->periodEnabled() << appGroup->limitInEnabled()
|
||||
<< appGroup->limitOutEnabled() << appGroup->speedLimitIn() << appGroup->speedLimitOut()
|
||||
<< appGroup->name() << appGroup->blockText() << appGroup->allowText()
|
||||
<< appGroup->periodFrom() << appGroup->periodTo();
|
||||
|
||||
const char *sql = rowExists ? sqlUpdateAppGroup : sqlInsertAppGroup;
|
||||
|
||||
@ -658,8 +664,8 @@ void ConfManager::logBlockedApp(const LogEntryBlocked &logEntry)
|
||||
const QString appName = IoC<AppInfoCache>()->appName(appPath);
|
||||
constexpr int groupIndex = 0; // "Main" app. group
|
||||
|
||||
const bool ok = addOrUpdateApp(
|
||||
appPath, appName, QDateTime(), groupIndex, false, logEntry.blocked(), true);
|
||||
const bool ok = addOrUpdateApp(appPath, appName, QDateTime(), groupIndex,
|
||||
/*useGroupPerm=*/false, /*applyChild=*/false, logEntry.blocked(), /*alerted=*/true);
|
||||
if (ok) {
|
||||
emitAppAlerted();
|
||||
}
|
||||
@ -671,12 +677,13 @@ qint64 ConfManager::appIdByPath(const QString &appPath)
|
||||
}
|
||||
|
||||
bool ConfManager::addApp(const QString &appPath, const QString &appName, const QDateTime &endTime,
|
||||
int groupIndex, bool useGroupPerm, bool blocked)
|
||||
int groupIndex, bool useGroupPerm, bool applyChild, bool blocked)
|
||||
{
|
||||
if (!updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, blocked))
|
||||
if (!updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, applyChild, applyChild, blocked))
|
||||
return false;
|
||||
|
||||
return addOrUpdateApp(appPath, appName, endTime, groupIndex, useGroupPerm, blocked, false);
|
||||
return addOrUpdateApp(
|
||||
appPath, appName, endTime, groupIndex, useGroupPerm, applyChild, blocked, false);
|
||||
}
|
||||
|
||||
bool ConfManager::deleteApp(qint64 appId)
|
||||
@ -732,21 +739,22 @@ bool ConfManager::purgeApps()
|
||||
}
|
||||
|
||||
bool ConfManager::updateApp(qint64 appId, const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked)
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild, bool blocked)
|
||||
{
|
||||
const AppGroup *appGroup = conf()->appGroupAt(groupIndex);
|
||||
if (appGroup->isNull())
|
||||
return false;
|
||||
|
||||
if (!updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, blocked))
|
||||
if (!updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, applyChild, blocked))
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
|
||||
sqliteDb()->beginTransaction();
|
||||
|
||||
const auto vars = QVariantList() << appId << appGroup->id() << appName << useGroupPerm
|
||||
<< blocked << (!endTime.isNull() ? endTime : QVariant());
|
||||
const auto vars = QVariantList()
|
||||
<< appId << appGroup->id() << appName << useGroupPerm << applyChild << blocked
|
||||
<< (!endTime.isNull() ? endTime : QVariant());
|
||||
|
||||
sqliteDb()->executeEx(sqlUpdateApp, vars, 0, &ok);
|
||||
if (ok) {
|
||||
@ -821,10 +829,11 @@ bool ConfManager::walkApps(const std::function<walkAppsCallback> &func)
|
||||
const int groupIndex = stmt.columnInt(0);
|
||||
const QString appPath = stmt.columnText(1);
|
||||
const bool useGroupPerm = stmt.columnBool(2);
|
||||
const bool blocked = stmt.columnBool(3);
|
||||
const bool alerted = stmt.columnBool(4);
|
||||
const bool applyChild = stmt.columnBool(3);
|
||||
const bool blocked = stmt.columnBool(4);
|
||||
const bool alerted = stmt.columnBool(5);
|
||||
|
||||
if (!func(groupIndex, useGroupPerm, blocked, alerted, appPath))
|
||||
if (!func(groupIndex, useGroupPerm, applyChild, blocked, alerted, appPath))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -850,8 +859,10 @@ void ConfManager::updateAppEndTimes()
|
||||
const QString appPath = stmt.columnText(3);
|
||||
const QString appName = stmt.columnText(4);
|
||||
const bool useGroupPerm = stmt.columnBool(5);
|
||||
const bool applyChild = stmt.columnBool(6);
|
||||
|
||||
updateApp(appId, appPath, appName, QDateTime(), groupIndex, useGroupPerm, true);
|
||||
updateApp(appId, appPath, appName, QDateTime(), groupIndex, useGroupPerm, applyChild,
|
||||
/*blocked=*/true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1042,7 +1053,8 @@ bool ConfManager::updateDriverConf(bool onlyFlags)
|
||||
}
|
||||
|
||||
bool ConfManager::addOrUpdateApp(const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked, bool alerted)
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild, bool blocked,
|
||||
bool alerted)
|
||||
{
|
||||
const AppGroup *appGroup = conf()->appGroupAt(groupIndex);
|
||||
if (appGroup->isNull())
|
||||
@ -1053,7 +1065,7 @@ bool ConfManager::addOrUpdateApp(const QString &appPath, const QString &appName,
|
||||
sqliteDb()->beginTransaction();
|
||||
|
||||
const auto vars = QVariantList()
|
||||
<< appGroup->id() << appPath << appName << useGroupPerm << blocked
|
||||
<< appGroup->id() << appPath << appName << useGroupPerm << applyChild << blocked
|
||||
<< QDateTime::currentDateTime() << (!endTime.isNull() ? endTime : QVariant());
|
||||
|
||||
const auto appIdVar = sqliteDb()->executeEx(sqlUpsertApp, vars, 1, &ok);
|
||||
@ -1090,10 +1102,11 @@ bool ConfManager::updateDriverAppBlocked(qint64 appId, bool blocked, bool &chang
|
||||
const int groupIndex = stmt.columnInt(0);
|
||||
const QString appPath = stmt.columnText(1);
|
||||
const bool useGroupPerm = stmt.columnBool(2);
|
||||
const bool wasBlocked = stmt.columnBool(3);
|
||||
const bool applyChild = stmt.columnBool(3);
|
||||
const bool wasBlocked = stmt.columnBool(4);
|
||||
|
||||
if (blocked != wasBlocked) {
|
||||
if (!updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, blocked))
|
||||
if (!updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, applyChild, blocked))
|
||||
return false;
|
||||
|
||||
changed = true;
|
||||
@ -1104,17 +1117,18 @@ bool ConfManager::updateDriverAppBlocked(qint64 appId, bool blocked, bool &chang
|
||||
|
||||
bool ConfManager::updateDriverDeleteApp(const QString &appPath)
|
||||
{
|
||||
return updateDriverUpdateApp(appPath, 0, false, false, true);
|
||||
return updateDriverUpdateApp(appPath, /*groupIndex=*/0, /*useGroupPerm=*/false,
|
||||
/*applyChild=*/false, /*blocked=*/false, /*remove=*/true);
|
||||
}
|
||||
|
||||
bool ConfManager::updateDriverUpdateApp(
|
||||
const QString &appPath, int groupIndex, bool useGroupPerm, bool blocked, bool remove)
|
||||
bool ConfManager::updateDriverUpdateApp(const QString &appPath, int groupIndex, bool useGroupPerm,
|
||||
bool applyChild, bool blocked, bool remove)
|
||||
{
|
||||
ConfUtil confUtil;
|
||||
QByteArray buf;
|
||||
|
||||
const int entrySize =
|
||||
confUtil.writeAppEntry(groupIndex, useGroupPerm, blocked, false, false, appPath, buf);
|
||||
const int entrySize = confUtil.writeAppEntry(
|
||||
groupIndex, useGroupPerm, applyChild, blocked, false, false, appPath, buf);
|
||||
|
||||
if (entrySize == 0) {
|
||||
showErrorMessage(confUtil.errorMessage());
|
||||
|
@ -59,11 +59,12 @@ public:
|
||||
|
||||
qint64 appIdByPath(const QString &appPath);
|
||||
virtual bool addApp(const QString &appPath, const QString &appName, const QDateTime &endTime,
|
||||
int groupIndex, bool useGroupPerm, bool blocked);
|
||||
int groupIndex, bool useGroupPerm, bool applyChild, bool blocked);
|
||||
virtual bool deleteApp(qint64 appId);
|
||||
virtual bool purgeApps();
|
||||
virtual bool updateApp(qint64 appId, const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked);
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild,
|
||||
bool blocked);
|
||||
virtual bool updateAppBlocked(qint64 appId, bool blocked);
|
||||
virtual bool updateAppName(qint64 appId, const QString &appName);
|
||||
|
||||
@ -120,12 +121,12 @@ private:
|
||||
void emitAppUpdated();
|
||||
|
||||
bool addOrUpdateApp(const QString &appPath, const QString &appName, const QDateTime &endTime,
|
||||
int groupIndex, bool useGroupPerm, bool blocked, bool alerted);
|
||||
int groupIndex, bool useGroupPerm, bool applyChild, bool blocked, bool alerted);
|
||||
bool updateDriverAppBlocked(qint64 appId, bool blocked, bool &changed);
|
||||
|
||||
bool updateDriverDeleteApp(const QString &appPath);
|
||||
bool updateDriverUpdateApp(const QString &appPath, int groupIndex, bool useGroupPerm,
|
||||
bool blocked, bool remove = false);
|
||||
bool applyChild, bool blocked, bool remove = false);
|
||||
bool updateDriverZoneFlag(int zoneId, bool enabled);
|
||||
|
||||
bool loadFromDb(FirewallConf &conf, bool &isNew);
|
||||
|
@ -84,6 +84,7 @@ CREATE TABLE app_group(
|
||||
app_group_id INTEGER PRIMARY KEY,
|
||||
order_index INTEGER NOT NULL,
|
||||
enabled BOOLEAN NOT NULL,
|
||||
apply_child BOOLEAN NOT NULL DEFAULT 0,
|
||||
log_conn BOOLEAN NOT NULL DEFAULT 1,
|
||||
fragment_packet BOOLEAN NOT NULL,
|
||||
period_enabled BOOLEAN NOT NULL,
|
||||
@ -105,6 +106,7 @@ CREATE TABLE app(
|
||||
path TEXT NOT NULL,
|
||||
name TEXT,
|
||||
use_group_perm BOOLEAN NOT NULL DEFAULT 1,
|
||||
apply_child BOOLEAN NOT NULL DEFAULT 0,
|
||||
blocked BOOLEAN NOT NULL,
|
||||
creat_time INTEGER NOT NULL,
|
||||
end_time INTEGER,
|
||||
|
@ -79,6 +79,8 @@ void ApplicationsPage::onRetranslateUi()
|
||||
m_cbAllowAll->setText(tr("Allow All"));
|
||||
|
||||
m_btGroupOptions->setText(tr("Options"));
|
||||
m_cbApplyChild->setText(tr("Apply same rules to child processes"));
|
||||
|
||||
m_cscLimitIn->checkBox()->setText(tr("Download speed limit:"));
|
||||
m_cscLimitOut->checkBox()->setText(tr("Upload speed limit:"));
|
||||
retranslateGroupLimits();
|
||||
@ -373,14 +375,16 @@ void ApplicationsPage::setupGroupPeriodEnabled()
|
||||
|
||||
void ApplicationsPage::setupGroupOptions()
|
||||
{
|
||||
setupGroupApplyChild();
|
||||
setupGroupLimitIn();
|
||||
setupGroupLimitOut();
|
||||
setupGroupLogConn();
|
||||
setupGroupFragmentPacket();
|
||||
|
||||
// Menu
|
||||
const QList<QWidget *> menuWidgets = { m_cscLimitIn, m_cscLimitOut,
|
||||
ControlUtil::createSeparator(), m_cbLogConn, m_cbFragmentPacket };
|
||||
const QList<QWidget *> menuWidgets = { m_cbApplyChild, ControlUtil::createSeparator(),
|
||||
m_cscLimitIn, m_cscLimitOut, ControlUtil::createSeparator(), m_cbLogConn,
|
||||
m_cbFragmentPacket };
|
||||
auto layout = ControlUtil::createLayoutByWidgets(menuWidgets);
|
||||
|
||||
auto menu = ControlUtil::createMenuByLayout(layout, this);
|
||||
@ -389,6 +393,18 @@ void ApplicationsPage::setupGroupOptions()
|
||||
m_btGroupOptions->setMenu(menu);
|
||||
}
|
||||
|
||||
void ApplicationsPage::setupGroupApplyChild()
|
||||
{
|
||||
m_cbApplyChild = ControlUtil::createCheckBox(false, [&](bool checked) {
|
||||
if (appGroup()->applyChild() == checked)
|
||||
return;
|
||||
|
||||
appGroup()->setApplyChild(checked);
|
||||
|
||||
ctrl()->setOptEdited();
|
||||
});
|
||||
}
|
||||
|
||||
void ApplicationsPage::setupGroupLimitIn()
|
||||
{
|
||||
m_cscLimitIn = createGroupLimit();
|
||||
@ -549,6 +565,8 @@ void ApplicationsPage::setupSplitterButtons()
|
||||
|
||||
void ApplicationsPage::updateGroup()
|
||||
{
|
||||
m_cbApplyChild->setChecked(appGroup()->applyChild());
|
||||
|
||||
m_cscLimitIn->checkBox()->setChecked(appGroup()->limitInEnabled());
|
||||
m_cscLimitIn->spinBox()->setValue(int(appGroup()->speedLimitIn()));
|
||||
|
||||
|
@ -47,6 +47,7 @@ private:
|
||||
void setupGroupPeriod();
|
||||
void setupGroupPeriodEnabled();
|
||||
void setupGroupOptions();
|
||||
void setupGroupApplyChild();
|
||||
void setupGroupLimitIn();
|
||||
void setupGroupLimitOut();
|
||||
void setupGroupLogConn();
|
||||
@ -80,6 +81,7 @@ private:
|
||||
QCheckBox *m_cbGroupEnabled = nullptr;
|
||||
CheckTimePeriod *m_ctpGroupPeriod = nullptr;
|
||||
QPushButton *m_btGroupOptions = nullptr;
|
||||
QCheckBox *m_cbApplyChild = nullptr;
|
||||
CheckSpinCombo *m_cscLimitIn = nullptr;
|
||||
CheckSpinCombo *m_cscLimitOut = nullptr;
|
||||
QCheckBox *m_cbLogConn = nullptr;
|
||||
|
@ -76,6 +76,7 @@ void ProgramEditDialog::initialize(const AppRow &appRow, const QVector<qint64> &
|
||||
m_btGetName->setEnabled(isSingleSelection);
|
||||
m_comboAppGroup->setCurrentIndex(appRow.groupIndex);
|
||||
m_cbUseGroupPerm->setChecked(appRow.useGroupPerm);
|
||||
m_cbApplyChild->setChecked(appRow.applyChild);
|
||||
m_rbAllowApp->setChecked(!appRow.blocked);
|
||||
m_rbBlockApp->setChecked(appRow.blocked);
|
||||
m_cscBlockAppIn->checkBox()->setChecked(false);
|
||||
@ -116,6 +117,7 @@ void ProgramEditDialog::retranslateUi()
|
||||
|
||||
m_labelAppGroup->setText(tr("Application Group:"));
|
||||
m_cbUseGroupPerm->setText(tr("Use Application Group's Enabled State"));
|
||||
m_cbApplyChild->setText(tr("Apply same rules to child processes"));
|
||||
m_rbAllowApp->setText(tr("Allow"));
|
||||
m_rbBlockApp->setText(tr("Block"));
|
||||
|
||||
@ -222,6 +224,11 @@ QLayout *ProgramEditDialog::setupAppLayout()
|
||||
|
||||
layout->addRow(QString(), m_cbUseGroupPerm);
|
||||
|
||||
// Apply Child
|
||||
m_cbApplyChild = new QCheckBox();
|
||||
|
||||
layout->addRow(QString(), m_cbApplyChild);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
@ -361,6 +368,7 @@ bool ProgramEditDialog::save()
|
||||
|
||||
const int groupIndex = m_comboAppGroup->currentIndex();
|
||||
const bool useGroupPerm = m_cbUseGroupPerm->isChecked();
|
||||
const bool applyChild = m_cbApplyChild->isChecked();
|
||||
const bool blocked = m_rbBlockApp->isChecked();
|
||||
|
||||
QDateTime endTime;
|
||||
@ -376,28 +384,29 @@ bool ProgramEditDialog::save()
|
||||
|
||||
// Add new app or edit non-selected app
|
||||
if (appIdsCount == 0) {
|
||||
return confManager()->addApp(appPath, appName, endTime, groupIndex, useGroupPerm, blocked);
|
||||
return confManager()->addApp(
|
||||
appPath, appName, endTime, groupIndex, useGroupPerm, applyChild, blocked);
|
||||
}
|
||||
|
||||
// Edit selected app
|
||||
if (isSingleSelection) {
|
||||
return saveApp(appPath, appName, endTime, groupIndex, useGroupPerm, blocked);
|
||||
return saveApp(appPath, appName, endTime, groupIndex, useGroupPerm, applyChild, blocked);
|
||||
}
|
||||
|
||||
// Edit selected apps
|
||||
return saveMulti(endTime, groupIndex, useGroupPerm, blocked);
|
||||
return saveMulti(endTime, groupIndex, useGroupPerm, applyChild, blocked);
|
||||
}
|
||||
|
||||
bool ProgramEditDialog::saveApp(const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked)
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild, bool blocked)
|
||||
{
|
||||
const bool appEdited = (appPath != m_appRow.appPath || groupIndex != m_appRow.groupIndex
|
||||
|| useGroupPerm != m_appRow.useGroupPerm || blocked != m_appRow.blocked
|
||||
|| endTime != m_appRow.endTime);
|
||||
|| useGroupPerm != m_appRow.useGroupPerm || applyChild != m_appRow.applyChild
|
||||
|| blocked != m_appRow.blocked || endTime != m_appRow.endTime);
|
||||
|
||||
if (appEdited) {
|
||||
return confManager()->updateApp(
|
||||
m_appRow.appId, appPath, appName, endTime, groupIndex, useGroupPerm, blocked);
|
||||
return confManager()->updateApp(m_appRow.appId, appPath, appName, endTime, groupIndex,
|
||||
useGroupPerm, applyChild, blocked);
|
||||
}
|
||||
|
||||
if (appName == m_appRow.appName)
|
||||
@ -407,13 +416,13 @@ bool ProgramEditDialog::saveApp(const QString &appPath, const QString &appName,
|
||||
}
|
||||
|
||||
bool ProgramEditDialog::saveMulti(
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked)
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild, bool blocked)
|
||||
{
|
||||
for (qint64 appId : m_appIdList) {
|
||||
const auto appRow = appListModel()->appRowById(appId);
|
||||
|
||||
if (!confManager()->updateApp(appId, appRow.appPath, appRow.appName, endTime, groupIndex,
|
||||
useGroupPerm, blocked))
|
||||
useGroupPerm, applyChild, blocked))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,9 @@ private:
|
||||
|
||||
bool save();
|
||||
bool saveApp(const QString &appPath, const QString &appName, const QDateTime &endTime,
|
||||
int groupIndex, bool useGroupPerm, bool blocked);
|
||||
bool saveMulti(const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked);
|
||||
int groupIndex, bool useGroupPerm, bool applyChild, bool blocked);
|
||||
bool saveMulti(const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild,
|
||||
bool blocked);
|
||||
|
||||
private:
|
||||
ProgramsController *m_ctrl = nullptr;
|
||||
@ -68,6 +69,7 @@ private:
|
||||
QLabel *m_labelAppGroup = nullptr;
|
||||
QComboBox *m_comboAppGroup = nullptr;
|
||||
QCheckBox *m_cbUseGroupPerm = nullptr;
|
||||
QCheckBox *m_cbApplyChild = nullptr;
|
||||
QRadioButton *m_rbAllowApp = nullptr;
|
||||
QRadioButton *m_rbBlockApp = nullptr;
|
||||
CheckSpinCombo *m_cscBlockAppIn = nullptr;
|
||||
|
@ -277,10 +277,11 @@ bool AppListModel::updateAppRow(const QString &sql, const QVariantList &vars, Ap
|
||||
appRow.appPath = stmt.columnText(2);
|
||||
appRow.appName = stmt.columnText(3);
|
||||
appRow.useGroupPerm = stmt.columnBool(4);
|
||||
appRow.blocked = stmt.columnBool(5);
|
||||
appRow.alerted = stmt.columnBool(6);
|
||||
appRow.endTime = stmt.columnDateTime(7);
|
||||
appRow.creatTime = stmt.columnDateTime(8);
|
||||
appRow.applyChild = stmt.columnBool(5);
|
||||
appRow.blocked = stmt.columnBool(6);
|
||||
appRow.alerted = stmt.columnBool(7);
|
||||
appRow.endTime = stmt.columnDateTime(8);
|
||||
appRow.creatTime = stmt.columnDateTime(9);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -321,6 +322,7 @@ QString AppListModel::sqlBase() const
|
||||
" t.path,"
|
||||
" t.name,"
|
||||
" t.use_group_perm,"
|
||||
" t.apply_child,"
|
||||
" t.blocked,"
|
||||
" (alert.app_id IS NOT NULL) as alerted,"
|
||||
" t.end_time,"
|
||||
|
@ -14,6 +14,7 @@ class SqliteDb;
|
||||
struct AppRow : TableRow
|
||||
{
|
||||
bool useGroupPerm = true;
|
||||
bool applyChild = false;
|
||||
bool blocked = false;
|
||||
bool alerted = false;
|
||||
|
||||
|
@ -15,10 +15,10 @@ ConfManagerRpc::ConfManagerRpc(const QString &filePath, QObject *parent) :
|
||||
}
|
||||
|
||||
bool ConfManagerRpc::addApp(const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked)
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild, bool blocked)
|
||||
{
|
||||
return IoC<RpcManager>()->doOnServer(Control::Rpc_ConfManager_addApp,
|
||||
{ appPath, appName, endTime, groupIndex, useGroupPerm, blocked });
|
||||
{ appPath, appName, endTime, groupIndex, useGroupPerm, applyChild, blocked });
|
||||
}
|
||||
|
||||
bool ConfManagerRpc::deleteApp(qint64 appId)
|
||||
@ -32,10 +32,10 @@ bool ConfManagerRpc::purgeApps()
|
||||
}
|
||||
|
||||
bool ConfManagerRpc::updateApp(qint64 appId, const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked)
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild, bool blocked)
|
||||
{
|
||||
return IoC<RpcManager>()->doOnServer(Control::Rpc_ConfManager_updateApp,
|
||||
{ appId, appPath, appName, endTime, groupIndex, useGroupPerm, blocked });
|
||||
{ appId, appPath, appName, endTime, groupIndex, useGroupPerm, applyChild, blocked });
|
||||
}
|
||||
|
||||
bool ConfManagerRpc::updateAppBlocked(qint64 appId, bool blocked)
|
||||
|
@ -14,11 +14,12 @@ public:
|
||||
explicit ConfManagerRpc(const QString &filePath, QObject *parent = nullptr);
|
||||
|
||||
bool addApp(const QString &appPath, const QString &appName, const QDateTime &endTime,
|
||||
int groupIndex, bool useGroupPerm, bool blocked) override;
|
||||
int groupIndex, bool useGroupPerm, bool applyChild, bool blocked) override;
|
||||
bool deleteApp(qint64 appId) override;
|
||||
bool purgeApps() override;
|
||||
bool updateApp(qint64 appId, const QString &appPath, const QString &appName,
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked) override;
|
||||
const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool applyChild,
|
||||
bool blocked) override;
|
||||
bool updateAppBlocked(qint64 appId, bool blocked) override;
|
||||
bool updateAppName(qint64 appId, const QString &appName) override;
|
||||
|
||||
|
@ -51,7 +51,7 @@ inline bool processConfManager_addApp(ConfManager *confManager, const QVariantLi
|
||||
{
|
||||
return confManager->addApp(args.value(0).toString(), args.value(1).toString(),
|
||||
args.value(2).toDateTime(), args.value(3).toInt(), args.value(4).toBool(),
|
||||
args.value(5).toBool());
|
||||
args.value(5).toBool(), args.value(6).toBool());
|
||||
}
|
||||
|
||||
inline bool processConfManager_deleteApp(ConfManager *confManager, const QVariantList &args)
|
||||
@ -63,7 +63,7 @@ inline bool processConfManager_updateApp(ConfManager *confManager, const QVarian
|
||||
{
|
||||
return confManager->updateApp(args.value(0).toLongLong(), args.value(1).toString(),
|
||||
args.value(2).toString(), args.value(3).toDateTime(), args.value(4).toInt(),
|
||||
args.value(5).toBool(), args.value(6).toBool());
|
||||
args.value(5).toBool(), args.value(6).toBool(), args.value(7).toBool());
|
||||
}
|
||||
|
||||
inline bool processConfManager_updateAppBlocked(ConfManager *confManager, const QVariantList &args)
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
using walkAppsCallback = bool(
|
||||
int groupIndex, bool useGroupPerm, bool blocked, bool alerted, const QString &appPath);
|
||||
using walkAppsCallback = bool(int groupIndex, bool useGroupPerm, bool applyChild, bool blocked,
|
||||
bool alerted, const QString &appPath);
|
||||
|
||||
class ConfAppsWalker
|
||||
{
|
||||
|
@ -124,13 +124,13 @@ int ConfUtil::writeFlags(const FirewallConf &conf, QByteArray &buf)
|
||||
return flagsSize;
|
||||
}
|
||||
|
||||
int ConfUtil::writeAppEntry(int groupIndex, bool useGroupPerm, bool blocked, bool alerted,
|
||||
bool isNew, const QString &appPath, QByteArray &buf)
|
||||
int ConfUtil::writeAppEntry(int groupIndex, bool useGroupPerm, bool applyChild, bool blocked,
|
||||
bool alerted, bool isNew, const QString &appPath, QByteArray &buf)
|
||||
{
|
||||
appentry_map_t exeAppsMap;
|
||||
quint32 exeAppsSize = 0;
|
||||
|
||||
if (!addApp(groupIndex, useGroupPerm, blocked, alerted, isNew, appPath, exeAppsMap,
|
||||
if (!addApp(groupIndex, useGroupPerm, applyChild, blocked, alerted, isNew, appPath, exeAppsMap,
|
||||
exeAppsSize))
|
||||
return 0;
|
||||
|
||||
@ -340,11 +340,12 @@ bool ConfUtil::parseExeApps(
|
||||
if (Q_UNLIKELY(!confAppsWalker))
|
||||
return true;
|
||||
|
||||
return confAppsWalker->walkApps([&](int groupIndex, bool useGroupPerm, bool blocked,
|
||||
bool alerted, const QString &appPath) -> bool {
|
||||
return addApp(
|
||||
groupIndex, useGroupPerm, blocked, alerted, true, appPath, exeAppsMap, exeAppsSize);
|
||||
});
|
||||
return confAppsWalker->walkApps(
|
||||
[&](int groupIndex, bool useGroupPerm, bool applyChild, bool blocked, bool alerted,
|
||||
const QString &appPath) -> bool {
|
||||
return addApp(groupIndex, useGroupPerm, applyChild, blocked, alerted,
|
||||
/*isNew=*/true, appPath, exeAppsMap, exeAppsSize);
|
||||
});
|
||||
}
|
||||
|
||||
bool ConfUtil::parseAppsText(int groupIndex, bool blocked, const QString &text,
|
||||
@ -380,11 +381,13 @@ bool ConfUtil::addParsedApp(int groupIndex, bool blocked, bool isWild, bool isPr
|
||||
appentry_map_t &appsMap = isWild ? wildAppsMap : (isPrefix ? prefixAppsMap : exeAppsMap);
|
||||
quint32 &appsSize = isWild ? wildAppsSize : (isPrefix ? prefixAppsSize : exeAppsSize);
|
||||
|
||||
return addApp(groupIndex, true, blocked, false, true, appPath, appsMap, appsSize, false);
|
||||
return addApp(groupIndex, /*useGroupPerm=*/true, /*applyChild=*/false, blocked,
|
||||
/*alerted=*/false, /*isNew=*/true, appPath, appsMap, appsSize, /*canOverwrite=*/false);
|
||||
}
|
||||
|
||||
bool ConfUtil::addApp(int groupIndex, bool useGroupPerm, bool blocked, bool alerted, bool isNew,
|
||||
const QString &appPath, appentry_map_t &appsMap, quint32 &appsSize, bool canOverwrite)
|
||||
bool ConfUtil::addApp(int groupIndex, bool useGroupPerm, bool applyChild, bool blocked,
|
||||
bool alerted, bool isNew, const QString &appPath, appentry_map_t &appsMap,
|
||||
quint32 &appsSize, bool canOverwrite)
|
||||
{
|
||||
const QString kernelPath = FileUtil::pathToKernelPath(appPath);
|
||||
|
||||
@ -408,6 +411,7 @@ bool ConfUtil::addApp(int groupIndex, bool useGroupPerm, bool blocked, bool aler
|
||||
appEntry.path_len = appPathLen;
|
||||
appEntry.flags.group_index = quint8(groupIndex);
|
||||
appEntry.flags.use_group_perm = useGroupPerm;
|
||||
appEntry.flags.apply_child = applyChild;
|
||||
appEntry.flags.blocked = blocked;
|
||||
appEntry.flags.alerted = alerted;
|
||||
appEntry.flags.is_new = isNew;
|
||||
@ -495,7 +499,8 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf,
|
||||
writeApps(&data, exeAppsMap);
|
||||
#undef CONF_DATA_OFFSET
|
||||
|
||||
writeAppGroupFlags(&drvConfIo->conf_group.log_conn, &drvConfIo->conf_group.fragment_bits, conf);
|
||||
writeAppGroupFlags(&drvConfIo->conf_group.apply_child, &drvConfIo->conf_group.log_conn,
|
||||
&drvConfIo->conf_group.fragment_bits, conf);
|
||||
|
||||
writeLimits(drvConfIo->conf_group.limits, &drvConfIo->conf_group.limit_bits,
|
||||
&drvConfIo->conf_group.limit_2bits, conf.appGroups());
|
||||
@ -519,13 +524,17 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf,
|
||||
drvConf->exe_apps_off = exeAppsOff;
|
||||
}
|
||||
|
||||
void ConfUtil::writeAppGroupFlags(
|
||||
quint16 *logConnBits, quint16 *fragmentBits, const FirewallConf &conf)
|
||||
void ConfUtil::writeAppGroupFlags(quint16 *applyChildBits, quint16 *logConnBits,
|
||||
quint16 *fragmentBits, const FirewallConf &conf)
|
||||
{
|
||||
*applyChildBits = 0;
|
||||
*logConnBits = 0;
|
||||
*fragmentBits = 0;
|
||||
int i = 0;
|
||||
for (const AppGroup *appGroup : conf.appGroups()) {
|
||||
if (appGroup->applyChild()) {
|
||||
*applyChildBits |= (1 << i);
|
||||
}
|
||||
if (appGroup->logConn()) {
|
||||
*logConnBits |= (1 << i);
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ public slots:
|
||||
int write(const FirewallConf &conf, ConfAppsWalker *confAppsWalker, EnvManager &envManager,
|
||||
QByteArray &buf);
|
||||
int writeFlags(const FirewallConf &conf, QByteArray &buf);
|
||||
int writeAppEntry(int groupIndex, bool useGroupPerm, bool blocked, bool alerted, bool isNew,
|
||||
const QString &appPath, QByteArray &buf);
|
||||
int writeAppEntry(int groupIndex, bool useGroupPerm, bool applyChild, bool blocked,
|
||||
bool alerted, bool isNew, const QString &appPath, QByteArray &buf);
|
||||
int writeVersion(QByteArray &buf);
|
||||
int writeZone(const Ip4Range &ip4Range, QByteArray &buf);
|
||||
int writeZones(quint32 zonesMask, quint32 enabledMask, quint32 dataSize,
|
||||
@ -78,8 +78,8 @@ private:
|
||||
appentry_map_t &exeAppsMap, quint32 &wildAppsSize, quint32 &prefixAppsSize,
|
||||
quint32 &exeAppsSize);
|
||||
|
||||
bool addApp(int groupIndex, bool useGroupPerm, bool blocked, bool alerted, bool isNew,
|
||||
const QString &appPath, appentry_map_t &appsMap, quint32 &appsSize,
|
||||
bool addApp(int groupIndex, bool useGroupPerm, bool applyChild, bool blocked, bool alerted,
|
||||
bool isNew, const QString &appPath, appentry_map_t &appsMap, quint32 &appsSize,
|
||||
bool canOverwrite = true);
|
||||
|
||||
static QString parseAppPath(const StringView line, bool &isWild, bool &isPrefix);
|
||||
@ -93,8 +93,8 @@ private:
|
||||
const appentry_map_t &wildAppsMap, const appentry_map_t &prefixAppsMap,
|
||||
const appentry_map_t &exeAppsMap);
|
||||
|
||||
static void writeAppGroupFlags(
|
||||
quint16 *logConnBits, quint16 *fragmentBits, const FirewallConf &conf);
|
||||
static void writeAppGroupFlags(quint16 *applyChildBits, quint16 *logConnBits,
|
||||
quint16 *fragmentBits, const FirewallConf &conf);
|
||||
|
||||
static void writeLimits(struct fort_traf *limits, quint16 *limitBits, quint32 *limit2Bits,
|
||||
const QList<AppGroup *> &appGroups);
|
||||
|
Loading…
Reference in New Issue
Block a user