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 /* ACTION local command. Same as ME but takes the channel as mandatory
493 static void command_action(const char *data, SILC_SERVER_REC *server,
496 SILC_CHANNEL_REC *chanrec;
497 char *tmpcmd = "ME", *tmp;
499 unsigned char **argv;
500 uint32 *argv_lens, *argv_types;
503 if (!IS_SILC_SERVER(server) || !server->connected)
504 cmd_return_error(CMDERR_NOT_CONNECTED);
506 if (!IS_SILC_CHANNEL(item))
507 cmd_return_error(CMDERR_NOT_JOINED);
509 /* Now parse all arguments */
510 tmp = g_strconcat(tmpcmd, " ", data, NULL);
511 silc_parse_command_line(tmp, &argv, &argv_lens,
512 &argv_types, &argc, 3);
516 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
518 chanrec = silc_channel_find(server, argv[1]);
520 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
522 /* Send the action message */
523 silc_client_send_channel_message(silc_client, server->conn,
524 chanrec->entry, NULL,
525 SILC_MESSAGE_FLAG_ACTION,
526 argv[2], argv_lens[2], TRUE);
528 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
529 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION, argv[2]);
531 for (i = 0; i < argc; i++)
533 silc_free(argv_lens);
534 silc_free(argv_types);
537 /* NOTICE local command. */
539 static void command_notice(const char *data, SILC_SERVER_REC *server,
542 SILC_CHANNEL_REC *chanrec;
543 char *tmpcmd = "ME", *tmp;
545 unsigned char **argv;
546 uint32 *argv_lens, *argv_types;
549 if (!IS_SILC_SERVER(server) || !server->connected)
550 cmd_return_error(CMDERR_NOT_CONNECTED);
552 if (!IS_SILC_CHANNEL(item))
553 cmd_return_error(CMDERR_NOT_JOINED);
555 /* Now parse all arguments */
556 tmp = g_strconcat(tmpcmd, " ", data, NULL);
557 silc_parse_command_line(tmp, &argv, &argv_lens,
558 &argv_types, &argc, 2);
562 cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
564 chanrec = silc_channel_find(server, item->name);
566 cmd_return_error(CMDERR_CHAN_NOT_FOUND);
568 /* Send the action message */
569 silc_client_send_channel_message(silc_client, server->conn,
570 chanrec->entry, NULL,
571 SILC_MESSAGE_FLAG_NOTICE,
572 argv[1], argv_lens[1], TRUE);
574 printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
575 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE, argv[1]);
577 for (i = 0; i < argc; i++)
579 silc_free(argv_lens);
580 silc_free(argv_types);
583 /* AWAY local command. Sends UMODE command that sets the SILC_UMODE_GONE
586 static void command_away(const char *data, SILC_SERVER_REC *server,
591 if (!IS_SILC_SERVER(server) || !server->connected)
592 cmd_return_error(CMDERR_NOT_CONNECTED);
595 /* Remove any possible away message */
596 silc_client_set_away_message(silc_client, server->conn, NULL);
599 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
602 /* Set the away message */
603 silc_client_set_away_message(silc_client, server->conn, (char *)data);
606 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
607 SILCTXT_SET_AWAY, data);
610 signal_emit("away mode changed", 1, server);
612 silc_command_exec(server, "UMODE", set ? "+g" : "-g");
616 int type; /* 1 = msg, 2 = channel */
617 SILC_SERVER_REC *server;
620 /* Key agreement callback that is called after the key agreement protocol
621 has been performed. This is called also if error occured during the
622 key agreement protocol. The `key' is the allocated key material and
623 the caller is responsible of freeing it. The `key' is NULL if error
624 has occured. The application can freely use the `key' to whatever
625 purpose it needs. See lib/silcske/silcske.h for the definition of
626 the SilcSKEKeyMaterial structure. */
628 static void keyagr_completion(SilcClient client,
629 SilcClientConnection conn,
630 SilcClientEntry client_entry,
631 SilcKeyAgreementStatus status,
632 SilcSKEKeyMaterial *key,
635 KeyInternal i = (KeyInternal)context;
638 case SILC_KEY_AGREEMENT_OK:
639 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
640 SILCTXT_KEY_AGREEMENT_OK, client_entry->nickname);
643 /* Set the private key for this client */
644 silc_client_del_private_message_key(client, conn, client_entry);
645 silc_client_add_private_message_key_ske(client, conn, client_entry,
647 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
648 SILCTXT_KEY_AGREEMENT_PRIVMSG,
649 client_entry->nickname);
650 silc_ske_free_key_material(key);
655 case SILC_KEY_AGREEMENT_ERROR:
656 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
657 SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
660 case SILC_KEY_AGREEMENT_FAILURE:
661 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
662 SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
665 case SILC_KEY_AGREEMENT_TIMEOUT:
666 printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_NOTICES,
667 SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
678 /* Local command KEY. This command is used to set and unset private
679 keys for channels, set and unset private keys for private messages
680 with remote clients and to send key agreement requests and
681 negotiate the key agreement protocol with remote client. The
682 key agreement is supported only to negotiate private message keys,
683 it currently cannot be used to negotiate private keys for channels,
684 as it is not convenient for that purpose. */
687 SILC_SERVER_REC *server;
692 /* Callback to be called after client information is resolved from the
695 SILC_CLIENT_CMD_FUNC(key_get_clients)
697 KeyGetClients internal = (KeyGetClients)context;
698 signal_emit("command key", 3, internal->data, internal->server,
700 silc_free(internal->data);
704 static void command_key(const char *data, SILC_SERVER_REC *server,
707 SilcClientConnection conn = server->conn;
708 SilcClientEntry client_entry = NULL;
709 SilcChannelEntry channel_entry = NULL;
711 char *nickname = NULL, *serv = NULL, *tmp;
712 int command = 0, port = 0, type = 0;
713 char *hostname = NULL;
714 KeyInternal internal = NULL;
716 unsigned char **argv;
717 uint32 *argv_lens, *argv_types;
719 if (!IS_SILC_SERVER(server) || !server->connected)
720 cmd_return_error(CMDERR_NOT_CONNECTED);
722 /* Now parse all arguments */
723 tmp = g_strconcat("KEY", " ", data, NULL);
724 silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 7);
728 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
729 "set|unset|agreement|negotiate [<arguments>]");
734 if (!strcasecmp(argv[1], "msg"))
736 if (!strcasecmp(argv[1], "channel"))
740 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
741 "set|unset|agreement|negotiate [<arguments>]");
746 if (argv[2][0] == '*') {
749 /* Parse the typed nickname. */
750 if (!silc_parse_nickname(argv[2], &nickname, &serv, &num)) {
751 printformat_module("fe-common/silc", server, NULL,
752 MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
756 /* Find client entry */
757 client_entry = silc_idlist_get_client(silc_client, conn, nickname,
760 KeyGetClients inter = silc_calloc(1, sizeof(*inter));
761 inter->server = server;
762 inter->data = strdup(data);
765 /* Client entry not found, it was requested thus mark this to be
767 silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
769 NULL, silc_client_command_key_get_clients,
777 /* Get channel entry */
780 if (argv[2][0] == '*') {
781 if (!conn->current_channel) {
786 cmd_return_error(CMDERR_NOT_JOINED);
788 name = conn->current_channel->channel_name;
793 channel_entry = silc_client_get_channel(silc_client, conn, name);
794 if (!channel_entry) {
799 cmd_return_error(CMDERR_NOT_JOINED);
804 if (!strcasecmp(argv[3], "set")) {
808 if (type == 1 && client_entry) {
809 /* Set private message key */
811 silc_client_del_private_message_key(silc_client, conn, client_entry);
814 silc_client_add_private_message_key(silc_client, conn, client_entry,
820 silc_client_add_private_message_key(silc_client, conn, client_entry,
826 /* Send the key to the remote client so that it starts using it
828 silc_client_send_private_message_key(silc_client, conn,
830 } else if (type == 2) {
831 /* Set private channel key */
832 char *cipher = NULL, *hmac = NULL;
834 if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
835 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
836 SILCTXT_CH_PRIVATE_KEY_NOMODE,
837 channel_entry->channel_name);
846 if (!silc_client_add_channel_private_key(silc_client, conn,
851 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
852 SILCTXT_CH_PRIVATE_KEY_ERROR,
853 channel_entry->channel_name);
857 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
858 SILCTXT_CH_PRIVATE_KEY_ADD,
859 channel_entry->channel_name);
867 if (!strcasecmp(argv[3], "unset")) {
870 if (type == 1 && client_entry) {
871 /* Unset private message key */
872 silc_client_del_private_message_key(silc_client, conn, client_entry);
873 } else if (type == 2) {
874 /* Unset channel key(s) */
875 SilcChannelPrivateKey *keys;
880 silc_client_del_channel_private_keys(silc_client, conn,
884 number = atoi(argv[4]);
885 keys = silc_client_list_channel_private_keys(silc_client, conn,
891 if (!number || number > keys_count) {
892 silc_client_free_channel_private_keys(keys, keys_count);
896 silc_client_del_channel_private_key(silc_client, conn, channel_entry,
898 silc_client_free_channel_private_keys(keys, keys_count);
906 if (!strcasecmp(argv[3], "list")) {
910 SilcPrivateMessageKeys keys;
915 keys = silc_client_list_private_message_keys(silc_client, conn,
920 /* list the private message key(s) */
921 if (nickname[0] == '*') {
922 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
923 SILCTXT_PRIVATE_KEY_LIST);
924 for (k = 0; k < keys_count; k++) {
925 memset(buf, 0, sizeof(buf));
926 strncat(buf, " ", 2);
927 len = strlen(keys[k].client_entry->nickname);
928 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
930 for (i = 0; i < 30 - len; i++)
934 len = strlen(keys[k].cipher);
935 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
937 for (i = 0; i < 14 - len; i++)
942 strcat(buf, "<hidden>");
944 strcat(buf, "*generated*");
946 silc_say(silc_client, conn, "%s", buf);
949 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
950 SILCTXT_PRIVATE_KEY_LIST_NICK,
951 client_entry->nickname);
952 for (k = 0; k < keys_count; k++) {
953 if (keys[k].client_entry != client_entry)
956 memset(buf, 0, sizeof(buf));
957 strncat(buf, " ", 2);
958 len = strlen(keys[k].client_entry->nickname);
959 strncat(buf, keys[k].client_entry->nickname, len > 30 ? 30 : len);
961 for (i = 0; i < 30 - len; i++)
965 len = strlen(keys[k].cipher);
966 strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
968 for (i = 0; i < 14 - len; i++)
973 strcat(buf, "<hidden>");
975 strcat(buf, "*generated*");
977 silc_say(silc_client, conn, "%s", buf);
981 silc_client_free_private_message_keys(keys, keys_count);
982 } else if (type == 2) {
983 SilcChannelPrivateKey *keys;
988 keys = silc_client_list_channel_private_keys(silc_client, conn,
994 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
995 SILCTXT_CH_PRIVATE_KEY_LIST,
996 channel_entry->channel_name);
997 for (k = 0; k < keys_count; k++) {
998 memset(buf, 0, sizeof(buf));
999 strncat(buf, " ", 2);
1001 len = strlen(keys[k]->cipher->cipher->name);
1002 strncat(buf, keys[k]->cipher->cipher->name, len > 16 ? 16 : len);
1004 for (i = 0; i < 16 - len; i++)
1008 len = strlen(keys[k]->hmac->hmac->name);
1009 strncat(buf, keys[k]->hmac->hmac->name, len > 16 ? 16 : len);
1011 for (i = 0; i < 16 - len; i++)
1015 strcat(buf, "<hidden>");
1017 silc_say(silc_client, conn, "%s", buf);
1020 silc_client_free_channel_private_keys(keys, keys_count);
1026 /* Send command is used to send key agreement */
1027 if (!strcasecmp(argv[3], "agreement")) {
1033 port = atoi(argv[5]);
1035 internal = silc_calloc(1, sizeof(*internal));
1036 internal->type = type;
1037 internal->server = server;
1040 /* Start command is used to start key agreement (after receiving the
1041 key_agreement client operation). */
1042 if (!strcasecmp(argv[3], "negotiate")) {
1048 port = atoi(argv[5]);
1050 internal = silc_calloc(1, sizeof(*internal));
1051 internal->type = type;
1052 internal->server = server;
1056 silc_say(silc_client, conn, "Usage: /KEY msg|channel <nickname|channel> "
1057 "set|unset|agreement|negotiate [<arguments>]");
1061 if (command == 4 && client_entry) {
1062 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1063 SILCTXT_KEY_AGREEMENT, argv[2]);
1064 silc_client_send_key_agreement(silc_client, conn, client_entry, hostname,
1065 port, 120, keyagr_completion, internal);
1069 if (command == 5 && client_entry && hostname) {
1070 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_NOTICES,
1071 SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
1072 silc_client_perform_key_agreement(silc_client, conn, client_entry,
1073 hostname, port, keyagr_completion,
1080 silc_free(nickname);
1085 void silc_channels_init(void)
1087 signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1088 signal_add("server connected", (SIGNAL_FUNC) sig_connected);
1089 signal_add("server quit", (SIGNAL_FUNC) sig_server_quit);
1091 signal_add("silc event join", (SIGNAL_FUNC) event_join);
1092 signal_add("silc event leave", (SIGNAL_FUNC) event_leave);
1093 signal_add("silc event signoff", (SIGNAL_FUNC) event_signoff);
1094 signal_add("silc event topic", (SIGNAL_FUNC) event_topic);
1095 signal_add("silc event invite", (SIGNAL_FUNC) event_invite);
1096 signal_add("silc event nick", (SIGNAL_FUNC) event_nick);
1097 signal_add("silc event cmode", (SIGNAL_FUNC) event_cmode);
1098 signal_add("silc event cumode", (SIGNAL_FUNC) event_cumode);
1099 signal_add("silc event motd", (SIGNAL_FUNC) event_motd);
1100 signal_add("silc event channel_change", (SIGNAL_FUNC) event_channel_change);
1101 signal_add("silc event server_signoff", (SIGNAL_FUNC) event_server_signoff);
1102 signal_add("silc event kick", (SIGNAL_FUNC) event_kick);
1103 signal_add("silc event kill", (SIGNAL_FUNC) event_kill);
1104 signal_add("silc event ban", (SIGNAL_FUNC) event_ban);
1106 command_bind("part", MODULE_NAME, (SIGNAL_FUNC) command_part);
1107 command_bind("me", MODULE_NAME, (SIGNAL_FUNC) command_me);
1108 command_bind("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
1109 command_bind("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
1110 command_bind("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
1111 command_bind("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
1113 silc_nicklist_init();
1116 void silc_channels_deinit(void)
1118 signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
1119 signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
1120 signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit);
1122 signal_remove("silc event join", (SIGNAL_FUNC) event_join);
1123 signal_remove("silc event leave", (SIGNAL_FUNC) event_leave);
1124 signal_remove("silc event signoff", (SIGNAL_FUNC) event_signoff);
1125 signal_remove("silc event topic", (SIGNAL_FUNC) event_topic);
1126 signal_remove("silc event invite", (SIGNAL_FUNC) event_invite);
1127 signal_remove("silc event nick", (SIGNAL_FUNC) event_nick);
1128 signal_remove("silc event cmode", (SIGNAL_FUNC) event_cmode);
1129 signal_remove("silc event cumode", (SIGNAL_FUNC) event_cumode);
1130 signal_remove("silc event motd", (SIGNAL_FUNC) event_motd);
1131 signal_remove("silc event channel_change",
1132 (SIGNAL_FUNC) event_channel_change);
1133 signal_remove("silc event server_signoff",
1134 (SIGNAL_FUNC) event_server_signoff);
1135 signal_remove("silc event kick", (SIGNAL_FUNC) event_kick);
1136 signal_remove("silc event kill", (SIGNAL_FUNC) event_kill);
1137 signal_remove("silc event ban", (SIGNAL_FUNC) event_ban);
1139 command_unbind("part", (SIGNAL_FUNC) command_part);
1140 command_unbind("me", (SIGNAL_FUNC) command_me);
1141 command_unbind("action", (SIGNAL_FUNC) command_action);
1142 command_unbind("notice", (SIGNAL_FUNC) command_notice);
1143 command_unbind("away", (SIGNAL_FUNC) command_away);
1144 command_unbind("key", (SIGNAL_FUNC) command_key);
1146 silc_nicklist_deinit();