"Fossies" - the Fresh Open Source Software Archive

Member "mumble-1.3.2/src/mumble/ACLEditor.cpp" (9 Jul 2020, 25401 Bytes) of package /linux/misc/mumble-1.3.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ACLEditor.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.2.19_vs_1.3.0.

    1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
    2 // Use of this source code is governed by a BSD-style license
    3 // that can be found in the LICENSE file at the root of the
    4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
    5 
    6 #include "mumble_pch.hpp"
    7 
    8 #include "ACLEditor.h"
    9 
   10 #include "ACL.h"
   11 #include "Channel.h"
   12 #include "ClientUser.h"
   13 #include "Database.h"
   14 #include "Log.h"
   15 #include "ServerHandler.h"
   16 #include "User.h"
   17 
   18 // We define a global macro called 'g'. This can lead to issues when included code uses 'g' as a type or parameter name (like protobuf 3.7 does). As such, for now, we have to make this our last include.
   19 #include "Global.h"
   20 
   21 ACLGroup::ACLGroup(const QString &name) : Group(NULL, name) {
   22     bInherited = false;
   23 }
   24 
   25 ACLEditor::ACLEditor(int channelparentid, QWidget *p) : QDialog(p) {
   26     // Simple constructor for add channel menu
   27     bAddChannelMode = true;
   28     iChannel = channelparentid;
   29 
   30     setupUi(this);
   31 
   32     qsbChannelPosition->setRange(INT_MIN, INT_MAX);
   33 
   34     setWindowTitle(tr("Mumble - Add channel"));
   35     qtwTab->removeTab(2);
   36     qtwTab->removeTab(1);
   37 
   38     // Until I come around implementing it hide the password fields
   39     qleChannelPassword->hide();
   40     qlChannelPassword->hide();
   41 
   42     if (g.sh->uiVersion >= 0x010300) {
   43         qsbChannelMaxUsers->setRange(0, INT_MAX);
   44         qsbChannelMaxUsers->setValue(0);
   45         qsbChannelMaxUsers->setSpecialValueText(tr("Default server value"));
   46     } else {
   47         qlChannelMaxUsers->hide();
   48         qsbChannelMaxUsers->hide();
   49     }
   50 
   51     qlChannelID->hide();
   52 
   53     qleChannelName->setFocus();
   54 
   55     pcaPassword = NULL;
   56     adjustSize();
   57 }
   58 
   59 ACLEditor::ACLEditor(int channelid, const MumbleProto::ACL &mea, QWidget *p) : QDialog(p) {
   60     QLabel *l;
   61 
   62     bAddChannelMode = false;
   63 
   64     iChannel = channelid;
   65     Channel *pChannel = Channel::get(iChannel);
   66     if (pChannel == NULL) {
   67         g.l->log(Log::Warning, tr("Failed: Invalid channel"));
   68         QDialog::reject();
   69         return;
   70     }
   71 
   72     msg = mea;
   73 
   74     setupUi(this);
   75 
   76     qcbChannelTemporary->hide();
   77 
   78     iId = mea.channel_id();
   79     setWindowTitle(tr("Mumble - Edit %1").arg(Channel::get(iId)->qsName));
   80 
   81     qlChannelID->setText(tr("ID: %1").arg(iId));
   82 
   83     qleChannelName->setText(pChannel->qsName);
   84     if (channelid == 0)
   85         qleChannelName->setEnabled(false);
   86 
   87     rteChannelDescription->setText(pChannel->qsDesc);
   88 
   89     qsbChannelPosition->setRange(INT_MIN, INT_MAX);
   90     qsbChannelPosition->setValue(pChannel->iPosition);
   91 
   92     if (g.sh->uiVersion >= 0x010300) {
   93         qsbChannelMaxUsers->setRange(0, INT_MAX);
   94         qsbChannelMaxUsers->setValue(pChannel->uiMaxUsers);
   95         qsbChannelMaxUsers->setSpecialValueText(tr("Default server value"));
   96     } else {
   97         qlChannelMaxUsers->hide();
   98         qsbChannelMaxUsers->hide();
   99     }
  100 
  101     QGridLayout *grid = new QGridLayout(qgbACLpermissions);
  102 
  103     l = new QLabel(tr("Deny"), qgbACLpermissions);
  104     grid->addWidget(l, 0, 1);
  105     l = new QLabel(tr("Allow"), qgbACLpermissions);
  106     grid->addWidget(l, 0, 2);
  107 
  108     int idx = 1;
  109     for (int i = 0; i < ((iId == 0) ? 30 : 16); ++i) {
  110         ChanACL::Perm perm = static_cast<ChanACL::Perm>(1 << i);
  111         QString name = ChanACL::permName(perm);
  112 
  113         if (! name.isEmpty()) {
  114             QCheckBox *qcb;
  115             l = new QLabel(name, qgbACLpermissions);
  116             grid->addWidget(l, idx, 0);
  117             qcb = new QCheckBox(qgbACLpermissions);
  118             qcb->setToolTip(tr("Deny %1").arg(name));
  119             qcb->setWhatsThis(tr("This revokes the %1 privilege. If a privilege is both allowed and denied, it is denied.<br />%2").arg(name).arg(ChanACL::whatsThis(perm)));
  120             connect(qcb, SIGNAL(clicked(bool)), this, SLOT(ACLPermissions_clicked()));
  121             grid->addWidget(qcb, idx, 1);
  122 
  123             qlACLDeny << qcb;
  124 
  125             qcb = new QCheckBox(qgbACLpermissions);
  126             qcb->setToolTip(tr("Allow %1").arg(name));
  127             qcb->setWhatsThis(tr("This grants the %1 privilege. If a privilege is both allowed and denied, it is denied.<br />%2").arg(name).arg(ChanACL::whatsThis(perm)));
  128             connect(qcb, SIGNAL(clicked(bool)), this, SLOT(ACLPermissions_clicked()));
  129             grid->addWidget(qcb, idx, 2);
  130 
  131             qlACLAllow << qcb;
  132 
  133             qlPerms << perm;
  134 
  135             ++idx;
  136         }
  137     }
  138     QSpacerItem *si = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
  139     grid->addItem(si, idx, 0);
  140 
  141     connect(qcbGroupAdd->lineEdit(), SIGNAL(returnPressed()), qpbGroupAddAdd, SLOT(animateClick()));
  142     connect(qcbGroupRemove->lineEdit(), SIGNAL(returnPressed()), qpbGroupRemoveAdd, SLOT(animateClick()));
  143 
  144     foreach(User *u, ClientUser::c_qmUsers) {
  145         if (u->iId >= 0) {
  146             qhNameCache.insert(u->iId, u->qsName);
  147             qhIDCache.insert(u->qsName.toLower(), u->iId);
  148         }
  149     }
  150 
  151     ChanACL *def = new ChanACL(NULL);
  152 
  153     def->bApplyHere = true;
  154     def->bApplySubs = true;
  155     def->bInherited = true;
  156     def->iUserId = -1;
  157     def->qsGroup = QLatin1String("all");
  158     def->pAllow = ChanACL::Traverse | ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage;
  159     def->pDeny = (~def->pAllow) & ChanACL::All;
  160 
  161     qlACLs << def;
  162 
  163     for (int i = 0; i < mea.acls_size(); ++i) {
  164         const MumbleProto::ACL_ChanACL &as = mea.acls(i);
  165 
  166         ChanACL *acl = new ChanACL(NULL);
  167         acl->bApplyHere = as.apply_here();
  168         acl->bApplySubs = as.apply_subs();
  169         acl->bInherited = as.inherited();
  170         acl->iUserId = -1;
  171         if (as.has_user_id())
  172             acl->iUserId = as.user_id();
  173         else
  174             acl->qsGroup = u8(as.group());
  175         acl->pAllow = static_cast<ChanACL::Permissions>(as.grant());
  176         acl->pDeny = static_cast<ChanACL::Permissions>(as.deny());
  177 
  178         qlACLs << acl;
  179     }
  180 
  181     for (int i = 0; i < mea.groups_size(); ++i) {
  182         const MumbleProto::ACL_ChanGroup &gs = mea.groups(i);
  183 
  184         ACLGroup *gp = new ACLGroup(u8(gs.name()));
  185         gp->bInherit = gs.inherit();
  186         gp->bInherited = gs.inherited();
  187         gp->bInheritable = gs.inheritable();
  188         for (int j = 0; j < gs.add_size(); ++j)
  189             gp->qsAdd.insert(gs.add(j));
  190         for (int j = 0; j < gs.remove_size(); ++j)
  191             gp->qsRemove.insert(gs.remove(j));
  192         for (int j = 0; j < gs.inherited_members_size(); ++j)
  193             gp->qsTemporary.insert(gs.inherited_members(j));
  194 
  195         qlGroups << gp;
  196     }
  197 
  198     iUnknown = -2;
  199 
  200     numInheritACL = -1;
  201 
  202     bInheritACL = mea.inherit_acls();
  203     qcbACLInherit->setChecked(bInheritACL);
  204 
  205     foreach(ChanACL *acl, qlACLs) {
  206         if (acl->bInherited)
  207             numInheritACL++;
  208     }
  209 
  210     refill(GroupAdd);
  211     refill(GroupRemove);
  212     refill(GroupInherit);
  213     refill(ACLList);
  214     refillGroupNames();
  215 
  216     ACLEnableCheck();
  217     groupEnableCheck();
  218 
  219     updatePasswordField();
  220 
  221     qleChannelName->setFocus();
  222     adjustSize();
  223 }
  224 
  225 ACLEditor::~ACLEditor() {
  226     foreach(ChanACL *acl, qlACLs) {
  227         delete acl;
  228     }
  229     foreach(ACLGroup *gp, qlGroups) {
  230         delete gp;
  231     }
  232 }
  233 
  234 void ACLEditor::showEvent(QShowEvent *evt) {
  235     ACLEnableCheck();
  236     QDialog::showEvent(evt);
  237 }
  238 
  239 void ACLEditor::accept() {
  240     Channel *pChannel = Channel::get(iChannel);
  241     if (pChannel == NULL) {
  242         // Channel gone while editing
  243         g.l->log(Log::Warning, tr("Failed: Invalid channel"));
  244         QDialog::reject();
  245         return;
  246     }
  247 
  248     if (qleChannelName->text().isEmpty()) {
  249         // Empty channel name
  250         QMessageBox::warning(this, QLatin1String("Mumble"), tr("Channel must have a name"), QMessageBox::Ok);
  251         qleChannelName->setFocus();
  252         return;
  253     }
  254 
  255     // Update channel state
  256     if (bAddChannelMode) {
  257         g.sh->createChannel(iChannel, qleChannelName->text(), rteChannelDescription->text(), qsbChannelPosition->value(), qcbChannelTemporary->isChecked(), qsbChannelMaxUsers->value());
  258     } else {
  259         bool needs_update = false;
  260 
  261         updatePasswordACL();
  262 
  263         MumbleProto::ChannelState mpcs;
  264         mpcs.set_channel_id(pChannel->iId);
  265         if (pChannel->qsName != qleChannelName->text()) {
  266             mpcs.set_name(u8(qleChannelName->text()));
  267             needs_update = true;
  268         }
  269         if (rteChannelDescription->isModified() && (pChannel->qsDesc != rteChannelDescription->text())) {
  270             const QString &descriptionText = rteChannelDescription->text();
  271             mpcs.set_description(u8(descriptionText));
  272             needs_update = true;
  273             g.db->setBlob(sha1(descriptionText), descriptionText.toUtf8());
  274         }
  275         if (pChannel->iPosition != qsbChannelPosition->value()) {
  276             mpcs.set_position(qsbChannelPosition->value());
  277             needs_update = true;
  278         }
  279         if (pChannel->uiMaxUsers != static_cast<unsigned int>(qsbChannelMaxUsers->value())) {
  280             mpcs.set_max_users(qsbChannelMaxUsers->value());
  281             needs_update = true;
  282         }
  283         if (needs_update)
  284             g.sh->sendMessage(mpcs);
  285 
  286         // Update ACL
  287         msg.set_inherit_acls(bInheritACL);
  288         msg.clear_acls();
  289         msg.clear_groups();
  290 
  291         foreach(ChanACL *acl, qlACLs) {
  292             if (acl->bInherited || (acl->iUserId < -1))
  293                 continue;
  294             MumbleProto::ACL_ChanACL *mpa = msg.add_acls();
  295             mpa->set_apply_here(acl->bApplyHere);
  296             mpa->set_apply_subs(acl->bApplySubs);
  297             if (acl->iUserId != -1)
  298                 mpa->set_user_id(acl->iUserId);
  299             else
  300                 mpa->set_group(u8(acl->qsGroup));
  301             mpa->set_grant(acl->pAllow);
  302             mpa->set_deny(acl->pDeny);
  303         }
  304 
  305         foreach(ACLGroup *gp, qlGroups) {
  306             if (gp->bInherited && gp->bInherit && gp->bInheritable && (gp->qsAdd.count() == 0) && (gp->qsRemove.count() == 0))
  307                 continue;
  308             MumbleProto::ACL_ChanGroup *mpg = msg.add_groups();
  309             mpg->set_name(u8(gp->qsName));
  310             mpg->set_inherit(gp->bInherit);
  311             mpg->set_inheritable(gp->bInheritable);
  312             foreach(int pid, gp->qsAdd)
  313                 if (pid >= 0)
  314                     mpg->add_add(pid);
  315             foreach(int pid, gp->qsRemove)
  316                 if (pid >= 0)
  317                     mpg->add_remove(pid);
  318         }
  319         g.sh->sendMessage(msg);
  320     }
  321     QDialog::accept();
  322 }
  323 
  324 
  325 const QString ACLEditor::userName(int pid) {
  326     if (qhNameCache.contains(pid))
  327         return qhNameCache.value(pid);
  328     else
  329         return QString::fromLatin1("#%1").arg(pid);
  330 }
  331 
  332 int ACLEditor::id(const QString &uname) {
  333     QString name = uname.toLower();
  334     if (qhIDCache.contains(name)) {
  335         return qhIDCache.value(name);
  336     } else {
  337         if (! qhNameWait.contains(name)) {
  338             MumbleProto::QueryUsers mpuq;
  339             mpuq.add_names(u8(name));
  340             g.sh->sendMessage(mpuq);
  341 
  342             iUnknown--;
  343             qhNameWait.insert(name, iUnknown);
  344             qhNameCache.insert(iUnknown, name);
  345         }
  346         return qhNameWait.value(name);
  347     }
  348 }
  349 
  350 void ACLEditor::returnQuery(const MumbleProto::QueryUsers &mqu) {
  351     if (mqu.names_size() != mqu.ids_size())
  352         return;
  353 
  354     for (int i = 0; i < mqu.names_size(); ++i) {
  355         int pid = mqu.ids(i);
  356         QString name = u8(mqu.names(i));
  357         QString lname = name.toLower();
  358         qhIDCache.insert(lname, pid);
  359         qhNameCache.insert(pid, name);
  360 
  361         if (qhNameWait.contains(lname)) {
  362             int tid = qhNameWait.take(lname);
  363 
  364             foreach(ChanACL *acl, qlACLs)
  365                 if (acl->iUserId == tid)
  366                     acl->iUserId = pid;
  367             foreach(ACLGroup *gp, qlGroups) {
  368                 if (gp->qsAdd.remove(tid))
  369                     gp->qsAdd.insert(pid);
  370                 if (gp->qsRemove.remove(tid))
  371                     gp->qsRemove.insert(pid);
  372             }
  373             qhNameCache.remove(tid);
  374         }
  375     }
  376     refillGroupInherit();
  377     refillGroupRemove();
  378     refillGroupAdd();
  379     refillComboBoxes();
  380     refillACL();
  381 }
  382 
  383 void ACLEditor::refill(WaitID wid) {
  384     switch (wid) {
  385         case ACLList:
  386             refillACL();
  387             break;
  388         case GroupInherit:
  389             refillGroupInherit();
  390             break;
  391         case GroupRemove:
  392             refillGroupRemove();
  393             break;
  394         case GroupAdd:
  395             refillGroupAdd();
  396             break;
  397     }
  398 }
  399 
  400 void ACLEditor::refillComboBoxes() {
  401     QList<QComboBox *> ql;
  402     ql << qcbGroupAdd;
  403     ql << qcbGroupRemove;
  404     ql << qcbACLUser;
  405 
  406     QStringList names = qhNameCache.values();
  407     names.sort();
  408 
  409     foreach(QComboBox *qcb, ql) {
  410         qcb->clear();
  411         qcb->addItems(names);
  412         qcb->clearEditText();
  413     }
  414 }
  415 
  416 void ACLEditor::refillACL() {
  417     int idx = qlwACLs->currentRow();
  418     bool previousinherit = bInheritACL;
  419     bInheritACL = qcbACLInherit->isChecked();
  420 
  421     qlwACLs->clear();
  422 
  423     bool first = true;
  424 
  425     foreach(ChanACL *acl, qlACLs) {
  426         if (first)
  427             first = false;
  428         else if (! bInheritACL && acl->bInherited)
  429             continue;
  430         QString text;
  431         if (acl->iUserId == -1)
  432             text = QString::fromLatin1("@%1").arg(acl->qsGroup);
  433         else
  434             text = userName(acl->iUserId);
  435         QListWidgetItem *item = new QListWidgetItem(text, qlwACLs);
  436         if (acl->bInherited) {
  437             QFont f = item->font();
  438             f.setItalic(true);
  439             item->setFont(f);
  440         }
  441     }
  442     if (bInheritACL && ! previousinherit && (idx != 0))
  443         idx += numInheritACL;
  444     if (! bInheritACL && previousinherit)
  445         idx -= numInheritACL;
  446 
  447     qlwACLs->setCurrentRow(idx);
  448 }
  449 
  450 void ACLEditor::refillGroupNames() {
  451     QString text = qcbGroupList->currentText().toLower();
  452     QStringList qsl;
  453 
  454     foreach(ACLGroup *gp, qlGroups) {
  455         qsl << gp->qsName;
  456     }
  457     qsl.sort();
  458 
  459     qcbGroupList->clear();
  460 
  461     foreach(QString name, qsl) {
  462         qcbGroupList->addItem(name);
  463     }
  464 
  465     int wantindex = qcbGroupList->findText(text, Qt::MatchFixedString);
  466     qcbGroupList->setCurrentIndex(wantindex);
  467 }
  468 
  469 ACLGroup *ACLEditor::currentGroup() {
  470     QString group = qcbGroupList->currentText();
  471 
  472     foreach(ACLGroup *gp, qlGroups)
  473         if (gp->qsName == group)
  474             return gp;
  475 
  476     group = group.toLower();
  477 
  478     foreach(ACLGroup *gp, qlGroups)
  479         if (gp->qsName == group)
  480             return gp;
  481 
  482     return NULL;
  483 }
  484 
  485 ChanACL *ACLEditor::currentACL() {
  486     int idx = qlwACLs->currentRow();
  487     if (idx < 0)
  488         return NULL;
  489 
  490     if (idx && ! bInheritACL)
  491         idx += numInheritACL;
  492     return qlACLs[idx];
  493 }
  494 
  495 void ACLEditor::fillWidgetFromSet(QListWidget *qlw, const QSet<int> &qs) {
  496     qlw->clear();
  497 
  498     QList<idname> ql;
  499     foreach(int pid, qs) {
  500         ql << idname(userName(pid), pid);
  501     }
  502     qStableSort(ql);
  503     foreach(idname i, ql) {
  504         QListWidgetItem *qlwi = new QListWidgetItem(i.first, qlw);
  505         qlwi->setData(Qt::UserRole, i.second);
  506         if (i.second < 0) {
  507             QFont f = qlwi->font();
  508             f.setItalic(true);
  509             qlwi->setFont(f);
  510         }
  511     }
  512 }
  513 
  514 void ACLEditor::refillGroupAdd() {
  515     ACLGroup *gp = currentGroup();
  516 
  517     if (! gp)
  518         return;
  519 
  520     fillWidgetFromSet(qlwGroupAdd, gp->qsAdd);
  521 }
  522 
  523 void ACLEditor::refillGroupRemove() {
  524     ACLGroup *gp = currentGroup();
  525     if (! gp)
  526         return;
  527 
  528     fillWidgetFromSet(qlwGroupRemove, gp->qsRemove);
  529 }
  530 
  531 void ACLEditor::refillGroupInherit() {
  532     ACLGroup *gp = currentGroup();
  533 
  534     if (! gp)
  535         return;
  536 
  537     fillWidgetFromSet(qlwGroupInherit, gp->qsTemporary);
  538 }
  539 
  540 void ACLEditor::groupEnableCheck() {
  541     ACLGroup *gp = currentGroup();
  542 
  543     bool enabled;
  544     if (! gp)
  545         enabled = false;
  546     else
  547         enabled = gp->bInherit;
  548 
  549     qlwGroupRemove->setEnabled(enabled);
  550     qlwGroupInherit->setEnabled(enabled);
  551     qcbGroupRemove->setEnabled(enabled);
  552     qpbGroupRemoveAdd->setEnabled(enabled);
  553     qpbGroupRemoveRemove->setEnabled(enabled);
  554     qpbGroupInheritRemove->setEnabled(enabled);
  555 
  556     enabled = (gp != NULL);
  557     qlwGroupAdd->setEnabled(enabled);
  558     qcbGroupAdd->setEnabled(enabled);
  559     qpbGroupAddAdd->setEnabled(enabled);
  560     qpbGroupAddRemove->setEnabled(enabled);
  561     qcbGroupInherit->setEnabled(enabled);
  562     qcbGroupInheritable->setEnabled(enabled);
  563 
  564     if (gp) {
  565         qcbGroupInherit->setChecked(gp->bInherit);
  566         qcbGroupInheritable->setChecked(gp->bInheritable);
  567         qcbGroupInherited->setChecked(gp->bInherited);
  568     }
  569 }
  570 
  571 void ACLEditor::ACLEnableCheck() {
  572     ChanACL *as = currentACL();
  573 
  574     bool enabled;
  575     if (! as)
  576         enabled = false;
  577     else
  578         enabled = ! as->bInherited;
  579 
  580     qpbACLRemove->setEnabled(enabled);
  581     qpbACLUp->setEnabled(enabled);
  582     qpbACLDown->setEnabled(enabled);
  583     qcbACLApplyHere->setEnabled(enabled);
  584     qcbACLApplySubs->setEnabled(enabled);
  585     qcbACLGroup->setEnabled(enabled);
  586     qcbACLUser->setEnabled(enabled);
  587 
  588     for (int idx = 0; idx < qlACLAllow.count(); idx++) {
  589         // Only enable other checkboxes if writeacl isn't set
  590         bool enablethis = enabled && (qlPerms[idx] == ChanACL::Write || !(as && (as->pAllow & ChanACL::Write)) || qlPerms[idx] == ChanACL::Speak);
  591         qlACLAllow[idx]->setEnabled(enablethis);
  592         qlACLDeny[idx]->setEnabled(enablethis);
  593     }
  594 
  595     if (as) {
  596         qcbACLApplyHere->setChecked(as->bApplyHere);
  597         qcbACLApplySubs->setChecked(as->bApplySubs);
  598 
  599         for (int idx = 0; idx < qlACLAllow.count(); idx++) {
  600             ChanACL::Perm p = qlPerms[idx];
  601             qlACLAllow[idx]->setChecked(as->pAllow & p);
  602             qlACLDeny[idx]->setChecked(as->pDeny & p);
  603         }
  604 
  605         qcbACLGroup->clear();
  606         qcbACLGroup->addItem(QString());
  607         qcbACLGroup->addItem(QLatin1String("all"));
  608         qcbACLGroup->addItem(QLatin1String("auth"));
  609         qcbACLGroup->addItem(QLatin1String("in"));
  610         qcbACLGroup->addItem(QLatin1String("sub"));
  611         qcbACLGroup->addItem(QLatin1String("out"));
  612         qcbACLGroup->addItem(QLatin1String("~in"));
  613         qcbACLGroup->addItem(QLatin1String("~sub"));
  614         qcbACLGroup->addItem(QLatin1String("~out"));
  615 
  616         foreach(ACLGroup *gs, qlGroups)
  617             qcbACLGroup->addItem(gs->qsName);
  618 
  619         if (as->iUserId == -1) {
  620             qcbACLUser->clearEditText();
  621             qcbACLGroup->addItem(as->qsGroup);
  622             qcbACLGroup->setCurrentIndex(qcbACLGroup->findText(as->qsGroup, Qt::MatchExactly));
  623         } else {
  624             qcbACLUser->setEditText(userName(as->iUserId));
  625         }
  626     }
  627     foreach(QAbstractButton *b, qdbbButtons->buttons()) {
  628         QPushButton *qpb = qobject_cast<QPushButton *>(b);
  629         if (qpb) {
  630             qpb->setAutoDefault(false);
  631             qpb->setDefault(false);
  632         }
  633     }
  634 }
  635 
  636 void ACLEditor::on_qtwTab_currentChanged(int index) {
  637     if (index == 0) {
  638         // Switched to property tab, update password field
  639         updatePasswordField();
  640     } else if (index == 2) {
  641         // Switched to ACL tab, update ACL list
  642         updatePasswordACL();
  643         refillACL();
  644     }
  645 }
  646 
  647 void ACLEditor::updatePasswordField() {
  648     pcaPassword = NULL;
  649     foreach(ChanACL *acl, qlACLs) {
  650         // Check for sth that applies to '#<something>' AND grants 'Enter' AND may grant 'Speak', 'Whisper',
  651         // 'TextMessage', 'Link' but NOTHING else AND does not deny anything, then '<something>' is the password.
  652         if (acl->qsGroup.startsWith(QLatin1Char('#')) &&
  653                 acl->bApplyHere &&
  654                 !acl->bInherited &&
  655                 (acl->pAllow & ChanACL::Enter) &&
  656                 (acl->pAllow == (ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage | ChanACL::LinkChannel) || // Backwards compat with old behaviour that didn't deny traverse
  657                  acl->pAllow == (ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage | ChanACL::LinkChannel | ChanACL::Traverse)) &&
  658                 acl->pDeny == ChanACL::None) {
  659             pcaPassword = acl;
  660         }
  661     }
  662     if (pcaPassword)
  663         qleChannelPassword->setText(pcaPassword->qsGroup.mid(1));
  664     else
  665         qleChannelPassword->clear();
  666 
  667 }
  668 
  669 void ACLEditor::updatePasswordACL() {
  670     if (qleChannelPassword->text().isEmpty()) {
  671         // Remove the password if we had one to begin with
  672         if (pcaPassword && qlACLs.removeOne(pcaPassword)) {
  673             delete pcaPassword;
  674 
  675             // Search and remove the @all deny ACL
  676             ChanACL *denyall = NULL;
  677             foreach(ChanACL *acl, qlACLs) {
  678                 if (acl->qsGroup == QLatin1String("all") &&
  679                         acl->bInherited == false &&
  680                         acl->bApplyHere == true &&
  681                         acl->pAllow == ChanACL::None &&
  682                         (acl->pDeny == (ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage | ChanACL::LinkChannel) || // Backwards compat with old behaviour that didn't deny traverse
  683                          acl->pDeny == (ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage | ChanACL::LinkChannel | ChanACL::Traverse))) {
  684                     denyall = acl;
  685                 }
  686             }
  687             if (denyall) {
  688                 qlACLs.removeOne(denyall);
  689                 delete denyall;
  690             }
  691         }
  692     } else {
  693         // Add or Update
  694         if (pcaPassword == NULL || !qlACLs.contains(pcaPassword)) {
  695             pcaPassword = new ChanACL(NULL);
  696             pcaPassword->bApplyHere = true;
  697             pcaPassword->bApplySubs = false;
  698             pcaPassword->bInherited = false;
  699             pcaPassword->pAllow = ChanACL::None;
  700             pcaPassword->pDeny = ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage | ChanACL::LinkChannel | ChanACL::Traverse;
  701             pcaPassword->qsGroup = QLatin1String("all");
  702             qlACLs << pcaPassword;
  703 
  704             pcaPassword = new ChanACL(NULL);
  705             pcaPassword->bApplyHere = true;
  706             pcaPassword->bApplySubs = false;
  707             pcaPassword->bInherited = false;
  708             pcaPassword->pAllow = ChanACL::Enter | ChanACL::Speak | ChanACL::Whisper | ChanACL::TextMessage | ChanACL::LinkChannel | ChanACL::Traverse;
  709             pcaPassword->pDeny = ChanACL::None;
  710             pcaPassword->qsGroup = QString(QLatin1String("#%1")).arg(qleChannelPassword->text());
  711             qlACLs << pcaPassword;
  712         } else {
  713             pcaPassword->qsGroup = QString(QLatin1String("#%1")).arg(qleChannelPassword->text());
  714         }
  715     }
  716 }
  717 
  718 void ACLEditor::on_qlwACLs_currentRowChanged() {
  719     ACLEnableCheck();
  720 }
  721 
  722 void ACLEditor::on_qpbACLAdd_clicked() {
  723     ChanACL *as = new ChanACL(NULL);
  724     as->bApplyHere = true;
  725     as->bApplySubs = true;
  726     as->bInherited = false;
  727     as->qsGroup = QLatin1String("all");
  728     as->iUserId = -1;
  729     as->pAllow = ChanACL::None;
  730     as->pDeny = ChanACL::None;
  731     qlACLs << as;
  732     refillACL();
  733     qlwACLs->setCurrentRow(qlwACLs->count() - 1);
  734 }
  735 
  736 void ACLEditor::on_qpbACLRemove_clicked() {
  737     ChanACL *as = currentACL();
  738     if (! as || as->bInherited)
  739         return;
  740 
  741     qlACLs.removeAll(as);
  742     delete as;
  743     refillACL();
  744 }
  745 
  746 void ACLEditor::on_qpbACLUp_clicked() {
  747     ChanACL *as = currentACL();
  748     if (! as || as->bInherited)
  749         return;
  750 
  751     int idx = qlACLs.indexOf(as);
  752     if (idx <= numInheritACL + 1)
  753         return;
  754 
  755     qlACLs.swap(idx - 1, idx);
  756     qlwACLs->setCurrentRow(qlwACLs->currentRow() - 1);
  757     refillACL();
  758 }
  759 
  760 void ACLEditor::on_qpbACLDown_clicked() {
  761     ChanACL *as = currentACL();
  762     if (! as || as->bInherited)
  763         return;
  764 
  765     int idx = qlACLs.indexOf(as) + 1;
  766     if (idx >= qlACLs.count())
  767         return;
  768 
  769     qlACLs.swap(idx - 1, idx);
  770     qlwACLs->setCurrentRow(qlwACLs->currentRow() + 1);
  771     refillACL();
  772 }
  773 
  774 void ACLEditor::on_qcbACLInherit_clicked(bool) {
  775     refillACL();
  776 }
  777 
  778 void ACLEditor::on_qcbACLApplyHere_clicked(bool checked) {
  779     ChanACL *as = currentACL();
  780     if (! as || as->bInherited)
  781         return;
  782 
  783     as->bApplyHere = checked;
  784 }
  785 
  786 void ACLEditor::on_qcbACLApplySubs_clicked(bool checked) {
  787     ChanACL *as = currentACL();
  788     if (! as || as->bInherited)
  789         return;
  790 
  791     as->bApplySubs = checked;
  792 }
  793 
  794 void ACLEditor::on_qcbACLGroup_activated(const QString &text) {
  795     ChanACL *as = currentACL();
  796     if (! as || as->bInherited)
  797         return;
  798 
  799     as->iUserId = -1;
  800 
  801     if (text.isEmpty()) {
  802         qcbACLGroup->setCurrentIndex(1);
  803         as->qsGroup = QLatin1String("all");
  804     } else {
  805         qcbACLUser->clearEditText();
  806         as->qsGroup = text;
  807     }
  808     refillACL();
  809 }
  810 
  811 void ACLEditor::on_qcbACLUser_activated() {
  812     QString text = qcbACLUser->currentText();
  813 
  814     ChanACL *as = currentACL();
  815     if (! as || as->bInherited)
  816         return;
  817 
  818     if (text.isEmpty()) {
  819         as->iUserId = -1;
  820         if (qcbACLGroup->currentIndex() == 0) {
  821             qcbACLGroup->setCurrentIndex(1);
  822             as->qsGroup = QLatin1String("all");
  823         }
  824         refillACL();
  825     } else {
  826         qcbACLGroup->setCurrentIndex(0);
  827         as->iUserId = id(text);
  828         refillACL();
  829     }
  830 }
  831 
  832 void ACLEditor::ACLPermissions_clicked() {
  833     QCheckBox *source = qobject_cast<QCheckBox *>(sender());
  834 
  835     ChanACL *as = currentACL();
  836     if (! as || as->bInherited)
  837         return;
  838 
  839     int allowed = 0;
  840     int denied = 0;
  841 
  842     bool enabled = true;
  843     for (int idx = 0; idx < qlACLAllow.count(); idx++) {
  844         ChanACL::Perm p = qlPerms[idx];
  845         if (qlACLAllow[idx]->isChecked() && qlACLDeny[idx]->isChecked()) {
  846             if (source == qlACLAllow[idx])
  847                 qlACLDeny[idx]->setChecked(false);
  848             else
  849                 qlACLAllow[idx]->setChecked(false);
  850         }
  851 
  852         qlACLAllow[idx]->setEnabled(enabled || p == ChanACL::Speak);
  853         qlACLDeny[idx]->setEnabled(enabled || p == ChanACL::Speak);
  854 
  855         if (p == ChanACL::Write && qlACLAllow[idx]->isChecked())
  856             enabled = false;
  857 
  858         if (qlACLAllow[idx]->isChecked())
  859             allowed |= p;
  860         if (qlACLDeny[idx]->isChecked())
  861             denied |= p;
  862     }
  863 
  864     as->pAllow = static_cast<ChanACL::Permissions>(allowed);
  865     as->pDeny = static_cast<ChanACL::Permissions>(denied);
  866 }
  867 
  868 void ACLEditor::on_qcbGroupList_activated(const QString &text) {
  869     ACLGroup *gs = currentGroup();
  870     if (text.isEmpty())
  871         return;
  872     if (! gs) {
  873         QString name = text.toLower();
  874         gs = new ACLGroup(name);
  875         gs->bInherited = false;
  876         gs->bInherit = true;
  877         gs->bInheritable = true;
  878         gs->qsName = name;
  879         qlGroups << gs;
  880     }
  881 
  882     refillGroupNames();
  883     refillGroupAdd();
  884     refillGroupRemove();
  885     refillGroupInherit();
  886     groupEnableCheck();
  887     qpbGroupAdd->setEnabled(false);
  888 }
  889 
  890 void ACLEditor::on_qcbGroupList_editTextChanged(const QString & text) {
  891     qpbGroupAdd->setEnabled(!text.isEmpty());
  892 }
  893 
  894 void ACLEditor::on_qpbGroupAdd_clicked() {
  895     on_qcbGroupList_activated(qcbGroupList->currentText());
  896 }
  897 
  898 void ACLEditor::on_qpbGroupRemove_clicked() {
  899     ACLGroup *gs = currentGroup();
  900     if (! gs)
  901         return;
  902 
  903     if (gs->bInherited) {
  904         gs->bInheritable = true;
  905         gs->bInherit = true;
  906         gs->qsAdd.clear();
  907         gs->qsRemove.clear();
  908     } else {
  909         qlGroups.removeAll(gs);
  910         delete gs;
  911     }
  912     refillGroupNames();
  913     refillGroupAdd();
  914     refillGroupRemove();
  915     refillGroupInherit();
  916     groupEnableCheck();
  917 }
  918 
  919 void ACLEditor::on_qcbGroupInherit_clicked(bool checked) {
  920     ACLGroup *gs = currentGroup();
  921     if (! gs)
  922         return;
  923 
  924     gs->bInherit = checked;
  925     groupEnableCheck();
  926 }
  927 
  928 void ACLEditor::on_qcbGroupInheritable_clicked(bool checked) {
  929     ACLGroup *gs = currentGroup();
  930     if (! gs)
  931         return;
  932 
  933     gs->bInheritable = checked;
  934 }
  935 
  936 void ACLEditor::on_qpbGroupAddAdd_clicked() {
  937     ACLGroup *gs = currentGroup();
  938     QString text = qcbGroupAdd->currentText();
  939 
  940     if (! gs)
  941         return;
  942 
  943     if (text.isEmpty())
  944         return;
  945 
  946     gs->qsAdd << id(text);
  947     refillGroupAdd();
  948     qcbGroupAdd->clearEditText();
  949 }
  950 
  951 void ACLEditor::on_qpbGroupAddRemove_clicked() {
  952     ACLGroup *gs = currentGroup();
  953     if (! gs)
  954         return;
  955 
  956     QListWidgetItem *item = qlwGroupAdd->currentItem();
  957     if (! item)
  958         return;
  959 
  960     gs->qsAdd.remove(item->data(Qt::UserRole).toInt());
  961     refillGroupAdd();
  962     qcbGroupRemove->clearEditText();
  963 }
  964 
  965 void ACLEditor::on_qpbGroupRemoveAdd_clicked() {
  966     QString text = qcbGroupRemove->currentText();
  967 
  968     ACLGroup *gs = currentGroup();
  969     if (! gs)
  970         return;
  971 
  972     if (text.isEmpty())
  973         return;
  974 
  975     gs->qsRemove << id(text);
  976     refillGroupRemove();
  977 }
  978 
  979 void ACLEditor::on_qpbGroupRemoveRemove_clicked() {
  980     ACLGroup *gs = currentGroup();
  981     if (! gs)
  982         return;
  983 
  984     QListWidgetItem *item = qlwGroupRemove->currentItem();
  985     if (! item)
  986         return;
  987 
  988     gs->qsRemove.remove(item->data(Qt::UserRole).toInt());
  989     refillGroupRemove();
  990 }
  991 
  992 void ACLEditor::on_qpbGroupInheritRemove_clicked() {
  993     ACLGroup *gs = currentGroup();
  994     if (! gs)
  995         return;
  996 
  997     QListWidgetItem *item = qlwGroupInherit->currentItem();
  998     if (! item)
  999         return;
 1000 
 1001     gs->qsRemove.insert(item->data(Qt::UserRole).toInt());
 1002     refillGroupRemove();
 1003 }