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 /* Key agreement callback that is called after the key agreement protocol
554 has been performed. This is called also if error occured during the
555 key agreement protocol. The `key' is the allocated key material and
556 the caller is responsible of freeing it. The `key' is NULL if error
557 has occured. The application can freely use the `key' to whatever
558 purpose it needs. See lib/silcske/silcske.h for the definition of
559 the SilcSKEKeyMaterial structure. */
561 static void keyagr_completion(SilcClient client,
562 SilcClientConnection conn,
563 SilcClientEntry client_entry,
564 SilcKeyAgreementStatus status,
565 SilcSKEKeyMaterial *key,
568 KeyInternal i = (KeyInternal)context;
571 case SILC_KEY_AGREEMENT_OK:
572 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
573 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
576 /* Set the private key for this client */
577 silc_client_del_private_message_key(client, conn, client_entry);
578 silc_client_add_private_message_key_ske(client, conn, client_entry,
580 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
581 SILCTXT_KEY_AGREEMENT_PRIVMSG,
582 client_entry->nickname);
583 silc_ske_free_key_material(key);
588 case SILC_KEY_AGREEMENT_ERROR:
589 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
590 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
593 case SILC_KEY_AGREEMENT_FAILURE:
594 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
595 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
598 case SILC_KEY_AGREEMENT_TIMEOUT:
599 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
600 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
611 /* Local command KEY. This command is used to set and unset private
612 keys for channels, set and unset private keys for private messages
613 with remote clients and to send key agreement requests and
614 negotiate the key agreement protocol with remote client. The
615 key agreement is supported only to negotiate private message keys,
616 it currently cannot be used to negotiate private keys for channels,
617 as it is not convenient for that purpose. */
620 SILC_SERVER_REC *server;
625 /* Callback to be called after client information is resolved from the
628 SILC_CLIENT_CMD_FUNC(key_get_clients)
630 KeyGetClients internal = (KeyGetClients)context;
631 signal_emit("command key", 3, internal->data, internal->server,
633 silc_free(internal->data);
637 static void command_key(const char *data, SILC_SERVER_REC *server,
640 SilcClientConnection conn = server->conn;
641 SilcClientEntry client_entry = NULL;
642 SilcChannelEntry channel_entry = NULL;
644 char *nickname = NULL, *serv = NULL, *tmp;
645 int command = 0, port = 0, type = 0;
646 char *hostname = NULL;
647 KeyInternal internal = NULL;
649 unsigned char **argv;
650 uint32 *argv_lens, *argv_types;
652 if (!IS_SILC_SERVER(server) || !server->connected)
653 cmd_return_error(CMDERR_NOT_CONNECTED);
655 /* Now parse all arguments */
656 tmp = g_strconcat("KEY", " ", data, NULL);
657 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
661 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
662 "set|unset|agreement|negotiate [<arguments>]");
667 if (!strcasecmp(argv[1], "msg"))
669 if (!strcasecmp(argv[1], "channel"))
673 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
674 "set|unset|agreement|negotiate [<arguments>]");
679 if (argv[2][0] == '*') {
682 /* Parse the typed nickname. */
683 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
684 printformat_module("fe-common/silc", server, NULL,
685 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
689 /* Find client entry */
690 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
693 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
694 inter->server = server;
695 inter->data = strdup(data);
698 /* Client entry not found, it was requested thus mark this to be
700 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
702 NULL, silc_client_command_key_get_clients,
710 /* Get channel entry */
713 if (argv[2][0] == '*') {
714 if (!conn->current_channel) {
719 cmd_return_error(CMDERR_NOT_JOINED);
721 name = conn->current_channel->channel_name;
726 channel_entry = silc_client_get_channel(silc_client, conn, name);
727 if (!channel_entry) {
732 cmd_return_error(CMDERR_NOT_JOINED);
737 if (!strcasecmp(argv[3], "set")) {
741 if (type == 1 && client_entry) {
742 /* Set private message key */
744 silc_client_del_private_message_key(silc_client, conn, client_entry);
747 silc_client_add_private_message_key(silc_client, conn, client_entry,
753 silc_client_add_private_message_key(silc_client, conn, client_entry,
759 /* Send the key to the remote client so that it starts using it
761 silc_client_send_private_message_key(silc_client, conn,
763 } else if (type == 2) {
764 /* Set private channel key */
765 char *cipher = NULL, *hmac = NULL;
767 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
768 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
769 SILCTXT_CH_PRIVATE_KEY_NOMODE,
770 channel_entry->channel_name);
779 if (!silc_client_add_channel_private_key(silc_client, conn,
784 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
785 SILCTXT_CH_PRIVATE_KEY_ERROR,
786 channel_entry->channel_name);
790 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
791 SILCTXT_CH_PRIVATE_KEY_ADD,
792 channel_entry->channel_name);
800 if (!strcasecmp(argv[3], "unset")) {
803 if (type == 1 && client_entry) {
804 /* Unset private message key */
805 silc_client_del_private_message_key(silc_client, conn, client_entry);
806 } else if (type == 2) {
807 /* Unset channel key(s) */
808 SilcChannelPrivateKey *keys;
813 silc_client_del_channel_private_keys(silc_client, conn,
817 number = atoi(argv[4]);
818 keys = silc_client_list_channel_private_keys(silc_client, conn,
824 if (!number || number > keys_count) {
825 silc_client_free_channel_private_keys(keys, keys_count);
829 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
831 silc_client_free_channel_private_keys(keys, keys_count);
839 if (!strcasecmp(argv[3], "list")) {
843 SilcPrivateMessageKeys keys;
848 keys = silc_client_list_private_message_keys(silc_client, conn,
853 /* list the private message key(s) */
854 if (nickname[0] == '*') {
855 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
856 SILCTXT_PRIVATE_KEY_LIST);
857 for (k = 0; k < keys_count; k++) {
858 memset(buf, 0, sizeof(buf));
859 strncat(buf, " ", 2);
860 len = strlen(keys[k].client_entry->nickname);
861 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
863 for (i = 0; i < 30 - len; i++)
867 len = strlen(keys[k].cipher);
868 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
870 for (i = 0; i < 14 - len; i++)
875 strcat(buf, "<hidden>");
877 strcat(buf, "*generated*");
879 silc_say(silc_client, conn, "%s", buf);
882 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
883 SILCTXT_PRIVATE_KEY_LIST_NICK,
884 client_entry->nickname);
885 for (k = 0; k < keys_count; k++) {
886 if (keys[k].client_entry != client_entry)
889 memset(buf, 0, sizeof(buf));
890 strncat(buf, " ", 2);
891 len = strlen(keys[k].client_entry->nickname);
892 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
894 for (i = 0; i < 30 - len; i++)
898 len = strlen(keys[k].cipher);
899 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
901 for (i = 0; i < 14 - len; i++)
906 strcat(buf, "<hidden>");
908 strcat(buf, "*generated*");
910 silc_say(silc_client, conn, "%s", buf);
914 silc_client_free_private_message_keys(keys, keys_count);
915 } else if (type == 2) {
916 SilcChannelPrivateKey *keys;
921 keys = silc_client_list_channel_private_keys(silc_client, conn,
927 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
928 SILCTXT_CH_PRIVATE_KEY_LIST,
929 channel_entry->channel_name);
930 for (k = 0; k < keys_count; k++) {
931 memset(buf, 0, sizeof(buf));
932 strncat(buf, " ", 2);
934 len = strlen(keys[k]->cipher->cipher->name);
935 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
937 for (i = 0; i < 16 - len; i++)
941 len = strlen(keys[k]->hmac->hmac->name);
942 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
944 for (i = 0; i < 16 - len; i++)
948 strcat(buf, "<hidden>");
950 silc_say(silc_client, conn, "%s", buf);
953 silc_client_free_channel_private_keys(keys, keys_count);
959 /* Send command is used to send key agreement */
960 if (!strcasecmp(argv[3], "agreement")) {
966 port = atoi(argv[5]);
968 internal = silc_calloc(1, sizeof(*internal));
969 internal->type = type;
970 internal->server = server;
973 /* Start command is used to start key agreement (after receiving the
974 key_agreement client operation). */
975 if (!strcasecmp(argv[3], "negotiate")) {
981 port = atoi(argv[5]);
983 internal = silc_calloc(1, sizeof(*internal));
984 internal->type = type;
985 internal->server = server;
989 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
990 "set|unset|agreement|negotiate [<arguments>]");
994 if (command == 4 && client_entry) {
995 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
996 SILCTXT_KEY_AGREEMENT, argv[2]);
997 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
998 port, 120, keyagr_completion, internal);
1002 if (command == 5 && client_entry && hostname) {
1003 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1004 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1005 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1006 hostname, port, keyagr_completion,
1013 silc_free(nickname);
1018 void silc_channels_init(void)
1020 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1021 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1022 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1024 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1025 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1026 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1027 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1028 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1029 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1030 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1031 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1032 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1033 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1034 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1035 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1036 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1037 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1039 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1040 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1041 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1042 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1043 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1045 silc_nicklist_init();
1048 void silc_channels_deinit(void)
1050 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1051 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1052 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1054 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1055 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1056 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1057 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1058 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1059 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1060 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1061 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1062 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1063 signal_remove("silc event channel_change",
1064 (SIGNAL_FUNC) event_channel_change);
1065 signal_remove("silc event server_signoff",
1066 (SIGNAL_FUNC) event_server_signoff);
1067 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1068 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1069 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1071 command_unbind("part", (SIGNAL_FUNC) command_part);
1072 command_unbind("me", (SIGNAL_FUNC) command_me);
1073 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1074 command_unbind("away", (SIGNAL_FUNC) command_away);
1075 command_unbind("key", (SIGNAL_FUNC) command_key);
1077 silc_nicklist_deinit();