#include "fe-common/core/keyboard.h"
#include "fe-common/silc/module-formats.h"
+#include "core.h"
+
static void
silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
const char *name, SilcSocketType conn_type,
- unsigned char *pk, uint32 pk_len,
+ unsigned char *pk, SilcUInt32 pk_len,
SilcSKEPKType pk_type,
SilcVerifyPublicKey completion, void *context);
+static void silc_get_umode_string(SilcUInt32 mode, char *buf,
+ SilcUInt32 buf_size)
+{
+ if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
+ (mode & SILC_UMODE_ROUTER_OPERATOR)) {
+ strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
+ "[server operator]" :
+ (mode & SILC_UMODE_ROUTER_OPERATOR) ?
+ "[SILC operator]" : "[unknown mode]");
+ }
+ if (mode & SILC_UMODE_GONE)
+ strcat(buf, " [away]");
+ if (mode & SILC_UMODE_INDISPOSED)
+ strcat(buf, " [indisposed]");
+ if (mode & SILC_UMODE_BUSY)
+ strcat(buf, " [busy]");
+ if (mode & SILC_UMODE_PAGE)
+ strcat(buf, " [page to reach]");
+ if (mode & SILC_UMODE_HYPER)
+ strcat(buf, " [hyper active]");
+ if (mode & SILC_UMODE_ROBOT)
+ strcat(buf, " [robot]");
+ if (mode & SILC_UMODE_ANONYMOUS)
+ strcat(buf, " [anonymous]");
+ if (mode & SILC_UMODE_BLOCK_PRIVMSG)
+ strcat(buf, " [blocks private messages]");
+ if (mode & SILC_UMODE_DETACHED)
+ strcat(buf, " [detached]");
+}
+
void silc_say(SilcClient client, SilcClientConnection conn,
SilcClientMessageType type, char *msg, ...)
{
void silc_channel_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcChannelEntry channel,
- SilcMessageFlags flags, char *msg)
+ SilcMessageFlags flags, const unsigned char *message,
+ SilcUInt32 message_len)
{
SILC_SERVER_REC *server;
SILC_NICK_REC *nick;
SILC_LOG_DEBUG(("Start"));
+ if (!message)
+ return;
+
server = conn == NULL ? NULL : conn->context;
chanrec = silc_channel_find_entry(server, channel);
if (!chanrec)
nick = silc_nicklist_find(chanrec, sender);
if (!nick) {
- /* We didn't find client but it clearly exists, add it. It must be
- found on the channel->clients list. */
- SilcChannelUser chu;
-
- silc_list_start(channel->clients);
- while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
- if (chu->client == sender) {
- nick = silc_nicklist_insert(chanrec, chu, FALSE);
- break;
- }
+ /* We didn't find client but it clearly exists, add it. */
+ SilcChannelUser chu = silc_client_on_channel(channel, sender);
+ if (chu)
+ nick = silc_nicklist_insert(chanrec, chu, FALSE);
+ }
+
+ if (flags & SILC_MESSAGE_FLAG_DATA) {
+ /* MIME object received, try to display it as well as we can */
+ char type[128];
+ unsigned char *data;
+
+ memset(type, 0, sizeof(type));
+ if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
+ NULL, 0, &data, NULL))
+ return;
+
+ /* Then figure out what we can display */
+ if (strstr(type, "text/") && !strstr(type, "text/t140") &&
+ !strstr(type, "text/vnd")) {
+ /* It is something textual, display it */
+ message = (const unsigned char *)data;
+ } else {
+ message = NULL;
}
}
+ if (!message)
+ return;
+
if (flags & SILC_MESSAGE_FLAG_ACTION)
printformat_module("fe-common/silc", server, channel->channel_name,
MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
- nick == NULL ? "[<unknown>]" : nick->nick, msg);
+ nick == NULL ? "[<unknown>]" : nick->nick, message);
else if (flags & SILC_MESSAGE_FLAG_NOTICE)
printformat_module("fe-common/silc", server, channel->channel_name,
MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
- nick == NULL ? "[<unknown>]" : nick->nick, msg);
+ nick == NULL ? "[<unknown>]" : nick->nick, message);
else
- signal_emit("message public", 6, server, msg,
+ signal_emit("message public", 6, server, message,
nick == NULL ? "[<unknown>]" : nick->nick,
nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
chanrec->name, nick);
void silc_private_message(SilcClient client, SilcClientConnection conn,
SilcClientEntry sender, SilcMessageFlags flags,
- char *msg)
+ const unsigned char *message,
+ SilcUInt32 message_len)
{
SILC_SERVER_REC *server;
char userhost[256];
if (sender->username)
snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
sender->username, sender->hostname);
- signal_emit("message private", 4, server, msg,
+
+ if (flags & SILC_MESSAGE_FLAG_DATA) {
+ /* MIME object received, try to display it as well as we can */
+ char type[128];
+ unsigned char *data;
+
+ memset(type, 0, sizeof(type));
+ if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
+ NULL, 0, &data, NULL))
+ return;
+
+ /* Then figure out what we can display */
+ if (strstr(type, "text/") && !strstr(type, "text/t140") &&
+ !strstr(type, "text/vnd")) {
+ /* It is something textual, display it */
+ message = (const unsigned char *)data;
+ } else {
+ message = NULL;
+ }
+ }
+
+ if (!message)
+ return;
+
+ signal_emit("message private", 4, server, message,
sender->nickname ? sender->nickname : "[<unknown>]",
sender->username ? userhost : NULL);
}
for channel the channel entry is sent to application (even if server
does not send it). */
-typedef struct {
- int type;
- const char *name;
-} NOTIFY_REC;
-
-#define MAX_NOTIFY (sizeof(notifies)/sizeof(notifies[0]))
-static NOTIFY_REC notifies[] = {
- { SILC_NOTIFY_TYPE_NONE, NULL },
- { SILC_NOTIFY_TYPE_INVITE, "invite" },
- { SILC_NOTIFY_TYPE_JOIN, "join" },
- { SILC_NOTIFY_TYPE_LEAVE, "leave" },
- { SILC_NOTIFY_TYPE_SIGNOFF, "signoff" },
- { SILC_NOTIFY_TYPE_TOPIC_SET, "topic" },
- { SILC_NOTIFY_TYPE_NICK_CHANGE, "nick" },
- { SILC_NOTIFY_TYPE_CMODE_CHANGE, "cmode" },
- { SILC_NOTIFY_TYPE_CUMODE_CHANGE, "cumode" },
- { SILC_NOTIFY_TYPE_MOTD, "motd" },
- { SILC_NOTIFY_TYPE_CHANNEL_CHANGE, "channel_change" },
- { SILC_NOTIFY_TYPE_SERVER_SIGNOFF, "server_signoff" },
- { SILC_NOTIFY_TYPE_KICKED, "kick" },
- { SILC_NOTIFY_TYPE_KILLED, "kill" },
- { SILC_NOTIFY_TYPE_UMODE_CHANGE, "umode" },
- { SILC_NOTIFY_TYPE_BAN, "ban" },
-};
-
void silc_notify(SilcClient client, SilcClientConnection conn,
SilcNotifyType type, ...)
{
- SILC_SERVER_REC *server;
va_list va;
-
+ SILC_SERVER_REC *server;
+ SILC_CHANNEL_REC *chanrec;
+ SILC_NICK_REC *nickrec;
+ SilcClientEntry client_entry, client_entry2;
+ SilcChannelEntry channel, channel2;
+ SilcServerEntry server_entry;
+ SilcIdType idtype;
+ void *entry;
+ SilcUInt32 mode;
+ char buf[512];
+ char *name, *tmp;
+ GSList *list1, *list_tmp;
+
SILC_LOG_DEBUG(("Start"));
- server = conn == NULL ? NULL : conn->context;
va_start(va, type);
+
+ server = conn == NULL ? NULL : conn->context;
- if (type == SILC_NOTIFY_TYPE_NONE) {
+ switch(type) {
+ case SILC_NOTIFY_TYPE_NONE:
/* Some generic notice from server */
printtext(server, NULL, MSGLEVEL_CRAP, "%s", (char *)va_arg(va, char *));
- } else if (type < MAX_NOTIFY) {
- /* Send signal about the notify event */
- char signal[50];
- g_snprintf(signal, sizeof(signal), "silc event %s", notifies[type].name);
- signal_emit(signal, 2, server, va);
- } else {
+ break;
+
+ case SILC_NOTIFY_TYPE_INVITE:
+ /*
+ * Invited or modified invite list.
+ */
+
+ SILC_LOG_DEBUG(("Notify: INVITE"));
+
+ channel = va_arg(va, SilcChannelEntry);
+ name = va_arg(va, char *);
+ client_entry = va_arg(va, SilcClientEntry);
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ client_entry->username, client_entry->hostname);
+ signal_emit("message invite", 4, server, channel ? channel->channel_name :
+ name, client_entry->nickname, buf);
+ break;
+
+ case SILC_NOTIFY_TYPE_JOIN:
+ /*
+ * Joined channel.
+ */
+
+ SILC_LOG_DEBUG(("Notify: JOIN"));
+
+ client_entry = va_arg(va, SilcClientEntry);
+ channel = va_arg(va, SilcChannelEntry);
+
+ if (client_entry == server->conn->local_entry) {
+ /* You joined to channel */
+ chanrec = silc_channel_find(server, channel->channel_name);
+ if (chanrec != NULL && !chanrec->joined)
+ chanrec->entry = channel;
+ } else {
+ chanrec = silc_channel_find_entry(server, channel);
+ if (chanrec != NULL) {
+ SilcChannelUser chu = silc_client_on_channel(channel, client_entry);
+ if (chu)
+ nickrec = silc_nicklist_insert(chanrec, chu, TRUE);
+ }
+ }
+
+ memset(buf, 0, sizeof(buf));
+ if (client_entry->username)
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ client_entry->username, client_entry->hostname);
+ signal_emit("message join", 4, server, channel->channel_name,
+ client_entry->nickname,
+ client_entry->username == NULL ? "" : buf);
+ break;
+
+ case SILC_NOTIFY_TYPE_LEAVE:
+ /*
+ * Left a channel.
+ */
+
+ SILC_LOG_DEBUG(("Notify: LEAVE"));
+
+ client_entry = va_arg(va, SilcClientEntry);
+ channel = va_arg(va, SilcChannelEntry);
+
+ memset(buf, 0, sizeof(buf));
+ if (client_entry->username)
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ client_entry->username, client_entry->hostname);
+ signal_emit("message part", 5, server, channel->channel_name,
+ client_entry->nickname, client_entry->username ?
+ buf : "", client_entry->nickname);
+
+ chanrec = silc_channel_find_entry(server, channel);
+ if (chanrec != NULL) {
+ nickrec = silc_nicklist_find(chanrec, client_entry);
+ if (nickrec != NULL)
+ nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_SIGNOFF:
+ /*
+ * Left the network.
+ */
+
+ SILC_LOG_DEBUG(("Notify: SIGNOFF"));
+
+ client_entry = va_arg(va, SilcClientEntry);
+ tmp = va_arg(va, char *);
+
+ silc_server_free_ftp(server, client_entry);
+
+ memset(buf, 0, sizeof(buf));
+ if (client_entry->username)
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ client_entry->username, client_entry->hostname);
+ signal_emit("message quit", 4, server, client_entry->nickname,
+ client_entry->username ? buf : "",
+ tmp ? tmp : "");
+
+ list1 = nicklist_get_same_unique(SERVER(server), client_entry);
+ for (list_tmp = list1; list_tmp != NULL; list_tmp =
+ list_tmp->next->next) {
+ CHANNEL_REC *channel = list_tmp->data;
+ NICK_REC *nickrec = list_tmp->next->data;
+
+ nicklist_remove(channel, nickrec);
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_TOPIC_SET:
+ /*
+ * Changed topic.
+ */
+
+ SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
+
+ idtype = va_arg(va, int);
+ entry = va_arg(va, void *);
+ tmp = va_arg(va, char *);
+ channel = va_arg(va, SilcChannelEntry);
+
+ chanrec = silc_channel_find_entry(server, channel);
+ if (chanrec != NULL) {
+ g_free_not_null(chanrec->topic);
+ chanrec->topic = *tmp == '\0' ? NULL : g_strdup(tmp);
+ signal_emit("channel topic changed", 1, chanrec);
+ }
+
+ if (idtype == SILC_ID_CLIENT) {
+ client_entry = (SilcClientEntry)entry;
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ client_entry->username, client_entry->hostname);
+ signal_emit("message topic", 5, server, channel->channel_name,
+ tmp, client_entry->nickname, buf);
+ } else if (idtype == SILC_ID_SERVER) {
+ server_entry = (SilcServerEntry)entry;
+ signal_emit("message topic", 5, server, channel->channel_name,
+ tmp, server_entry->server_name,
+ server_entry->server_name);
+ } else if (idtype == SILC_ID_CHANNEL) {
+ channel = (SilcChannelEntry)entry;
+ signal_emit("message topic", 5, server, channel->channel_name,
+ tmp, channel->channel_name, channel->channel_name);
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_NICK_CHANGE:
+ /*
+ * Changed nickname.
+ */
+
+ SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
+
+ client_entry = va_arg(va, SilcClientEntry);
+ client_entry2 = va_arg(va, SilcClientEntry);
+
+ if (!strcmp(client_entry->nickname, client_entry2->nickname))
+ break;
+
+ memset(buf, 0, sizeof(buf));
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ client_entry2->username, client_entry2->hostname);
+ nicklist_rename_unique(SERVER(server),
+ client_entry, client_entry->nickname,
+ client_entry2, client_entry2->nickname);
+ signal_emit("message nick", 4, server, client_entry2->nickname,
+ client_entry->nickname, buf);
+ break;
+
+ case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+ /*
+ * Changed channel mode.
+ */
+
+ SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
+
+ idtype = va_arg(va, int);
+ entry = va_arg(va, void *);
+ mode = va_arg(va, SilcUInt32);
+ (void)va_arg(va, char *);
+ (void)va_arg(va, char *);
+ channel = va_arg(va, SilcChannelEntry);
+
+ tmp = silc_client_chmode(mode,
+ channel->channel_key ?
+ channel->channel_key->cipher->name : "",
+ channel->hmac ?
+ silc_hmac_get_name(channel->hmac) : "");
+
+ chanrec = silc_channel_find_entry(server, channel);
+ if (chanrec != NULL) {
+ g_free_not_null(chanrec->mode);
+ chanrec->mode = g_strdup(tmp == NULL ? "" : tmp);
+ signal_emit("channel mode changed", 1, chanrec);
+ }
+
+ if (idtype == SILC_ID_CLIENT) {
+ client_entry = (SilcClientEntry)entry;
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
+ channel->channel_name, tmp ? tmp : "removed all",
+ client_entry->nickname);
+ } else if (idtype == SILC_ID_SERVER) {
+ server_entry = (SilcServerEntry)entry;
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
+ channel->channel_name, tmp ? tmp : "removed all",
+ server_entry->server_name);
+ } else if (idtype == SILC_ID_CHANNEL) {
+ channel2 = (SilcChannelEntry)entry;
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
+ channel->channel_name, tmp ? tmp : "removed all",
+ channel2->channel_name);
+ }
+
+ silc_free(tmp);
+ break;
+
+ case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+ /*
+ * Changed user's mode on channel.
+ */
+
+ SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
+
+ idtype = va_arg(va, int);
+ entry = va_arg(va, void *);
+ mode = va_arg(va, SilcUInt32);
+ client_entry2 = va_arg(va, SilcClientEntry);
+ channel = va_arg(va, SilcChannelEntry);
+
+ tmp = silc_client_chumode(mode);
+ chanrec = silc_channel_find_entry(server, channel);
+ if (chanrec != NULL) {
+ SILC_NICK_REC *nick;
+
+ if (client_entry2 == server->conn->local_entry)
+ chanrec->chanop = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
+
+ nick = silc_nicklist_find(chanrec, client_entry2);
+ if (nick != NULL) {
+ nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
+ nick->founder = (mode & SILC_CHANNEL_UMODE_CHANFO) != 0;
+ signal_emit("nick mode changed", 2, chanrec, nick);
+ }
+ }
+
+ if (idtype == SILC_ID_CLIENT) {
+ client_entry = (SilcClientEntry)entry;
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
+ channel->channel_name, client_entry2->nickname,
+ tmp ? tmp : "removed all",
+ client_entry->nickname);
+ } else if (idtype == SILC_ID_SERVER) {
+ server_entry = (SilcServerEntry)entry;
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
+ channel->channel_name, client_entry2->nickname,
+ tmp ? tmp : "removed all",
+ server_entry->server_name);
+ } else if (idtype == SILC_ID_CHANNEL) {
+ channel2 = (SilcChannelEntry)entry;
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
+ channel->channel_name, client_entry2->nickname,
+ tmp ? tmp : "removed all",
+ channel2->channel_name);
+ }
+
+ if (mode & SILC_CHANNEL_UMODE_CHANFO)
+ printformat_module("fe-common/silc",
+ server, channel->channel_name, MSGLEVEL_CRAP,
+ SILCTXT_CHANNEL_FOUNDER,
+ channel->channel_name, client_entry2->nickname);
+
+ silc_free(tmp);
+ break;
+
+ case SILC_NOTIFY_TYPE_MOTD:
+ /*
+ * Received MOTD.
+ */
+
+ SILC_LOG_DEBUG(("Notify: MOTD"));
+
+ tmp = va_arg(va, char *);
+
+ if (!settings_get_bool("skip_motd"))
+ printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", tmp);
+ break;
+
+ case SILC_NOTIFY_TYPE_KICKED:
+ /*
+ * Someone was kicked from channel.
+ */
+
+ SILC_LOG_DEBUG(("Notify: KICKED"));
+
+ client_entry = va_arg(va, SilcClientEntry);
+ tmp = va_arg(va, char *);
+ client_entry2 = va_arg(va, SilcClientEntry);
+ channel = va_arg(va, SilcChannelEntry);
+
+ chanrec = silc_channel_find_entry(server, channel);
+
+ if (client_entry == conn->local_entry) {
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
+ channel->channel_name,
+ client_entry ? client_entry2->nickname : "",
+ tmp ? tmp : "");
+ if (chanrec) {
+ chanrec->kicked = TRUE;
+ channel_destroy((CHANNEL_REC *)chanrec);
+ }
+ } else {
+ printformat_module("fe-common/silc", server, channel->channel_name,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
+ client_entry->nickname, channel->channel_name,
+ client_entry2 ? client_entry2->nickname : "",
+ tmp ? tmp : "");
+
+ if (chanrec) {
+ SILC_NICK_REC *nickrec = silc_nicklist_find(chanrec, client_entry);
+ if (nickrec != NULL)
+ nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
+ }
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_KILLED:
+ /*
+ * Someone was killed from the network.
+ */
+
+ SILC_LOG_DEBUG(("Notify: KILLED"));
+
+ client_entry = va_arg(va, SilcClientEntry);
+ tmp = va_arg(va, char *);
+ idtype = va_arg(va, int);
+ entry = va_arg(va, SilcClientEntry);
+
+ if (client_entry == conn->local_entry) {
+ if (idtype == SILC_ID_CLIENT) {
+ client_entry2 = (SilcClientEntry)entry;
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
+ client_entry2 ? client_entry2->nickname : "",
+ tmp ? tmp : "");
+ } else if (idtype == SILC_ID_SERVER) {
+ server_entry = (SilcServerEntry)entry;
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
+ server_entry->server_name, tmp ? tmp : "");
+ } else if (idtype == SILC_ID_CHANNEL) {
+ channel = (SilcChannelEntry)entry;
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
+ channel->channel_name, tmp ? tmp : "");
+ }
+ } else {
+ list1 = nicklist_get_same_unique(SERVER(server), client_entry);
+ for (list_tmp = list1; list_tmp != NULL; list_tmp =
+ list_tmp->next->next) {
+ CHANNEL_REC *channel = list_tmp->data;
+ NICK_REC *nickrec = list_tmp->next->data;
+ nicklist_remove(channel, nickrec);
+ }
+
+ if (idtype == SILC_ID_CLIENT) {
+ client_entry2 = (SilcClientEntry)entry;
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
+ client_entry->nickname,
+ client_entry2 ? client_entry2->nickname : "",
+ tmp ? tmp : "");
+ } else if (idtype == SILC_ID_SERVER) {
+ server_entry = (SilcServerEntry)entry;
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
+ client_entry->nickname,
+ server_entry->server_name, tmp ? tmp : "");
+ } else if (idtype == SILC_ID_CHANNEL) {
+ channel = (SilcChannelEntry)entry;
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
+ client_entry->nickname,
+ channel->channel_name, tmp ? tmp : "");
+ }
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
+ break;
+
+ case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
+ {
+ /*
+ * Server has quit the network.
+ */
+ int i;
+ SilcClientEntry *clients;
+ SilcUInt32 clients_count;
+
+ SILC_LOG_DEBUG(("Notify: SIGNOFF"));
+
+ (void)va_arg(va, void *);
+ clients = va_arg(va, SilcClientEntry *);
+ clients_count = va_arg(va, SilcUInt32);
+
+ for (i = 0; i < clients_count; i++) {
+ memset(buf, 0, sizeof(buf));
+ if (clients[i]->username)
+ snprintf(buf, sizeof(buf) - 1, "%s@%s",
+ clients[i]->username, clients[i]->hostname);
+ signal_emit("message quit", 4, server, clients[i]->nickname,
+ clients[i]->username ? buf : "",
+ "server signoff");
+
+ silc_server_free_ftp(server, clients[i]);
+
+ list1 = nicklist_get_same_unique(SERVER(server), clients[i]);
+ for (list_tmp = list1; list_tmp != NULL; list_tmp =
+ list_tmp->next->next) {
+ CHANNEL_REC *channel = list_tmp->data;
+ NICK_REC *nickrec = list_tmp->next->data;
+ nicklist_remove(channel, nickrec);
+ }
+ }
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_ERROR:
+ {
+ SilcStatus error = va_arg(va, int);
+
+ silc_say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+ "%s", silc_get_status_message(error));
+ }
+ break;
+
+ case SILC_NOTIFY_TYPE_WATCH:
+ {
+ SilcNotifyType notify;
+
+ client_entry = va_arg(va, SilcClientEntry);
+ name = va_arg(va, char *); /* Maybe NULL */
+ mode = va_arg(va, SilcUInt32);
+ notify = va_arg(va, int);
+
+ if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
+ if (name)
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_NICK_CHANGE,
+ client_entry->nickname, name);
+ else
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
+ client_entry->nickname);
+ } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
+ /* See if client was away and is now present */
+ if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
+ SILC_UMODE_BUSY | SILC_UMODE_PAGE |
+ SILC_UMODE_DETACHED)) &&
+ (client_entry->mode & SILC_UMODE_GONE ||
+ client_entry->mode & SILC_UMODE_INDISPOSED ||
+ client_entry->mode & SILC_UMODE_BUSY ||
+ client_entry->mode & SILC_UMODE_PAGE ||
+ client_entry->mode & SILC_UMODE_DETACHED)) {
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
+ client_entry->nickname);
+ }
+
+ if (mode) {
+ memset(buf, 0, sizeof(buf));
+ silc_get_umode_string(mode, buf, sizeof(buf) - 1);
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_UMODE_CHANGE,
+ client_entry->nickname, buf);
+ }
+ } else if (notify == SILC_NOTIFY_TYPE_KILLED) {
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_KILLED,
+ client_entry->nickname);
+ } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
+ notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF) {
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_SIGNOFF,
+ client_entry->nickname);
+ } else if (notify == SILC_NOTIFY_TYPE_NONE) {
+ /* Client logged in to the network */
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
+ client_entry->nickname);
+ }
+ }
+ break;
+
+ default:
/* Unknown notify */
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_UNKNOWN_NOTIFY, type);
+ break;
}
va_end(va);
or connecting failed. This is also the first time application receives
the SilcClientConnection object which it should save somewhere. */
-void silc_connect(SilcClient client, SilcClientConnection conn, int success)
+void silc_connect(SilcClient client, SilcClientConnection conn,
+ SilcClientConnectionStatus status)
{
SILC_SERVER_REC *server = conn->context;
- if (!server && !success) {
- silc_client_close_connection(client, NULL, conn);
+ if (!server) {
+ silc_client_close_connection(client, conn);
return;
}
- if (success) {
+ switch (status) {
+ case SILC_CLIENT_CONN_SUCCESS:
+ /* We have successfully connected to server */
server->connected = TRUE;
signal_emit("event connected", 1, server);
- } else {
+ break;
+
+ case SILC_CLIENT_CONN_SUCCESS_RESUME:
+ /* We have successfully resumed old detached session */
+ server->connected = TRUE;
+ signal_emit("event connected", 1, server);
+
+ /* If we resumed old session check whether we need to update
+ our nickname */
+ if (strcmp(server->nick, conn->local_entry->nickname)) {
+ char *old;
+ old = g_strdup(server->nick);
+ server_change_nick(SERVER(server), conn->local_entry->nickname);
+ nicklist_rename_unique(SERVER(server),
+ conn->local_entry, server->nick,
+ conn->local_entry, conn->local_entry->nickname);
+ signal_emit("message own_nick", 4, server, server->nick, old, "");
+ g_free(old);
+ }
+ break;
+
+ default:
server->connection_lost = TRUE;
- server->conn->context = NULL;
+ if (server->conn)
+ server->conn->context = NULL;
server_disconnect(SERVER(server));
+ break;
}
}
SILC_LOG_DEBUG(("Start"));
- if (server->conn) {
+ if (!server || server->connection_lost)
+ return;
+
+ if (server->conn && server->conn->local_entry) {
nicklist_rename_unique(SERVER(server),
server->conn->local_entry, server->nick,
server->conn->local_entry,
that the command really was processed. */
void silc_command(SilcClient client, SilcClientConnection conn,
- SilcClientCommandContext cmd_context, int success,
- SilcCommand command)
+ SilcClientCommandContext cmd_context, bool success,
+ SilcCommand command, SilcStatus status)
{
SILC_SERVER_REC *server = conn->context;
static void silc_client_join_get_users(SilcClient client,
SilcClientConnection conn,
SilcClientEntry *clients,
- uint32 clients_count,
+ SilcUInt32 clients_count,
void *context)
{
SilcChannelEntry channel = (SilcChannelEntry)context;
+ SilcHashTableList htl;
SilcChannelUser chu;
SILC_SERVER_REC *server = conn->context;
SILC_CHANNEL_REC *chanrec;
SilcClientEntry founder = NULL;
NICK_REC *ownnick;
+ SILC_LOG_DEBUG(("Start, channel %s, %d users", channel->channel_name,
+ silc_hash_table_count(channel->user_list)));
+
if (!clients)
return;
if (chanrec == NULL)
return;
- silc_list_start(channel->clients);
- while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
+ silc_hash_table_list(channel->user_list, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
if (!chu->client->nickname)
continue;
if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
founder = chu->client;
silc_nicklist_insert(chanrec, chu, FALSE);
}
+ silc_hash_table_list_reset(&htl);
ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
nicklist_set_own(CHANNEL(chanrec), ownnick);
signal_emit("channel joined", 1, chanrec);
+ chanrec->entry = channel;
if (chanrec->topic)
printformat_module("fe-common/silc", server, channel->channel_name,
void
silc_command_reply(SilcClient client, SilcClientConnection conn,
- SilcCommandPayload cmd_payload, int success,
- SilcCommand command, SilcCommandStatus status, ...)
+ SilcCommandPayload cmd_payload, bool success,
+ SilcCommand command, SilcStatus status, ...)
{
SILC_SERVER_REC *server = conn->context;
{
char buf[1024], *nickname, *username, *realname, *nick;
unsigned char *fingerprint;
- uint32 idle, mode;
- SilcBuffer channels;
+ SilcUInt32 idle, mode;
+ SilcBuffer channels, user_modes;
SilcClientEntry client_entry;
if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
3, NULL);
if (tmp)
silc_say_error("%s: %s", tmp,
- silc_client_command_status_message(status));
+ silc_get_status_message(status));
break;
} else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
/* Try to find the entry for the unknown client ID, since we
might have, and print the nickname of it for user. */
- uint32 tmp_len;
+ SilcUInt32 tmp_len;
unsigned char *tmp =
silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
2, &tmp_len);
if (tmp) {
- SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
+ NULL);
if (client_id) {
client_entry = silc_client_get_client_by_id(client, conn,
client_id);
if (client_entry && client_entry->nickname)
silc_say_error("%s: %s", client_entry->nickname,
- silc_client_command_status_message(status));
+ silc_get_status_message(status));
silc_free(client_id);
}
}
username = va_arg(vp, char *);
realname = va_arg(vp, char *);
channels = va_arg(vp, SilcBuffer);
- mode = va_arg(vp, uint32);
- idle = va_arg(vp, uint32);
+ mode = va_arg(vp, SilcUInt32);
+ idle = va_arg(vp, SilcUInt32);
fingerprint = va_arg(vp, unsigned char *);
+ user_modes = va_arg(vp, SilcBuffer);
silc_parse_userfqdn(nickname, &nick, NULL);
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_WHOIS_REALNAME, realname);
silc_free(nick);
- if (channels) {
+ if (channels && user_modes) {
+ SilcUInt32 *umodes;
SilcDList list = silc_channel_payload_parse_list(channels->data,
channels->len);
- if (list) {
+ if (list && silc_get_mode_list(user_modes, silc_dlist_count(list),
+ &umodes)) {
SilcChannelPayload entry;
+ int i = 0;
+
memset(buf, 0, sizeof(buf));
silc_dlist_start(list);
while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
- char *m = silc_client_chumode_char(silc_channel_get_mode(entry));
- uint32 name_len;
+ SilcUInt32 name_len;
+ char *m = silc_client_chumode_char(umodes[i++]);
char *name = silc_channel_get_name(entry, &name_len);
if (m)
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_WHOIS_CHANNELS, buf);
silc_channel_payload_list_free(list);
+ silc_free(umodes);
}
}
if (mode) {
memset(buf, 0, sizeof(buf));
-
- if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
- (mode & SILC_UMODE_ROUTER_OPERATOR)) {
- strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
- "Server Operator " :
- (mode & SILC_UMODE_ROUTER_OPERATOR) ?
- "SILC Operator " : "[Unknown mode] ");
- }
- if (mode & SILC_UMODE_GONE)
- strcat(buf, "away");
-
+ silc_get_umode_string(mode, buf, sizeof(buf - 1));
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_WHOIS_MODES, buf);
}
3, NULL);
if (tmp)
silc_say_error("%s: %s", tmp,
- silc_client_command_status_message(status));
+ silc_get_status_message(status));
break;
} else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
/* Try to find the entry for the unknown client ID, since we
might have, and print the nickname of it for user. */
- uint32 tmp_len;
+ SilcUInt32 tmp_len;
unsigned char *tmp =
silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
2, &tmp_len);
if (tmp) {
- SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
+ NULL);
if (client_id) {
client_entry = silc_client_get_client_by_id(client, conn,
client_id);
if (client_entry && client_entry->nickname)
silc_say_error("%s: %s", client_entry->nickname,
- silc_client_command_status_message(status));
+ silc_get_status_message(status));
silc_free(client_id);
}
}
3, NULL);
if (tmp)
silc_say_error("%s: %s", tmp,
- silc_client_command_status_message(status));
+ silc_get_status_message(status));
break;
}
case SILC_COMMAND_JOIN:
{
char *channel, *mode, *topic;
- uint32 modei;
+ SilcUInt32 modei;
SilcChannelEntry channel_entry;
SilcBuffer client_id_list;
- uint32 list_count;
+ SilcUInt32 list_count;
if (!success)
return;
channel = va_arg(vp, char *);
channel_entry = va_arg(vp, SilcChannelEntry);
- modei = va_arg(vp, uint32);
- (void)va_arg(vp, uint32);
+ modei = va_arg(vp, SilcUInt32);
+ (void)va_arg(vp, SilcUInt32);
(void)va_arg(vp, unsigned char *);
(void)va_arg(vp, unsigned char *);
(void)va_arg(vp, unsigned char *);
topic = va_arg(vp, char *);
(void)va_arg(vp, unsigned char *);
- list_count = va_arg(vp, uint32);
+ list_count = va_arg(vp, SilcUInt32);
client_id_list = va_arg(vp, SilcBuffer);
chanrec = silc_channel_find(server, channel);
silc_client_get_clients_by_list(client, conn, list_count, client_id_list,
silc_client_join_get_users,
channel_entry);
+
break;
}
nicklist_rename_unique(SERVER(server),
server->conn->local_entry, server->nick,
client, client->nickname);
-
signal_emit("message own_nick", 4, server, server->nick, old, "");
g_free(old);
break;
case SILC_COMMAND_UMODE:
{
- uint32 mode;
+ SilcUInt32 mode;
if (!success)
return;
- mode = va_arg(vp, uint32);
+ mode = va_arg(vp, SilcUInt32);
if (mode & SILC_UMODE_SERVER_OPERATOR &&
!(server->umode & SILC_UMODE_SERVER_OPERATOR))
MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
server->umode = mode;
+ signal_emit("user mode changed", 2, server, NULL);
}
break;
if (!success)
return;
+ server->umode |= SILC_UMODE_SERVER_OPERATOR;
+ signal_emit("user mode changed", 2, server, NULL);
+
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
break;
if (!success)
return;
+ server->umode |= SILC_UMODE_ROUTER_OPERATOR;
+ signal_emit("user mode changed", 2, server, NULL);
+
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
break;
case SILC_COMMAND_USERS:
{
+ SilcHashTableList htl;
SilcChannelEntry channel;
SilcChannelUser chu;
MSGLEVEL_CRAP, SILCTXT_USERS_HEADER,
channel->channel_name);
- silc_list_start(channel->clients);
- while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
+ silc_hash_table_list(channel->user_list, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
SilcClientEntry e = chu->client;
char stat[5], *mode;
mode = silc_client_chumode_char(chu->mode);
if (e->mode & SILC_UMODE_GONE)
strcat(stat, "G");
- else
+ else if (e->mode & SILC_UMODE_INDISPOSED)
+ strcat(stat, "I");
+ else if (e->mode & SILC_UMODE_BUSY)
+ strcat(stat, "B");
+ else if (e->mode & SILC_UMODE_PAGE)
+ strcat(stat, "P");
+ else if (e->mode & SILC_UMODE_HYPER)
strcat(stat, "H");
+ else if (e->mode & SILC_UMODE_ROBOT)
+ strcat(stat, "R");
+ else if (e->mode & SILC_UMODE_ANONYMOUS)
+ strcat(stat, "?");
+ else
+ strcat(stat, "A");
if (mode)
strcat(stat, mode);
if (mode)
silc_free(mode);
}
+ silc_hash_table_list_reset(&htl);
}
break;
void *entry;
SilcPublicKey public_key;
unsigned char *pk;
- uint32 pk_len;
+ SilcUInt32 pk_len;
GetkeyContext getkey;
char *name;
if (!success)
return;
- id_type = va_arg(vp, uint32);
+ id_type = va_arg(vp, SilcUInt32);
entry = va_arg(vp, void *);
public_key = va_arg(vp, SilcPublicKey);
}
break;
+ case SILC_COMMAND_WATCH:
+ break;
}
va_end(vp);
char *entity;
char *entity_name;
unsigned char *pk;
- uint32 pk_len;
+ SilcUInt32 pk_len;
SilcSKEPKType pk_type;
SilcVerifyPublicKey completion;
void *context;
static void
silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
const char *name, SilcSocketType conn_type,
- unsigned char *pk, uint32 pk_len,
+ unsigned char *pk, SilcUInt32 pk_len,
SilcSKEPKType pk_type,
SilcVerifyPublicKey completion, void *context)
{
if (!name) {
snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
conn->sock->ip, conn->sock->port);
- snprintf(filename, sizeof(filename) - 1, "%s/.silc/%skeys/%s",
- pw->pw_dir, entity, file);
+ snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
+ get_irssi_dir(), entity, file);
snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
conn->sock->hostname, conn->sock->port);
- snprintf(filename2, sizeof(filename2) - 1, "%s/.silc/%skeys/%s",
- pw->pw_dir, entity, file);
+ snprintf(filename2, sizeof(filename2) - 1, "%s/%skeys/%s",
+ get_irssi_dir(), entity, file);
ipf = filename;
hostf = filename2;
} else {
snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
name, conn->sock->port);
- snprintf(filename, sizeof(filename) - 1, "%s/.silc/%skeys/%s",
- pw->pw_dir, entity, file);
+ snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
+ get_irssi_dir(), entity, file);
ipf = filename;
}
fingerprint[i] = '_';
snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
- snprintf(filename, sizeof(filename) - 1, "%s/.silc/%skeys/%s",
- pw->pw_dir, entity, file);
+ snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
+ get_irssi_dir(), entity, file);
silc_free(fingerprint);
ipf = filename;
/* The key already exists, verify it. */
SilcPublicKey public_key;
unsigned char *encpk;
- uint32 encpk_len;
+ SilcUInt32 encpk_len;
/* Load the key file, try for both IP filename and hostname filename */
if (!silc_pkcs_load_public_key(ipf, &public_key,
void
silc_verify_public_key(SilcClient client, SilcClientConnection conn,
SilcSocketType conn_type, unsigned char *pk,
- uint32 pk_len, SilcSKEPKType pk_type,
+ SilcUInt32 pk_len, SilcSKEPKType pk_type,
SilcVerifyPublicKey completion, void *context)
{
silc_verify_public_key_internal(client, conn, NULL, conn_type, pk,
is found and FALSE if not. `conn' may be NULL. */
void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
- char *hostname, uint16 port,
+ char *hostname, SilcUInt16 port,
SilcGetAuthMeth completion, void *context)
{
InternalGetAuthMethod internal;
}
if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
- uint32 err = (uint32)failure;
+ SilcUInt32 err = (SilcUInt32)failure;
if (err == SILC_AUTH_FAILED)
printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
int silc_key_agreement(SilcClient client, SilcClientConnection conn,
SilcClientEntry client_entry, const char *hostname,
- uint16 port, SilcKeyAgreementCallback *completion,
+ SilcUInt16 port, SilcKeyAgreementCallback *completion,
void **context)
{
char portstr[12];
return FALSE;
}
+/* Notifies application that file transfer protocol session is being
+ requested by the remote client indicated by the `client_entry' from
+ the `hostname' and `port'. The `session_id' is the file transfer
+ session and it can be used to either accept or reject the file
+ transfer request, by calling the silc_client_file_receive or
+ silc_client_file_close, respectively. */
+
void silc_ftp(SilcClient client, SilcClientConnection conn,
- SilcClientEntry client_entry, uint32 session_id,
- const char *hostname, uint16 port)
+ SilcClientEntry client_entry, SilcUInt32 session_id,
+ const char *hostname, SilcUInt16 port)
{
SILC_SERVER_REC *server;
char portstr[12];
client_entry->nickname, hostname, portstr);
}
+/* Delivers SILC session detachment data indicated by `detach_data' to the
+ application. If application has issued SILC_COMMAND_DETACH command
+ the client session in the SILC network is not quit. The client remains
+ in the network but is detached. The detachment data may be used later
+ to resume the session in the SILC Network. The appliation is
+ responsible of saving the `detach_data', to for example in a file.
+
+ The detachment data can be given as argument to the functions
+ silc_client_connect_to_server, or silc_client_add_connection when
+ creating connection to remote server, inside SilcClientConnectionParams
+ structure. If it is provided the client library will attempt to resume
+ the session in the network. After the connection is created
+ successfully, the application is responsible of setting the user
+ interface for user into the same state it was before detaching (showing
+ same channels, channel modes, etc). It can do this by fetching the
+ information (like joined channels) from the client library. */
+
+void
+silc_detach(SilcClient client, SilcClientConnection conn,
+ const unsigned char *detach_data, SilcUInt32 detach_data_len)
+{
+ char file[256];
+
+ /* Save the detachment data to file. */
+
+ memset(file, 0, sizeof(file));
+ snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
+ silc_file_writefile(file, detach_data, detach_data_len);
+}
+
+
/* SILC client operations */
SilcClientOperations ops = {
silc_say,
silc_failure,
silc_key_agreement,
silc_ftp,
+ silc_detach,
};