Skip to content
Permalink
Browse files

First set of fixes for filter patch

Compare to review comments on 304bf43

- No longer use channel name for identifying filtered channels.
  Switched to using server certificate digest combined with Channel
  id which works between servers and with duplicate channel names.
  The digest should be replaced by proper server identification soon.
  Ideally the client should keep a list which identifies servers
  by their address or - if a strong certificate is available - by
  certificate email. This can be re-used for tokens and other server
  dependent configuration.
- Changed naming from 'hidden' to 'filtered'
- Removed tray menu entry
- Removed global shortcut for channel hiding/showing
  • Loading branch information...
hacst committed Sep 1, 2013
1 parent b422e0a commit 8f30d0c26b7b4b97eed288b74facac60d383e55e
@@ -51,7 +51,7 @@ Channel::Channel(int id, const QString &name, QObject *p) : QObject(p) {
cParent->addChannel(this);
#ifdef MUMBLE
uiPermissions = 0;
bHidden = false;
bFiltered = false;
#endif
}

@@ -73,7 +73,7 @@ class Channel : public QObject {

#ifdef MUMBLE
unsigned int uiPermissions;
bool bHidden;
bool bFiltered;

static QHash<int, Channel *> c_qhChannels;
static QReadWriteLock c_qrwlChannels;
@@ -166,8 +166,9 @@ Database::Database() {
execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `muted` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `muted_hash` ON `muted`(`hash`)"));

execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `hidden` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `hidden_hash` ON `hidden`(`hash`)"));
//Note: A previous snapshot version created a table called 'hidden'
execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `filtered_channels` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `server_cert_digest` TEXT NOT NULL, `channel_id` INTEGER NOT NULL)"));
execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `filtered_channels_entry` ON `filtered_channels`(`server_cert_digest`, `channel_id`)"));

execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `pingcache` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hostname` TEXT, `port` INTEGER, `ping` INTEGER)"));
execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `pingcache_host_port` ON `pingcache`(`hostname`,`port`)"));
@@ -283,26 +284,31 @@ void Database::setLocalMuted(const QString &hash, bool muted) {
execQueryAndLogFailure(query);
}

bool Database::isLocalHidden(const QString &hash) {
bool Database::isChannelFiltered(const QByteArray &server_cert_digest, const int channel_id) {
QSqlQuery query;

query.prepare(QLatin1String("SELECT `hash` FROM `hidden` WHERE `hash` = ?"));
query.addBindValue(hash);
query.prepare(QLatin1String("SELECT `channel_id` FROM `filtered_channels` WHERE `server_cert_digest` = ? AND `channel_id` = ?"));
query.addBindValue(server_cert_digest);
query.addBindValue(channel_id);
execQueryAndLogFailure(query);

while (query.next()) {
return true;
}
return false;
}

void Database::setLocalHidden(const QString &hash, bool hidden) {
void Database::setChannelFiltered(const QByteArray &server_cert_digest, const int channel_id, const bool hidden) {
QSqlQuery query;

if (hidden)
query.prepare(QLatin1String("INSERT INTO `hidden` (`hash`) VALUES (?)"));
query.prepare(QLatin1String("INSERT INTO `filtered_channels` (`server_cert_digest`, `channel_id`) VALUES (?, ?)"));
else
query.prepare(QLatin1String("DELETE FROM `hidden` WHERE `hash` = ?"));
query.addBindValue(hash);
query.prepare(QLatin1String("DELETE FROM `filtered_channels` WHERE `server_cert_digest` = ? AND `channel_id` = ?"));

query.addBindValue(server_cert_digest);
query.addBindValue(channel_id);

execQueryAndLogFailure(query);
}

@@ -60,8 +60,8 @@ class Database : public QObject {
static bool isLocalMuted(const QString &hash);
static void setLocalMuted(const QString &hash, bool muted);

static bool isLocalHidden(const QString &hash);
static void setLocalHidden(const QString &hash, bool hidden);
static bool isChannelFiltered(const QByteArray &server_cert_digest, const int channel_id);
static void setChannelFiltered(const QByteArray &server_cert_digest, const int channel_id, bool hidden);

static QMap<QPair<QString, unsigned short>, unsigned int> getPingCache();
static void setPingCache(const QMap<QPair<QString, unsigned short>, unsigned int> &cache);
@@ -218,10 +218,6 @@ void MainWindow::createActions() {
gsJoinChannel->setObjectName(QLatin1String("MetaChannel"));
gsJoinChannel->qsToolTip = tr("Use in conjunction with Whisper to.", "Global Shortcut");

gsHideChannel=new GlobalShortcut(this, idx++, tr("Hide Channel when Filtering", "Global Shortcut"));
gsHideChannel->setObjectName(QLatin1String("HideChannel"));
gsHideChannel->qsToolTip = tr("Mark the channel to be hidden when Filtering is active. Use in conjunction with Whisper to.", "Global Shortcut");

gsToggleOverlay=new GlobalShortcut(this, idx++, tr("Toggle Overlay", "Global Shortcut"), false);
gsToggleOverlay->setObjectName(QLatin1String("ToggleOverlay"));
gsToggleOverlay->qsToolTip = tr("Toggle state of in-game overlay.", "Global Shortcut");
@@ -251,9 +247,6 @@ void MainWindow::createActions() {
gsCycleTransmitMode=new GlobalShortcut(this, idx++, tr("Cycle Transmit Mode", "Global Shortcut"));
gsCycleTransmitMode->setObjectName(QLatin1String("gsCycleTransmitMode"));

gsChannelFilter=new GlobalShortcut(this, idx++, tr("Channel Filter", "Global Shortcut"), false, 0);
gsChannelFilter->setObjectName(QLatin1String("gsChannelFilter"));

#ifndef Q_OS_MAC
qstiIcon->show();
#endif
@@ -1609,7 +1602,7 @@ void MainWindow::qmChannel_aboutToShow() {
// hiding the root is nonsense
if(c && c->cParent) {
qmChannel->addSeparator();
qmChannel->addAction(qaChannelHide);
qmChannel->addAction(qaChannelFilter);
}

#ifndef Q_OS_MAC
@@ -1653,7 +1646,7 @@ void MainWindow::qmChannel_aboutToShow() {
}

if(c)
qaChannelHide->setChecked(c->bHidden);
qaChannelFilter->setChecked(c->bFiltered);

qaChannelAdd->setEnabled(add);
qaChannelRemove->setEnabled(remove);
@@ -1673,14 +1666,12 @@ void MainWindow::on_qaChannelJoin_triggered() {
}
}

void MainWindow::on_qaChannelHide_triggered() {
void MainWindow::on_qaChannelFilter_triggered() {
Channel *c = getContextMenuChannel();

if (c) {
QByteArray ba = c->qsName.toLocal8Bit();

UserModel *um = static_cast<UserModel *>(qtvUsers->model());
um->toggleHidden(c);
um->toggleChannelFiltered(c);
}
}

@@ -1898,7 +1889,7 @@ void MainWindow::updateMenuPermissions() {
qaChannelUnlinkAll->setEnabled(p & (ChanACL::Write | ChanACL::LinkChannel));

qaChannelSendMessage->setEnabled(p & (ChanACL::Write | ChanACL::TextMessage));
qaChannelHide->setEnabled(true);
qaChannelFilter->setEnabled(true);
qteChat->setEnabled(p & (ChanACL::Write | ChanACL::TextMessage));
}

@@ -1934,7 +1925,7 @@ void MainWindow::on_qaFilterToggle_triggered() {
g.s.bFilterActive = qaFilterToggle->isChecked();

UserModel *um = static_cast<UserModel *>(qtvUsers->model());
um->toggleHidden(NULL); // force a UI refresh
um->toggleChannelFiltered(NULL); // force a UI refresh
}

void MainWindow::on_qaAudioMute_triggered() {
@@ -2046,7 +2037,7 @@ void MainWindow::on_qaConfigDialog_triggered() {
updateTrayIcon();

UserModel *um = static_cast<UserModel *>(qtvUsers->model());
um->toggleHidden(NULL); // force a UI refresh
um->toggleChannelFiltered(NULL); // force a UI refresh
}

delete dlg;
@@ -2306,16 +2297,6 @@ void MainWindow::on_gsWhisper_triggered(bool down, QVariant scdata) {
}
}

if (gsHideChannel->active()) {
if (! st.bUsers) {
Channel *c = mapChannel(st.iChannel);
if (c) {
c->bHidden = !c->bHidden;
}
return;
}
}

qsCurrentTargets.insert(st);
updateTarget();

@@ -98,8 +98,8 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin

GlobalShortcut *gsPushTalk, *gsResetAudio, *gsMuteSelf, *gsDeafSelf;
GlobalShortcut *gsUnlink, *gsPushMute, *gsJoinChannel, *gsToggleOverlay;
GlobalShortcut *gsMinimal, *gsVolumeUp, *gsVolumeDown, *gsWhisper, *gsLinkChannel, *gsHideChannel;
GlobalShortcut *gsCycleTransmitMode, *gsChannelFilter;
GlobalShortcut *gsMinimal, *gsVolumeUp, *gsVolumeDown, *gsWhisper, *gsLinkChannel;
GlobalShortcut *gsCycleTransmitMode;
DockTitleBar *dtbLogDockTitle, *dtbChatDockTitle;

ACLEditor *aclEdit;
@@ -210,7 +210,7 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin
void on_qaChannelUnlink_triggered();
void on_qaChannelUnlinkAll_triggered();
void on_qaChannelSendMessage_triggered();
void on_qaChannelHide_triggered();
void on_qaChannelFilter_triggered();
void on_qaChannelCopyURL_triggered();
void on_qaAudioReset_triggered();
void on_qaAudioMute_triggered();
@@ -99,7 +99,7 @@
<property name="minimumSize">
<size>
<width>250</width>
<height>50</height>
<height>93</height>
</size>
</property>
<property name="features">
@@ -202,7 +202,7 @@
</action>
<action name="qaServerConnect">
<property name="icon">
<iconset resource="mumble_tango.qrc">
<iconset>
<normaloff>skin:categories/applications-internet.svg</normaloff>skin:categories/applications-internet.svg</iconset>
</property>
<property name="text">
@@ -251,7 +251,7 @@
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="mumble.qrc">
<iconset>
<normaloff>skin:Information_icon.svg</normaloff>skin:Information_icon.svg</iconset>
</property>
<property name="text">
@@ -438,7 +438,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="mumble_tango.qrc">
<iconset>
<normaloff>skin:actions/audio-input-microphone.svg</normaloff>
<normalon>skin:actions/audio-input-microphone-muted.svg</normalon>
<activeon>skin:actions/audio-input-microphone-muted.svg</activeon>skin:actions/audio-input-microphone.svg</iconset>
@@ -461,7 +461,7 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="mumble.qrc">
<iconset>
<normaloff>skin:self_undeafened.svg</normaloff>
<normalon>skin:deafened_self.svg</normalon>
<activeon>skin:deafened_self.svg</activeon>skin:self_undeafened.svg</iconset>
@@ -517,7 +517,7 @@
</action>
<action name="qaConfigDialog">
<property name="icon">
<iconset resource="mumble.qrc">
<iconset>
<normaloff>skin:config_basic.png</normaloff>skin:config_basic.png</iconset>
</property>
<property name="text">
@@ -541,10 +541,10 @@
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="mumble.qrc">
<iconset>
<normaloff>skin:filter.svg</normaloff>
<normalon>skin:filter.svg</normalon>
<activeon>skin:filter.svg</activeon>filter.svg</iconset>
<activeon>skin:filter.svg</activeon>skin:filter.svg</iconset>
</property>
<property name="text">
<string>&amp;Filter on/off</string>
@@ -787,7 +787,7 @@
<string>&amp;Join Channel</string>
</property>
</action>
<action name="qaChannelHide">
<action name="qaChannelFilter">
<property name="checkable">
<bool>true</bool>
</property>
@@ -813,7 +813,7 @@
</action>
<action name="qaSelfComment">
<property name="icon">
<iconset resource="mumble.qrc">
<iconset>
<normaloff>skin:comment.svg</normaloff>skin:comment.svg</iconset>
</property>
<property name="text">
@@ -852,7 +852,7 @@
</action>
<action name="qaRecording">
<property name="icon">
<iconset resource="mumble_tango.qrc">
<iconset>
<normaloff>skin:actions/media-record.svg</normaloff>skin:actions/media-record.svg</iconset>
</property>
<property name="text">
@@ -880,9 +880,6 @@
<header>CustomElements.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="mumble.qrc"/>
<include location="mumble_tango.qrc"/>
</resources>
<resources/>
<connections/>
</ui>
@@ -533,20 +533,31 @@ void MainWindow::msgChannelState(const MumbleProto::ChannelState &msg) {
Channel *p = msg.has_parent() ? Channel::get(msg.parent()) : NULL;

if (!c) {
if (msg.has_parent() && p && msg.has_name()) {
// Addresses channel does not exist so create it
if (p && msg.has_name()) {
c = pmModel->addChannel(msg.channel_id(), p, u8(msg.name()));
c->bTemporary = msg.temporary();
p = NULL;
p = NULL; // No need to move it later

ServerHandlerPtr sh = g.sh;
if (sh)
c->bFiltered = Database::isChannelFiltered(sh->qbaDigest, c->iId);

} else {
qWarning("Server attempted state change on nonexistent channel");
return;
}
}

if (p) {
// Channel move
Channel *pp = p;
while (pp) {
if (pp == c)
if (pp == c) {
qWarning("Server asked to move a channel into itself or one of its children");
return;
}

pp = pp->cParent;
}
pmModel->moveChannel(c, p);
@@ -564,9 +575,6 @@ void MainWindow::msgChannelState(const MumbleProto::ChannelState &msg) {
pmModel->repositionChannel(c, msg.position());
}

if (Database::isLocalHidden(c->qsName))
c->bHidden = true;

if (msg.links_size()) {
QList<Channel *> ql;
pmModel->unlinkAll(c);
@@ -602,8 +610,15 @@ void MainWindow::msgChannelState(const MumbleProto::ChannelState &msg) {

void MainWindow::msgChannelRemove(const MumbleProto::ChannelRemove &msg) {
Channel *c = Channel::get(msg.channel_id());
if (c && (c->iId != 0))
if (c && (c->iId != 0)) {
if (c->bFiltered) {
ServerHandlerPtr sh = g.sh;
if (sh)
Database::setChannelFiltered(sh->qbaDigest, c->iId, false);
c->bFiltered = false;
}
pmModel->removeChannel(c);
}
}

void MainWindow::msgTextMessage(const MumbleProto::TextMessage &msg) {
@@ -449,7 +449,7 @@ QVariant UserModel::data(const QModelIndex &idx, int role) const {
}
if (! c->qbaDescHash.isEmpty())
l << (item->bCommentSeen ? qiCommentSeen : qiComment);
if (c->bHidden)
if (c->bFiltered)
l << (qiFilter);
return l;
case Qt::FontRole:
@@ -1315,11 +1315,13 @@ void UserModel::userMuteDeafChanged() {
updateOverlay();
}

void UserModel::toggleHidden(Channel *c) {
void UserModel::toggleChannelFiltered(Channel *c) {
QModelIndex idx;
if(c) {
c->bHidden = !c->bHidden;
Database::setLocalHidden(c->qsName, c->bHidden);
c->bFiltered = !c->bFiltered;

ServerHandlerPtr sh = g.sh;
Database::setChannelFiltered(sh->qbaDigest, c->iId, c->bFiltered);
idx = index(c);
}

0 comments on commit 8f30d0c

Please sign in to comment.
You can’t perform that action at this time.