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, argv[1]);
484 for (i = 0; i < argc; i++)
486 silc_free(argv_lens);
487 silc_free(argv_types);
490 /* NOTICE local command. */
492 static void command_notice(const char *data, SILC_SERVER_REC *server,
495 SILC_CHANNEL_REC *chanrec;
496 char *tmpcmd = "ME", *tmp;
498 unsigned char **argv;
499 uint32 *argv_lens, *argv_types;
502 if (!IS_SILC_SERVER(server) || !server->connected)
503 cmd_return_error(CMDERR_NOT_CONNECTED);
505 if (!IS_SILC_CHANNEL(item))
506 cmd_return_error(CMDERR_NOT_JOINED);
508 /* Now parse all arguments */
509 tmp = g_strconcat(tmpcmd, " ", data, NULL);
510 silc_parse_command_line(tmp, &argv, &argv_lens,
511 &argv_types, &argc, 2);
515 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
517 chanrec = silc_channel_find(server, item->name);
519 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
521 /* Send the action message */
522 silc_client_send_channel_message(silc_client, server->conn,
523 chanrec->entry, NULL,
524 SILC_MESSAGE_FLAG_NOTICE,
525 argv[1], argv_lens[1], TRUE);
527 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
528 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE, argv[1]);
530 for (i = 0; i < argc; i++)
532 silc_free(argv_lens);
533 silc_free(argv_types);
536 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
539 static void command_away(const char *data, SILC_SERVER_REC *server,
542 if (!IS_SILC_SERVER(server) || !server->connected)
543 cmd_return_error(CMDERR_NOT_CONNECTED);
549 int type; /* 1 = msg, 2 = channel */
550 SILC_SERVER_REC *server;
553 static SilcSKEKeyMaterial *curr_key = NULL;
555 /* Key agreement callback that is called after the key agreement protocol
556 has been performed. This is called also if error occured during the
557 key agreement protocol. The `key' is the allocated key material and
558 the caller is responsible of freeing it. The `key' is NULL if error
559 has occured. The application can freely use the `key' to whatever
560 purpose it needs. See lib/silcske/silcske.h for the definition of
561 the SilcSKEKeyMaterial structure. */
563 static void keyagr_completion(SilcClient client,
564 SilcClientConnection conn,
565 SilcClientEntry client_entry,
566 SilcKeyAgreementStatus status,
567 SilcSKEKeyMaterial *key,
570 KeyInternal i = (KeyInternal)context;
575 case SILC_KEY_AGREEMENT_OK:
576 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
577 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
580 /* Set the private key for this client */
581 silc_client_del_private_message_key(client, conn, client_entry);
582 silc_client_add_private_message_key_ske(client, conn, client_entry,
584 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
585 SILCTXT_KEY_AGREEMENT_PRIVMSG,
586 client_entry->nickname);
587 silc_ske_free_key_material(key);
592 case SILC_KEY_AGREEMENT_ERROR:
593 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
594 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
597 case SILC_KEY_AGREEMENT_FAILURE:
598 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
599 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
602 case SILC_KEY_AGREEMENT_TIMEOUT:
603 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
604 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
615 /* Local command KEY. This command is used to set and unset private
616 keys for channels, set and unset private keys for private messages
617 with remote clients and to send key agreement requests and
618 negotiate the key agreement protocol with remote client. The
619 key agreement is supported only to negotiate private message keys,
620 it currently cannot be used to negotiate private keys for channels,
621 as it is not convenient for that purpose. */
624 SILC_SERVER_REC *server;
629 /* Callback to be called after client information is resolved from the
632 SILC_CLIENT_CMD_FUNC(key_get_clients)
634 KeyGetClients internal = (KeyGetClients)context;
635 signal_emit("command key", 3, internal->data, internal->server,
637 silc_free(internal->data);
641 static void command_key(const char *data, SILC_SERVER_REC *server,
644 SilcClientConnection conn = server->conn;
645 SilcClientEntry client_entry = NULL;
646 SilcChannelEntry channel_entry = NULL;
648 char *nickname = NULL, *serv = NULL, *tmp;
649 int command = 0, port = 0, type = 0;
650 char *hostname = NULL;
651 KeyInternal internal = NULL;
653 unsigned char **argv;
654 uint32 *argv_lens, *argv_types;
656 if (!IS_SILC_SERVER(server) || !server->connected)
657 cmd_return_error(CMDERR_NOT_CONNECTED);
659 /* Now parse all arguments */
660 tmp = g_strconcat("KEY", " ", data, NULL);
661 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
665 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
666 "set|unset|agreement|negotiate [<arguments>]");
671 if (!strcasecmp(argv[1], "msg"))
673 if (!strcasecmp(argv[1], "channel"))
677 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
678 "set|unset|agreement|negotiate [<arguments>]");
683 if (argv[2][0] == '*') {
686 /* Parse the typed nickname. */
687 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
688 silc_say(silc_client, conn, "Bad nickname");
692 /* Find client entry */
693 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
696 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
697 inter->server = server;
698 inter->data = strdup(data);
701 /* Client entry not found, it was requested thus mark this to be
703 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
705 NULL, silc_client_command_key_get_clients,
713 /* Get channel entry */
716 if (argv[2][0] == '*') {
717 if (!conn->current_channel) {
722 cmd_return_error(CMDERR_NOT_JOINED);
724 name = conn->current_channel->channel_name;
729 channel_entry = silc_client_get_channel(silc_client, conn, name);
730 if (!channel_entry) {
735 cmd_return_error(CMDERR_NOT_JOINED);
740 if (!strcasecmp(argv[3], "set")) {
744 if (curr_key && type == 1 && client_entry) {
745 silc_client_del_private_message_key(silc_client, conn, client_entry);
746 silc_client_add_private_message_key_ske(silc_client, conn,
747 client_entry, NULL, curr_key);
753 if (type == 1 && client_entry) {
754 /* Set private message key */
756 silc_client_del_private_message_key(silc_client, conn, client_entry);
759 silc_client_add_private_message_key(silc_client, conn, client_entry,
765 silc_client_add_private_message_key(silc_client, conn, client_entry,
771 /* Send the key to the remote client so that it starts using it
773 silc_client_send_private_message_key(silc_client, conn,
775 } else if (type == 2) {
776 /* Set private channel key */
777 char *cipher = NULL, *hmac = NULL;
779 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
780 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
781 SILCTXT_CH_PRIVATE_KEY_NOMODE,
782 channel_entry->channel_name);
791 if (!silc_client_add_channel_private_key(silc_client, conn,
796 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
797 SILCTXT_CH_PRIVATE_KEY_ERROR,
798 channel_entry->channel_name);
802 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
803 SILCTXT_CH_PRIVATE_KEY_ADD,
804 channel_entry->channel_name);
812 if (!strcasecmp(argv[3], "unset")) {
815 if (type == 1 && client_entry) {
816 /* Unset private message key */
817 silc_client_del_private_message_key(silc_client, conn, client_entry);
818 } else if (type == 2) {
819 /* Unset channel key(s) */
820 SilcChannelPrivateKey *keys;
825 silc_client_del_channel_private_keys(silc_client, conn,
829 number = atoi(argv[4]);
830 keys = silc_client_list_channel_private_keys(silc_client, conn,
836 if (!number || number > keys_count) {
837 silc_client_free_channel_private_keys(keys, keys_count);
841 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
843 silc_client_free_channel_private_keys(keys, keys_count);
851 if (!strcasecmp(argv[3], "list")) {
855 SilcPrivateMessageKeys keys;
860 keys = silc_client_list_private_message_keys(silc_client, conn,
865 /* list the private message key(s) */
866 if (nickname[0] == '*') {
867 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
868 SILCTXT_PRIVATE_KEY_LIST);
869 for (k = 0; k < keys_count; k++) {
870 memset(buf, 0, sizeof(buf));
871 strncat(buf, " ", 2);
872 len = strlen(keys[k].client_entry->nickname);
873 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
875 for (i = 0; i < 30 - len; i++)
879 len = strlen(keys[k].cipher);
880 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
882 for (i = 0; i < 14 - len; i++)
887 strcat(buf, "<hidden>");
889 strcat(buf, "*generated*");
891 silc_say(silc_client, conn, "%s", buf);
894 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
895 SILCTXT_PRIVATE_KEY_LIST_NICK,
896 client_entry->nickname);
897 for (k = 0; k < keys_count; k++) {
898 if (keys[k].client_entry != client_entry)
901 memset(buf, 0, sizeof(buf));
902 strncat(buf, " ", 2);
903 len = strlen(keys[k].client_entry->nickname);
904 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
906 for (i = 0; i < 30 - len; i++)
910 len = strlen(keys[k].cipher);
911 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
913 for (i = 0; i < 14 - len; i++)
918 strcat(buf, "<hidden>");
920 strcat(buf, "*generated*");
922 silc_say(silc_client, conn, "%s", buf);
926 silc_client_free_private_message_keys(keys, keys_count);
927 } else if (type == 2) {
928 SilcChannelPrivateKey *keys;
933 keys = silc_client_list_channel_private_keys(silc_client, conn,
939 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
940 SILCTXT_CH_PRIVATE_KEY_LIST,
941 channel_entry->channel_name);
942 for (k = 0; k < keys_count; k++) {
943 memset(buf, 0, sizeof(buf));
944 strncat(buf, " ", 2);
946 len = strlen(keys[k]->cipher->cipher->name);
947 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
949 for (i = 0; i < 16 - len; i++)
953 len = strlen(keys[k]->hmac->hmac->name);
954 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
956 for (i = 0; i < 16 - len; i++)
960 strcat(buf, "<hidden>");
962 silc_say(silc_client, conn, "%s", buf);
965 silc_client_free_channel_private_keys(keys, keys_count);
971 /* Send command is used to send key agreement */
972 if (!strcasecmp(argv[3], "agreement")) {
978 port = atoi(argv[5]);
980 internal = silc_calloc(1, sizeof(*internal));
981 internal->type = type;
982 internal->server = server;
985 /* Start command is used to start key agreement (after receiving the
986 key_agreement client operation). */
987 if (!strcasecmp(argv[3], "negotiate")) {
993 port = atoi(argv[5]);
995 internal = silc_calloc(1, sizeof(*internal));
996 internal->type = type;
997 internal->server = server;
1001 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1002 "set|unset|agreement|negotiate [<arguments>]");
1006 if (command == 4 && client_entry) {
1007 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1008 SILCTXT_KEY_AGREEMENT, argv[2]);
1009 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1010 port, 120, keyagr_completion, internal);
1014 if (command == 5 && client_entry && hostname) {
1015 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1016 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1017 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1018 hostname, port, keyagr_completion,
1025 silc_free(nickname);
1030 void silc_channels_init(void)
1032 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1033 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1034 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1036 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1037 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1038 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1039 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1040 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1041 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1042 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1043 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1044 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1045 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1046 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1047 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1048 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1049 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1051 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1052 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1053 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1054 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1055 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1057 silc_nicklist_init();
1060 void silc_channels_deinit(void)
1062 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1063 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1064 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1066 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1067 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1068 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1069 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1070 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1071 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1072 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1073 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1074 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1075 signal_remove("silc event channel_change",
1076 (SIGNAL_FUNC) event_channel_change);
1077 signal_remove("silc event server_signoff",
1078 (SIGNAL_FUNC) event_server_signoff);
1079 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1080 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1081 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1083 command_unbind("part", (SIGNAL_FUNC) command_part);
1084 command_unbind("me", (SIGNAL_FUNC) command_me);
1085 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1086 command_unbind("away", (SIGNAL_FUNC) command_away);
1087 command_unbind("key", (SIGNAL_FUNC) command_key);
1089 silc_nicklist_deinit();