/*
silc-channels.c : irssi
- Copyright (C) 2000 - 2001 Timo Sirainen
- Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Copyright (C) 2000 - 2001, 2004, 2006 Timo Sirainen
+ Pekka Riikonen <priikone@silcnet.org>
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
#include "silc-channels.h"
#include "silc-queries.h"
#include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
#include "window-item-def.h"
#include "fe-common/core/printtext.h"
#include "fe-common/silc/module-formats.h"
+#include "silc-commands.h"
+
+void sig_mime(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
+ const char *blob, const char *nick, int verified)
+{
+ unsigned char *message;
+ SilcUInt32 message_len;
+ SilcMime mime;
+
+ if (!(IS_SILC_SERVER(server)))
+ return;
+
+ message = silc_unescape_data(blob, &message_len);
+
+ mime = silc_mime_decode(NULL, message, message_len);
+ if (!mime) {
+ silc_free(message);
+ return;
+ }
+
+ printformat_module("fe-common/silc", server,
+ channel == NULL ? NULL : channel->name,
+ MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
+ nick == NULL ? "[<unknown>]" : nick,
+ silc_mime_get_field(mime, "Content-Type"));
+
+ silc_free(message);
+ silc_mime_free(mime);
+}
+
SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server,
- const char *name, int automatic)
+ const char *name,
+ const char *visible_name,
+ int automatic)
{
SILC_CHANNEL_REC *rec;
rec = g_new0(SILC_CHANNEL_REC, 1);
rec->chat_type = SILC_PROTOCOL;
- rec->name = g_strdup(name);
- rec->server = server;
-
- channel_init((CHANNEL_REC *) rec, automatic);
+ channel_init((CHANNEL_REC *)rec, (SERVER_REC *)server, name, name,
+ automatic);
return rec;
}
{
if (!IS_SILC_CHANNEL(channel))
return;
+ if (channel->server && channel->server->disconnected)
+ return;
if (channel->server != NULL && !channel->left && !channel->kicked) {
/* destroying channel record without actually
having left the channel yet */
- silc_command_exec(channel->server, "PART", channel->name);
+ silc_command_exec(channel->server, "LEAVE", channel->name);
+ /* enable queueing because we destroy the channel immedially */
+ silc_queue_enable(channel->server->conn);
}
}
static void silc_channels_join(SILC_SERVER_REC *server,
const char *channels, int automatic)
{
- char **list, **tmp, *channel;
+ char **list, **tmp;
SILC_CHANNEL_REC *chanrec;
list = g_strsplit(channels, ",", -1);
for (tmp = list; *tmp != NULL; tmp++) {
- channel = **tmp == '#' ? g_strdup(*tmp) :
- g_strconcat("#", *tmp, NULL);
-
- chanrec = silc_channel_find(server, channel);
- if (chanrec) {
- g_free(channel);
+ chanrec = silc_channel_find(server, *tmp);
+ if (chanrec)
continue;
- }
- silc_channel_create(server, channel, FALSE);
- silc_command_exec(server, "JOIN", channel);
- g_free(channel);
+ silc_command_exec(server, "JOIN", *tmp);
}
g_strfreev(list);
static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
{
- if (IS_SILC_SERVER(server) && server->conn && server->conn->sock)
+ if (IS_SILC_SERVER(server) && server->conn)
silc_command_exec(server, "QUIT", msg);
}
-/*
- * "event join". Joined to a channel.
- */
+static void sig_gui_quit(SILC_SERVER_REC *server, const char *msg)
+{
+ silc_client_stop(silc_client);
+}
+
+/* Find Irssi channel entry by SILC channel entry */
SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
SilcChannelEntry entry)
return NULL;
}
-static void event_join(SILC_SERVER_REC *server, va_list va)
-{
- SILC_CHANNEL_REC *chanrec;
- SILC_NICK_REC *nickrec;
- SilcClientEntry client;
- SilcChannelEntry channel;
-
- client = va_arg(va, SilcClientEntry);
- channel = va_arg(va, SilcChannelEntry);
-
- if (client == 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 user;
-
- silc_list_start(chanrec->entry->clients);
- while ((user = silc_list_get(chanrec->entry->clients)) != NULL)
- if (user->client == client) {
- nickrec = silc_nicklist_insert(chanrec, user, TRUE);
- break;
- }
- }
- }
-
- signal_emit("message join", 4, server, channel->channel_name,
- client->nickname,
- client->username == NULL ? "" : client->username);
-}
-
-/*
- * "event leave". Left a channel.
- */
-
-static void event_leave(SILC_SERVER_REC *server, va_list va)
-{
- SILC_CHANNEL_REC *chanrec;
- SILC_NICK_REC *nickrec;
- SilcClientEntry client;
- SilcChannelEntry channel;
-
- client = va_arg(va, SilcClientEntry);
- channel = va_arg(va, SilcChannelEntry);
-
- signal_emit("message part", 5, server, channel->channel_name,
- client->nickname, client->username ? client->username : "",
- client->nickname);
-
- chanrec = silc_channel_find_entry(server, channel);
- if (chanrec != NULL) {
- nickrec = silc_nicklist_find(chanrec, client);
- if (nickrec != NULL)
- nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
- }
-}
-
-/*
- * "event signoff". Left the network.
- */
-
-static void event_signoff(SILC_SERVER_REC *server, va_list va)
-{
- SilcClientEntry client;
- GSList *nicks, *tmp;
- char *message;
-
- client = va_arg(va, SilcClientEntry);
- message = va_arg(va, char *);
-
- signal_emit("message quit", 4, server, client->nickname,
- client->username ? client->username : "",
- message ? message : "");
-
- nicks = nicklist_get_same_unique(SERVER(server), client);
- for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
- CHANNEL_REC *channel = tmp->data;
- NICK_REC *nickrec = tmp->next->data;
-
- nicklist_remove(channel, nickrec);
- }
-}
-
-/*
- * "event topic". Changed topic.
- */
-
-static void event_topic(SILC_SERVER_REC *server, va_list va)
-{
- SILC_CHANNEL_REC *chanrec;
- SilcClientEntry client;
- SilcChannelEntry channel;
- char *topic;
-
- client = va_arg(va, SilcClientEntry);
- topic = 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 = *topic == '\0' ? NULL : g_strdup(topic);
- signal_emit("channel topic changed", 1, chanrec);
- }
-
- signal_emit("message topic", 5, server, channel->channel_name,
- topic, client->nickname, client->username);
-}
-
-/*
- * "event invite". Invited or modified invite list.
- */
-
-static void event_invite(SILC_SERVER_REC *server, va_list va)
-{
- SilcClientEntry client;
- SilcChannelEntry channel;
- char *channel_name;
-
- channel = va_arg(va, SilcChannelEntry);
- channel_name = va_arg(va, char *);
- client = va_arg(va, SilcClientEntry);
-
- signal_emit("message invite", 4, server, channel ? channel->channel_name :
- channel_name, client->nickname, client->username);
-}
-
-/*
- * "event nick". Changed nickname.
- */
-
-static void event_nick(SILC_SERVER_REC *server, va_list va)
-{
- SilcClientEntry oldclient, newclient;
-
- oldclient = va_arg(va, SilcClientEntry);
- newclient = va_arg(va, SilcClientEntry);
-
- nicklist_rename_unique(SERVER(server),
- oldclient, oldclient->nickname,
- newclient, newclient->nickname);
-
- signal_emit("message nick", 4, server, newclient->nickname,
- oldclient->nickname, newclient->username);
-}
-
-/*
- * "event cmode". Changed channel mode.
- */
-
-static void event_cmode(SILC_SERVER_REC *server, va_list va)
-{
- SILC_CHANNEL_REC *chanrec;
- SilcClientEntry client;
- SilcChannelEntry channel;
- char *mode;
- uint32 modei;
-
- client = va_arg(va, SilcClientEntry);
- modei = va_arg(va, uint32);
- (void)va_arg(va, char *);
- (void)va_arg(va, char *);
- channel = va_arg(va, SilcChannelEntry);
-
- mode = silc_client_chmode(modei,
- channel->channel_key->cipher->name,
- channel->hmac->hmac->name);
-
- chanrec = silc_channel_find_entry(server, channel);
- if (chanrec != NULL) {
- g_free_not_null(chanrec->mode);
- chanrec->mode = g_strdup(mode == NULL ? "" : mode);
- signal_emit("channel mode changed", 1, chanrec);
- }
-
- printformat_module("fe-common/silc", server, channel->channel_name,
- MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
- channel->channel_name, mode ? mode : "removed all",
- client->nickname);
-
- g_free(mode);
-}
-
-/*
- * "event cumode". Changed user's mode on channel.
- */
-
-static void event_cumode(SILC_SERVER_REC *server, va_list va)
-{
- SILC_CHANNEL_REC *chanrec;
- SilcClientEntry client, destclient;
- SilcChannelEntry channel;
- int mode;
- char *modestr;
-
- client = va_arg(va, SilcClientEntry);
- mode = va_arg(va, uint32);
- destclient = va_arg(va, SilcClientEntry);
- channel = va_arg(va, SilcChannelEntry);
-
- modestr = silc_client_chumode(mode);
- chanrec = silc_channel_find_entry(server, channel);
- if (chanrec != NULL) {
- SILC_NICK_REC *nick;
-
- if (destclient == server->conn->local_entry) {
- chanrec->chanop =
- (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
- }
-
- nick = silc_nicklist_find(chanrec, destclient);
- 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);
- }
- }
-
- printformat_module("fe-common/silc", server, channel->channel_name,
- MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
- channel->channel_name, destclient->nickname,
- modestr ? modestr : "removed all",
- client->nickname);
-
- if (mode & SILC_CHANNEL_UMODE_CHANFO)
- printformat_module("fe-common/silc",
- server, channel->channel_name, MSGLEVEL_CRAP,
- SILCTXT_CHANNEL_FOUNDER,
- channel->channel_name, destclient->nickname);
-
- g_free(modestr);
-}
-
-/*
- * "event motd". Received MOTD.
- */
-
-static void event_motd(SILC_SERVER_REC *server, va_list va)
-{
- char *text = va_arg(va, char *);
-
- if (!settings_get_bool("skip_motd"))
- printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
-}
-
-/*
- * "event channel_change". Channel ID has changed.
- */
-
-static void event_channel_change(SILC_SERVER_REC *server, va_list va)
-{
- /* Nothing interesting to do */
-}
-
-/*
- * "event server_signoff". Server has quit the network.
- */
-
-static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
-{
- SilcClientEntry *clients;
- uint32 clients_count;
- int i;
-
- (void)va_arg(va, void *);
- clients = va_arg(va, SilcClientEntry *);
- clients_count = va_arg(va, uint32);
-
- for (i = 0; i < clients_count; i++)
- signal_emit("message quit", 4, server, clients[i]->nickname,
- clients[i]->username ? clients[i]->username : "",
- "server signoff");
-}
-
-/*
- * "event kick". Someone was kicked from channel.
- */
-
-static void event_kick(SILC_SERVER_REC *server, va_list va)
-{
- SilcClientConnection conn = server->conn;
- SilcClientEntry client_entry;
- SilcChannelEntry channel_entry;
- char *tmp;
-
- client_entry = va_arg(va, SilcClientEntry);
- tmp = va_arg(va, char *);
- channel_entry = va_arg(va, SilcChannelEntry);
-
- if (client_entry == conn->local_entry) {
- printformat_module("fe-common/silc", server, channel_entry->channel_name,
- MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
- channel_entry->channel_name, tmp ? tmp : "");
- } else {
- printformat_module("fe-common/silc", server, channel_entry->channel_name,
- MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
- client_entry->nickname,
- channel_entry->channel_name, tmp ? tmp : "");
- }
-}
-
-/*
- * "event kill". Someone was killed from the network.
- */
-
-static void event_kill(SILC_SERVER_REC *server, va_list va)
-{
- SilcClientConnection conn = server->conn;
- SilcClientEntry client_entry;
- char *tmp;
-
- client_entry = va_arg(va, SilcClientEntry);
- tmp = va_arg(va, char *);
-
- if (client_entry == conn->local_entry) {
- printformat_module("fe-common/silc", server, NULL,
- MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
- tmp ? tmp : "");
- } else {
- printformat_module("fe-common/silc", server, NULL,
- MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
- client_entry->nickname,
- tmp ? tmp : "");
- }
-}
-
/* PART (LEAVE) command. */
static void command_part(const char *data, SILC_SERVER_REC *server,
WI_ITEM_REC *item)
{
SILC_CHANNEL_REC *chanrec;
-
+ char userhost[256];
+
+ CMD_SILC_SERVER(server);
+
if (!IS_SILC_SERVER(server) || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
- if (*data == '\0') {
+ if (!strcmp(data, "*") || *data == '\0') {
if (!IS_SILC_CHANNEL(item))
cmd_return_error(CMDERR_NOT_JOINED);
- data = item->name;
+ data = item->visible_name;
}
chanrec = silc_channel_find(server, data);
- if (chanrec == NULL)
+ if (chanrec == NULL)
cmd_return_error(CMDERR_CHAN_NOT_FOUND);
+ memset(userhost, 0, sizeof(userhost));
+ snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
+ server->conn->local_entry->username,
+ server->conn->local_entry->hostname);
signal_emit("message part", 5, server, chanrec->name,
- server->nick, server->conn->local_entry->username, "");
-
+ server->nick, userhost, "");
+
+ chanrec->left = TRUE;
silc_command_exec(server, "LEAVE", chanrec->name);
+ /* enable queueing because we destroy the channel immedially */
+ silc_queue_enable(server->conn);
signal_stop();
-
+
channel_destroy(CHANNEL(chanrec));
}
-/* ME local command. */
-static void command_me(const char *data, SILC_SERVER_REC *server,
- WI_ITEM_REC *item)
+/* ACTION local command. */
+
+static void command_action(const char *data, SILC_SERVER_REC *server,
+ WI_ITEM_REC *item)
{
- SILC_CHANNEL_REC *chanrec;
- char *tmpcmd = "ME", *tmp;
- uint32 argc = 0;
- unsigned char **argv;
- uint32 *argv_lens, *argv_types;
- int i;
-
+ GHashTable *optlist;
+ char *target, *msg;
+ char *message = NULL;
+ int target_type;
+ void *free_arg;
+
+ CMD_SILC_SERVER(server);
if (!IS_SILC_SERVER(server) || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
- if (!IS_SILC_CHANNEL(item))
+ if ((item != NULL) && (!IS_SILC_CHANNEL(item) && !IS_SILC_QUERY(item)))
cmd_return_error(CMDERR_NOT_JOINED);
/* Now parse all arguments */
- tmp = g_strconcat(tmpcmd, " ", data, NULL);
- silc_parse_command_line(tmp, &argv, &argv_lens,
- &argv_types, &argc, 2);
- g_free(tmp);
-
- if (argc < 2)
- cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST,
+ "action", &optlist, &target, &msg))
+ return;
- chanrec = silc_channel_find(server, item->name);
- if (chanrec == NULL)
- cmd_return_error(CMDERR_CHAN_NOT_FOUND);
+ if (*target == '\0' || *msg == '\0')
+ cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+ if (strcmp(target, "*") == 0) {
+ /* send to active channel/query */
+ if (item == NULL)
+ cmd_param_error(CMDERR_NOT_JOINED);
+
+ target_type = IS_SILC_CHANNEL(item) ?
+ SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+ target = (char *)window_item_get_target(item);
+ } else if (g_hash_table_lookup(optlist, "channel") != NULL)
+ target_type = SEND_TARGET_CHANNEL;
+ else {
+ target_type = SEND_TARGET_NICK;
+ }
- /* Send the action message */
- silc_client_send_channel_message(silc_client, server->conn,
- chanrec->entry, NULL,
- SILC_MESSAGE_FLAG_ACTION,
- argv[1], argv_lens[1], TRUE);
+ if (!silc_term_utf8()) {
+ int len = silc_utf8_encoded_len(msg, strlen(msg),
+ SILC_STRING_LOCALE);
+ message = silc_calloc(len + 1, sizeof(*message));
+ g_return_if_fail(message != NULL);
+ silc_utf8_encode(msg, strlen(msg), SILC_STRING_LOCALE,
+ message, len);
+ }
- printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
- MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
- server->conn->local_entry->nickname, argv[1]);
+ if (target != NULL) {
+ if (target_type == SEND_TARGET_CHANNEL) {
+ if (silc_send_channel(server, target, (message != NULL ? message : msg),
+ SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 |
+ (g_hash_table_lookup(optlist, "sign") != NULL ?
+ SILC_MESSAGE_FLAG_SIGNED : 0))) {
+ if (g_hash_table_lookup(optlist, "sign"))
+ signal_emit("message silc signed_own_action", 3, server, msg, target);
+ else
+ signal_emit("message silc own_action", 3, server, msg, target);
+ }
+ } else {
+ if (silc_send_msg(server, target, (message != NULL ? message : msg),
+ (message != NULL ? strlen(message) : strlen(msg)),
+ SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 |
+ (g_hash_table_lookup(optlist, "sign") != NULL ?
+ SILC_MESSAGE_FLAG_SIGNED : 0))) {
+ if (g_hash_table_lookup(optlist, "sign"))
+ signal_emit("message silc signed_own_private_action", 3,
+ server, msg, target);
+ else
+ signal_emit("message silc own_private_action", 3,
+ server, msg, target);
+ }
+ }
+ }
- for (i = 0; i < argc; i++)
- silc_free(argv[i]);
- silc_free(argv_lens);
- silc_free(argv_types);
+ cmd_params_free(free_arg);
+ silc_free(message);
}
-/* ACTION local command. Same as ME but takes the channel as mandatory
- argument. */
+/* ME local command. */
-static void command_action(const char *data, SILC_SERVER_REC *server,
- WI_ITEM_REC *item)
+static void command_me(const char *data, SILC_SERVER_REC *server,
+ WI_ITEM_REC *item)
{
- SILC_CHANNEL_REC *chanrec;
- char *tmpcmd = "ME", *tmp;
- uint32 argc = 0;
- unsigned char **argv;
- uint32 *argv_lens, *argv_types;
- int i;
-
+ char *tmpcmd;
+
+ CMD_SILC_SERVER(server);
if (!IS_SILC_SERVER(server) || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
- if (!IS_SILC_CHANNEL(item))
+ if (!IS_SILC_CHANNEL(item) && !IS_SILC_QUERY(item))
cmd_return_error(CMDERR_NOT_JOINED);
- /* Now parse all arguments */
- tmp = g_strconcat(tmpcmd, " ", data, NULL);
- silc_parse_command_line(tmp, &argv, &argv_lens,
- &argv_types, &argc, 3);
- g_free(tmp);
-
- if (argc < 3)
- cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
-
- chanrec = silc_channel_find(server, argv[1]);
- if (chanrec == NULL)
- cmd_return_error(CMDERR_CHAN_NOT_FOUND);
-
- /* Send the action message */
- silc_client_send_channel_message(silc_client, server->conn,
- chanrec->entry, NULL,
- SILC_MESSAGE_FLAG_ACTION,
- argv[2], argv_lens[2], TRUE);
+ if (IS_SILC_CHANNEL(item))
+ tmpcmd = g_strdup_printf("-channel %s %s", item->visible_name, data);
+ else
+ tmpcmd = g_strdup_printf("%s %s", item->visible_name, data);
- printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
- MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
- server->conn->local_entry->nickname, argv[2]);
-
- for (i = 0; i < argc; i++)
- silc_free(argv[i]);
- silc_free(argv_lens);
- silc_free(argv_types);
+ command_action(tmpcmd, server, item);
+ g_free(tmpcmd);
}
/* NOTICE local command. */
static void command_notice(const char *data, SILC_SERVER_REC *server,
WI_ITEM_REC *item)
{
- SILC_CHANNEL_REC *chanrec;
- char *tmpcmd = "ME", *tmp;
- uint32 argc = 0;
- unsigned char **argv;
- uint32 *argv_lens, *argv_types;
- int i;
-
+ GHashTable *optlist;
+ char *target, *msg;
+ char *message = NULL;
+ int target_type;
+ void *free_arg;
+
+ CMD_SILC_SERVER(server);
if (!IS_SILC_SERVER(server) || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
- if (!IS_SILC_CHANNEL(item))
+ if ((item != NULL) && (!IS_SILC_CHANNEL(item) && !IS_SILC_QUERY(item)))
cmd_return_error(CMDERR_NOT_JOINED);
/* Now parse all arguments */
- tmp = g_strconcat(tmpcmd, " ", data, NULL);
- silc_parse_command_line(tmp, &argv, &argv_lens,
- &argv_types, &argc, 2);
- g_free(tmp);
-
- if (argc < 2)
- cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST,
+ "notice", &optlist, &target, &msg))
+ return;
- chanrec = silc_channel_find(server, item->name);
- if (chanrec == NULL)
- cmd_return_error(CMDERR_CHAN_NOT_FOUND);
+ if (*target == '\0' || *msg == '\0')
+ cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+ if (strcmp(target, "*") == 0) {
+ /* send to active channel/query */
+ if (item == NULL)
+ cmd_param_error(CMDERR_NOT_JOINED);
+
+ target_type = IS_SILC_CHANNEL(item) ?
+ SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+ target = (char *)window_item_get_target(item);
+ } else if (g_hash_table_lookup(optlist, "channel") != NULL)
+ target_type = SEND_TARGET_CHANNEL;
+ else {
+ target_type = SEND_TARGET_NICK;
+ }
- /* Send the action message */
- silc_client_send_channel_message(silc_client, server->conn,
- chanrec->entry, NULL,
- SILC_MESSAGE_FLAG_NOTICE,
- argv[1], argv_lens[1], TRUE);
+ if (!silc_term_utf8()) {
+ int len = silc_utf8_encoded_len(msg, strlen(msg),
+ SILC_STRING_LOCALE);
+ message = silc_calloc(len + 1, sizeof(*message));
+ g_return_if_fail(message != NULL);
+ silc_utf8_encode(msg, strlen(msg), SILC_STRING_LOCALE,
+ message, len);
+ }
- printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
- MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
- server->conn->local_entry->nickname, argv[1]);
+ if (target != NULL) {
+ if (target_type == SEND_TARGET_CHANNEL) {
+ if (silc_send_channel(server, target, (message != NULL ? message : msg),
+ SILC_MESSAGE_FLAG_NOTICE | SILC_MESSAGE_FLAG_UTF8 |
+ (g_hash_table_lookup(optlist, "sign") != NULL ?
+ SILC_MESSAGE_FLAG_SIGNED : 0))) {
+ if (g_hash_table_lookup(optlist, "sign"))
+ signal_emit("message silc signed_own_notice", 3, server, msg, target);
+ else
+ signal_emit("message silc own_notice", 3, server, msg, target);
+ }
+ } else {
+ if (silc_send_msg(server, target, (message != NULL ? message : msg),
+ (message != NULL ? strlen(message) : strlen(msg)),
+ SILC_MESSAGE_FLAG_NOTICE | SILC_MESSAGE_FLAG_UTF8 |
+ (g_hash_table_lookup(optlist, "sign") != NULL ?
+ SILC_MESSAGE_FLAG_SIGNED : 0))) {
+ if (g_hash_table_lookup(optlist, "sign"))
+ signal_emit("message silc signed_own_private_notice", 3,
+ server, msg, target);
+ else
+ signal_emit("message silc own_private_notice", 3,
+ server, msg, target);
+ }
+ }
+ }
- for (i = 0; i < argc; i++)
- silc_free(argv[i]);
- silc_free(argv_lens);
- silc_free(argv_types);
+ cmd_params_free(free_arg);
+ silc_free(message);
}
/* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
flag. */
-static void command_away(const char *data, SILC_SERVER_REC *server,
- WI_ITEM_REC *item)
+bool silc_set_away(const char *reason, SILC_SERVER_REC *server)
{
bool set;
if (!IS_SILC_SERVER(server) || !server->connected)
- cmd_return_error(CMDERR_NOT_CONNECTED);
+ return FALSE;
- if (*data == '\0') {
+ if (*reason == '\0') {
/* Remove any possible away message */
silc_client_set_away_message(silc_client, server->conn, NULL);
set = FALSE;
- printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+ printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_UNSET_AWAY);
} else {
/* Set the away message */
- silc_client_set_away_message(silc_client, server->conn, (char *)data);
+ silc_client_set_away_message(silc_client, server->conn, (char *)reason);
set = TRUE;
- printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
- SILCTXT_SET_AWAY, data);
+ printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_SET_AWAY, reason);
}
+ server->usermode_away = set;
+ g_free_and_null(server->away_reason);
+ if (set)
+ server->away_reason = g_strdup((char *)reason);
+
signal_emit("away mode changed", 1, server);
- silc_command_exec(server, "UMODE", set ? "+g" : "-g");
+ return set;
+}
+
+static void command_away(const char *data, SILC_SERVER_REC *server,
+ WI_ITEM_REC *item)
+{
+ CMD_SILC_SERVER(server);
+
+ if (!IS_SILC_SERVER(server) || !server->connected)
+ cmd_return_error(CMDERR_NOT_CONNECTED);
+
+ g_free_and_null(server->away_reason);
+ if ((data) && (*data != '\0'))
+ server->away_reason = g_strdup(data);
+
+ silc_command_exec(server, "UMODE",
+ (server->away_reason != NULL) ? "+g" : "-g");
}
typedef struct {
int type; /* 1 = msg, 2 = channel */
+ bool responder;
SILC_SERVER_REC *server;
} *KeyInternal;
switch(status) {
case SILC_KEY_AGREEMENT_OK:
- printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
if (i->type == 1) {
/* Set the private key for this client */
silc_client_del_private_message_key(client, conn, client_entry);
silc_client_add_private_message_key_ske(client, conn, client_entry,
- NULL, key);
- printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
- SILCTXT_KEY_AGREEMENT_PRIVMSG,
+ NULL, NULL, key, i->responder);
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_KEY_AGREEMENT_PRIVMSG,
client_entry->nickname);
silc_ske_free_key_material(key);
}
-
+
break;
-
+
case SILC_KEY_AGREEMENT_ERROR:
- printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
break;
-
+
case SILC_KEY_AGREEMENT_FAILURE:
- printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
break;
-
+
case SILC_KEY_AGREEMENT_TIMEOUT:
- printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
break;
-
+
+ case SILC_KEY_AGREEMENT_ABORTED:
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_KEY_AGREEMENT_ABORTED, client_entry->nickname);
+ break;
+
+ case SILC_KEY_AGREEMENT_ALREADY_STARTED:
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_KEY_AGREEMENT_ALREADY_STARTED,
+ client_entry->nickname);
+ break;
+
+ case SILC_KEY_AGREEMENT_SELF_DENIED:
+ printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_KEY_AGREEMENT_SELF_DENIED);
+ break;
+
default:
break;
- }
+ }
if (i)
silc_free(i);
}
+#if 0
/* Local command KEY. This command is used to set and unset private
keys for channels, set and unset private keys for private messages
with remote clients and to send key agreement requests and
typedef struct {
SILC_SERVER_REC *server;
char *data;
+ char *nick;
WI_ITEM_REC *item;
} *KeyGetClients;
/* Callback to be called after client information is resolved from the
server. */
-SILC_CLIENT_CMD_FUNC(key_get_clients)
+static void silc_client_command_key_get_clients(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry *clients,
+ SilcUInt32 clients_count,
+ void *context)
{
KeyGetClients internal = (KeyGetClients)context;
+
+ if (!clients) {
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
+ internal->nick);
+ silc_free(internal->data);
+ silc_free(internal->nick);
+ silc_free(internal);
+ return;
+ }
+
signal_emit("command key", 3, internal->data, internal->server,
internal->item);
+
silc_free(internal->data);
+ silc_free(internal->nick);
silc_free(internal);
}
static void command_key(const char *data, SILC_SERVER_REC *server,
WI_ITEM_REC *item)
{
- SilcClientConnection conn = server->conn;
- SilcClientEntry client_entry = NULL;
+ SilcClientConnection conn;
+ SilcClientEntry *entrys, client_entry = NULL;
+ SilcUInt32 entry_count;
+ SILC_CHANNEL_REC *chanrec = NULL;
SilcChannelEntry channel_entry = NULL;
- uint32 num = 0;
- char *nickname = NULL, *serv = NULL, *tmp;
+ char *nickname = NULL, *tmp;
int command = 0, port = 0, type = 0;
char *hostname = NULL;
KeyInternal internal = NULL;
- uint32 argc = 0;
+ SilcUInt32 argc = 0;
unsigned char **argv;
- uint32 *argv_lens, *argv_types;
-
- if (!IS_SILC_SERVER(server) || !server->connected)
+ SilcUInt32 *argv_lens, *argv_types;
+ char *bindhost = NULL;
+
+ CMD_SILC_SERVER(server);
+
+ if (!server || !IS_SILC_SERVER(server) || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
+ conn = server->conn;
+
/* Now parse all arguments */
tmp = g_strconcat("KEY", " ", data, NULL);
silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
g_free(tmp);
- if (argc < 4) {
- silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
- "set|unset|agreement|negotiate [<arguments>]");
- return;
- }
+ if (argc < 4)
+ cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
/* Get type */
if (!strcasecmp(argv[1], "msg"))
if (!strcasecmp(argv[1], "channel"))
type = 2;
- if (type == 0) {
- silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
- "set|unset|agreement|negotiate [<arguments>]");
- return;
- }
+ if (type == 0)
+ cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
if (type == 1) {
if (argv[2][0] == '*') {
- nickname = "*";
+ nickname = strdup("*");
} else {
/* Parse the typed nickname. */
- if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
+ if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) {
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
return;
}
-
+
/* Find client entry */
- client_entry = silc_idlist_get_client(silc_client, conn, nickname,
- serv, num, TRUE);
- if (!client_entry) {
+ entrys = silc_client_get_clients_local(silc_client, conn, nickname,
+ argv[2], &entry_count);
+ if (!entrys) {
KeyGetClients inter = silc_calloc(1, sizeof(*inter));
inter->server = server;
inter->data = strdup(data);
+ inter->nick = strdup(nickname);
inter->item = item;
-
- /* Client entry not found, it was requested thus mark this to be
- pending command. */
- silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident,
- NULL, silc_client_command_key_get_clients,
- inter);
+ silc_client_get_clients(silc_client, conn, nickname, argv[2],
+ silc_client_command_key_get_clients, inter);
goto out;
}
+ client_entry = entrys[0];
+ silc_free(entrys);
}
}
if (argv[2][0] == '*') {
if (!conn->current_channel) {
- if (nickname)
- silc_free(nickname);
- if (serv)
- silc_free(serv);
+ silc_free(nickname);
cmd_return_error(CMDERR_NOT_JOINED);
}
name = conn->current_channel->channel_name;
name = argv[2];
}
- channel_entry = silc_client_get_channel(silc_client, conn, name);
- if (!channel_entry) {
- if (nickname)
- silc_free(nickname);
- if (serv)
- silc_free(serv);
- cmd_return_error(CMDERR_NOT_JOINED);
+ chanrec = silc_channel_find(server, name);
+ if (chanrec == NULL) {
+ silc_free(nickname);
+ cmd_return_error(CMDERR_CHAN_NOT_FOUND);
}
+ channel_entry = chanrec->entry;
}
/* Set command */
command = 1;
if (argc >= 5) {
+ char *cipher = NULL, *hmac = NULL;
+
if (type == 1 && client_entry) {
/* Set private message key */
-
+ bool responder = FALSE;
+
silc_client_del_private_message_key(silc_client, conn, client_entry);
- if (argc >= 6)
- silc_client_add_private_message_key(silc_client, conn, client_entry,
- argv[5], argv[4],
- argv_lens[4],
- (argv[4][0] == '*' ?
- TRUE : FALSE));
- else
- silc_client_add_private_message_key(silc_client, conn, client_entry,
- NULL, argv[4],
- argv_lens[4],
- (argv[4][0] == '*' ?
- TRUE : FALSE));
+ if (argc >= 6) {
+ if (!strcasecmp(argv[5], "-responder"))
+ responder = TRUE;
+ else
+ cipher = argv[5];
+ }
+ if (argc >= 7) {
+ if (!strcasecmp(argv[6], "-responder"))
+ responder = TRUE;
+ else
+ hmac = argv[6];
+ }
+ if (argc >= 8) {
+ if (!strcasecmp(argv[7], "-responder"))
+ responder = TRUE;
+ }
+
+ silc_client_add_private_message_key(silc_client, conn, client_entry,
+ cipher, hmac,
+ argv[4], argv_lens[4],
+ (argv[4][0] == '*' ?
+ TRUE : FALSE), responder);
/* Send the key to the remote client so that it starts using it
too. */
- silc_client_send_private_message_key(silc_client, conn,
+ /* XXX for now we don't do this. This feature is pretty stupid
+ and should perhaps be removed altogether from SILC.
+ silc_client_send_private_message_key(silc_client, conn,
client_entry, TRUE);
+ */
} else if (type == 2) {
/* Set private channel key */
- char *cipher = NULL, *hmac = NULL;
-
if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
- SILCTXT_CH_PRIVATE_KEY_NOMODE,
+ SILCTXT_CH_PRIVATE_KEY_NOMODE,
channel_entry->channel_name);
goto out;
}
if (argc >= 7)
hmac = argv[6];
- if (!silc_client_add_channel_private_key(silc_client, conn,
- channel_entry,
+ if (!silc_client_add_channel_private_key(silc_client, conn,
+ channel_entry, NULL,
cipher, hmac,
argv[4],
- argv_lens[4])) {
+ argv_lens[4], NULL)) {
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
- SILCTXT_CH_PRIVATE_KEY_ERROR,
+ SILCTXT_CH_PRIVATE_KEY_ERROR,
channel_entry->channel_name);
goto out;
}
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
- SILCTXT_CH_PRIVATE_KEY_ADD,
+ SILCTXT_CH_PRIVATE_KEY_ADD,
channel_entry->channel_name);
}
}
goto out;
}
-
+
/* Unset command */
if (!strcasecmp(argv[3], "unset")) {
command = 2;
} else if (type == 2) {
/* Unset channel key(s) */
SilcChannelPrivateKey *keys;
- uint32 keys_count;
+ SilcUInt32 keys_count;
int number;
if (argc == 4)
- silc_client_del_channel_private_keys(silc_client, conn,
+ silc_client_del_channel_private_keys(silc_client, conn,
channel_entry);
if (argc > 4) {
number = atoi(argv[4]);
- keys = silc_client_list_channel_private_keys(silc_client, conn,
+ keys = silc_client_list_channel_private_keys(silc_client, conn,
channel_entry,
&keys_count);
if (!keys)
if (type == 1) {
SilcPrivateMessageKeys keys;
- uint32 keys_count;
+ SilcUInt32 keys_count;
int k, i, len;
char buf[1024];
- keys = silc_client_list_private_message_keys(silc_client, conn,
+ keys = silc_client_list_private_message_keys(silc_client, conn,
&keys_count);
if (!keys)
goto out;
for (i = 0; i < 30 - len; i++)
strcat(buf, " ");
strcat(buf, " ");
-
+
len = strlen(keys[k].cipher);
strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
if (len < 14)
else
strcat(buf, "*generated*");
- silc_say(silc_client, conn, "%s", buf);
+ silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
}
} else {
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
for (i = 0; i < 30 - len; i++)
strcat(buf, " ");
strcat(buf, " ");
-
+
len = strlen(keys[k].cipher);
strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
if (len < 14)
else
strcat(buf, "*generated*");
- silc_say(silc_client, conn, "%s", buf);
+ silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
}
}
silc_client_free_private_message_keys(keys, keys_count);
+
} else if (type == 2) {
SilcChannelPrivateKey *keys;
- uint32 keys_count;
+ SilcUInt32 keys_count;
int k, i, len;
char buf[1024];
- keys = silc_client_list_channel_private_keys(silc_client, conn,
+ keys = silc_client_list_channel_private_keys(silc_client, conn,
channel_entry,
&keys_count);
- if (!keys)
- goto out;
-
+
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_CH_PRIVATE_KEY_LIST,
channel_entry->channel_name);
+
+ if (!keys)
+ goto out;
+
for (k = 0; k < keys_count; k++) {
memset(buf, 0, sizeof(buf));
strncat(buf, " ", 2);
- len = strlen(keys[k]->cipher->cipher->name);
- strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
+ len = strlen(silc_cipher_get_name(keys[k]->cipher));
+ strncat(buf, silc_cipher_get_name(keys[k]->cipher),
+ len > 16 ? 16 : len);
if (len < 16)
for (i = 0; i < 16 - len; i++)
strcat(buf, " ");
strcat(buf, " ");
-
- len = strlen(keys[k]->hmac->hmac->name);
- strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
+
+ len = strlen(silc_hmac_get_name(keys[k]->hmac));
+ strncat(buf, silc_hmac_get_name(keys[k]->hmac), len > 16 ? 16 : len);
if (len < 16)
for (i = 0; i < 16 - len; i++)
strcat(buf, " ");
strcat(buf, " ");
-
+
strcat(buf, "<hidden>");
- silc_say(silc_client, conn, "%s", buf);
+ silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
}
-
+
silc_client_free_channel_private_keys(keys, keys_count);
}
internal = silc_calloc(1, sizeof(*internal));
internal->type = type;
internal->server = server;
+
+ if (!hostname) {
+ if (settings_get_bool("use_auto_addr")) {
+
+ hostname = (char *)settings_get_str("auto_public_ip");
+
+ /* If the hostname isn't set, treat this case as if auto_public_ip
+ wasn't set. */
+ if ((hostname) && (*hostname == '\0')) {
+ hostname = NULL;
+ } else {
+ bindhost = (char *)settings_get_str("auto_bind_ip");
+
+ /* if the bind_ip isn't set, but the public_ip IS, then assume then
+ public_ip is the same value as the bind_ip. */
+ if ((bindhost) && (*bindhost == '\0'))
+ bindhost = hostname;
+ port = settings_get_int("auto_bind_port");
+ }
+ } /* if use_auto_addr */
+ }
}
/* Start command is used to start key agreement (after receiving the
internal->server = server;
}
+ /* Change current channel private key */
+ if (!strcasecmp(argv[3], "change")) {
+ command = 6;
+ if (type == 2) {
+ /* Unset channel key(s) */
+ SilcChannelPrivateKey *keys;
+ SilcUInt32 keys_count;
+ int number;
+
+ keys = silc_client_list_channel_private_keys(silc_client, conn,
+ channel_entry,
+ &keys_count);
+ if (!keys)
+ goto out;
+
+ if (argc == 4) {
+ chanrec->cur_key++;
+ if (chanrec->cur_key >= keys_count)
+ chanrec->cur_key = 0;
+ }
+
+ if (argc > 4) {
+ number = atoi(argv[4]);
+ if (!number || number > keys_count)
+ chanrec->cur_key = 0;
+ else
+ chanrec->cur_key = number - 1;
+ }
+
+ /* Set the current channel private key */
+ silc_client_current_channel_private_key(silc_client, conn,
+ channel_entry,
+ keys[chanrec->cur_key]);
+ printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+ SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
+ channel_entry->channel_name);
+
+ silc_client_free_channel_private_keys(keys, keys_count);
+ goto out;
+ }
+ }
+
if (command == 0) {
- silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
+ silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO,
+ "Usage: /KEY msg|channel <nickname|channel> "
"set|unset|agreement|negotiate [<arguments>]");
goto out;
}
if (command == 4 && client_entry) {
- printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
+ printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT, argv[2]);
- silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
- port, 120, keyagr_completion, internal);
+ internal->responder = TRUE;
+ silc_client_send_key_agreement(
+ silc_client, conn, client_entry, hostname,
+ bindhost, port,
+ settings_get_int("key_exchange_timeout_secs"),
+ keyagr_completion, internal);
+ if (!hostname)
+ silc_free(internal);
goto out;
}
if (command == 5 && client_entry && hostname) {
- printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
+ printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
- silc_client_perform_key_agreement(silc_client, conn, client_entry,
- hostname, port, keyagr_completion,
+ internal->responder = FALSE;
+ silc_client_perform_key_agreement(silc_client, conn, client_entry,
+ hostname, port, keyagr_completion,
internal);
goto out;
}
out:
- if (nickname)
- silc_free(nickname);
- if (serv)
- silc_free(serv);
+ silc_free(nickname);
+}
+
+void silc_list_key(const char *pub_filename, int verbose)
+{
+ SilcPublicKey public_key;
+ SilcPublicKeyIdentifier ident;
+ char *fingerprint, *babbleprint;
+ unsigned char *pk;
+ SilcUInt32 pk_len;
+ SilcPKCS pkcs;
+ SilcUInt32 key_len = 0;
+ int is_server_key = (strstr(pub_filename, "serverkeys") != NULL);
+
+ if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
+ SILC_PKCS_FILE_PEM) == FALSE)
+ if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
+ SILC_PKCS_FILE_BIN) == FALSE) {
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_LOADPUB,
+ pub_filename);
+ return;
+ }
+
+ ident = silc_pkcs_decode_identifier(public_key->identifier);
+
+ pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+ babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+ if (silc_pkcs_alloc(public_key->name, &pkcs)) {
+ key_len = silc_pkcs_public_key_set(pkcs, public_key);
+ silc_pkcs_free(pkcs);
+ }
+
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_FILE,
+ pub_filename);
+
+ if (verbose)
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_ALG,
+ public_key->name);
+ if (key_len && verbose)
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_BITS,
+ (unsigned int)key_len);
+ if (ident->realname && (!is_server_key || verbose))
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_RN,
+ ident->realname);
+ if (ident->username && verbose)
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_UN,
+ ident->username);
+ if (ident->host && (is_server_key || verbose))
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_HN,
+ ident->host);
+ if (ident->email && verbose)
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_EMAIL,
+ ident->email);
+ if (ident->org && verbose)
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_ORG,
+ ident->org);
+ if (ident->country && verbose)
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_C,
+ ident->country);
+
+ if (verbose) {
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_FINGER,
+ fingerprint);
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_BABL,
+ babbleprint);
+ }
+
+ silc_free(fingerprint);
+ silc_free(babbleprint);
+ silc_free(pk);
+ silc_pkcs_public_key_free(public_key);
+ silc_pkcs_free_identifier(ident);
+
+}
+
+void silc_list_keys_in_dir(const char *dirname, const char *where)
+{
+ DIR *dir;
+ struct dirent *entry;
+
+ dir = opendir(dirname);
+
+ if (dir == NULL)
+ cmd_return_error(CMDERR_ERRNO);
+
+ printformat_module("fe-common/silc", NULL, NULL,
+ MSGLEVEL_CRAP, SILCTXT_LISTKEY_LIST,
+ where);
+
+ rewinddir(dir);
+
+ while ((entry = readdir(dir)) != NULL) {
+ /* try to open everything that isn't a directory */
+ struct stat buf;
+ char filename[256];
+
+ snprintf(filename, sizeof(filename) - 1, "%s/%s", dirname, entry->d_name);
+ if (!stat(filename, &buf) && S_ISREG(buf.st_mode))
+ silc_list_key(filename, FALSE);
+ }
+
+ closedir(dir);
+}
+
+void silc_list_file(const char *filename)
+{
+
+ char path[256];
+ struct stat buf;
+
+ snprintf(path, sizeof(path) - 1, "%s", filename);
+ if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+ goto list_key;
+
+ snprintf(path, sizeof(path) - 1, "%s/%s", get_irssi_dir(), filename);
+ if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+ goto list_key;
+
+ snprintf(path,sizeof(path) - 1, "%s/clientkeys/%s", get_irssi_dir(),
+ filename);
+ if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+ goto list_key;
+
+ snprintf(path,sizeof(path) - 1, "%s/serverkeys/%s", get_irssi_dir(),
+ filename);
+ if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+ goto list_key;
+
+ return;
+
+list_key:
+
+ silc_list_key(path, TRUE);
+
+}
+#endif /* 0 */
+
+/* Lists locally saved client and server public keys. */
+static void command_listkeys(const char *data, SILC_SERVER_REC *server,
+ WI_ITEM_REC *item)
+{
+ GHashTable *optlist;
+ char *filename;
+ void *free_arg;
+ char dirname[256];
+
+ if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
+ PARAM_FLAG_GETREST, "listkeys", &optlist,
+ &filename))
+ return;
+
+ if (*filename != '\0') {
+
+ silc_list_file(filename);
+
+ } else {
+ int clients, servers;
+
+ clients = (g_hash_table_lookup(optlist, "clients") != NULL);
+ servers = (g_hash_table_lookup(optlist, "servers") != NULL);
+
+ if (!(clients || servers))
+ clients = servers = 1;
+
+ if (servers) {
+ snprintf(dirname, sizeof(dirname) - 1, "%s/serverkeys", get_irssi_dir());
+ silc_list_keys_in_dir(dirname, "server");
+ }
+
+ if (clients) {
+ snprintf(dirname, sizeof(dirname) - 1, "%s/clientkeys", get_irssi_dir());
+ silc_list_keys_in_dir(dirname, "client");
+ }
+ }
+ cmd_params_free(free_arg);
}
void silc_channels_init(void)
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
signal_add("server connected", (SIGNAL_FUNC) sig_connected);
signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
+ signal_add("gui exit", (SIGNAL_FUNC) sig_gui_quit);
+ signal_add("mime", (SIGNAL_FUNC) sig_mime);
+
+ command_bind_silc("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
+ command_bind_silc("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
+ command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
+ command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
+ command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
+ // command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
+ // command_bind("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
- signal_add("silc event join", (SIGNAL_FUNC) event_join);
- signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
- signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
- signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
- signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
- signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
- signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
- signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
- signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
- signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
- signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
- signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
- signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
-
- command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
- command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
- command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
- command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
- command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
- command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
+ command_set_options("listkeys", "clients servers");
+ command_set_options("action", "sign channel");
+ command_set_options("notice", "sign channel");
silc_nicklist_init();
}
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
+ signal_remove("gui exit", (SIGNAL_FUNC) sig_gui_quit);
+ signal_remove("mime", (SIGNAL_FUNC) sig_mime);
- signal_remove("silc event join", (SIGNAL_FUNC) event_join);
- signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
- signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
- signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
- signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
- signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
- signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
- signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
- signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
- signal_remove("silc event channel_change",
- (SIGNAL_FUNC) event_channel_change);
- signal_remove("silc event server_signoff",
- (SIGNAL_FUNC) event_server_signoff);
- signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
- signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
-
command_unbind("part", (SIGNAL_FUNC) command_part);
command_unbind("me", (SIGNAL_FUNC) command_me);
command_unbind("action", (SIGNAL_FUNC) command_action);
command_unbind("notice", (SIGNAL_FUNC) command_notice);
command_unbind("away", (SIGNAL_FUNC) command_away);
- command_unbind("key", (SIGNAL_FUNC) command_key);
+ // command_unbind("key", (SIGNAL_FUNC) command_key);
+ // command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
silc_nicklist_deinit();
}