/*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate$
* $Revision$
* $LastChangedBy$
* $URL$
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Mangler is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mangler. If not, see .
*/
#include "mangler.h"
#include "mangleradmin.h"
#include "manglercharset.h"
#include "inilib.h"
#include
#include
#include
int natsort(const char *l, const char *r);
Glib::ustring
ManglerAdmin::trimString(Glib::ustring s) {/*{{{*/
if (s.empty()) {
return s;
}
while (s.length() && (s[0] == ' ' || s[0] == '\t')) {
s.erase(0, 1);
}
if (s.empty()) {
return s;
}
for (int i = s.length() - 1; i >= 0; --i) {
if (s[i] == '\n') {
continue;
}
if (s[i] != ' ' && s[i] != '\t') {
break;
}
s.erase(i, 1);
}
return s;
}/*}}}*/
ManglerAdmin::ManglerAdmin(Glib::RefPtr builder) {/*{{{*/
/* set up the basic window variables */
this->builder = builder;
Gtk::TreeModel::Row row;
Gtk::TreeView::Column *pColumn;
Gtk::CellRendererText *renderer;
builder->get_widget("adminWindow", adminWindow);
adminWindow->signal_show().connect(sigc::mem_fun(this, &ManglerAdmin::adminWindow_show_cb));
adminWindow->signal_hide().connect(sigc::mem_fun(this, &ManglerAdmin::adminWindow_hide_cb));
builder->get_widget("adminNotebook", adminNotebook);
builder->get_widget("CloseButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::CloseButton_clicked_cb));
builder->get_widget("ServerTab", ServerTab);
ServerTab->hide();
builder->get_widget("ChannelsTab", ChannelsTab);
builder->get_widget("UsersTab", UsersTab);
builder->get_widget("RanksTab", RanksTab);
builder->get_widget("BansTab", BansTab);
builder->get_widget("AdminStatusbar", AdminStatusbar);
AdminStatusbar->set_has_resize_grip(false);
StatusbarTime = ::time(NULL);
StatusbarCount = 0;
Glib::signal_timeout().connect_seconds(sigc::mem_fun(this, &ManglerAdmin::statusbarPop), 1);
/* set up the server settings editor stuff */
builder->get_widget("ServerChatFilter", combobox);
SrvChatFilterModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvChatFilterModel);
combobox->pack_start(adminRecord.name);
row = *(SrvChatFilterModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Global to Server";
row = *(SrvChatFilterModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Per Channel";
builder->get_widget("ServerChannelOrdering", combobox);
SrvChanOrderModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvChanOrderModel);
combobox->pack_start(adminRecord.name);
row = *(SrvChanOrderModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Sort Alphabetically";
row = *(SrvChanOrderModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Manual";
builder->get_widget("ServerAction", combobox);
SrvInactActionModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvInactActionModel);
combobox->pack_start(adminRecord.name);
row = *(SrvInactActionModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Kick User";
row = *(SrvInactActionModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Move to Channel";
builder->get_widget("ServerChannel", combobox);
SrvInactChannelModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvInactChannelModel);
combobox->pack_start(adminRecord.name);
renderer = (Gtk::CellRendererText*)(*(combobox->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
builder->get_widget("ServerSpamFilterChannelAction", combobox);
SrvSpamFilterChannelModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterChannelModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterChannelModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterChannelModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterChannelModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterChatAction", combobox);
SrvSpamFilterChatModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterChatModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterChatModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterChatModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterChatModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterCommentAction", combobox);
SrvSpamFilterCommentModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterCommentModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterCommentModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterCommentModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterCommentModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterTTSAction", combobox);
SrvSpamFilterTTSModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterTTSModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterTTSModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterTTSModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterTTSModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterWaveAction", combobox);
SrvSpamFilterWaveModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterWaveModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterWaveModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterWaveModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterWaveModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerUpdate", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ServerUpdate_clicked_cb));
/* set up the channel editor stuff */
builder->get_widget("ChannelEditorTree", ChannelEditorTree);
ChannelEditorTreeModel = adminChannelStore::create();
ChannelEditorTree->set_model(ChannelEditorTreeModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Channels") );
pColumn->pack_start(adminRecord.name);
pColumn->set_expand(true);
ChannelEditorTree->append_column(*pColumn);
ChannelEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelTree_cursor_changed_cb));
ChannelEditorTree->enable_model_drag_source();
ChannelEditorTree->enable_model_drag_dest();
builder->get_widget("ChannelEditor", ChannelEditor);
ChannelEditor->set_sensitive(false);
builder->get_widget("ChannelAdd", ChannelAdd);
ChannelAdd->set_sensitive(false);
ChannelAdd->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelAdd_clicked_cb));
builder->get_widget("ChannelRemove", ChannelRemove);
ChannelRemove->set_sensitive(false);
ChannelRemove->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelRemove_clicked_cb));
builder->get_widget("ChannelUpdate", ChannelUpdate);
ChannelUpdate->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelUpdate_clicked_cb));
currentChannelID = 0;
currentChannelParent = 0;
builder->get_widget("ChannelProtMode", combobox);
ChannelProtModel = Gtk::TreeStore::create(ChannelProtColumns);
combobox->set_model(ChannelProtModel);
combobox->pack_start(adminRecord.name);
row = *(ChannelProtModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Open to Public";
row = *(ChannelProtModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Channel Password";
row = *(ChannelProtModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "User Authorization";
combobox->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelProtMode_changed_cb));
builder->get_widget("ChannelVoiceMode", combobox);
ChannelVoiceModel = Gtk::TreeStore::create(ChannelVoiceColumns);
combobox->set_model(ChannelVoiceModel);
combobox->pack_start(adminRecord.name);
row = *(ChannelVoiceModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Normal";
row = *(ChannelVoiceModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Queued";
row = *(ChannelVoiceModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Muted";
combobox->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelVoiceMode_changed_cb));
builder->get_widget("ChannelCodec", combobox);
ChannelCodecModel = Gtk::TreeStore::create(ChannelCodecColumns);
combobox->set_model(ChannelCodecModel);
combobox->pack_start(adminRecord.name);
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "GSM";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Codec 1";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Codec 2";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 3; row[adminRecord.name] = "Speex";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 4; row[adminRecord.name] = "Server Default";
combobox->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::LoadCodecFormats));
builder->get_widget("ChannelFormat", combobox);
ChannelFormatModel = Gtk::TreeStore::create(ChannelCodecColumns);
combobox->set_model(ChannelFormatModel);
combobox->pack_start(adminRecord.name);
/* set up the user editor stuff */
UserEditorTreeModel = Gtk::TreeStore::create(UserEditorColumns);
builder->get_widget("UserEditorTree", UserEditorTree);
UserEditorTree->set_model(UserEditorTreeModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Users") );
pColumn->pack_start(adminRecord.name);
pColumn->set_expand(true);
UserEditorTree->append_column(*pColumn);
UserEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::UserTree_cursor_changed_cb));
UserChanAdminModel = Gtk::TreeStore::create(UserChanAdminColumns);
builder->get_widget("UserChanAdminTree", UserChanAdminTree);
UserChanAdminTree->set_model(UserChanAdminModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Channels") );
pColumn->pack_start(adminCheckRecord.name);
pColumn->set_expand(true);
UserChanAdminTree->append_column_editable("Select", adminCheckRecord.on);
UserChanAdminTree->append_column(*pColumn);
UserChanAuthModel = Gtk::TreeStore::create(UserChanAuthColumns);
builder->get_widget("UserChanAuthTree", UserChanAuthTree);
UserChanAuthTree->set_model(UserChanAuthModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Channels") );
pColumn->pack_start(adminCheckRecord.name);
pColumn->set_expand(true);
UserChanAuthTree->append_column_editable("Select", adminCheckRecord.on);
UserChanAuthTree->append_column(*pColumn);
builder->get_widget("UserInfoSection", UserInfoSection);
builder->get_widget("UserNetworkSection", UserNetworkSection);
builder->get_widget("UserTransmitSection", UserTransmitSection);
builder->get_widget("UserDisplaySection", UserDisplaySection);
builder->get_widget("UserAdminSection", UserAdminSection);
builder->get_widget("UserEditor", UserEditor);
builder->get_widget("UserOwner", combobox);
UserOwnerModel = Gtk::TreeStore::create(UserEditorColumns);
combobox->set_model(UserOwnerModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Owners") );
pColumn->pack_start(adminCheckRecord.name);
pColumn->set_expand(true);
combobox->pack_start(adminRecord.name);
builder->get_widget("UserRank", combobox);
UserRankModel = Gtk::TreeStore::create(UserRankColumns);
combobox->set_model(UserRankModel);
combobox->pack_start(adminRecord.name);
builder->get_widget("UserDuplicateIPs", combobox);
UserDuplicateIPsModel = Gtk::TreeStore::create(UserDuplicateIPsColumns);
combobox->set_model(UserDuplicateIPsModel);
combobox->pack_start(adminRecord.name);
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "No Limit";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Do Not Allow Duplicates";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "2";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 3; row[adminRecord.name] = "3";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 4; row[adminRecord.name] = "4";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 5; row[adminRecord.name] = "5";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 6; row[adminRecord.name] = "6";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 7; row[adminRecord.name] = "7";
builder->get_widget("UserDefaultChannel", combobox);
UserDefaultChannelModel = Gtk::TreeStore::create(UserDefaultChannelColumns);
combobox->set_model(UserDefaultChannelModel);
combobox->pack_start(adminRecord.name);
renderer = (Gtk::CellRendererText*)(*(combobox->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
builder->get_widget("UserAdd", UserAdd);
UserAdd->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserAdd_clicked_cb));
builder->get_widget("UserRemove", UserRemove);
UserRemove->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserRemove_clicked_cb));
builder->get_widget("UserUpdate", UserUpdate);
UserUpdate->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserUpdate_clicked_cb));
currentUserID = 0;
builder->get_widget("UserInfoButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserInfoButton_toggled_cb));
builder->get_widget("UserNetworkButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserNetworkButton_toggled_cb));
builder->get_widget("UserTransmitButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserTransmitButton_toggled_cb));
builder->get_widget("UserDisplayButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserDisplayButton_toggled_cb));
builder->get_widget("UserAdminButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserAdminButton_toggled_cb));
builder->get_widget("UserChanAdminButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserChanAdminButton_toggled_cb));
builder->get_widget("UserChanAuthButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserChanAuthButton_toggled_cb));
builder->get_widget("UserTemplate", UserTemplate);
UserTemplateModel = Gtk::TreeStore::create(UserTemplateColumns);
UserTemplate->set_model(UserTemplateModel);
UserTemplate->pack_start(adminRecord.name);
renderer = (Gtk::CellRendererText*)(*(UserTemplate->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
UserTemplate->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplate_changed_cb));
builder->get_widget("UserTemplateLoad", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplateLoad_clicked_cb));
builder->get_widget("UserTemplateDelete", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplateDelete_clicked_cb));
builder->get_widget("UserTemplateSave", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplateSave_clicked_cb));
/* set up the rank editor stuff */
RankEditorModel = Gtk::TreeStore::create(RankEditorColumns);
builder->get_widget("RankTree", RankEditorTree);
RankEditorTree->set_model(RankEditorModel);
RankEditorTree->append_column("Name", rankRecord.name);
RankEditorTree->append_column("Level", rankRecord.level);
RankEditorTree->append_column("Description", rankRecord.description);
RankEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::RankEditorTree_cursor_changed_cb));
builder->get_widget("RankEditor", RankEditor);
builder->get_widget("RankAdd", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::RankAdd_clicked_cb));
builder->get_widget("RankRemove", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::RankRemove_clicked_cb));
builder->get_widget("RankUpdate", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::RankUpdate_clicked_cb));
/* set up the ban editor stuff */
BanEditorModel = Gtk::TreeStore::create(BanEditorColumns);
builder->get_widget("BanTree", BanEditorTree);
BanEditorTree->set_model(BanEditorModel);
BanEditorTree->append_column("IP Address", banRecord.ip);
BanEditorTree->append_column("Netmask", banRecord.netmask);
BanEditorTree->append_column("User", banRecord.user);
BanEditorTree->append_column("Admin", banRecord.by);
BanEditorTree->append_column("Reason", banRecord.reason);
BanEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::BanEditorTree_cursor_changed_cb));
builder->get_widget("BanEditor", BanEditor);
builder->get_widget("BanNetmask", combobox);
BanNetmaskModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(BanNetmaskModel);
combobox->pack_start(adminRecord.name);
for (uint32_t ctr = 8; _v3_bitmasks[ctr] != NULL; ctr++) {
Gtk::TreeModel::iterator iter = BanNetmaskModel->append();
(*iter)[adminRecord.id] = ctr;
(*iter)[adminRecord.name] = c_to_ustring(_v3_bitmasks[ctr]);
combobox->set_active(iter);
BanNetmaskDefault = ctr;
}
builder->get_widget("BanAdd", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::BanAdd_clicked_cb));
builder->get_widget("BanRemove", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::BanRemove_clicked_cb));
builder->get_widget("BanUpdate", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::BanUpdate_clicked_cb));
/* set up the editor tabs */
clear();
tmpldialog = NULL;
isOpen = false;
}/*}}}*/
ManglerAdmin::~ManglerAdmin() {/*{{{*/
if (tmpldialog) {
delete tmpldialog;
}
}/*}}}*/
void
ManglerAdmin::show(void) {/*{{{*/
adminWindow->set_icon(mangler->icons["tray_icon"]);
adminWindow->present();
if (isOpen) {
permsUpdated(true);
}
}/*}}}*/
void
ManglerAdmin::hide(void) {/*{{{*/
adminWindow->hide();
}/*}}}*/
void
ManglerAdmin::permsUpdated(bool refresh) {/*{{{*/
const v3_permissions *perms = v3_get_permissions();
clearRankEditor();
setWidgetSensitive("RankAdd", RankEditorOpen && perms->edit_rank);
if (isOpen && !refresh) {
return;
}
if (mangler->isAdmin || perms->add_user || perms->del_user) {
UserAdd->set_sensitive(mangler->isAdmin || perms->add_user);
UsersTab->show();
} else {
UsersTab->hide();
}
if (perms->ban_user) {
BansTab->show();
} else {
BansTab->hide();
}
}/*}}}*/
void
ManglerAdmin::adminWindow_show_cb(void) {/*{{{*/
const v3_permissions *perms = v3_get_permissions();
permsUpdated();
if (perms->ban_user) {
v3_admin_ban_list();
}
if (mangler->isAdmin || perms->add_user || perms->del_user) {
UserEditorOpen = true;
v3_userlist_open();
}
if (perms->edit_rank) {
RankEditorOpen = true;
v3_ranklist_open();
}
if (mangler->isAdmin && SrvIsNotUpdating) {
SrvEditorOpen = true;
v3_serverprop_open();
}
loadUserTemplates();
ChannelEditorTree->expand_all();
UserChanAdminTree->expand_all();
UserChanAuthTree->expand_all();
Gtk::TreeModel::iterator iter = ChannelEditorTreeModel->children().begin();
if (iter) {
ChannelEditorTree->set_cursor(ChannelEditorTreeModel->get_path(iter));
}
isOpen = true;
}/*}}}*/
void
ManglerAdmin::adminWindow_hide_cb(void) {/*{{{*/
if (SrvEditorOpen && SrvIsNotUpdating) {
SrvEditorOpen = false;
v3_serverprop_close();
}
if (RankEditorOpen) {
RankEditorOpen = false;
v3_ranklist_close();
}
if (UserEditorOpen) {
UserEditorOpen = false;
v3_userlist_close();
}
ServerTab->hide();
clearUsers();
clearRankEditor();
clearBans();
isOpen = false;
}/*}}}*/
void
ManglerAdmin::queue_resize(Gtk::TreeView *treeview) {/*{{{*/
for (int ctr = 0, cnt = treeview->get_columns().size(); ctr < cnt; ctr++) {
treeview->get_column(ctr)->queue_resize();
}
}/*}}}*/
void
ManglerAdmin::statusbarPush(Glib::ustring msg) {/*{{{*/
AdminStatusbar->push(msg);
StatusbarCount++;
StatusbarTime = time(NULL);
}/*}}}*/
bool
ManglerAdmin::statusbarPop(void) {/*{{{*/
if (StatusbarTime + 3 > ::time(NULL)) return true;
while (StatusbarCount) {
AdminStatusbar->pop();
StatusbarCount--;
}
return true;
}/*}}}*/
void
ManglerAdmin::CloseButton_clicked_cb(void) {/*{{{*/
adminWindow->hide();
}/*}}}*/
void
ManglerAdmin::copyToEntry(const char *widgetName, Glib::ustring src) {/*{{{*/
builder->get_widget(widgetName, entry);
//if (src) entry->set_text(src);
//else entry->set_text("");
entry->set_text(src);
}/*}}}*/
void
ManglerAdmin::copyToSpinbutton(const char *widgetName, uint32_t src) {/*{{{*/
builder->get_widget(widgetName, spinbutton);
spinbutton->set_value(src);
}/*}}}*/
void
ManglerAdmin::copyToCheckbutton(const char *widgetName, bool src) {/*{{{*/
builder->get_widget(widgetName, checkbutton);
checkbutton->set_active(src);
}/*}}}*/
void
ManglerAdmin::copyToCombobox(const char *widgetName, uint32_t src, uint32_t deflt) {/*{{{*/
builder->get_widget(widgetName, combobox);
Glib::RefPtr mdl = combobox->get_model();
Gtk::TreeModel::Children children = mdl->children();
if (! children || ! children.size()) {
combobox->set_sensitive(false);
return;
} else combobox->set_sensitive(true);
Gtk::TreeModel::iterator iter = children.begin();
Gtk::TreeModel::iterator dIter = iter;
while (iter != children.end()) {
if ((*iter)[adminRecord.id] == deflt) dIter = iter;
if ((*iter)[adminRecord.id] == src) break;
iter++;
}
if (iter == children.end()) combobox->set_active(dIter);
else combobox->set_active(iter);
}/*}}}*/
Glib::ustring
ManglerAdmin::getFromEntry(const char *widgetName) {/*{{{*/
builder->get_widget(widgetName, entry);
return entry->get_text();
}/*}}}*/
uint32_t
ManglerAdmin::getFromSpinbutton(const char *widgetName) {/*{{{*/
builder->get_widget(widgetName, spinbutton);
return uint32_t( spinbutton->get_value() );
}/*}}}*/
bool
ManglerAdmin::getFromCheckbutton(const char *widgetName) {/*{{{*/
builder->get_widget(widgetName, checkbutton);
return checkbutton->get_active();
}/*}}}*/
uint32_t
ManglerAdmin::getFromCombobox(const char *widgetName, uint32_t deflt) {/*{{{*/
builder->get_widget(widgetName, combobox);
Gtk::TreeModel::iterator iter = combobox->get_active();
if (iter) return (*iter)[adminRecord.id];
else return deflt;
}/*}}}*/
void
ManglerAdmin::setWidgetSensitive(const char *widgetName, bool widgetSens) {/*{{{*/
Gtk::Widget *w;
builder->get_widget(widgetName, w);
w->set_sensitive(widgetSens);
}/*}}}*/
/* ---------- Server Settings Related Methods ---------- */
void
ManglerAdmin::ServerUpdate_clicked_cb(void) {/*{{{*/
v3_server_prop prop;
memset(&prop, 0, sizeof(v3_server_prop));
strncpy(prop.server_comment, ustring_to_c(getFromEntry("ServerComment")).c_str(), sizeof(prop.server_comment));
prop.chat_filter = getFromCombobox("ServerChatFilter");
prop.channel_order = getFromCombobox("ServerChannelOrdering");
prop.motd_always = getFromCheckbutton("ServerAlwaysDisplayMOTD");
// guest accounts
prop.max_guest = getFromSpinbutton("ServerMaxGuests");
prop.autokick_time = getFromSpinbutton("ServerKickGuests");
prop.autoban_time = getFromSpinbutton("ServerBanGuests");
// inactivity
prop.inactivity_timeout = getFromSpinbutton("ServerTimeout");
prop.inactivity_action = getFromCombobox("ServerAction");
prop.inactivity_channel = getFromCombobox("ServerChannel", 0);
// spam filters
prop.channel_spam_filter.action = getFromCombobox("ServerSpamFilterChannelAction");
prop.channel_spam_filter.interval = getFromSpinbutton("ServerSpamFilterChannelInterval");
prop.channel_spam_filter.times = getFromSpinbutton("ServerSpamFilterChannelTimes");
prop.chat_spam_filter.action = getFromCombobox("ServerSpamFilterChatAction");
prop.chat_spam_filter.interval = getFromSpinbutton("ServerSpamFilterChatInterval");
prop.chat_spam_filter.times = getFromSpinbutton("ServerSpamFilterChatTimes");
prop.comment_spam_filter.action = getFromCombobox("ServerSpamFilterCommentAction");
prop.comment_spam_filter.interval = getFromSpinbutton("ServerSpamFilterCommentInterval");
prop.comment_spam_filter.times = getFromSpinbutton("ServerSpamFilterCommentTimes");
prop.tts_spam_filter.action = getFromCombobox("ServerSpamFilterTTSAction");
prop.tts_spam_filter.interval = getFromSpinbutton("ServerSpamFilterTTSInterval");
prop.tts_spam_filter.times = getFromSpinbutton("ServerSpamFilterTTSTimes");
prop.wave_spam_filter.action = getFromCombobox("ServerSpamFilterWaveAction");
prop.wave_spam_filter.interval = getFromSpinbutton("ServerSpamFilterWaveInterval");
prop.wave_spam_filter.times = getFromSpinbutton("ServerSpamFilterWaveTimes");
// bind filters
prop.tts_bind_filter = getFromCheckbutton("ServerBindFilterTTS");
prop.wave_bind_filter = getFromCheckbutton("ServerBindFilterWave");
// remote status
prop.rem_srv_comment = getFromCheckbutton("ServerRemoteStatusServerComment");
prop.rem_chan_names = getFromCheckbutton("ServerRemoteStatusChannelNames");
prop.rem_chan_comments = getFromCheckbutton("ServerRemoteStatusChannelComments");
prop.rem_user_names = getFromCheckbutton("ServerRemoteStatusUserNames");
prop.rem_user_comments = getFromCheckbutton("ServerRemoteStatusUserComments");
prop.rem_show_login_names = getFromCheckbutton("ServerRemoteStatusUseless");
setWidgetSensitive("ServerVBox", false);
SrvIsNotUpdating = false;
v3_serverprop_update(&prop);
statusbarPush("Sending server properties...");
}/*}}}*/
void
ManglerAdmin::serverSettingsUpdated(v3_server_prop &prop) {/*{{{*/
copyToEntry("ServerComment", c_to_ustring(prop.server_comment));
copyToCombobox("ServerChatFilter", prop.chat_filter, 0);
copyToCombobox("ServerChannelOrdering", prop.channel_order, 0);
copyToCheckbutton("ServerAlwaysDisplayMOTD", prop.motd_always);
// guest accounts
copyToSpinbutton("ServerMaxGuests", prop.max_guest);
copyToSpinbutton("ServerKickGuests", prop.autokick_time);
copyToSpinbutton("ServerBanGuests", prop.autoban_time);
// inactivity
copyToSpinbutton("ServerTimeout", prop.inactivity_timeout);
copyToCombobox("ServerAction", prop.inactivity_action, 0);
copyToCombobox("ServerChannel", prop.inactivity_channel, 0);
// spam filters
copyToCombobox("ServerSpamFilterChannelAction", prop.channel_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterChannelInterval", prop.channel_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterChannelTimes", prop.channel_spam_filter.times);
copyToCombobox("ServerSpamFilterChatAction", prop.chat_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterChatInterval", prop.chat_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterChatTimes", prop.chat_spam_filter.times);
copyToCombobox("ServerSpamFilterCommentAction", prop.comment_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterCommentInterval", prop.comment_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterCommentTimes", prop.comment_spam_filter.times);
copyToCombobox("ServerSpamFilterTTSAction", prop.tts_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterTTSInterval", prop.tts_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterTTSTimes", prop.tts_spam_filter.times);
copyToCombobox("ServerSpamFilterWaveAction", prop.wave_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterWaveInterval", prop.wave_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterWaveTimes", prop.wave_spam_filter.times);
// bind filters
copyToCheckbutton("ServerBindFilterTTS", prop.tts_bind_filter);
copyToCheckbutton("ServerBindFilterWave", prop.wave_bind_filter);
// remote status
copyToCheckbutton("ServerRemoteStatusServerComment", prop.rem_srv_comment);
copyToCheckbutton("ServerRemoteStatusChannelNames", prop.rem_chan_names);
copyToCheckbutton("ServerRemoteStatusChannelComments", prop.rem_chan_comments);
copyToCheckbutton("ServerRemoteStatusUserNames", prop.rem_user_names);
copyToCheckbutton("ServerRemoteStatusUserComments", prop.rem_user_comments);
copyToCheckbutton("ServerRemoteStatusUseless", prop.rem_show_login_names);
setWidgetSensitive("ServerVBox", true);
SrvIsNotUpdating = true;
ServerTab->show();
}/*}}}*/
void
ManglerAdmin::serverSettingsSendDone(void) {/*{{{*/
statusbarPush("Sending server properties... done.");
v3_serverprop_close();
SrvIsNotUpdating = true;
if ((SrvEditorOpen = isOpen)) {
v3_serverprop_open();
} else {
setWidgetSensitive("ServerVBox", true);
}
}/*}}}*/
/* ---------- Channel Editor Related Methods ---------- */
Glib::RefPtr
adminChannelStore::create() {/*{{{*/
return Glib::RefPtr( new adminChannelStore() );
}/*}}}*/
bool
adminChannelStore::row_draggable_vfunc(const Gtk::TreeModel::Path& path) const {/*{{{*/
adminChannelStore* _this = const_cast(this);
const_iterator iter = _this->get_iter(path);
if (!iter) {
return Gtk::TreeStore::row_draggable_vfunc(path);
}
return (mangler->isAdmin && mangler->admin->channelSortManual && (*iter)[c.id] != 0);
}/*}}}*/
bool
adminChannelStore::row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) const {/*{{{*/
Gtk::TreeModel::Path sel;
Gtk::TreeModel::Path::get_from_selection_data(selection_data, sel);
return (sel.get_depth() == dest.get_depth());
}/*}}}*/
bool
adminChannelStore::drag_data_received_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) {/*{{{*/
Gtk::TreeModel::Path sel;
Gtk::TreeModel::Path::get_from_selection_data(selection_data, sel);
if (sel.get_depth() != dest.get_depth()) {
return false;
}
adminChannelStore* _this = const_cast(this);
const_iterator iter;
uint16_t src_id, dest_id;
if (!(iter = _this->get_iter(sel)) || !(src_id = (*iter)[c.id]) ||
!(iter = _this->get_iter(dest)) || !(dest_id = (*iter)[c.id]) || src_id == dest_id) {
return false;
}
v3_force_channel_move(src_id, dest_id);
return false;
}/*}}}*/
void
ManglerAdmin::ChannelTree_cursor_changed_cb() {/*{{{*/
Gtk::TreeModel::iterator iter = ChannelEditorTree->get_selection()->get_selected();
if (!iter) {
return;
}
Gtk::TreeModel::Row row = *iter;
currentChannelID = row[adminRecord.id];
if (currentChannelID) {
// load channel data into editor
v3_channel *channel;
if ((channel = v3_get_channel(currentChannelID))) {
populateChannelEditor(channel);
v3_free_channel(channel);
} else {
fprintf(stderr, "failed to retrieve channel information for channel id %d\n", currentChannelID);
populateChannelEditor(NULL);
currentChannelID = 0;
currentChannelParent = 0;
}
} else {
populateChannelEditor(NULL);
}
// get user permissions
//const v3_permissions *perms = v3_get_permissions();
// enable or disable editor and necessary buttons
bool editAccess( mangler->isAdmin || v3_is_channel_admin(currentChannelID) );
ChannelUpdate->set_sensitive(editAccess && currentChannelID);
ChannelEditor->set_sensitive(currentChannelID);
ChannelRemove->set_sensitive(editAccess && currentChannelID);
ChannelAdd->set_sensitive(editAccess);
}/*}}}*/
Gtk::TreeModel::Row
ManglerAdmin::getChannel(uint32_t id, Gtk::TreeModel::Children children, bool hasCheckbox) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
Gtk::TreeModel::Row row = *iter;
uint32_t rowId = hasCheckbox ? row[adminCheckRecord.id] : row[adminRecord.id];
if (rowId == id) {
return row;
}
if (row.children().size()) {
if (row = getChannel(id, row->children())) {
return row;
}
}
iter++;
}
return *iter;
}/*}}}*/
Glib::ustring
ManglerAdmin::getChannelPathString(uint32_t id, Gtk::TreeModel::Children children) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
Gtk::TreeModel::Row row = *iter;
uint32_t rowId = row[adminRecord.id];
if (rowId == id) {
return row[adminRecord.name];
}
if (row.children().size()) {
Glib::ustring retstr = getChannelPathString(id, row->children());
if (! retstr.empty()) {
if (rowId == 0) return retstr;
else return Glib::ustring::compose("%1 : %2", row[adminRecord.name], retstr);
}
}
iter++;
}
return "";
}/*}}}*/
void
ManglerAdmin::channelUpdated(v3_channel *channel) {/*{{{*/
/* channel editor tree */
Gtk::TreeModel::Row chanrow;
Gtk::TreeModel::iterator iter;
chanrow = getChannel(channel->id, ChannelEditorTreeModel->children());
if (chanrow) {
chanrow[adminRecord.id] = channel->id;
chanrow[adminRecord.name] = c_to_ustring(channel->name);
if (currentChannelID == channel->id) populateChannelEditor(channel);
}
queue_resize(ChannelEditorTree);
/* server inactive "move to" channel combo box */
Gtk::TreeModel::Children siChildren = SrvInactChannelModel->children();
bool found( false );
if (siChildren.size()) {
iter = siChildren.begin();
while (iter != siChildren.end()) {
if ((*iter)[adminRecord.id] == channel->id) {
found = true;
break;
}
iter++;
}
}
if (! found) iter = SrvInactChannelModel->append();
(*iter)[adminRecord.id] = channel->id;
(*iter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user default channel combo box */
Gtk::TreeModel::Children udChildren = UserDefaultChannelModel->children();
found = false;
if (udChildren.size()) {
iter = udChildren.begin();
while (iter != udChildren.end()) {
if ((*iter)[adminRecord.id] == channel->id) {
found = true;
break;
}
iter++;
}
}
if (! found) iter = UserDefaultChannelModel->append();
(*iter)[adminRecord.id] = channel->id;
(*iter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user channel admin tree */
chanrow = getChannel(channel->id, UserChanAdminModel->children(), true);
if (chanrow) {
chanrow[adminCheckRecord.id] = channel->id;
chanrow[adminCheckRecord.name] = c_to_ustring(channel->name);
}
queue_resize(UserChanAdminTree);
/* user channel auth tree */
chanrow = getChannel(channel->id, UserChanAuthModel->children(), true);
if (chanrow) {
if (channel->protect_mode == 2) {
chanrow[adminCheckRecord.id] = channel->id;
chanrow[adminCheckRecord.name] = c_to_ustring(channel->name);
} else UserChanAuthModel->erase(chanrow);
} else if (channel->protect_mode == 2) {
chanrow = *(UserChanAuthModel->append());
if (chanrow) {
chanrow[adminCheckRecord.id] = channel->id;
chanrow[adminCheckRecord.name] = c_to_ustring(channel->name);
}
}
queue_resize(UserChanAuthTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("Channel %1 (%2) updated.", Glib::ustring::format(channel->id), c_to_ustring(channel->name)));
}/*}}}*/
void
ManglerAdmin::channelRemoved(uint32_t chanid) {/*{{{*/
/* channel editor tree */
Gtk::TreeModel::Row chanrow;
Gtk::TreeModel::iterator iter;
chanrow = getChannel(chanid, ChannelEditorTreeModel->children());
if (chanrow) {
iter = ChannelEditorTree->get_selection()->get_selected();
if (iter && (*iter)[adminRecord.id] == chanrow[adminRecord.id]) {
populateChannelEditor(NULL);
currentChannelID = 0;
currentChannelParent = 0;
}
ChannelEditorTreeModel->erase(chanrow);
}
queue_resize(ChannelEditorTree);
/* server inactive "move to" channel combo box */
Gtk::TreeModel::Children siChildren = SrvInactChannelModel->children();
if (siChildren.size()) {
iter = siChildren.begin();
while (iter != siChildren.end()) {
if ((*iter)[adminRecord.id] == chanid) {
SrvInactChannelModel->erase(*iter);
break;
}
iter++;
}
}
/* user default channel combo box */
Gtk::TreeModel::Children udChildren = UserDefaultChannelModel->children();
if (udChildren.size()) {
iter = udChildren.begin();
while (iter != udChildren.end()) {
if ((*iter)[adminRecord.id] == chanid) {
UserDefaultChannelModel->erase(*iter);
break;
}
iter++;
}
}
/* user channel admin tree */
chanrow = getChannel(chanid, UserChanAdminModel->children());
if (chanrow) UserChanAdminModel->erase(chanrow);
queue_resize(UserChanAdminTree);
/* user channel auth tree */
chanrow = getChannel(chanid, UserChanAuthModel->children());
if (chanrow) UserChanAuthModel->erase(chanrow);
queue_resize(UserChanAuthTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("Channel %1 removed.", Glib::ustring::format(chanid)));
}/*}}}*/
void
ManglerAdmin::channelRemoved(v3_channel *channel) {/*{{{*/
channelRemoved(channel->id);
}/*}}}*/
void
ManglerAdmin::channelAdded(v3_channel *channel) {/*{{{*/
/* channel editor tree */
Gtk::TreeModel::Row parent;
Gtk::TreeModel::iterator channelIter;
Gtk::TreeModel::Row channelRow;
parent = getChannel(channel->parent, ChannelEditorTreeModel->children());
if (parent) {
channelIter = ChannelEditorTreeModel->append(parent.children());
} else {
channelIter = ChannelEditorTreeModel->append();
}
channelRow = *channelIter;
channelRow[adminRecord.id] = channel->id;
channelRow[adminRecord.name] = c_to_ustring(channel->name);
if (ChannelAdded) {
ChannelAdded = false;
if (currentChannelID == 0xffff && c_to_ustring(channel->name) == trimString(getFromEntry("ChannelName"))) {
if (parent) {
ChannelEditorTree->expand_row(ChannelEditorTreeModel->get_path(parent), false);
}
ChannelEditorTree->set_cursor(ChannelEditorTreeModel->get_path(channelIter));
}
}
queue_resize(ChannelEditorTree);
/* server inactive "move to" channel combo box */
channelIter = SrvInactChannelModel->append();
(*channelIter)[adminRecord.id] = channel->id;
(*channelIter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user default channel combo box */
channelIter = UserDefaultChannelModel->append();
(*channelIter)[adminRecord.id] = channel->id;
(*channelIter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user channel admin tree */
parent = getChannel(channel->parent, UserChanAdminModel->children(), true);
if (parent) {
channelIter = UserChanAdminModel->append(parent.children());
} else {
channelIter = UserChanAdminModel->append();
}
channelRow = *channelIter;
channelRow[adminCheckRecord.id] = channel->id;
channelRow[adminCheckRecord.name] = c_to_ustring(channel->name);
queue_resize(UserChanAdminTree);
/* user channel auth tree */
if (channel->protect_mode == 2) {
parent = getChannel(channel->parent, UserChanAuthModel->children(), true);
if (parent) {
channelIter = UserChanAuthModel->append(parent.children());
} else {
channelIter = UserChanAuthModel->append();
}
channelRow = *channelIter;
channelRow[adminCheckRecord.id] = channel->id;
channelRow[adminCheckRecord.name] = c_to_ustring(channel->name);
}
queue_resize(UserChanAuthTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("Channel %1 (%2) added.", Glib::ustring::format(channel->id), c_to_ustring(channel->name)));
}/*}}}*/
void
ManglerAdmin::populateChannelEditor(const v3_channel *channel) {/*{{{*/
v3_channel c;
::memset(&c, 0, sizeof(v3_channel));
c.channel_codec = 0xffff;
if (channel) {
::memcpy(&c, channel, sizeof(v3_channel));
currentChannelID = c.id;
currentChannelParent = c.parent;
} else {
ChannelUpdate->set_sensitive(false);
ChannelEditor->set_sensitive(false);
ChannelRemove->set_sensitive(false);
}
//fprintf(stderr, "Populate: channel %lu, parent %lu\n", currentChannelID, currentChannelParent);
copyToEntry("ChannelName", c_to_ustring(c.name));
copyToEntry("ChannelPhonetic", c_to_ustring(c.phonetic));
copyToEntry("ChannelComment", c_to_ustring(c.comment));
copyToEntry("ChannelPassword", (c.password_protected) ? " " : "");
copyToCombobox("ChannelProtMode", c.protect_mode, 0);
copyToCombobox("ChannelVoiceMode", c.voice_mode, 0);
copyToCheckbutton("AllowRecording", c.allow_recording);
copyToCheckbutton("AllowCCxmit", c.allow_cross_channel_transmit);
copyToCheckbutton("AllowPaging", c.allow_paging);
copyToCheckbutton("AllowWaveBinds", c.allow_wave_file_binds);
copyToCheckbutton("AllowTTSBinds", c.allow_tts_binds);
copyToCheckbutton("AllowU2Uxmit", c.allow_u2u_transmit);
copyToCheckbutton("AllowPhantoms", c.allow_phantoms);
copyToCheckbutton("AllowGuests", c.allow_guests);
copyToCheckbutton("AllowVoiceTargets", c.allow_voice_target);
copyToCheckbutton("AllowCommandTargets", c.allow_command_target);
copyToCheckbutton("TimerExempt", c.inactive_exempt);
copyToCheckbutton("MuteGuests", c.disable_guest_transmit);
copyToCheckbutton("DisableSoundEvents", c.disable_sound_events);
if (v3_is_licensed()) {
copyToCombobox("ChannelCodec" , c.channel_codec, 4);
if (c.channel_codec != 0xffff) {
copyToCombobox("ChannelFormat", c.channel_format);
}
setWidgetSensitive("ChannelCodecLabel", true);
setWidgetSensitive("ChannelCodec", true);
setWidgetSensitive("ChannelFormatLabel", true);
setWidgetSensitive("ChannelFormat", true);
setWidgetSensitive("AllowVoiceTargets", true);
setWidgetSensitive("AllowCommandTargets", true);
} else {
copyToCombobox("ChannelCodec" , 4);
setWidgetSensitive("ChannelCodecLabel", false);
setWidgetSensitive("ChannelCodec", false);
setWidgetSensitive("ChannelFormatLabel", false);
setWidgetSensitive("ChannelFormat", false);
setWidgetSensitive("AllowVoiceTargets", false);
setWidgetSensitive("AllowCommandTargets", false);
}
builder->get_widget("ChannelEditorLabel", label);
label->set_text("Editing: " + ((channel) ? c_to_ustring(c.name) : "NONE"));
//LoadCodecFormats();
}/*}}}*/
void
ManglerAdmin::ChannelAdd_clicked_cb(void) {/*{{{*/
ChannelEditorTree->get_selection()->unselect_all();
populateChannelEditor(NULL);
copyToCheckbutton("AllowRecording", true);
copyToCheckbutton("AllowCCxmit", true);
copyToCheckbutton("AllowPaging", true);
copyToCheckbutton("AllowWaveBinds", true);
copyToCheckbutton("AllowTTSBinds", true);
copyToCheckbutton("AllowU2Uxmit", true);
copyToCheckbutton("AllowPhantoms", true);
copyToCheckbutton("AllowGuests", true);
bool isLicensed( v3_is_licensed() );
copyToCheckbutton("AllowVoiceTargets", isLicensed);
copyToCheckbutton("AllowCommandTargets", isLicensed);
builder->get_widget("ChannelEditorLabel", label);
label->set_text("Editing: NEW CHANNEL");
currentChannelParent = currentChannelID;
currentChannelID = 0xffff;
//fprintf(stderr, "Add: channel %lu, parent %lu\n", currentChannelID, currentChannelParent);
ChannelAdd->set_sensitive(false);
ChannelRemove->set_sensitive(false);
ChannelEditor->set_sensitive(true);
ChannelUpdate->set_sensitive(true);
}/*}}}*/
void
ManglerAdmin::ChannelRemove_clicked_cb(void) {/*{{{*/
v3_channel *channel = v3_get_channel(currentChannelID);
if (!channel) return;
Gtk::MessageDialog confirmDlg( Glib::ustring::compose("Are you sure you want to remove channel %1 (%2)?", Glib::ustring::format(channel->id), c_to_ustring(channel->name)), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true );
v3_free_channel(channel);
if (confirmDlg.run() == Gtk::RESPONSE_YES) {
v3_channel_remove(currentChannelID);
}
}/*}}}*/
void
ManglerAdmin::ChannelUpdate_clicked_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
v3_channel channel;
Glib::ustring password;
::memset(&channel, 0, sizeof(v3_channel));
if (currentChannelID == 0xffff) {
// New Record
channel.id = 0;
ChannelAdded = true;
} else {
channel.id = currentChannelID;
}
channel.parent = currentChannelParent;
//fprintf(stderr, "Update: channel %lu, parent %lu\n", channel.id, channel.parent);
channel.name = ::strdup(ustring_to_c(getFromEntry("ChannelName")).c_str());
channel.phonetic = ::strdup(ustring_to_c(getFromEntry("ChannelPhonetic")).c_str());
channel.comment = ::strdup(ustring_to_c(getFromEntry("ChannelComment")).c_str());
password = trimString(getFromEntry("ChannelPassword"));
if (password.length()) channel.password_protected = 1;
channel.protect_mode = getFromCombobox("ChannelProtMode", 0);
channel.voice_mode = getFromCombobox("ChannelVoiceMode", 0);
channel.allow_recording = getFromCheckbutton("AllowRecording") ? 1 : 0;
channel.allow_cross_channel_transmit = getFromCheckbutton("AllowCCxmit") ? 1 : 0;
channel.allow_paging = getFromCheckbutton("AllowPaging") ? 1 : 0;
channel.allow_wave_file_binds = getFromCheckbutton("AllowWaveBinds") ? 1 : 0;
channel.allow_tts_binds = getFromCheckbutton("AllowTTSBinds") ? 1 : 0;
channel.allow_u2u_transmit = getFromCheckbutton("AllowU2Uxmit") ? 1 : 0;
channel.allow_phantoms = getFromCheckbutton("AllowPhantoms") ? 1 : 0;
channel.allow_guests = getFromCheckbutton("AllowGuests") ? 1 : 0;
channel.allow_voice_target = getFromCheckbutton("AllowVoiceTargets") ? 1 : 0;
channel.allow_command_target = getFromCheckbutton("AllowCommandTargets") ? 1 : 0;
channel.inactive_exempt = getFromCheckbutton("TimerExempt") ? 1 : 0;
channel.disable_guest_transmit = getFromCheckbutton("MuteGuests") ? 1 : 0;
channel.disable_sound_events = getFromCheckbutton("DisableSoundEvents") ? 1 : 0;
if (v3_is_licensed()) {
channel.channel_codec = getFromCombobox("ChannelCodec", 4);
if (channel.channel_codec < 4) {
channel.channel_format = getFromCombobox("ChannelFormat", 0);
} else {
channel.channel_codec = 0xffff;
channel.channel_format = 0xffff;
}
} else {
channel.channel_codec = 0xffff;
channel.channel_format = 0xffff;
}
//fprintf(stderr, "Updating:\nname: %s\nphonetic: %s\ncomment: %s\npassword: %s\n",
// channel.name, channel.phonetic, channel.comment, password.c_str());
v3_channel_update(&channel, ustring_to_c(password).c_str());
::free(channel.name);
::free(channel.phonetic);
::free(channel.comment);
}/*}}}*/
void
ManglerAdmin::channelSort(bool manual) {/*{{{*/
channelSortManual = manual;
if (!manual) {
ChannelEditorTreeModel->set_sort_func(0, sigc::mem_fun(*this, &ManglerAdmin::channelSortFunction));
ChannelEditorTreeModel->set_sort_column(adminRecord.name, Gtk::SORT_ASCENDING);
} else {
ChannelEditorTreeModel->set_sort_func(adminRecord.id, sigc::mem_fun(*this, &ManglerAdmin::channelSortFunction));
ChannelEditorTreeModel->set_sort_column(adminRecord.id, Gtk::SORT_ASCENDING);
}
}/*}}}*/
void
ManglerAdmin::channelResort(void) {/*{{{*/
channelSort(channelSortManual);
}/*}}}*/
int
ManglerAdmin::channelSortFunction(const Gtk::TreeModel::iterator &left, const Gtk::TreeModel::iterator &right) {/*{{{*/
if (!channelSortManual) {
Glib::ustring leftstr = (*left)[adminRecord.name];
Glib::ustring rightstr = (*right)[adminRecord.name];
return natsort(leftstr.c_str(), rightstr.c_str());
} else {
return v3_get_channel_sort((*left)[adminRecord.id], (*right)[adminRecord.id]);
}
}/*}}}*/
void
ManglerAdmin::clearChannels(void) {/*{{{*/
ChannelAdded = false;
ChannelEditorTreeModel->clear();
queue_resize(ChannelEditorTree);
Gtk::TreeModel::Row lobby = *(ChannelEditorTreeModel->append());
lobby[adminRecord.id] = 0;
lobby[adminRecord.name] = "(Lobby)";
currentChannelID = 0;
currentChannelParent = 0;
ChannelUpdate->set_sensitive(false);
ChannelEditor->set_sensitive(false);
ChannelRemove->set_sensitive(false);
ChannelAdd->set_sensitive(false);
SrvInactChannelModel->clear();
lobby = *(SrvInactChannelModel->append());
lobby[adminRecord.id] = 0;
lobby[adminRecord.name] = "(Lobby)";
UserDefaultChannelModel->clear();
lobby = *(UserDefaultChannelModel->append());
lobby[adminRecord.id] = 0;
lobby[adminRecord.name] = "(Lobby)";
UserChanAdminModel->clear();
queue_resize(UserChanAdminTree);
UserChanAuthModel->clear();
queue_resize(UserChanAuthTree);
}/*}}}*/
void
ManglerAdmin::LoadCodecFormats(void) {/*{{{*/
builder->get_widget("ChannelCodec", combobox);
uint16_t c = 4;
Gtk::TreeModel::iterator iter = combobox->get_active();
if (iter) c = (*iter)[adminRecord.id];
builder->get_widget("ChannelFormat", combobox);
combobox->set_sensitive(c < 4);
uint16_t f = 0;
const v3_codec *codec;
Gtk::TreeModel::Row row;
ChannelFormatModel->clear();
while ((codec = v3_get_codec(c, f)) && codec->codec != (uint8_t)-1) {
row = *(ChannelFormatModel->append());
row[adminRecord.id] = f;
row[adminRecord.name] = codec->name;
f++;
}
if (c < 4 && ! combobox->get_active()) {
combobox->set_active(0);
} else {
combobox->set_active(-1);
}
}/*}}}*/
void
ManglerAdmin::ChannelProtMode_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
builder->get_widget("ChannelProtMode", combobox);
iter = combobox->get_active();
bool isPassword( iter && (*iter)[adminRecord.id] == 1);
builder->get_widget("ChannelPassword", entry);
entry->set_sensitive(isPassword);
}/*}}}*/
void
ManglerAdmin::ChannelVoiceMode_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
builder->get_widget("ChannelVoiceMode", combobox);
iter = combobox->get_active();
bool notNormal( iter && (*iter)[adminRecord.id] );
builder->get_widget("TransmitRank", spinbutton);
spinbutton->set_sensitive(notNormal);
}/*}}}*/
/* ---------- User Editor Related Methods ---------- */
Gtk::TreeModel::Row
ManglerAdmin::getAccount(uint32_t id, Gtk::TreeModel::Children children) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
if ((*iter)[adminRecord.id] == id) break;
iter++;
}
return *iter;
}/*}}}*/
void
ManglerAdmin::accountUpdated(v3_account *account) {/*{{{*/
/* main user list */
Gtk::TreeModel::Row acct;
acct = getAccount(account->perms.account_id, UserEditorTreeModel->children());
if (! acct) return;
acct[adminRecord.name] = c_to_ustring(account->username);
/* User Owner combo box */
acct = getAccount(account->perms.account_id, UserOwnerModel->children());
if (acct) {
if (account->perms.srv_admin || account->perms.add_user) {
/* update name in owner list */
acct[adminRecord.name] = c_to_ustring(account->username);
} else {
/* needs to be removed, no longer an admin */
UserOwnerModel->erase(acct);
}
} else if (account->perms.srv_admin || account->perms.add_user) {
/* needs to be added to owner list */
acct = *(UserOwnerModel->append());
acct[adminRecord.id] = account->perms.account_id;
acct[adminRecord.name] = c_to_ustring(account->username);
}
if (account->perms.account_id == currentUserID) populateUserEditor(account);
queue_resize(UserEditorTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("User %1 (%2) updated.", Glib::ustring::format(account->perms.account_id), c_to_ustring(account->username)));
}/*}}}*/
void
ManglerAdmin::accountAdded(v3_account *account) {/*{{{*/
/* main user list */
Gtk::TreeModel::iterator iter;
Gtk::TreeModel::Row acct;
iter = UserEditorTreeModel->append();
acct = *iter;
acct[adminRecord.id] = account->perms.account_id;
acct[adminRecord.name] = c_to_ustring(account->username);
/* User Owner combo box */
if (account->perms.srv_admin || account->perms.add_user) {
/* needs to be added to owner list */
acct = *(UserOwnerModel->append());
acct[adminRecord.id] = account->perms.account_id;
acct[adminRecord.name] = c_to_ustring(account->username);
}
if (currentUserID == 0xffff && c_to_ustring(account->username) == trimString(getFromEntry("UserLogin"))) {
UserEditorTree->set_cursor(UserEditorTreeModel->get_path(iter));
}
queue_resize(UserEditorTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("User %1 (%2) added.", Glib::ustring::format(account->perms.account_id), c_to_ustring(account->username)));
}/*}}}*/
void
ManglerAdmin::accountRemoved(uint32_t acctid) {/*{{{*/
/* main user list */
Gtk::TreeModel::Row acct;
Gtk::TreeModel::iterator iter;
acct = getAccount(acctid, UserEditorTreeModel->children());
if (acct) {
iter = UserEditorTree->get_selection()->get_selected();
if (iter && (*iter)[adminRecord.id] == acct[adminRecord.id]) {
populateUserEditor(NULL);
currentUserID = 0;
}
UserEditorTreeModel->erase(acct);
}
queue_resize(UserEditorTree);
/* User Owner combo box */
acct = getAccount(acctid, UserOwnerModel->children());
if (acct) UserOwnerModel->erase(acct);
/* update status bar */
statusbarPush(Glib::ustring::compose("User %1 removed.", Glib::ustring::format(acctid)));
}/*}}}*/
void
ManglerAdmin::accountRemoved(v3_account *account) {/*{{{*/
if (account) accountRemoved(account->perms.account_id);
}/*}}}*/
void
ManglerAdmin::UserTree_cursor_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = UserEditorTree->get_selection()->get_selected();
if (!iter) {
return;
}
Gtk::TreeModel::Row row = *iter;
currentUserID = row[adminRecord.id];
if (currentUserID) {
// load user data into editor
v3_account *account;
if ((account = v3_get_account(currentUserID))) {
populateUserEditor(account);
v3_free_account(account);
} else {
fprintf(stderr, "failed to retrieve user information for account id %d\n", currentUserID);
populateUserEditor(NULL);
currentUserID = 0;
}
} else {
populateUserEditor(NULL);
}
// get user permissions
const v3_permissions *perms = v3_get_permissions();
// enable or disable editor and necessary buttons
bool editAccess( mangler->isAdmin );
UserUpdate->set_sensitive((editAccess || perms->add_user) && currentUserID);
UserEditor->set_sensitive(currentUserID);
UserRemove->set_sensitive((editAccess || perms->del_user) && currentUserID);
UserAdd->set_sensitive(editAccess || perms->add_user);
}/*}}}*/
void
ManglerAdmin::populateUserEditor(const v3_account *account, bool isTemplate) {/*{{{*/
v3_account a;
::memset(&a, 0, sizeof(v3_account));
bool isLicensed( v3_is_licensed() );
if (!isTemplate) {
if (account) {
::memcpy(&a, account, sizeof(v3_account));
setWidgetSensitive("UserLogin", false);
} else {
setWidgetSensitive("UserLogin", true);
UserUpdate->set_sensitive(false);
UserEditor->set_sensitive(false);
UserRemove->set_sensitive(false);
}
copyToEntry("UserLogin", c_to_ustring(a.username));
copyToEntry("UserPassword", (a.perms.account_id > 1) ? " " : "");
setWidgetSensitive("UserPassword", a.perms.account_id != 1);
copyToCombobox("UserRank", a.perms.rank_id, 0);
copyToCombobox("UserOwner", 0);
Glib::ustring ownerName = c_to_ustring(a.owner);
if (ownerName.length()) {
Gtk::TreeModel::iterator iter = UserOwnerModel->children().begin();
while (iter != UserOwnerModel->children().end()) {
if ((*iter)[adminRecord.name] == ownerName) {
copyToCombobox("UserOwner", (*iter)[adminRecord.id], 0);
break;
}
iter++;
}
}
Gtk::TextView *textview;
builder->get_widget("UserNotes", textview);
textview->get_buffer()->set_text(c_to_ustring(a.notes));
} else if (account) {
::memcpy(&a, account, sizeof(v3_account));
}
copyToCheckbutton("UserLocked", a.perms.lock_acct);
copyToEntry("UserLockedReason", c_to_ustring(a.lock_reason));
copyToCheckbutton("UserInReservedList", a.perms.in_reserve_list);
copyToCheckbutton("UserReceiveBroadcasts", a.perms.recv_bcast);
copyToCheckbutton("UserAddPhantoms", a.perms.add_phantom);
copyToCheckbutton("UserAllowRecord", a.perms.record);
copyToCheckbutton("UserIgnoreTimers", a.perms.inactive_exempt);
copyToCheckbutton("UserSendComplaints", a.perms.send_complaint);
copyToCheckbutton("UserReceiveComplaints", a.perms.recv_complaint);
copyToCombobox("UserDuplicateIPs", a.perms.dupe_ip, 0);
copyToCheckbutton("UserSwitchChannels", a.perms.switch_chan);
copyToCombobox("UserDefaultChannel", a.perms.dfl_chan);
copyToCheckbutton("UserBroadcast", a.perms.bcast);
copyToCheckbutton("UserBroadcastLobby", a.perms.bcast_lobby);
copyToCheckbutton("UserBroadcastU2U", a.perms.bcast_user);
copyToCheckbutton("UserBroadcastxChan", a.perms.bcast_x_chan);
copyToCheckbutton("UserSendTTSBinds", a.perms.send_tts_bind);
copyToCheckbutton("UserSendWaveBinds", a.perms.send_wav_bind);
copyToCheckbutton("UserSendPages", a.perms.send_page);
copyToCheckbutton("UserSetPhonetic", a.perms.set_phon_name);
copyToCheckbutton("UserSendComment", a.perms.send_comment);
copyToCheckbutton("UserGenCommentSounds", a.perms.gen_comment_snds);
copyToCheckbutton("UserEventSounds", a.perms.event_snds);
copyToCheckbutton("UserMuteGlobally", a.perms.mute_glbl);
copyToCheckbutton("UserMuteOthers", a.perms.mute_other);
copyToCheckbutton("UserGlobalChat", a.perms.glbl_chat);
copyToCheckbutton("UserPrivateChat", a.perms.start_priv_chat);
setWidgetSensitive("UserPrivateChat", isLicensed);
copyToCheckbutton("UserEqOut", a.perms.eq_out);
copyToCheckbutton("UserSeeGuests", a.perms.see_guest);
copyToCheckbutton("UserSeeNonGuests", a.perms.see_nonguest);
copyToCheckbutton("UserSeeMOTD", a.perms.see_motd);
copyToCheckbutton("UserSeeServerComment", a.perms.see_srv_comment);
copyToCheckbutton("UserSeeChannelList", a.perms.see_chan_list);
copyToCheckbutton("UserSeeChannelComments", a.perms.see_chan_comment);
copyToCheckbutton("UserSeeUserComments", a.perms.see_user_comment);
copyToCheckbutton("UserServerAdmin", a.perms.srv_admin);
copyToCheckbutton("UserRemoveUsers", a.perms.del_user);
copyToCheckbutton("UserAddUsers", a.perms.add_user);
copyToCheckbutton("UserBanUsers", a.perms.ban_user);
copyToCheckbutton("UserKickUsers", a.perms.kick_user);
copyToCheckbutton("UserMoveUsers", a.perms.move_user);
copyToCheckbutton("UserAssignChanAdmin", a.perms.assign_chan_admin);
copyToCheckbutton("UserAssignRank", a.perms.assign_rank);
copyToCheckbutton("UserEditRanks", a.perms.edit_rank);
copyToCheckbutton("UserEditMOTD", a.perms.edit_motd);
copyToCheckbutton("UserEditGuestMOTD", a.perms.edit_guest_motd);
copyToCheckbutton("UserIssueRcon", a.perms.issue_rcon_cmd);
copyToCheckbutton("UserEditVoiceTargets", a.perms.edit_voice_target);
setWidgetSensitive("UserEditVoiceTargets", isLicensed);
copyToCheckbutton("UserEditCommandTargets", a.perms.edit_command_target);
setWidgetSensitive("UserEditCommandTargets", isLicensed);
copyToCheckbutton("UserAssignReserved", a.perms.assign_reserved);
if (!isTemplate) {
setAdminCheckTree(UserChanAdminModel->children(), a.chan_admin, a.chan_admin_count);
setAdminCheckTree(UserChanAuthModel->children(), a.chan_auth, a.chan_auth_count);
builder->get_widget("UserEditorLabel", label);
label->set_text("Editing: " + ((account) ? c_to_ustring(a.username) : "NONE"));
}
}/*}}}*/
void
ManglerAdmin::setAdminCheckTree(Gtk::TreeModel::Children children, uint16_t *chanids, int chan_count) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
Gtk::TreeModel::Row row;
uint32_t rowId;
int i;
bool found;
while (iter != children.end()) {
row = *iter;
rowId = row[adminCheckRecord.id];
found = false;
for (i = 0; i < chan_count; ++i) {
if (chanids[i] == rowId) {
found = true;
break;
}
}
row[adminCheckRecord.on] = found;
if (row.children().size()) setAdminCheckTree(row->children(), chanids, chan_count);
iter++;
}
}/*}}}*/
void
ManglerAdmin::getAdminCheckTree(Gtk::TreeModel::Children children, std::vector &chanids) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
Gtk::TreeModel::Row row;
uint32_t rowId;
bool rowOn;
while (iter != children.end()) {
row = *iter;
rowId = row[adminCheckRecord.id];
rowOn = row[adminCheckRecord.on];
if (rowOn) chanids.push_back(rowId);
if (row.children().size()) getAdminCheckTree(row->children(), chanids);
iter++;
}
}/*}}}*/
void
ManglerAdmin::getAdminCheckTree(Gtk::TreeModel::Children children, uint16_t *&chanids, int &chan_count) {/*{{{*/
std::vector chanvec;
getAdminCheckTree(children, chanvec);
chan_count = chanvec.size();
if (chan_count) {
chanids = (uint16_t*)::malloc(sizeof(uint16_t) * chanvec.size());
if (chanids) {
for (int i = 0; i < chan_count; ++i) chanids[i] = chanvec[i];
} else chan_count = 0; // failed malloc
} else chanids = NULL;
}/*}}}*/
void
ManglerAdmin::UserAdd_clicked_cb(void) {/*{{{*/
UserEditorTree->get_selection()->unselect_all();
v3_account a;
memset(&a, 0, sizeof(v3_account));
a.perms.recv_bcast = true;
a.perms.add_phantom = true;
a.perms.record = true;
a.perms.send_complaint = true;
a.perms.switch_chan = true;
a.perms.bcast = true;
a.perms.bcast_lobby = true;
a.perms.bcast_user = true;
a.perms.bcast_x_chan = true;
a.perms.send_tts_bind = true;
a.perms.send_wav_bind = true;
a.perms.send_page = true;
a.perms.set_phon_name = true;
a.perms.send_comment = true;
a.perms.gen_comment_snds = true;
a.perms.event_snds = true;
a.perms.glbl_chat = true;
a.perms.start_priv_chat = true;
a.perms.see_guest = true;
a.perms.see_nonguest = true;
a.perms.see_motd = true;
a.perms.see_srv_comment = true;
a.perms.see_chan_list = true;
a.perms.see_chan_comment = true;
a.perms.see_user_comment = true;
populateUserEditor(NULL);
populateUserEditor(&a, true);
builder->get_widget("UserEditorLabel", label);
label->set_text("Editing: NEW USER");
currentUserID = 0xffff;
// enable or disable editor and necessary buttons
UserUpdate->set_sensitive(true);
UserEditor->set_sensitive(true);
UserRemove->set_sensitive(false);
UserAdd->set_sensitive(false);
}/*}}}*/
void
ManglerAdmin::UserRemove_clicked_cb(void) {/*{{{*/
v3_account *account = v3_get_account(currentUserID);
if (!account) return;
Gtk::MessageDialog confirmDlg( Glib::ustring::compose("Are you sure you want to remove user %1 (%2)?", Glib::ustring::format(account->perms.account_id), c_to_ustring(account->username)), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true );
v3_free_account(account);
if (confirmDlg.run() == Gtk::RESPONSE_YES) {
v3_userlist_remove(currentUserID);
}
}/*}}}*/
void
ManglerAdmin::UserUpdate_clicked_cb(void) {/*{{{*/
v3_account account;
::memset(&account, 0, sizeof(v3_account));
account.perms.account_id = (currentUserID == 0xffff) ? 0 : currentUserID;
account.username = ::strdup(ustring_to_c(getFromEntry("UserLogin")).c_str());
Glib::ustring password = trimString(getFromEntry("UserPassword"));
if (password.length()) {
_v3_hash_password((uint8_t *)ustring_to_c(password).c_str(), (uint8_t *)account.perms.hash_password);
}
account.perms.rank_id = getFromCombobox("UserRank", 0);
uint16_t ownerID = getFromCombobox("UserOwner", 0);
if (ownerID) {
Gtk::TreeModel::Row ownerRow = getAccount(ownerID, UserEditorTreeModel->children());
Glib::ustring ownerName = ownerRow[adminRecord.name];
account.owner = ::strdup(ustring_to_c(ownerName).c_str());
} else {
account.owner = ::strdup("");
}
Gtk::TextView *textview;
builder->get_widget("UserNotes", textview);
account.notes = ::strdup(ustring_to_c(textview->get_buffer()->get_text()).c_str());
account.perms.lock_acct = getFromCheckbutton("UserLocked");
account.lock_reason = ::strdup(ustring_to_c(getFromEntry("UserLockedReason")).c_str());
account.perms.in_reserve_list = getFromCheckbutton("UserInReservedList");
account.perms.recv_bcast = getFromCheckbutton("UserReceiveBroadcasts");
account.perms.add_phantom = getFromCheckbutton("UserAddPhantoms");
account.perms.record = getFromCheckbutton("UserAllowRecord");
account.perms.inactive_exempt = getFromCheckbutton("UserIgnoreTimers");
account.perms.send_complaint = getFromCheckbutton("UserSendComplaints");
account.perms.recv_complaint = getFromCheckbutton("UserReceiveComplaints");
account.perms.dupe_ip = getFromCombobox("UserDuplicateIPs", 0);
account.perms.switch_chan = getFromCheckbutton("UserSwitchChannels");
account.perms.dfl_chan = getFromCombobox("UserDefaultChannel");
account.perms.bcast = getFromCheckbutton("UserBroadcast");
account.perms.bcast_lobby = getFromCheckbutton("UserBroadcastLobby");
account.perms.bcast_user = getFromCheckbutton("UserBroadcastU2U");
account.perms.bcast_x_chan = getFromCheckbutton("UserBroadcastxChan");
account.perms.send_tts_bind = getFromCheckbutton("UserSendTTSBinds");
account.perms.send_wav_bind = getFromCheckbutton("UserSendWaveBinds");
account.perms.send_page = getFromCheckbutton("UserSendPages");
account.perms.set_phon_name = getFromCheckbutton("UserSetPhonetic");
account.perms.send_comment = getFromCheckbutton("UserSendComment");
account.perms.gen_comment_snds = getFromCheckbutton("UserGenCommentSounds");
account.perms.event_snds = getFromCheckbutton("UserEventSounds");
account.perms.mute_glbl = getFromCheckbutton("UserMuteGlobally");
account.perms.mute_other = getFromCheckbutton("UserMuteOthers");
account.perms.glbl_chat = getFromCheckbutton("UserGlobalChat");
account.perms.start_priv_chat = getFromCheckbutton("UserPrivateChat");
account.perms.eq_out = getFromCheckbutton("UserEqOut");
account.perms.see_guest = getFromCheckbutton("UserSeeGuests");
account.perms.see_nonguest = getFromCheckbutton("UserSeeNonGuests");
account.perms.see_motd = getFromCheckbutton("UserSeeMOTD");
account.perms.see_srv_comment = getFromCheckbutton("UserSeeServerComment");
account.perms.see_chan_list = getFromCheckbutton("UserSeeChannelList");
account.perms.see_chan_comment = getFromCheckbutton("UserSeeChannelComments");
account.perms.see_user_comment = getFromCheckbutton("UserSeeUserComments");
account.perms.srv_admin = getFromCheckbutton("UserServerAdmin");
account.perms.del_user = getFromCheckbutton("UserRemoveUsers");
account.perms.add_user = getFromCheckbutton("UserAddUsers");
account.perms.ban_user = getFromCheckbutton("UserBanUsers");
account.perms.kick_user = getFromCheckbutton("UserKickUsers");
account.perms.move_user = getFromCheckbutton("UserMoveUsers");
account.perms.assign_chan_admin = getFromCheckbutton("UserAssignChanAdmin");
account.perms.assign_rank = getFromCheckbutton("UserAssignRank");
account.perms.edit_rank = getFromCheckbutton("UserEditRanks");
account.perms.edit_motd = getFromCheckbutton("UserEditMOTD");
account.perms.edit_guest_motd = getFromCheckbutton("UserEditGuestMOTD");
account.perms.issue_rcon_cmd = getFromCheckbutton("UserIssueRcon");
account.perms.edit_voice_target = getFromCheckbutton("UserEditVoiceTargets");
account.perms.edit_command_target = getFromCheckbutton("UserEditCommandTargets");
account.perms.assign_reserved = getFromCheckbutton("UserAssignReserved");
getAdminCheckTree(UserChanAdminModel->children(), account.chan_admin, account.chan_admin_count);
getAdminCheckTree(UserChanAuthModel->children(), account.chan_auth, account.chan_auth_count);
v3_userlist_update(&account);
::free(account.username);
::free(account.owner);
::free(account.notes);
::free(account.lock_reason);
if (account.chan_admin_count) ::free(account.chan_admin);
if (account.chan_auth_count) ::free(account.chan_auth);
}/*}}}*/
void
ManglerAdmin::UserInfoButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserInfoButton", togglebutton);
builder->get_widget("UserInfoArrow", arrow);
if (togglebutton->get_active()) {
UserInfoSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserInfoSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserNetworkButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserNetworkButton", togglebutton);
builder->get_widget("UserNetworkArrow", arrow);
if (togglebutton->get_active()) {
UserNetworkSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserNetworkSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserTransmitButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserTransmitButton", togglebutton);
builder->get_widget("UserTransmitArrow", arrow);
if (togglebutton->get_active()) {
UserTransmitSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserTransmitSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserDisplayButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserDisplayButton", togglebutton);
builder->get_widget("UserDisplayArrow", arrow);
if (togglebutton->get_active()) {
UserDisplaySection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserDisplaySection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserAdminButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserAdminButton", togglebutton);
builder->get_widget("UserAdminArrow", arrow);
if (togglebutton->get_active()) {
UserAdminSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserAdminSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserChanAdminButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserChanAdminButton", togglebutton);
builder->get_widget("UserChanAdminArrow", arrow);
if (togglebutton->get_active()) {
UserChanAdminTree->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserChanAdminTree->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserChanAuthButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserChanAuthButton", togglebutton);
builder->get_widget("UserChanAuthArrow", arrow);
if (togglebutton->get_active()) {
UserChanAuthTree->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserChanAuthTree->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::clearUsers(void) {/*{{{*/
UserEditorTreeModel->clear();
queue_resize(UserEditorTree);
populateUserEditor(NULL);
currentUserID = 0;
UserUpdate->set_sensitive(false);
UserEditor->set_sensitive(false);
UserRemove->set_sensitive(false);
UserAdd->set_sensitive(false);
UserOwnerModel->clear();
Gtk::TreeModel::Row row = *(UserOwnerModel->append());
row[adminRecord.id] = 0;
row[adminRecord.name] = "(None)";
}/*}}}*/
/* user editor 'profile' methods */
void
ManglerAdmin::loadUserTemplates(void) {/*{{{*/
tmpldir = ManglerConfig::confdir() + "/templates";
UserTemplateModel->clear();
Gtk::TreeStore::Row row = *(UserTemplateModel->append());
row[adminRecord.id] = 0;
row[adminRecord.name] = "Default Admin";
row = *(UserTemplateModel->append());
row[adminRecord.id] = 1;
row[adminRecord.name] = "Default User";
row = *(UserTemplateModel->append());
row[adminRecord.id] = 2;
row[adminRecord.name] = "(None)";
UserTemplate->set_active(2);
DIR *testdir;
if ((testdir = opendir(tmpldir.c_str()))) {
closedir(testdir);
} else if (mkdir(tmpldir.c_str(), 0700)) {
tmpldir = "";
return;
}
Glib::Dir dir(tmpldir);
int ctr = 3;
for (Glib::DirIterator iter = dir.begin(); iter != dir.end(); iter++) {
row = *(UserTemplateModel->append());
row[adminRecord.id] = ctr++;
row[adminRecord.name] = *iter;
}
}/*}}}*/
void
ManglerAdmin::UserTemplate_changed_cb(void) {/*{{{*/
Gtk::TreeStore::iterator iter = UserTemplate->get_active();
setWidgetSensitive("UserTemplateDelete", tmpldir.length() && iter && (*iter)[adminRecord.id] > 2);
}/*}}}*/
void
ManglerAdmin::UserTemplateLoad_clicked_cb(void) {/*{{{*/
Gtk::TreeStore::iterator iter = UserTemplate->get_active();
if (!iter) {
return;
}
uint32_t id = (*iter)[adminRecord.id];
Glib::ustring name = (*iter)[adminRecord.name];
v3_account a;
memset(&a, 0, sizeof(v3_account));
if (id < 2) {
a.perms.recv_bcast = true;
a.perms.add_phantom = true;
a.perms.record = true;
a.perms.send_complaint = true;
a.perms.switch_chan = true;
a.perms.bcast = true;
a.perms.bcast_lobby = true;
a.perms.bcast_user = true;
a.perms.bcast_x_chan = true;
a.perms.send_tts_bind = true;
a.perms.send_wav_bind = true;
a.perms.send_page = true;
a.perms.set_phon_name = true;
a.perms.send_comment = true;
a.perms.gen_comment_snds = true;
a.perms.event_snds = true;
a.perms.glbl_chat = true;
a.perms.start_priv_chat = true;
a.perms.see_guest = true;
a.perms.see_nonguest = true;
a.perms.see_motd = true;
a.perms.see_srv_comment = true;
a.perms.see_chan_list = true;
a.perms.see_chan_comment = true;
a.perms.see_user_comment = true;
if (id == 0) {
a.perms.in_reserve_list = true;
a.perms.recv_complaint = true;
a.perms.add_user = true;
a.perms.del_user = true;
a.perms.ban_user = true;
a.perms.kick_user = true;
a.perms.move_user = true;
a.perms.assign_chan_admin = true;
}
} else if (id > 2 && tmpldir.length() && name.length()) {
iniFile tmplfile(tmpldir + "/" + name, true, false);
if (!tmplfile.contains("Profile")) {
statusbarPush("Error: No 'Profile' section found in template.");
return;
}
iniSection &tmpl(tmplfile["Profile"]);
a.perms.lock_acct = tmpl["Locked"].toBool();
a.perms.in_reserve_list = tmpl["Reserved"].toBool();
a.perms.recv_bcast = tmpl["RecvStreams"].toBool();
a.perms.add_phantom = tmpl["Phantoms"].toBool();
a.perms.record = tmpl["Record"].toBool();
a.perms.inactive_exempt = tmpl["IgnoreInactivity"].toBool();
a.perms.send_complaint = tmpl["SendComplaints"].toBool();
a.perms.recv_complaint = tmpl["RecvComplaints"].toBool();
a.perms.switch_chan = tmpl["SwitchChannels"].toBool();
a.lock_reason = ::strdup(ustring_to_c(tmpl["LockedReason"].toUString()).c_str());
a.perms.dfl_chan = v3_get_channel_id(ustring_to_c(tmpl["DefChan"].toUString()).c_str());
a.perms.dupe_ip = tmpl["DuplicateIPs"].toInt();
a.perms.bcast = tmpl["Broadcast"].toBool();
a.perms.bcast_lobby = tmpl["BroadcastLobby"].toBool();
a.perms.bcast_user = tmpl["BroadcastU2U"].toBool();
a.perms.bcast_x_chan = tmpl["BroadcastCrossChannel"].toBool();
a.perms.send_tts_bind = tmpl["SendTTS"].toBool();
a.perms.send_wav_bind = tmpl["SendWave"].toBool();
a.perms.send_page = tmpl["SendPages"].toBool();
a.perms.set_phon_name = tmpl["SetPhonetic"].toBool();
a.perms.send_comment = tmpl["SendComments"].toBool();
a.perms.gen_comment_snds = tmpl["CommentSounds"].toBool();
a.perms.event_snds = tmpl["EventSounds"].toBool();
a.perms.mute_glbl = tmpl["MuteGlobally"].toBool();
a.perms.mute_other = tmpl["MuteOthersPTT"].toBool();
a.perms.glbl_chat = tmpl["Chat"].toBool();
a.perms.start_priv_chat = tmpl["InitPrivateChat"].toBool();
a.perms.eq_out = tmpl["Equalizer"].toBool();
a.perms.see_guest = tmpl["SeeGuest"].toBool();
a.perms.see_nonguest = tmpl["SeeNonGuest"].toBool();
a.perms.see_motd = tmpl["SeeMotd"].toBool();
a.perms.see_srv_comment = tmpl["SeeServerComment"].toBool();
a.perms.see_chan_list = tmpl["SeeChannels"].toBool();
a.perms.see_chan_comment = tmpl["SeeChannelComments"].toBool();
a.perms.see_user_comment = tmpl["SeeUserComments"].toBool();
a.perms.srv_admin = tmpl["ServerAdmin"].toBool();
a.perms.add_user = tmpl["AddUsers"].toBool();
a.perms.del_user = tmpl["DeleteUsers"].toBool();
a.perms.ban_user = tmpl["BanUsers"].toBool();
a.perms.kick_user = tmpl["KickUsers"].toBool();
a.perms.move_user = tmpl["MoveUsers"].toBool();
a.perms.assign_chan_admin = tmpl["EditChanAdmins"].toBool();
a.perms.edit_rank = tmpl["EditRanks"].toBool();
a.perms.edit_motd = tmpl["EditMotd"].toBool();
a.perms.edit_guest_motd = tmpl["EditGuestMotd"].toBool();
a.perms.issue_rcon_cmd = tmpl["RCon"].toBool();
a.perms.edit_voice_target = tmpl["GroupEditVoice"].toBool();
a.perms.edit_command_target = tmpl["GroupEditCmd"].toBool();
a.perms.assign_rank = tmpl["RankAssign"].toBool();
a.perms.assign_reserved = tmpl["ReservedAssign"].toBool();
}
populateUserEditor(&a, true);
if (a.lock_reason) {
::free(a.lock_reason);
}
statusbarPush("Loaded '" + name + "' template.");
}/*}}}*/
void
ManglerAdmin::UserTemplateDelete_clicked_cb(void) {/*{{{*/
Gtk::TreeStore::iterator iter = UserTemplate->get_active();
if (!iter || tmpldir.empty()) {
return;
}
Glib::ustring name = (*iter)[adminRecord.name];
Gtk::MessageDialog confirm("Are you sure you want to delete \"" + name + "\"?",
true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
if (confirm.run() == Gtk::RESPONSE_YES) {
unlink(Glib::ustring(tmpldir + "/" + name).c_str());
loadUserTemplates();
}
}/*}}}*/
void
ManglerAdmin::UserTemplateSave_clicked_cb(void) {/*{{{*/
if (!tmpldialog) {
tmpldialog = new Gtk::FileChooserDialog("Save User Template", Gtk::FILE_CHOOSER_ACTION_SAVE);
tmpldialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
tmpldialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
tpl_filter.set_name("Ventrilo User Editor Profile (*.vuep, *.ini)");
tpl_filter.add_pattern("*.vuep");
tpl_filter.add_pattern("*.ini");
tmpldialog->add_filter(tpl_filter);
all_filter.set_name("All Files");
all_filter.add_pattern("*");
tmpldialog->add_filter(all_filter);
if (tmpldir.length()) {
tmpldialog->set_current_folder(tmpldir);
}
}
int result = tmpldialog->run();
tmpldialog->hide();
if (result != Gtk::RESPONSE_OK) {
return;
}
Glib::ustring filename = tmpldialog->get_filename();
if (tmpldialog->get_filter() == &tpl_filter) {
Glib::PatternSpec vuep("*.vuep"), ini("*.ini");
if (!vuep.match(filename) && !ini.match(filename)) {
filename.append(".vuep");
}
}
Glib::ustring name = filename.substr(tmpldialog->get_current_folder().length() + 1);
char *path = v3_get_channel_path(getFromCombobox("UserDefaultChannel", 0));
iniFile tmplfile(filename, false, false);
iniSection &tmpl(tmplfile["Profile"]);
tmpl["Locked"] = (int)getFromCheckbutton("UserLocked");
tmpl["Reserved"] = (int)getFromCheckbutton("UserInReservedList");
tmpl["RecvStreams"] = (int)getFromCheckbutton("UserReceiveBroadcasts");
tmpl["Phantoms"] = (int)getFromCheckbutton("UserAddPhantoms");
tmpl["Record"] = (int)getFromCheckbutton("UserAllowRecord");
tmpl["IgnoreInactivity"] = (int)getFromCheckbutton("UserIgnoreTimers");
tmpl["SendComplaints"] = (int)getFromCheckbutton("UserSendComplaints");
tmpl["RecvComplaints"] = (int)getFromCheckbutton("UserReceiveComplaints");
tmpl["SwitchChannels"] = (int)getFromCheckbutton("UserSwitchChannels");
tmpl["LockedReason"] = getFromEntry("UserLockedReason");
tmpl["DefChan"] = c_to_ustring(path);
tmpl["DuplicateIPs"] = (int)getFromCombobox("UserDuplicateIPs", 0);
tmpl["Broadcast"] = (int)getFromCheckbutton("UserBroadcast");
tmpl["BroadcastLobby"] = (int)getFromCheckbutton("UserBroadcastLobby");
tmpl["BroadcastU2U"] = (int)getFromCheckbutton("UserBroadcastU2U");
tmpl["BroadcastCrossChannel"] = (int)getFromCheckbutton("UserBroadcastxChan");
tmpl["SendTTS"] = (int)getFromCheckbutton("UserSendTTSBinds");
tmpl["SendWave"] = (int)getFromCheckbutton("UserSendWaveBinds");
tmpl["SendPages"] = (int)getFromCheckbutton("UserSendPages");
tmpl["SetPhonetic"] = (int)getFromCheckbutton("UserSetPhonetic");
tmpl["SendComments"] = (int)getFromCheckbutton("UserSendComment");
tmpl["CommentSounds"] = (int)getFromCheckbutton("UserGenCommentSounds");
tmpl["EventSounds"] = (int)getFromCheckbutton("UserEventSounds");
tmpl["MuteGlobally"] = (int)getFromCheckbutton("UserMuteGlobally");
tmpl["MuteOthersPTT"] = (int)getFromCheckbutton("UserMuteOthers");
tmpl["Chat"] = (int)getFromCheckbutton("UserGlobalChat");
tmpl["InitPrivateChat"] = (int)getFromCheckbutton("UserPrivateChat");
tmpl["Equalizer"] = (int)getFromCheckbutton("UserEqOut");
tmpl["SeeGuest"] = (int)getFromCheckbutton("UserSeeGuests");
tmpl["SeeNonGuest"] = (int)getFromCheckbutton("UserSeeNonGuests");
tmpl["SeeMotd"] = (int)getFromCheckbutton("UserSeeMOTD");
tmpl["SeeServerComment"] = (int)getFromCheckbutton("UserSeeServerComment");
tmpl["SeeChannels"] = (int)getFromCheckbutton("UserSeeChannelList");
tmpl["SeeChannelComments"] = (int)getFromCheckbutton("UserSeeChannelComments");
tmpl["SeeUserComments"] = (int)getFromCheckbutton("UserSeeUserComments");
tmpl["ServerAdmin"] = (int)getFromCheckbutton("UserServerAdmin");
tmpl["AddUsers"] = (int)getFromCheckbutton("UserAddUsers");
tmpl["DeleteUsers"] = (int)getFromCheckbutton("UserRemoveUsers");
tmpl["BanUsers"] = (int)getFromCheckbutton("UserBanUsers");
tmpl["KickUsers"] = (int)getFromCheckbutton("UserKickUsers");
tmpl["MoveUsers"] = (int)getFromCheckbutton("UserMoveUsers");
tmpl["EditChanAdmins"] = (int)getFromCheckbutton("UserAssignChanAdmin");
tmpl["EditRanks"] = (int)getFromCheckbutton("UserEditRanks");
tmpl["EditMotd"] = (int)getFromCheckbutton("UserEditMOTD");
tmpl["EditGuestMotd"] = (int)getFromCheckbutton("UserEditGuestMOTD");
tmpl["RCon"] = (int)getFromCheckbutton("UserIssueRcon");
tmpl["GroupEditVoice"] = (int)getFromCheckbutton("UserEditVoiceTargets");
tmpl["GroupEditCmd"] = (int)getFromCheckbutton("UserEditCommandTargets");
tmpl["RankAssign"] = (int)getFromCheckbutton("UserAssignRank");
tmpl["ReservedAssign"] = (int)getFromCheckbutton("UserAssignReserved");
tmplfile.save();
if (path) {
::free(path);
}
loadUserTemplates();
statusbarPush("Saved '" + name + "' template.");
}/*}}}*/
/* ---------- Rank Editor Related Methods ---------- */
Gtk::TreeModel::iterator
ManglerAdmin::getRank(uint16_t id, Gtk::TreeModel::Children children) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
if ((*iter)[rankRecord.id] == id) break;
iter++;
}
return iter;
}/*}}}*/
void
ManglerAdmin::rankUpdated(v3_rank *rank) {/*{{{*/
Gtk::TreeModel::iterator iter = getRank(rank->id, RankEditorModel->children());
if (! iter) iter = RankEditorModel->append();
(*iter)[rankRecord.id] = rank->id;
(*iter)[rankRecord.level] = rank->level;
(*iter)[rankRecord.name] = c_to_ustring(rank->name);
(*iter)[rankRecord.description] = c_to_ustring(rank->description);
queue_resize(RankEditorTree);
/* now handle the User Rank combo box */
/* the poorly named getAccount() will work fine for this */
Gtk::TreeModel::Row row = getAccount(rank->id, UserRankModel->children());
if (! row) row = *(UserRankModel->append());
row[adminRecord.id] = rank->id;
row[adminRecord.name] = c_to_ustring(rank->name);
/* update status bar */
statusbarPush(Glib::ustring::compose("Rank %1 (%2) updated.", Glib::ustring::format(rank->id), c_to_ustring(rank->name)));
}/*}}}*/
void
ManglerAdmin::rankAdded(v3_rank *rank) {/*{{{*/
Gtk::TreeModel::iterator iter = RankEditorModel->append();
(*iter)[rankRecord.id] = rank->id;
(*iter)[rankRecord.level] = rank->level;
(*iter)[rankRecord.name] = c_to_ustring(rank->name);
(*iter)[rankRecord.description] = rank->description;
if (currentRankID == 0xffff && c_to_ustring(rank->name) == trimString(getFromEntry("RankName"))) {
RankEditorTree->set_cursor(RankEditorModel->get_path(iter));
}
queue_resize(RankEditorTree);
/* now handle the User Rank combo box */
iter = UserRankModel->append();
(*iter)[adminRecord.id] = rank->id;
(*iter)[adminRecord.name] = c_to_ustring(rank->name);
/* update status bar */
statusbarPush(Glib::ustring::compose("Rank %1 (%2) added.", Glib::ustring::format(rank->id), c_to_ustring(rank->name)));
}/*}}}*/
void
ManglerAdmin::rankRemoved(uint16_t rankid) {/*{{{*/
Gtk::TreeModel::iterator iter = getRank(rankid, RankEditorModel->children());
if (iter) {
Gtk::TreeModel::Row rank = *iter;
iter = RankEditorTree->get_selection()->get_selected();
if (iter && (*iter)[rankRecord.id] == rank[rankRecord.id]) {
clearRankEditor();
}
RankEditorModel->erase(rank);
}
queue_resize(RankEditorTree);
/* now handle the User Rank combo box */
/* the poorly named getAccount() will work fine for this */
Gtk::TreeModel::Row row = getAccount(rankid, UserRankModel->children());
if (row) UserRankModel->erase(row);
/* update status bar */
statusbarPush(Glib::ustring::compose("Rank %1 removed.", Glib::ustring::format(rankid)));
}/*}}}*/
void
ManglerAdmin::rankRemoved(v3_rank *rank) {/*{{{*/
rankRemoved(rank->id);
}/*}}}*/
void
ManglerAdmin::RankUpdate_clicked_cb(void) {/*{{{*/
v3_rank rank;
rank.id = (currentRankID == 0xffff) ? 0 : currentRankID;
rank.name = ::strdup(ustring_to_c(getFromEntry("RankName")).c_str());
rank.description = ::strdup(ustring_to_c(getFromEntry("RankDescription")).c_str());
rank.level = uint16_t( getFromSpinbutton("RankLevel") );
v3_rank_update(&rank);
::free(rank.name);
::free(rank.description);
}/*}}}*/
void
ManglerAdmin::RankEditorTree_cursor_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = RankEditorTree->get_selection()->get_selected();
bool isRank( false );
if (iter) {
isRank = true;
currentRankID = (*iter)[rankRecord.id];
copyToEntry("RankName", (*iter)[rankRecord.name]);
copyToEntry("RankDescription", (*iter)[rankRecord.description]);
copyToSpinbutton("RankLevel", (*iter)[rankRecord.level]);
}
const v3_permissions *perms = v3_get_permissions();
bool editAccess( RankEditorOpen && perms->edit_rank );
setWidgetSensitive("RankAdd", editAccess);
setWidgetSensitive("RankRemove", editAccess && isRank);
setWidgetSensitive("RankUpdate", editAccess && isRank);
RankEditor->set_sensitive(isRank);
}/*}}}*/
void
ManglerAdmin::RankAdd_clicked_cb(void) {/*{{{*/
clearRankEditor();
currentRankID = 0xffff;
setWidgetSensitive("RankAdd", false);
setWidgetSensitive("RankUpdate", true);
RankEditor->set_sensitive(true);
}/*}}}*/
void
ManglerAdmin::RankRemove_clicked_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = RankEditorTree->get_selection()->get_selected();
if (! iter) return;
uint16_t rankid = (*iter)[rankRecord.id];
Glib::ustring rankname = (*iter)[rankRecord.name];
Gtk::MessageDialog confirmDlg( Glib::ustring::compose("Are you sure you want to remove rank %1 (%2)?", Glib::ustring::format(rankid), rankname), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true );
if (confirmDlg.run() == Gtk::RESPONSE_YES) {
v3_rank_remove(rankid);
}
}/*}}}*/
void
ManglerAdmin::clearRankEditor(void) {/*{{{*/
RankEditorTree->get_selection()->unselect_all();
RankEditor->set_sensitive(false);
copyToEntry("RankName", "");
copyToEntry("RankDescription", "");
copyToSpinbutton("RankLevel", 0);
setWidgetSensitive("RankAdd", RankEditorOpen);
setWidgetSensitive("RankRemove", false);
setWidgetSensitive("RankUpdate", RankEditorOpen);
currentRankID = 0;
}/*}}}*/
void
ManglerAdmin::clearRanks(void) {/*{{{*/
RankEditorModel->clear();
queue_resize(RankEditorTree);
clearRankEditor();
UserRankModel->clear();
Gtk::TreeModel::Row row = *(UserRankModel->append());
row[adminRecord.id] = 0;
row[adminRecord.name] = "(None)";
}/*}}}*/
/* ---------- Ban Editor Related Methods ---------- */
void
ManglerAdmin::banList(uint16_t id, uint16_t count, uint16_t bitmask_id, uint32_t ip_address, char *user, char *by, char *reason) {/*{{{*/
if (!id) {
BanEditorModel->clear();
queue_resize(BanEditorTree);
}
if (!count) {
clearBanEditor();
return;
}
Gtk::TreeModel::iterator iter = BanEditorModel->append();
(*iter)[banRecord.id] = id;
(*iter)[banRecord.ip_val] = ip_address;
(*iter)[banRecord.netmask_id] = bitmask_id;
(*iter)[banRecord.ip] = Glib::ustring::compose("%1.%2.%3.%4",
Glib::ustring::format((ip_address >> 24) & 0xff),
Glib::ustring::format((ip_address >> 16) & 0xff),
Glib::ustring::format((ip_address >> 8) & 0xff),
Glib::ustring::format(ip_address & 0xff));
(*iter)[banRecord.netmask] = c_to_ustring(_v3_bitmasks[bitmask_id]);
(*iter)[banRecord.user] = c_to_ustring(user);
(*iter)[banRecord.by] = c_to_ustring(by);
(*iter)[banRecord.reason] = c_to_ustring(reason);
if (ip_address == currentBanIP) {
BanEditorTree->set_cursor(BanEditorModel->get_path(iter));
}
queue_resize(BanEditorTree);
}/*}}}*/
void
ManglerAdmin::BanEditorTree_cursor_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = BanEditorTree->get_selection()->get_selected();
bool isBan( false );
if (iter) {
isBan = true;
currentBanIP = (*iter)[banRecord.ip_val];
copyToEntry("BanIPAddress", (*iter)[banRecord.ip]);
copyToCombobox("BanNetmask", (*iter)[banRecord.netmask_id], BanNetmaskDefault);
copyToEntry("BanReason", (*iter)[banRecord.reason]);
}
setWidgetSensitive("BanAdd", true);
setWidgetSensitive("BanRemove", isBan);
BanEditor->set_sensitive(isBan);
}/*}}}*/
void
ManglerAdmin::BanAdd_clicked_cb(void) {/*{{{*/
clearBanEditor();
setWidgetSensitive("BanAdd", false);
BanEditor->set_sensitive(true);
}/*}}}*/
void
ManglerAdmin::BanRemove_clicked_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = BanEditorTree->get_selection()->get_selected();
if (! iter) return;
uint32_t ip_address = (*iter)[banRecord.ip_val];
uint16_t bitmask_id = (*iter)[banRecord.netmask_id];
clearBanEditor();
v3_admin_ban_remove(bitmask_id, ip_address);
v3_admin_ban_list();
}/*}}}*/
void
ManglerAdmin::BanUpdate_clicked_cb(void) {/*{{{*/
uint32_t ip_address = 0;
char *ip_str = ::strdup(ustring_to_c(getFromEntry("BanIPAddress")).c_str());
uint16_t b1 = 0, b2 = 0, b3 = 0, b4 = 0;
if (::sscanf(ip_str, "%hu.%hu.%hu.%hu", &b1, &b2, &b3, &b4) != 4) {
::free(ip_str);
statusbarPush("Invalid IPv4 address.");
return;
}
::free(ip_str);
currentBanIP = ip_address =
((b1 << 24) & 0xff000000) |
((b2 << 16) & 0x00ff0000) |
((b3 << 8) & 0x0000ff00) |
((b4) & 0x000000ff);
uint16_t bitmask_id = getFromCombobox("BanNetmask", BanNetmaskDefault);
char *reason = ::strdup(ustring_to_c(getFromEntry("BanReason")).c_str());
v3_admin_ban_add(bitmask_id, ip_address, "Remotely added IP", reason);
::free(reason);
v3_admin_ban_list();
}/*}}}*/
void
ManglerAdmin::clearBanEditor(void) {/*{{{*/
BanEditorTree->get_selection()->unselect_all();
BanEditor->set_sensitive(false);
copyToEntry("BanIPAddress", "");
copyToCombobox("BanNetmask", BanNetmaskDefault);
copyToEntry("BanReason", "");
setWidgetSensitive("BanAdd", true);
setWidgetSensitive("BanRemove", false);
currentBanIP = -1;
}/*}}}*/
void
ManglerAdmin::clearBans(void) {/*{{{*/
BanEditorModel->clear();
queue_resize(BanEditorTree);
clearBanEditor();
}/*}}}*/
void
ManglerAdmin::clear(void) {/*{{{*/
adminNotebook->set_current_page(1);
setWidgetSensitive("ServerVBox", true);
SrvIsNotUpdating = true;
ChannelAdded = false;
SrvEditorOpen = false;
UserEditorOpen = false;
RankEditorOpen = false;
clearChannels();
clearUsers();
clearRanks();
clearBans();
}/*}}}*/