mumble-voip_mumble/src/mumble/BanEditor.cpp

292 lines
7.0 KiB
C++

// Copyright 2007-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#include "BanEditor.h"
#include "Ban.h"
#include "Channel.h"
#include "QtUtils.h"
#include "ServerHandler.h"
#include "Global.h"
#include <cassert>
BanEditor::BanEditor(const MumbleProto::BanList &msg, QWidget *p) : QDialog(p), maskDefaultValue(32) {
setupUi(this);
qlwBans->setFocus();
qlBans.clear();
for (int i = 0; i < msg.bans_size(); ++i) {
const MumbleProto::BanList_BanEntry &be = msg.bans(i);
Ban b;
b.haAddress = be.address();
b.iMask = static_cast< int >(be.mask());
b.qsUsername = u8(be.name());
b.qsHash = u8(be.hash());
b.qsReason = u8(be.reason());
b.qdtStart = QDateTime::fromString(u8(be.start()), Qt::ISODate);
b.qdtStart.setTimeSpec(Qt::UTC);
if (!b.qdtStart.isValid())
b.qdtStart = QDateTime::currentDateTime();
b.iDuration = be.duration();
if (b.isValid())
qlBans << b;
}
refreshBanList();
}
void BanEditor::accept() {
MumbleProto::BanList msg;
foreach (const Ban &b, qlBans) {
MumbleProto::BanList_BanEntry *be = msg.add_bans();
be->set_address(b.haAddress.toStdString());
assert(b.iMask >= 0);
be->set_mask(static_cast< unsigned int >(b.iMask));
be->set_name(u8(b.qsUsername));
be->set_hash(u8(b.qsHash));
be->set_reason(u8(b.qsReason));
be->set_start(u8(b.qdtStart.toString(Qt::ISODate)));
be->set_duration(b.iDuration);
}
Global::get().sh->sendMessage(msg);
QDialog::accept();
}
void BanEditor::on_qlwBans_currentRowChanged() {
int idx = qlwBans->currentRow();
if (idx < 0)
return;
qpbAdd->setDisabled(true);
qpbUpdate->setEnabled(false);
qpbRemove->setEnabled(true);
const Ban &ban = qlBans.at(idx);
int maskbits = ban.iMask;
const QHostAddress &addr = ban.haAddress.toAddress();
qleIP->setText(addr.toString());
if (!ban.haAddress.isV6())
maskbits -= 96;
qsbMask->setValue(maskbits);
qleUser->setText(ban.qsUsername);
qleHash->setText(ban.qsHash);
qleReason->setText(ban.qsReason);
qdteStart->setDateTime(ban.qdtStart.toLocalTime());
qdteEnd->setDateTime(ban.qdtStart.toLocalTime().addSecs(ban.iDuration));
}
Ban BanEditor::toBan(bool &ok) {
Ban b;
QHostAddress addr;
ok = addr.setAddress(qleIP->text());
if (ok) {
b.haAddress = addr;
b.iMask = qsbMask->value();
if (!b.haAddress.isV6())
b.iMask += 96;
b.qsUsername = qleUser->text();
b.qsHash = qleHash->text();
b.qsReason = qleReason->text();
b.qdtStart = qdteStart->dateTime().toUTC();
const QDateTime &qdte = qdteEnd->dateTime();
if (qdte <= b.qdtStart)
b.iDuration = 0;
else
b.iDuration = static_cast< unsigned int >(b.qdtStart.secsTo(qdte));
ok = b.isValid();
}
return b;
}
void BanEditor::on_qpbAdd_clicked() {
bool ok;
qdteStart->setDateTime(QDateTime::currentDateTime());
Ban b = toBan(ok);
if (ok) {
qlBans << b;
refreshBanList();
qlwBans->setCurrentRow(qlBans.indexOf(b));
}
qlwBans->setCurrentRow(-1);
qleSearch->clear();
}
void BanEditor::on_qpbUpdate_clicked() {
int idx = qlwBans->currentRow();
if (idx >= 0) {
bool ok;
Ban b = toBan(ok);
if (ok) {
qlBans.replace(idx, b);
refreshBanList();
qlwBans->setCurrentRow(qlBans.indexOf(b));
}
}
}
void BanEditor::on_qpbRemove_clicked() {
int idx = qlwBans->currentRow();
if (idx >= 0)
qlBans.removeAt(idx);
refreshBanList();
qlwBans->setCurrentRow(-1);
qleUser->clear();
qleIP->clear();
qleReason->clear();
qsbMask->setValue(maskDefaultValue);
qleHash->clear();
qdteStart->setDateTime(QDateTime::currentDateTime());
qdteEnd->setDateTime(QDateTime::currentDateTime());
qpbRemove->setDisabled(true);
qpbAdd->setDisabled(true);
}
void BanEditor::refreshBanList() {
qlwBans->clear();
std::sort(qlBans.begin(), qlBans.end());
foreach (const Ban &ban, qlBans) {
const QHostAddress &addr = ban.haAddress.toAddress();
if (ban.qsUsername.isEmpty())
qlwBans->addItem(addr.toString());
else
qlwBans->addItem(ban.qsUsername);
}
int n = qlBans.count();
setWindowTitle(tr("Ban List - %n Ban(s)", "", n));
}
void BanEditor::on_qleSearch_textChanged(const QString &match) {
qlwBans->clearSelection();
qpbAdd->setDisabled(true);
qpbUpdate->setDisabled(true);
qpbRemove->setDisabled(true);
qleUser->clear();
qleIP->clear();
qleReason->clear();
qsbMask->setValue(maskDefaultValue);
qleHash->clear();
qdteStart->setDateTime(QDateTime::currentDateTime());
qdteEnd->setDateTime(QDateTime::currentDateTime());
foreach (QListWidgetItem *item, qlwBans->findItems(QString(), Qt::MatchContains)) {
if (!item->text().contains(match, Qt::CaseInsensitive))
item->setHidden(true);
else
item->setHidden(false);
}
}
void BanEditor::on_qleIP_textChanged(QString address) {
bool valid = false;
int maxMask = 0;
switch (QHostAddress(address).protocol()) {
case QAbstractSocket::IPv4Protocol:
valid = true;
// IPv4: 8 <= mask <= 32
maxMask = 32;
break;
case QAbstractSocket::IPv6Protocol:
valid = true;
// IPv6: 8 <= mask <= 128
maxMask = 128;
break;
default:
valid = false;
break;
}
if (!valid) {
// Set red-ish background to indicate an invalid IP address
qleIP->setStyleSheet("background-color: #F08080;");
} else {
qleIP->setStyleSheet("");
}
if (qlwBans->currentRow() >= 0) {
qpbUpdate->setEnabled(valid && qleIP->isModified());
}
qpbAdd->setEnabled(valid && qleIP->isModified());
// Only display the controls for setting the mask, if a valid IP address has been entered (so we know what kind of
// masks are valid)
qsbMask->setVisible(valid);
qlMask->setVisible(valid);
if (valid) {
int prevMask = qsbMask->value();
bool wasSetToMax = qsbMask->maximum() == prevMask;
qsbMask->setMaximum(maxMask);
if (wasSetToMax) {
// If the mask value was at its maximum value and we change from IPv4 to IPv6, we still want to set the mask
// to the max. value as we have to assume the user didn't explicitly modify the value (and thus we want the
// default, which always is the max. value).
qsbMask->setValue(maxMask);
}
}
}
void BanEditor::on_qleReason_textChanged(QString) {
if (qlwBans->currentRow() >= 0)
qpbUpdate->setEnabled(qleReason->isModified());
}
void BanEditor::on_qdteEnd_editingFinished() {
qpbUpdate->setEnabled(!qleIP->text().isEmpty());
qpbRemove->setDisabled(true);
}
void BanEditor::on_qleUser_textChanged(QString) {
if (qlwBans->currentRow() >= 0)
qpbUpdate->setEnabled(qleUser->isModified());
}
void BanEditor::on_qleHash_textChanged(QString) {
if (qlwBans->currentRow() >= 0)
qpbUpdate->setEnabled(qleHash->isModified());
}
void BanEditor::on_qpbClear_clicked() {
qlwBans->setCurrentRow(-1);
qleUser->clear();
qleIP->clear();
qleReason->clear();
qsbMask->setValue(maskDefaultValue);
qleHash->clear();
qdteStart->setDateTime(QDateTime::currentDateTime());
qdteEnd->setDateTime(QDateTime::currentDateTime());
qpbAdd->setDisabled(true);
qpbUpdate->setDisabled(true);
qpbRemove->setDisabled(true);
}