2 silc-channels.c : irssi
4 Copyright (C) 2000 - 2001 Timo Sirainen
5 Pekka Riikonen <priikone@poseidon.pspt.fi>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "net-nonblock.h"
25 #include "net-sendbuffer.h"
35 #include "channels-setup.h"
37 #include "silc-servers.h"
38 #include "silc-channels.h"
39 #include "silc-queries.h"
40 #include "silc-nicklist.h"
41 #include "window-item-def.h"
43 #include "fe-common/core/printtext.h"
44 #include "fe-common/silc/module-formats.h"
46 SILC_CHANNEL_REC *silc_channel_create(SILC_SERVER_REC *server,
47 const char *name, int automatic)
49 SILC_CHANNEL_REC *rec;
51 g_return_val_if_fail(server == NULL || IS_SILC_SERVER(server), NULL);
52 g_return_val_if_fail(name != NULL, NULL);
54 rec = g_new0(SILC_CHANNEL_REC, 1);
55 rec->chat_type = SILC_PROTOCOL;
56 rec->name = g_strdup(name);
59 channel_init((CHANNEL_REC *) rec, automatic);
63 static void sig_channel_destroyed(SILC_CHANNEL_REC *channel)
65 if (!IS_SILC_CHANNEL(channel))
68 if (channel->server != NULL && !channel->left && !channel->kicked) {
69 /* destroying channel record without actually
70 having left the channel yet */
71 silc_command_exec(channel->server, "PART", channel->name);
75 static void silc_channels_join(SILC_SERVER_REC *server,
76 const char *channels, int automatic)
78 char **list, **tmp, *channel;
80 list = g_strsplit(channels, ",", -1);
81 for (tmp = list; *tmp != NULL; tmp++) {
82 channel = **tmp == '#' ? g_strdup(*tmp) :
83 g_strconcat("#", *tmp, NULL);
84 silc_channel_create(server, channel, FALSE);
85 silc_command_exec(server, "JOIN", channel);
91 static void sig_connected(SILC_SERVER_REC *server)
93 if (IS_SILC_SERVER(server))
94 server->channels_join = (void *) silc_channels_join;
97 /* "server quit" signal from the core to indicate that QUIT command
100 static void sig_server_quit(SILC_SERVER_REC *server, const char *msg)
102 if (IS_SILC_SERVER(server))
103 silc_command_exec(server, "QUIT", msg);
107 * "event join". Joined to a channel.
110 SILC_CHANNEL_REC *silc_channel_find_entry(SILC_SERVER_REC *server,
111 SilcChannelEntry entry)
115 g_return_val_if_fail(IS_SILC_SERVER(server), NULL);
117 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
118 SILC_CHANNEL_REC *rec = tmp->data;
120 if (rec->entry == entry)
127 static void event_join(SILC_SERVER_REC *server, va_list va)
129 SILC_CHANNEL_REC *chanrec;
130 SILC_NICK_REC *nickrec;
131 SilcClientEntry client;
132 SilcChannelEntry channel;
134 client = va_arg(va, SilcClientEntry);
135 channel = va_arg(va, SilcChannelEntry);
137 if (client == server->conn->local_entry) {
138 /* You joined to channel */
139 chanrec = silc_channel_find(server, channel->channel_name);
140 if (chanrec != NULL && !chanrec->joined)
141 chanrec->entry = channel;
143 chanrec = silc_channel_find_entry(server, channel);
144 if (chanrec != NULL) {
145 SilcChannelUser user;
147 silc_list_start(chanrec->entry->clients);
148 while ((user = silc_list_get(chanrec->entry->clients)) != NULL)
149 if (user->client == client) {
150 nickrec = silc_nicklist_insert(chanrec, user, TRUE);
156 signal_emit("message join", 4, server, channel->channel_name,
158 client->username == NULL ? "" : client->username);
162 * "event leave". Left a channel.
165 static void event_leave(SILC_SERVER_REC *server, va_list va)
167 SILC_CHANNEL_REC *chanrec;
168 SILC_NICK_REC *nickrec;
169 SilcClientEntry client;
170 SilcChannelEntry channel;
172 client = va_arg(va, SilcClientEntry);
173 channel = va_arg(va, SilcChannelEntry);
175 signal_emit("message part", 5, server, channel->channel_name,
176 client->nickname, client->username ? client->username : "",
179 chanrec = silc_channel_find_entry(server, channel);
180 if (chanrec != NULL) {
181 nickrec = silc_nicklist_find(chanrec, client);
183 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
188 * "event signoff". Left the network.
191 static void event_signoff(SILC_SERVER_REC *server, va_list va)
193 SilcClientEntry client;
197 client = va_arg(va, SilcClientEntry);
198 message = va_arg(va, char *);
200 signal_emit("message quit", 4, server, client->nickname,
201 client->username ? client->username : "",
202 message ? message : "");
204 nicks = nicklist_get_same_unique(SERVER(server), client);
205 for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
206 CHANNEL_REC *channel = tmp->data;
207 NICK_REC *nickrec = tmp->next->data;
209 nicklist_remove(channel, nickrec);
214 * "event topic". Changed topic.
217 static void event_topic(SILC_SERVER_REC *server, va_list va)
219 SILC_CHANNEL_REC *chanrec;
220 SilcClientEntry client;
221 SilcChannelEntry channel;
224 client = va_arg(va, SilcClientEntry);
225 topic = va_arg(va, char *);
226 channel = va_arg(va, SilcChannelEntry);
228 chanrec = silc_channel_find_entry(server, channel);
229 if (chanrec != NULL) {
230 g_free_not_null(chanrec->topic);
231 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
232 signal_emit("channel topic changed", 1, chanrec);
235 signal_emit("message topic", 5, server, channel->channel_name,
236 topic, client->nickname, client->username);
240 * "event invite". Invited or modified invite list.
243 static void event_invite(SILC_SERVER_REC *server, va_list va)
245 SilcClientEntry client;
246 SilcChannelEntry channel;
248 client = va_arg(va, SilcClientEntry);
249 channel = va_arg(va, SilcChannelEntry);
251 signal_emit("message invite", 4, server, channel->channel_name,
252 client->nickname, client->username);
256 * "event nick". Changed nickname.
259 static void event_nick(SILC_SERVER_REC *server, va_list va)
261 SilcClientEntry oldclient, newclient;
263 oldclient = va_arg(va, SilcClientEntry);
264 newclient = va_arg(va, SilcClientEntry);
266 nicklist_rename_unique(SERVER(server),
267 oldclient, oldclient->nickname,
268 newclient, newclient->nickname);
270 signal_emit("message nick", 4, server, newclient->nickname,
271 oldclient->nickname, newclient->username);
275 * "event cmode". Changed channel mode.
278 static void event_cmode(SILC_SERVER_REC *server, va_list va)
280 SILC_CHANNEL_REC *chanrec;
281 SilcClientEntry client;
282 SilcChannelEntry channel;
286 client = va_arg(va, SilcClientEntry);
287 modei = va_arg(va, uint32);
288 (void)va_arg(va, char *);
289 (void)va_arg(va, char *);
290 channel = va_arg(va, SilcChannelEntry);
292 mode = silc_client_chmode(modei, channel);
294 chanrec = silc_channel_find_entry(server, channel);
295 if (chanrec != NULL) {
296 g_free_not_null(chanrec->mode);
297 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
298 signal_emit("channel mode changed", 1, chanrec);
301 printformat_module("fe-common/silc", server, channel->channel_name,
302 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
303 channel->channel_name, mode ? mode : "removed all",
310 * "event cumode". Changed user's mode on channel.
313 static void event_cumode(SILC_SERVER_REC *server, va_list va)
315 SILC_CHANNEL_REC *chanrec;
316 SilcClientEntry client, destclient;
317 SilcChannelEntry channel;
321 client = va_arg(va, SilcClientEntry);
322 mode = va_arg(va, uint32);
323 destclient = va_arg(va, SilcClientEntry);
324 channel = va_arg(va, SilcChannelEntry);
326 modestr = silc_client_chumode(mode);
327 chanrec = silc_channel_find_entry(server, channel);
328 if (chanrec != NULL) {
331 if (destclient == server->conn->local_entry) {
333 (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
336 nick = silc_nicklist_find(chanrec, destclient);
338 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
339 signal_emit("nick mode changed", 2, chanrec, nick);
343 printformat_module("fe-common/silc", server, channel->channel_name,
344 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
345 channel->channel_name, destclient->nickname,
346 modestr ? modestr : "removed all",
349 if (mode & SILC_CHANNEL_UMODE_CHANFO)
350 printformat_module("fe-common/silc",
351 server, channel->channel_name, MSGLEVEL_CRAP,
352 SILCTXT_CHANNEL_FOUNDER,
353 channel->channel_name, destclient->nickname);
359 * "event motd". Received MOTD.
362 static void event_motd(SILC_SERVER_REC *server, va_list va)
364 char *text = va_arg(va, char *);
366 if (!settings_get_bool("skip_motd"))
367 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", text);
371 * "event channel_change". Channel ID has changed.
374 static void event_channel_change(SILC_SERVER_REC *server, va_list va)
380 * "event server_signoff". Server has quit the network.
383 static void event_server_signoff(SILC_SERVER_REC *server, va_list va)
389 * "event kick". Someone was kicked from channel.
392 static void event_kick(SILC_SERVER_REC *server, va_list va)
398 * "event kill". Someone was killed from the network.
401 static void event_kill(SILC_SERVER_REC *server, va_list va)
407 * "event ban". Someone was banned or ban list was modified.
410 static void event_ban(SILC_SERVER_REC *server, va_list va)
415 /* PART (LEAVE) command. */
417 static void command_part(const char *data, SILC_SERVER_REC *server,
420 SILC_CHANNEL_REC *chanrec;
422 if (!IS_SILC_SERVER(server) || !server->connected)
423 cmd_return_error(CMDERR_NOT_CONNECTED);
426 if (!IS_SILC_CHANNEL(item))
427 cmd_return_error(CMDERR_NOT_JOINED);
431 chanrec = silc_channel_find(server, data);
433 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
435 signal_emit("message part", 5, server, chanrec->name,
436 server->nick, server->conn->local_entry->username, "");
438 silc_command_exec(server, "LEAVE", chanrec->name);
441 channel_destroy(CHANNEL(chanrec));
444 /* ME local command. */
446 static void command_me(const char *data, SILC_SERVER_REC *server,
449 SILC_CHANNEL_REC *chanrec;
450 char *tmpcmd = "ME", *tmp;
452 unsigned char **argv;
453 uint32 *argv_lens, *argv_types;
456 if (!IS_SILC_SERVER(server) || !server->connected)
457 cmd_return_error(CMDERR_NOT_CONNECTED);
459 if (!IS_SILC_CHANNEL(item))
460 cmd_return_error(CMDERR_NOT_JOINED);
462 /* Now parse all arguments */
463 tmp = g_strconcat(tmpcmd, " ", data, NULL);
464 silc_parse_command_line(tmp, &argv, &argv_lens,
465 &argv_types, &argc, 2);
469 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
471 chanrec = silc_channel_find(server, item->name);
473 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
475 /* Send the action message */
476 silc_client_send_channel_message(silc_client, server->conn,
477 chanrec->entry, NULL,
478 SILC_MESSAGE_FLAG_ACTION,
479 argv[1], argv_lens[1], TRUE);
481 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
482 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
483 server->conn->local_entry->nickname, argv[1]);
485 for (i = 0; i < argc; i++)
487 silc_free(argv_lens);
488 silc_free(argv_types);
491 /* ACTION local command. Same as ME but takes the channel as mandatory
494 static void command_action(const char *data, SILC_SERVER_REC *server,
497 SILC_CHANNEL_REC *chanrec;
498 char *tmpcmd = "ME", *tmp;
500 unsigned char **argv;
501 uint32 *argv_lens, *argv_types;
504 if (!IS_SILC_SERVER(server) || !server->connected)
505 cmd_return_error(CMDERR_NOT_CONNECTED);
507 if (!IS_SILC_CHANNEL(item))
508 cmd_return_error(CMDERR_NOT_JOINED);
510 /* Now parse all arguments */
511 tmp = g_strconcat(tmpcmd, " ", data, NULL);
512 silc_parse_command_line(tmp, &argv, &argv_lens,
513 &argv_types, &argc, 3);
517 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
519 chanrec = silc_channel_find(server, argv[1]);
521 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
523 /* Send the action message */
524 silc_client_send_channel_message(silc_client, server->conn,
525 chanrec->entry, NULL,
526 SILC_MESSAGE_FLAG_ACTION,
527 argv[2], argv_lens[2], TRUE);
529 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
530 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION,
531 server->conn->local_entry->nickname, argv[2]);
533 for (i = 0; i < argc; i++)
535 silc_free(argv_lens);
536 silc_free(argv_types);
539 /* NOTICE local command. */
541 static void command_notice(const char *data, SILC_SERVER_REC *server,
544 SILC_CHANNEL_REC *chanrec;
545 char *tmpcmd = "ME", *tmp;
547 unsigned char **argv;
548 uint32 *argv_lens, *argv_types;
551 if (!IS_SILC_SERVER(server) || !server->connected)
552 cmd_return_error(CMDERR_NOT_CONNECTED);
554 if (!IS_SILC_CHANNEL(item))
555 cmd_return_error(CMDERR_NOT_JOINED);
557 /* Now parse all arguments */
558 tmp = g_strconcat(tmpcmd, " ", data, NULL);
559 silc_parse_command_line(tmp, &argv, &argv_lens,
560 &argv_types, &argc, 2);
564 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
566 chanrec = silc_channel_find(server, item->name);
568 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
570 /* Send the action message */
571 silc_client_send_channel_message(silc_client, server->conn,
572 chanrec->entry, NULL,
573 SILC_MESSAGE_FLAG_NOTICE,
574 argv[1], argv_lens[1], TRUE);
576 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
577 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE,
578 server->conn->local_entry->nickname, argv[1]);
580 for (i = 0; i < argc; i++)
582 silc_free(argv_lens);
583 silc_free(argv_types);
586 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
589 static void command_away(const char *data, SILC_SERVER_REC *server,
594 if (!IS_SILC_SERVER(server) || !server->connected)
595 cmd_return_error(CMDERR_NOT_CONNECTED);
598 /* Remove any possible away message */
599 silc_client_set_away_message(silc_client, server->conn, NULL);
602 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
605 /* Set the away message */
606 silc_client_set_away_message(silc_client, server->conn, (char *)data);
609 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
610 SILCTXT_SET_AWAY, data);
613 signal_emit("away mode changed", 1, server);
615 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
619 int type; /* 1 = msg, 2 = channel */
620 SILC_SERVER_REC *server;
623 /* Key agreement callback that is called after the key agreement protocol
624 has been performed. This is called also if error occured during the
625 key agreement protocol. The `key' is the allocated key material and
626 the caller is responsible of freeing it. The `key' is NULL if error
627 has occured. The application can freely use the `key' to whatever
628 purpose it needs. See lib/silcske/silcske.h for the definition of
629 the SilcSKEKeyMaterial structure. */
631 static void keyagr_completion(SilcClient client,
632 SilcClientConnection conn,
633 SilcClientEntry client_entry,
634 SilcKeyAgreementStatus status,
635 SilcSKEKeyMaterial *key,
638 KeyInternal i = (KeyInternal)context;
641 case SILC_KEY_AGREEMENT_OK:
642 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
643 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
646 /* Set the private key for this client */
647 silc_client_del_private_message_key(client, conn, client_entry);
648 silc_client_add_private_message_key_ske(client, conn, client_entry,
650 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
651 SILCTXT_KEY_AGREEMENT_PRIVMSG,
652 client_entry->nickname);
653 silc_ske_free_key_material(key);
658 case SILC_KEY_AGREEMENT_ERROR:
659 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
660 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
663 case SILC_KEY_AGREEMENT_FAILURE:
664 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
665 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
668 case SILC_KEY_AGREEMENT_TIMEOUT:
669 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
670 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
681 /* Local command KEY. This command is used to set and unset private
682 keys for channels, set and unset private keys for private messages
683 with remote clients and to send key agreement requests and
684 negotiate the key agreement protocol with remote client. The
685 key agreement is supported only to negotiate private message keys,
686 it currently cannot be used to negotiate private keys for channels,
687 as it is not convenient for that purpose. */
690 SILC_SERVER_REC *server;
695 /* Callback to be called after client information is resolved from the
698 SILC_CLIENT_CMD_FUNC(key_get_clients)
700 KeyGetClients internal = (KeyGetClients)context;
701 signal_emit("command key", 3, internal->data, internal->server,
703 silc_free(internal->data);
707 static void command_key(const char *data, SILC_SERVER_REC *server,
710 SilcClientConnection conn = server->conn;
711 SilcClientEntry client_entry = NULL;
712 SilcChannelEntry channel_entry = NULL;
714 char *nickname = NULL, *serv = NULL, *tmp;
715 int command = 0, port = 0, type = 0;
716 char *hostname = NULL;
717 KeyInternal internal = NULL;
719 unsigned char **argv;
720 uint32 *argv_lens, *argv_types;
722 if (!IS_SILC_SERVER(server) || !server->connected)
723 cmd_return_error(CMDERR_NOT_CONNECTED);
725 /* Now parse all arguments */
726 tmp = g_strconcat("KEY", " ", data, NULL);
727 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
731 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
732 "set|unset|agreement|negotiate [<arguments>]");
737 if (!strcasecmp(argv[1], "msg"))
739 if (!strcasecmp(argv[1], "channel"))
743 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
744 "set|unset|agreement|negotiate [<arguments>]");
749 if (argv[2][0] == '*') {
752 /* Parse the typed nickname. */
753 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
754 printformat_module("fe-common/silc", server, NULL,
755 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
759 /* Find client entry */
760 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
763 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
764 inter->server = server;
765 inter->data = strdup(data);
768 /* Client entry not found, it was requested thus mark this to be
770 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
772 NULL, silc_client_command_key_get_clients,
780 /* Get channel entry */
783 if (argv[2][0] == '*') {
784 if (!conn->current_channel) {
789 cmd_return_error(CMDERR_NOT_JOINED);
791 name = conn->current_channel->channel_name;
796 channel_entry = silc_client_get_channel(silc_client, conn, name);
797 if (!channel_entry) {
802 cmd_return_error(CMDERR_NOT_JOINED);
807 if (!strcasecmp(argv[3], "set")) {
811 if (type == 1 && client_entry) {
812 /* Set private message key */
814 silc_client_del_private_message_key(silc_client, conn, client_entry);
817 silc_client_add_private_message_key(silc_client, conn, client_entry,
823 silc_client_add_private_message_key(silc_client, conn, client_entry,
829 /* Send the key to the remote client so that it starts using it
831 silc_client_send_private_message_key(silc_client, conn,
833 } else if (type == 2) {
834 /* Set private channel key */
835 char *cipher = NULL, *hmac = NULL;
837 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
838 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
839 SILCTXT_CH_PRIVATE_KEY_NOMODE,
840 channel_entry->channel_name);
849 if (!silc_client_add_channel_private_key(silc_client, conn,
854 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
855 SILCTXT_CH_PRIVATE_KEY_ERROR,
856 channel_entry->channel_name);
860 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
861 SILCTXT_CH_PRIVATE_KEY_ADD,
862 channel_entry->channel_name);
870 if (!strcasecmp(argv[3], "unset")) {
873 if (type == 1 && client_entry) {
874 /* Unset private message key */
875 silc_client_del_private_message_key(silc_client, conn, client_entry);
876 } else if (type == 2) {
877 /* Unset channel key(s) */
878 SilcChannelPrivateKey *keys;
883 silc_client_del_channel_private_keys(silc_client, conn,
887 number = atoi(argv[4]);
888 keys = silc_client_list_channel_private_keys(silc_client, conn,
894 if (!number || number > keys_count) {
895 silc_client_free_channel_private_keys(keys, keys_count);
899 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
901 silc_client_free_channel_private_keys(keys, keys_count);
909 if (!strcasecmp(argv[3], "list")) {
913 SilcPrivateMessageKeys keys;
918 keys = silc_client_list_private_message_keys(silc_client, conn,
923 /* list the private message key(s) */
924 if (nickname[0] == '*') {
925 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
926 SILCTXT_PRIVATE_KEY_LIST);
927 for (k = 0; k < keys_count; k++) {
928 memset(buf, 0, sizeof(buf));
929 strncat(buf, " ", 2);
930 len = strlen(keys[k].client_entry->nickname);
931 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
933 for (i = 0; i < 30 - len; i++)
937 len = strlen(keys[k].cipher);
938 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
940 for (i = 0; i < 14 - len; i++)
945 strcat(buf, "<hidden>");
947 strcat(buf, "*generated*");
949 silc_say(silc_client, conn, "%s", buf);
952 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
953 SILCTXT_PRIVATE_KEY_LIST_NICK,
954 client_entry->nickname);
955 for (k = 0; k < keys_count; k++) {
956 if (keys[k].client_entry != client_entry)
959 memset(buf, 0, sizeof(buf));
960 strncat(buf, " ", 2);
961 len = strlen(keys[k].client_entry->nickname);
962 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
964 for (i = 0; i < 30 - len; i++)
968 len = strlen(keys[k].cipher);
969 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
971 for (i = 0; i < 14 - len; i++)
976 strcat(buf, "<hidden>");
978 strcat(buf, "*generated*");
980 silc_say(silc_client, conn, "%s", buf);
984 silc_client_free_private_message_keys(keys, keys_count);
985 } else if (type == 2) {
986 SilcChannelPrivateKey *keys;
991 keys = silc_client_list_channel_private_keys(silc_client, conn,
997 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
998 SILCTXT_CH_PRIVATE_KEY_LIST,
999 channel_entry->channel_name);
1000 for (k = 0; k < keys_count; k++) {
1001 memset(buf, 0, sizeof(buf));
1002 strncat(buf, " ", 2);
1004 len = strlen(keys[k]->cipher->cipher->name);
1005 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1007 for (i = 0; i < 16 - len; i++)
1011 len = strlen(keys[k]->hmac->hmac->name);
1012 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1014 for (i = 0; i < 16 - len; i++)
1018 strcat(buf, "<hidden>");
1020 silc_say(silc_client, conn, "%s", buf);
1023 silc_client_free_channel_private_keys(keys, keys_count);
1029 /* Send command is used to send key agreement */
1030 if (!strcasecmp(argv[3], "agreement")) {
1036 port = atoi(argv[5]);
1038 internal = silc_calloc(1, sizeof(*internal));
1039 internal->type = type;
1040 internal->server = server;
1043 /* Start command is used to start key agreement (after receiving the
1044 key_agreement client operation). */
1045 if (!strcasecmp(argv[3], "negotiate")) {
1051 port = atoi(argv[5]);
1053 internal = silc_calloc(1, sizeof(*internal));
1054 internal->type = type;
1055 internal->server = server;
1059 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1060 "set|unset|agreement|negotiate [<arguments>]");
1064 if (command == 4 && client_entry) {
1065 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1066 SILCTXT_KEY_AGREEMENT, argv[2]);
1067 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1068 port, 120, keyagr_completion, internal);
1072 if (command == 5 && client_entry && hostname) {
1073 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1074 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1075 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1076 hostname, port, keyagr_completion,
1083 silc_free(nickname);
1088 void silc_channels_init(void)
1090 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1091 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1092 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1094 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1095 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1096 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1097 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1098 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1099 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1100 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1101 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1102 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1103 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1104 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1105 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1106 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1107 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1109 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1110 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1111 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1112 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1113 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1114 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1116 silc_nicklist_init();
1119 void silc_channels_deinit(void)
1121 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1122 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1123 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1125 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1126 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1127 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1128 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1129 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1130 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1131 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1132 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1133 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1134 signal_remove("silc event channel_change",
1135 (SIGNAL_FUNC) event_channel_change);
1136 signal_remove("silc event server_signoff",
1137 (SIGNAL_FUNC) event_server_signoff);
1138 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1139 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1140 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1142 command_unbind("part", (SIGNAL_FUNC) command_part);
1143 command_unbind("me", (SIGNAL_FUNC) command_me);
1144 command_unbind("action", (SIGNAL_FUNC) command_action);
1145 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1146 command_unbind("away", (SIGNAL_FUNC) command_away);
1147 command_unbind("key", (SIGNAL_FUNC) command_key);
1149 silc_nicklist_deinit();