/*
Silky - A GTK+ client for SILC.
Copyright (C) 2003,2004 Toni Willberg
- Command reply handler
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
http://silky.sourceforge.net/
*/
#include <glib.h>
#include <glade/glade.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "ui_buddylist.h"
#include "channel.h"
#include "ui_channel.h"
#include "ui_console.h"
#include "support.h"
#include "gui.h"
#include "log.h"
#include "keys.h"
#include "common.h"
extern GladeXML *xmlmain;
extern silkyStruct *silky; /* the client */
extern gchar *previous_nick; /* my nickname just before sending NICK command */
extern gint lastpong; /* last time we received a ping */
extern gchar * glade_silky_channel;
extern gchar * glade_silky_channel_label;
extern SilkyChannel *channel_active;
/*
Command reply handler. Called every time in the command reply function.
In case of an error, this function gets called as well. Usually this gets
called after the received command data has been parsed and processed.
The function is used to pass the received data to the real application.
'conn' is the associated client connection. 'cmd_payload' is the command
payload data received from server and thus can be ignored. It is provided
in case the application prefers to re-parse the received command data, but
it must be noted however, that the data has been parsed once already.
'success' is a boolean value, FALSE in case an error occurred. In case of
an error, no arguments are sent to the application. 'status' is the command
reply status that server returned. The function has variable argument list
and each command defines both the number and type of arguments is passes
to the application. (Excluding possible error scenario.)
*/
void silc_command_reply(SilcClient client, SilcClientConnection conn,
SilcCommandPayload cmd_payload, bool success,
SilcCommand command, SilcStatus status, ...) {
gchar *channel_name=NULL, *mode, *channel_topic=NULL, *nickname, *username,
*str_storid, *str_oldid, *channel_usercount, *str,
*str_fingerprint, *realname;
gchar chanstr[512];
va_list va;
gboolean valid;
SilcUInt32 modei=0, list_count=0, idletime, usermodei;
SilcClientID *stored_clientid, *client_id;
SilcChannelEntry channel_entry=NULL, userchannel;
SilcChannelID *channel_id;
SilcClientEntry client_entry;
SilcIdType entry_type;
SilcPublicKey public_key;
SilcBuffer client_id_list, channels, user_modes;
SilcHashTableList userhtl;
GtkWidget *window_channel, *widget_channel,
*treeview, *wid_channel_name, *wid_channel_topic, *wid_channel_usercount,
*wid_cmode_channel_name, *wid_channel_topicbutton;
GtkWidget *widget_tabhbox;
GtkNotebook *storednotebook, *notebook;
GtkListStore *liststore;
GtkTreeIter iter;
GtkTreeSelection *treeselect;
GtkTreeViewColumn *column;
GtkTextView *textview;
GtkCellRenderer *renderer_text;
GtkWidget *widget;
GtkTreeModel *sorted_nicklist;
SilkyBuddy *b = NULL;
GladeXML *xml_channel;
SilcDList list;
SilkyChannel *ch = NULL;
SilkyUserInfo *user = malloc(sizeof(SilkyUserInfo));
unsigned char *fingerprint;
lastpong = time(NULL); /* update date of last received data, used in timer.c */
debug("debug silc_command_reply with status (%d:%s)", status, silc_get_status_message(status));
va_start(va, status);
switch (command) {
case SILC_COMMAND_GETKEY: /* 26 */
debug_info("reply for SILC_COMMAND_GETKEY");
if (!success) {
debug_info("was not success (status %s)", silc_get_status_message(status) );
switch(status) {
case SILC_STATUS_ERR_NO_SUCH_NICK:
printconsole(_("No such user."));
break;
case SILC_STATUS_ERR_TIMEDOUT:
printconsole(_("The server did not respond."));
break;
default:
break;
}
return;
}
//SilcIdType entry_type, void *entry, SilcPublicKey public_key
entry_type = va_arg(va, int);
client_entry = va_arg(va, SilcClientEntry);
public_key = va_arg(va, SilcPublicKey);
{
SilcUInt32 keysize;
unsigned char *encpk = silc_pkcs_public_key_encode(public_key, &keysize);
gchar *fingerprint = silc_hash_fingerprint(NULL, encpk, keysize);
/* FIXME: use the key type (server/client) from the callback instead of hard-code
needed for /getkey servername
*/
if (encpk) {
debug("trying to save the key type '%d' '%s'...", SILC_SOCKET_TYPE_CLIENT, fingerprint);
silky_save_public_key(silky->client, silky->conn,
fingerprint, SILC_SOCKET_TYPE_CLIENT,
encpk, keysize,
SILC_SKE_PK_TYPE_SILC,
NULL, NULL);
} else {
debug("Error decoding the key, aborting");
}
}
debug("ready");
break;
case SILC_COMMAND_WHOIS:
debug_info("SILC_COMMAND_WHOIS");
if (!success) {
debug_info("was not success (status %s)", silc_get_status_message(status) );
switch(status) {
case SILC_STATUS_ERR_NO_SUCH_NICK:
printconsole(_("No such user."));
break;
case SILC_STATUS_ERR_TIMEDOUT:
printconsole(_("The server did not respond."));
break;
default:
break;
}
return;
}
client_entry = va_arg(va, SilcClientEntry);
nickname = va_arg(va, char *);
username = va_arg(va, char *);
realname = va_arg(va, char *);
channels = va_arg(va, SilcBuffer);
usermodei = va_arg(va, SilcUInt32);
idletime = va_arg(va, SilcUInt32);
fingerprint = va_arg(va, unsigned char *);
user_modes = va_arg(va, SilcBuffer);
user->attrs = va_arg(va, SilcDList);
if (!client_entry) {
debug("didn't find client_entry");
return;
}
if (fingerprint != NULL) {
str_fingerprint = silc_fingerprint(fingerprint, 20 ); /* FIXME: is 20 okey? */
}
else {
/* I18N This means "not available" */
str_fingerprint = g_strdup(_("N/A"));
}
if( channels && user_modes ) {
SilcUInt32 *umodes;
list = silc_channel_payload_parse_list(channels->data, channels->len);
if( list && silc_get_mode_list(user_modes, silc_dlist_count(list), &umodes) ) {
SilcChannelPayload entry;
int i = 0;
memset(chanstr, 0, sizeof(chanstr));
silc_dlist_start(list);
while(( entry = silc_dlist_get(list)) != SILC_LIST_END) {
SilcUInt32 name_len;
char *m = silc_client_chumode_char(umodes[i++]);
char *name = silc_channel_get_name(entry, &name_len);
if( m ) silc_strncat(chanstr, sizeof(chanstr) - 1, m, strlen(m));
silc_strncat(chanstr, sizeof(chanstr) - 1, name, name_len);
silc_strncat(chanstr, sizeof(chanstr) - 1, " ", 1);
silc_free(m);
}
silc_channel_payload_list_free(list);
silc_free(umodes);
}
}
/* Fill the SilkyUserInfo struct for GUI userinfo dialog */
user->nickname = g_strdup(nickname);
user->username = g_strdup(username);
user->realname = g_strdup(realname);
user->channels = g_strdup(chanstr);
user->fingerprint = g_strdup(str_fingerprint);
silky_show_user_info(user);
silky_free_user_info(user);
debug_info("got WHOIS for '%s' fingerprint: %s", nickname, str_fingerprint );
b = buddy_find_by_fp(str_fingerprint);
if (b) {
debug_info("this user is in our buddylist, updating data");
buddy_set_nick_by_fp(str_fingerprint, nickname);
buddy_set_realname_by_fp(str_fingerprint, realname);
buddy_set_clientid_by_fp(str_fingerprint, client_entry->id);
/* FIXME: parse and add user attrs if present */
} else {
debug_info("this is isn't in our buddylist");
}
valid = FALSE;
printconsole(g_strdup_printf("%s: %s (%s)", _("Nickname"), client_entry->nickname, username));
printconsole(g_strdup_printf("%s: %s", _("Realname"), realname));
printconsole(g_strdup_printf("%s: %s", _("Fingerprint"), str_fingerprint));
printconsole(g_strdup_printf("%s: %s", _("Channels"), chanstr));
g_free(str_fingerprint);
break;
case SILC_COMMAND_NICK:
debug_info("SILC_COMMAND_NICK");
/* ERROR */
if (!success) {
debug_info("Was not able to change nickname (%d)", status);
if (status == SILC_STATUS_ERR_BAD_NICKNAME) {
printconsole(_("Illegal nickname."));
}
else {
/* this should not happen, if it does, please add handler for the status code here */
}
return;
}
client_entry = va_arg(va, SilcClientEntry);
nickname = va_arg(va, char *);
client_id = va_arg(va, SilcClientID *);
debug_info("I changed nick from '%s' to '%s'.", previous_nick, nickname);
printconsole( g_strdup_printf(_("Your nickname is now '%s'."), nickname));
/* set my new nick entry into the label left of input line */
widget = glade_xml_get_widget (xmlmain, "input_my_nickname");
gtk_label_set_text(GTK_LABEL(widget), nickname);
gtk_widget_hide (glade_xml_get_widget (xmlmain, "dialog_nick_change"));
if (client_entry->channels) {
debug("calling silc_hash_table_list()");
silc_hash_table_list(client_entry->channels, &userhtl);
debug("returned");
str_oldid = silc_id_id2str(client_id, SILC_ID_CLIENT);
while (silc_hash_table_get(&userhtl, (void *)&userchannel, NULL)) {
ch = channel_find_by_name(userchannel->channel_name);
refresh_nicklist(ch->channel_entry);
printchannel (userchannel->channel_name, g_strdup_printf(_("You are now known as '%s'."), client_entry->nickname));
treeview = glade_xml_get_widget(channel_find_by_entry(userchannel)->glade_xml, "nicktreeview");
sorted_nicklist = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
liststore = GTK_LIST_STORE(gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(sorted_nicklist)));
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(liststore), &iter);
while (valid) {
gtk_tree_model_get (GTK_TREE_MODEL(liststore), &iter, 3, &stored_clientid, -1);
str_storid = silc_id_id2str(stored_clientid, SILC_ID_CLIENT);
if(str_storid == NULL) { /* FIXME! should compare ids and not pointers */
debug("\tmatching NULL found, using this row iter");
debug("Store new clientid and nickname to liststore");
gtk_list_store_set(GTK_LIST_STORE(liststore), &iter, 2, client_entry->nickname, -1);
gtk_list_store_set(GTK_LIST_STORE(liststore), &iter, 3, client_entry->id, -1);
break;
}
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(liststore), &iter);
}
}
silc_hash_table_list_reset(&userhtl);
debug("Iteration done. ");
}
else {
debug("not on any channels");
}
break;
/* MOTD (command) */
case SILC_COMMAND_MOTD:
debug_info ("SILC_COMMAND_MOTD");
if (!success) {
debug_info("ERROR !success");
return;
}
str = va_arg(va, char *);
printconsole(g_strdup(str));
break;
/* STATS */
case SILC_COMMAND_STATS:
debug_info("SILC_COMMAND_STATS");
if (!success) {
debug_info("ERROR !success");
return;
}
else {
debug_message("parsing stats not implemented yet");
/* fixme: parse and print the stats reply */
}
break;
/* TOPIC */
case SILC_COMMAND_TOPIC:
debug_info("SILC_COMMAND_TOPIC");
if (!success) {
debug_info("ERROR !success");
return;
}
channel_entry = va_arg(va, SilcChannelEntry);
channel_topic = va_arg(va, char *);
printconsole(g_strdup_printf(_("Topic for '%s' is '%s'."), channel_entry->channel_name, channel_topic));
break;
/* LEAVE */
case SILC_COMMAND_LEAVE:
debug_info("SILC_COMMAND_LEAVE");
if (!success) {
debug_info("ERROR !success");
return;
}
channel_entry = va_arg(va, SilcChannelEntry);
channel_name = channel_entry->channel_name;
printconsole(g_strdup_printf(_("I have left channel '%s'."), channel_name));
/* Remove the page from the notebook */
storednotebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs"));
gtk_widget_destroy(get_stored_channel_window(channel_name));
g_object_set_data(G_OBJECT(storednotebook), channel_name, NULL);
/* check that all tabs are associated with correct data structures, since
their numbers may have changed */
gui_renumber_tabs();
/* remove from internal list */
channel_remove_by_entry(channel_entry);
break;
/* JOIN */
case SILC_COMMAND_JOIN:
debug_info("SILC_COMMAND_JOIN");
debug("status code: '%d'", status);
/* get parameters */
if (success) { /* parameters are different depending on success */
debug("success=TRUE");
channel_name = va_arg(va, char *); /* channel_name */
channel_entry = va_arg(va, SilcChannelEntry); /* channel_entry */
modei = va_arg(va, SilcUInt32); /* channel's mode */
(void)va_arg(va, int); /* ignored */
(void)va_arg(va, unsigned char *); /* key_payload */
(void)va_arg(va, unsigned char *); /* NULL */
(void)va_arg(va, unsigned char *); /* NULL */
channel_topic = va_arg(va, char *); /* topic */
if (channel_topic == NULL) {
channel_topic = g_strdup(""); /* this is easier to handle */
}
if( !(ch = channel_add( channel_entry )) ) {
debug("Cannot create channel_t.");
channel_topic_set_by_entry ( channel_entry, channel_topic ); /* fixme: what happens? */
}
(void)va_arg(va, unsigned char *); /* hmac_name */
list_count = va_arg(va, SilcUInt32); /* list count */
client_id_list = va_arg(va, SilcBuffer); /* list of people in channel */
(void)va_arg(va, SilcBuffer); /* client mode list */
(void)va_arg(va, SilcPublicKey); /* founder_key */
(void)va_arg(va, SilcBuffer); /* channel pubkeys */
}
else {
debug_info("success=FALSE");
}
switch(status) {
case SILC_STATUS_OK:
debug_info("SILC_STATUS_OK");
break;
case SILC_STATUS_ERR_USER_ON_CHANNEL:
debug_info("SILC_STATUS_ERR_USER_ON_CHANNEL");
client_id = va_arg(va, SilcClientID *);
channel_id = va_arg(va, SilcChannelID *);
if (channel_id) {
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
/* we are there already, activate the tab */
if ((ch = channel_find_by_entry(channel_entry)) ) {
debug("already in channel, activating the tab for '%s'", channel_entry->channel_name);
/* set active in the struct */
channel_active = ch;
/* set active in the UI (FIXME: should use channel_xml from the struct!) */
notebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs"));
widget_channel = g_object_get_data(G_OBJECT(notebook), channel_entry->channel_name);
gtk_notebook_set_current_page(notebook, gtk_notebook_page_num(notebook, widget_channel));
}
else {
debug("didn't get channel_entry");
printconsole(_("You are already on that channel."));
}
}
else {
debug("didn't get channel_id");
printconsole(_("You are already on that channel."));
}
break;
case SILC_STATUS_ERR_NOT_REGISTERED:
debug_info("SILC_STATUS_ERR_NOT_REGISTERED");
printconsole(_("You are not yet connected to server."));
break;
case SILC_STATUS_ERR_BAD_PASSWORD:
debug_info("SILC_STATUS_ERR_BAD_PASSWORD");
printconsole(_("Password required for the channel."));
/* FIXME: should ask the password from the user?! */
debug_error("Silky doesn't yet support password protected channels.");
break;
case SILC_STATUS_ERR_NOT_INVITED:
debug_info("SILC_STATUS_ERR_NOT_INVITED");
channel_id = va_arg(va, SilcChannelID *);
if (channel_id == NULL) {
debug("null channel_id, this should not happen! we'll continue anyway...");
}
/* fixme: tell user which channel.. */
printconsole(_("The channel is an invite-only channel and you are not invited."));
break;
case SILC_STATUS_ERR_CHANNEL_IS_FULL:
debug_info("SILC_STATUS_ERR_CHANNEL_IS_FULL");
channel_id = va_arg(va, SilcChannelID *);
if (channel_id == NULL) {
debug("null channel_id, this should not happen! we'll continue anyway...");
}
printconsole(_("The channel is full."));
break;
case SILC_STATUS_ERR_BANNED_FROM_CHANNEL:
debug_info("SILC_STATUS_ERR_BANNED_FROM_CHANNEL");
channel_id = va_arg(va, SilcChannelID *);
if (channel_id == NULL) {
debug("null channel_id, this should not happen! we'll continue anyway...");
}
printconsole(_("Can not join. You are banned from the channel."));
break;
default:
debug_info("Unhandled status (%d:%s)", status, silc_get_status_message(status));
printconsole(_("Can not join the channel."));
break;
}
if (!success) {
debug("error processed, returning now");
return;
}
/* channel's mode */
mode = silc_client_chmode(modei,
channel_entry->channel_key ?
silc_cipher_get_name(channel_entry->
channel_key) : "",
channel_entry->hmac ?
silc_hmac_get_name(channel_entry->hmac) : "");
/* "" is easier to handle */
if (mode == NULL) {
mode = g_strdup("");
}
/* CREATE CHANNEL WIDGET for first time */
/* get notebook widget */
notebook = GTK_NOTEBOOK(glade_xml_get_widget (xmlmain, "tabs"));
/* if there's already tab open with same channel_name (usually after disconnect) */
if ((widget_channel = g_object_get_data(G_OBJECT(notebook), channel_name))) {
debug("found existing xml_channel, removing it");
g_free(widget_channel);
}
/* get xml for channel */
xml_channel = glade_xml_new (glade_silky_channel, NULL, NULL); /* current dir */
if (!xml_channel) {
g_error("Can not find the silky-channel.glade file. Are you sure you installed the application completely?");
}
ch->glade_xml = xml_channel;
/* connect signals */
glade_xml_signal_autoconnect (xml_channel);
/* get parent widget */
window_channel = glade_xml_get_widget (xml_channel, "window_channel");
/* get channel widget */
widget_channel = glade_xml_get_widget (xml_channel, "channelhbox");
/* DONT try to use stored data before this line! :) */
/* store pointer to the widget_channel by channel_name to the notebook object */
g_object_set_data(G_OBJECT(notebook), channel_name, widget_channel);
debug("storing channel_name and channel_id to widget_channel");
/* store channel name to the widget_channel object for later use */
g_object_set_data(G_OBJECT(widget_channel), "channel_name", strdup(channel_name));
g_object_set_data(G_OBJECT(widget_channel), "channel_id", channel_entry->id);
g_object_set_data(G_OBJECT(widget_channel), "tab_type", (gpointer *)TAB_TYPE_CHANNEL);
/* destroy unnecessary parent */
g_object_ref(widget_channel);
gtk_container_remove(GTK_CONTAINER(window_channel), widget_channel);
debug("generating hbox");
/* generate tab label stuff and pack it */
widget_tabhbox = gtk_hbox_new(FALSE, 2);
ch->label_text = (gpointer)gtk_label_new(channel_name);
ch->label_image = (gpointer)gtk_image_new_from_stock( GTK_STOCK_JUSTIFY_FILL, GTK_ICON_SIZE_BUTTON );
gtk_box_pack_start(GTK_BOX(widget_tabhbox), (gpointer)ch->label_image, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(widget_tabhbox), (gpointer)ch->label_text, TRUE, TRUE, 0);
/* create new page/tab to the notebook */
gtk_notebook_append_page(notebook, widget_channel, widget_tabhbox); /* create new tab */
ch->pagenr = gtk_notebook_get_n_pages(notebook)-1;
debug("appended page (%d)", ch->pagenr);
gtk_widget_show_all(widget_tabhbox);
/* ACTIVATE current page */
debug("activating page %d", (gint)ch->pagenr);
gtk_notebook_set_current_page(notebook, ch->pagenr);
channel_active = ch;
debug("setting columns for nicktreeview");
/* set columns */
liststore =
gtk_list_store_new (
5,
G_TYPE_STRING, /* founder */
G_TYPE_STRING, /* chanop */
G_TYPE_STRING, /* nickname */
G_TYPE_POINTER, /* SilcClientID */
G_TYPE_STRING, /* strSilcClientID */
G_TYPE_INT
);
sorted_nicklist = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(liststore));
treeview = glade_xml_get_widget(ch->glade_xml, "nicktreeview");
/* set the model for treeview, overwrites the old one if present */
gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(sorted_nicklist) );
/* set colors to the nicklist */
silky_colorize_nicklist(treeview);
/* assign a handler for CHANGED signal */
treeselect = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_tree_selection_set_mode (treeselect, GTK_SELECTION_SINGLE);
g_signal_connect (treeselect, "changed", G_CALLBACK(on_nicklist_selected), NULL);
/* connection for popup menu */
g_signal_connect(treeview, "button_press_event", G_CALLBACK(on_nick_pressed), NULL);
/* handler for ACTIVATED signal*/
g_signal_connect (treeview, "row-activated", G_CALLBACK(on_nicklist_activated), NULL);
debug("after treeselection handler");
/* ADD columns */
/* create renderer */
renderer_text = gtk_cell_renderer_text_new ();
debug("setting flags");
/* User founder type flag column */
column = gtk_tree_view_column_new_with_attributes ("", renderer_text, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
gtk_tree_view_set_search_column (GTK_TREE_VIEW(treeview), 0); /* set sortable column */
gtk_tree_view_column_set_sort_column_id(column, 0);
/* User chanoper type flag column */
column = gtk_tree_view_column_new_with_attributes ("@", renderer_text, "text", 1, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
gtk_tree_view_set_search_column (GTK_TREE_VIEW(treeview), 1); /* set sortable column */
gtk_tree_view_column_set_sort_column_id(column, 1);
/* User nickname column */
column = gtk_tree_view_column_new_with_attributes (_("Nickname"), renderer_text, "text", 2, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
gtk_tree_view_set_search_column (GTK_TREE_VIEW(treeview), 2); /* set sortable column */
gtk_tree_view_column_set_sort_column_id(column, 2);
gtk_list_store_clear(liststore);
debug("flags set");
/* SET CHANNEL attributes in GUI */
/* get stored widgets */
wid_channel_name = get_stored_channel_widget(channel_name, "channelname");
wid_cmode_channel_name = get_stored_channel_widget(channel_name, "cmode_channelname");
wid_channel_topic = get_stored_channel_widget(channel_name, "channeltopic");
wid_channel_topicbutton = get_stored_channel_widget(channel_name, "button_change_topic");
wid_channel_usercount = get_stored_channel_widget(channel_name, "channel_usercount");
channel_usercount = g_strdup_printf("%d users", (unsigned int) list_count);
/* CREATE STYLES FOR CHANNEL*/
textview = GTK_TEXT_VIEW(get_stored_channel_widget(channel_name, "textviewwidget"));
/* FIXME unused?
if (!xml_doc(CONFIG_MAIN)) {
debug("main xmlDoc is NULL!");
}
*/
/* set color tags for textview widget */
set_textview_colors(textview); /* in preferences.c */
/* set channel name, and topic and usercount*/
gtk_label_set_text(GTK_LABEL(wid_channel_name), channel_name);
if (channel_topic && strlen(channel_topic) > 0) {
gtk_entry_set_text(GTK_ENTRY(wid_channel_topic), channel_topic);
}
/* activate topicbar and the button */
if(CHANNEL_CMODE(ch) & SILC_CHANNEL_MODE_TOPIC) {
gtk_widget_set_sensitive(wid_channel_topic, FALSE);
gtk_widget_set_sensitive(wid_channel_topicbutton, FALSE);
} else {
gtk_widget_set_sensitive(wid_channel_topic, TRUE);
gtk_widget_set_sensitive(wid_channel_topicbutton, TRUE);
}
gtk_label_set_text(GTK_LABEL(wid_channel_usercount), channel_usercount);
/* set focus to inputbox of the main window*/
gtk_widget_grab_focus(glade_xml_get_widget (xmlmain, "inputbox"));
printchannel(channel_name, g_strdup_printf(_("Joined channel '%s'."), channel_name));
/* I18N first argument is channel name */
printchannel(channel_name, g_strdup_printf(_("Topic of '%s' is '%s'."), channel_name, channel_topic));
/* I18N first argument is channel name */
printchannel(channel_name, g_strdup_printf(_("Mode of '%s' is '%s'."), channel_name, mode));
set_cmode_window_widgets(channel_name, modei); /* set modes in gui */
/* Resolve the client information.
The callback function handles updating the GUI too.
The client library will call the given callback
function when finished. */
debug("calling refresh_nicklist(channel_entry)");
refresh_nicklist(channel_entry);
debug("returned");
break;
/* WATCH */
case SILC_COMMAND_WATCH:
debug_info("reply for SILC_COMMAND_WATCH");
/* refresh the buddy list */
refresh_gui_buddylist();
if (success) {
printconsole(_("OK"));
}
else {
debug_error("Add failed, status: '%d'", status);
if (status == 24) { /* FIXME: what's the enum? */
// printconsole(_("User already on list"));
break;
}
if (status == 54) { /* FIXME: what's the enum? */
// printconsole(_("Service timed out"));
// FIXME: should have saved the command earlier, and now we should try to resend it
break;
}
debug("unhandled status code");
printconsole(_("Command failed"));
}
break;
/* CUMODE */
case SILC_COMMAND_CUMODE:
debug_info("reply for SILC_COMMAND_CUMODE");
if (!success) {
debug_info("No success");
if (status == SILC_STATUS_ERR_NO_CHANNEL_FOPRIV) {
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
debug("Not channel oper on '%s'", channel_entry->channel_name);
error_no_channel_founder_priv(channel_entry->channel_name);
}
if (status == SILC_STATUS_ERR_NO_CHANNEL_PRIV) {
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
debug("Not channel oper on '%s'", channel_entry->channel_name);
error_no_channel_oper_priv(channel_entry->channel_name);
}
debug_info("error '%d' for SILC_COMMAND_KICK", status);
}
if (success) {
modei = va_arg(va, SilcUInt32);
debug("Was success");
}
break;
/* KICK */
case SILC_COMMAND_KICK:
debug_info("reply for SILC_COMMAND_KICK");
if (!success) {
debug("not success");
/* not chanop */
if (status == SILC_STATUS_ERR_NO_CHANNEL_PRIV) {
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
debug_info("Not channel oper on '%s'", channel_entry->channel_name);
error_no_channel_oper_priv(channel_entry->channel_name);
}
/* not founder */
if (status == SILC_STATUS_ERR_NO_CHANNEL_FOPRIV) {
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
debug_info("Not channel founder on '%s'", channel_entry->channel_name);
error_no_channel_founder_priv(channel_entry->channel_name);
}
if (status == SILC_STATUS_ERR_USER_NOT_ON_CHANNEL) {
debug_info("User not on given channel");
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
error_user_not_on_channel(channel_entry->channel_name);
}
debug("error '%d' for SILC_COMMAND_KICK", status);
}
else {
debug("was success");
}
break;
/* CMODE */
case SILC_COMMAND_CMODE:
debug_info("reply for SILC_COMMAND_CMODE");
if (!success) {
/* not chanop */
if (status == SILC_STATUS_ERR_NO_CHANNEL_PRIV) {
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
set_cmode_window_widgets(channel_entry->channel_name, channel_entry->mode); /* set modes in gui */
debug_info("Not channel oper on '%s'", channel_entry->channel_name);
error_no_channel_oper_priv(channel_entry->channel_name);
}
/* not founder */
if (status == SILC_STATUS_ERR_NO_CHANNEL_FOPRIV) {
channel_id = va_arg(va, SilcChannelID *);
channel_entry = silc_client_get_channel_by_id(client, conn, channel_id);
set_cmode_window_widgets(channel_entry->channel_name, channel_entry->mode); /* set modes in gui */
debug_info("Not channel founder on '%s'", channel_entry->channel_name);
error_no_channel_founder_priv(channel_entry->channel_name);
}
debug_info("error '%d' for SILC_COMMAND_CMODE", status);
}
break;
/* LIST */
case SILC_COMMAND_LIST:
debug_info("reply for SILC_COMMAND_LIST");
if (success) {
channel_entry = va_arg(va, SilcChannelEntry);
channel_name = va_arg(va, char *);
channel_topic = va_arg(va, char *);
list_count = va_arg(va, SilcUInt32);
if (status == 1) {
debug("LIST STARTS");
printconsole( _("Channel list starts:") );
}
debug_info("LIST for %s. %d users. Topic: '%s'", channel_name, list_count, channel_topic);
if (channel_topic && !g_utf8_validate(channel_topic, -1, NULL)) {
debug("*** INVALID utf8 in channel topic, skipping");
channel_topic = strdup("non-utf8 topic, can't show");
}
else if (channel_topic==NULL)
{
channel_topic= g_strdup_printf("");
}
printconsole(g_strdup_printf("%s (%d) %s", channel_name, (unsigned int) list_count, channel_topic));
/* this needs to be last... */
if (status == 3) {
debug("LIST ENDS");
printconsole( _("Channel list ends.") );
}
}
else {
debug("not success");
}
break;
case SILC_COMMAND_PING: /* 12 */
debug_info("reply for SILC_COMMAND_PING");
break;
/* DEFAULT */
default:
debug("Unknown command reply (%d).", command);
if (!success) {
debug("ERROR !success");
}
break;
}
va_end(va);
debug("returning");
}
syntax highlighted by Code2HTML, v. 0.9.1