5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "chat-protocols.h"
26 #include "servers-setup.h"
27 #include "channels-setup.h"
28 #include "silc-servers.h"
29 #include "silc-channels.h"
30 #include "silc-queries.h"
31 #include "silc-nicklist.h"
36 #include "fe-common/core/printtext.h"
37 #include "fe-common/core/fe-channels.h"
38 #include "fe-common/core/keyboard.h"
39 #include "fe-common/silc/module-formats.h"
45 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
46 const char *name, SilcSocketType conn_type,
47 unsigned char *pk, SilcUInt32 pk_len,
48 SilcSKEPKType pk_type,
49 SilcVerifyPublicKey completion, void *context);
51 static void silc_get_umode_string(SilcUInt32 mode, char *buf,
54 if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
55 (mode & SILC_UMODE_ROUTER_OPERATOR)) {
56 strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
58 (mode & SILC_UMODE_ROUTER_OPERATOR) ?
59 "[SILC operator]" : "[unknown mode]");
61 if (mode & SILC_UMODE_GONE)
62 strcat(buf, " [away]");
63 if (mode & SILC_UMODE_INDISPOSED)
64 strcat(buf, " [indisposed]");
65 if (mode & SILC_UMODE_BUSY)
66 strcat(buf, " [busy]");
67 if (mode & SILC_UMODE_PAGE)
68 strcat(buf, " [page to reach]");
69 if (mode & SILC_UMODE_HYPER)
70 strcat(buf, " [hyper active]");
71 if (mode & SILC_UMODE_ROBOT)
72 strcat(buf, " [robot]");
73 if (mode & SILC_UMODE_ANONYMOUS)
74 strcat(buf, " [anonymous]");
75 if (mode & SILC_UMODE_BLOCK_PRIVMSG)
76 strcat(buf, " [blocks private messages]");
77 if (mode & SILC_UMODE_DETACHED)
78 strcat(buf, " [detached]");
79 if (mode & SILC_UMODE_REJECT_WATCHING)
80 strcat(buf, " [rejects watching]");
81 if (mode & SILC_UMODE_BLOCK_INVITE)
82 strcat(buf, " [blocks invites]");
85 void silc_say(SilcClient client, SilcClientConnection conn,
86 SilcClientMessageType type, char *msg, ...)
88 SILC_SERVER_REC *server;
92 server = conn == NULL ? NULL : conn->context;
95 str = g_strdup_vprintf(msg, va);
96 printtext(server, NULL, MSGLEVEL_CRAP, "%s", str);
101 void silc_say_error(char *msg, ...)
107 str = g_strdup_vprintf(msg, va);
108 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str);
114 void silc_emit_mime_sig(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
115 const char *data, SilcUInt32 data_len,
116 const char *encoding, const char *type,
122 blob.octets = data_len;
123 blob.data = (char *)data;
125 signal_emit("mime", 6, server, channel, &blob, encoding, type, nick);
128 /* Message for a channel. The `sender' is the nickname of the sender
129 received in the packet. The `channel_name' is the name of the channel. */
131 void silc_channel_message(SilcClient client, SilcClientConnection conn,
132 SilcClientEntry sender, SilcChannelEntry channel,
133 SilcMessageFlags flags, const unsigned char *message,
134 SilcUInt32 message_len)
136 SILC_SERVER_REC *server;
138 SILC_CHANNEL_REC *chanrec;
140 SILC_LOG_DEBUG(("Start"));
145 server = conn == NULL ? NULL : conn->context;
146 chanrec = silc_channel_find_entry(server, channel);
150 nick = silc_nicklist_find(chanrec, sender);
152 /* We didn't find client but it clearly exists, add it. */
153 SilcChannelUser chu = silc_client_on_channel(channel, sender);
155 nick = silc_nicklist_insert(chanrec, chu, FALSE);
158 if (flags & SILC_MESSAGE_FLAG_DATA) {
159 /* MIME object received, try to display it as well as we can */
160 char type[128], enc[128];
164 memset(type, 0, sizeof(type));
165 memset(enc, 0, sizeof(enc));
166 if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
167 enc, sizeof(enc) - 1, &data, &data_len))
170 /* Then figure out what we can display */
171 if (strstr(type, "text/") && !strstr(type, "text/t140") &&
172 !strstr(type, "text/vnd")) {
173 /* It is something textual, display it */
174 message = (const unsigned char *)data;
176 silc_emit_mime_sig(server, chanrec, data, data_len,
177 enc, type, nick->nick);
185 if (flags & SILC_MESSAGE_FLAG_ACTION)
186 printformat_module("fe-common/silc", server, channel->channel_name,
187 MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
188 nick == NULL ? "[<unknown>]" : nick->nick, message);
189 else if (flags & SILC_MESSAGE_FLAG_NOTICE)
190 printformat_module("fe-common/silc", server, channel->channel_name,
191 MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
192 nick == NULL ? "[<unknown>]" : nick->nick, message);
194 if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
195 char tmp[256], *cp, *dm = NULL;
197 memset(tmp, 0, sizeof(tmp));
199 if (message_len > sizeof(tmp) - 1) {
200 dm = silc_calloc(message_len + 1, sizeof(*dm));
204 silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
206 signal_emit("message public", 6, server, cp,
207 nick == NULL ? "[<unknown>]" : nick->nick,
208 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
209 chanrec->name, nick);
214 signal_emit("message public", 6, server, message,
215 nick == NULL ? "[<unknown>]" : nick->nick,
216 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
217 chanrec->name, nick);
221 /* Private message to the client. The `sender' is the nickname of the
222 sender received in the packet. */
224 void silc_private_message(SilcClient client, SilcClientConnection conn,
225 SilcClientEntry sender, SilcMessageFlags flags,
226 const unsigned char *message,
227 SilcUInt32 message_len)
229 SILC_SERVER_REC *server;
232 SILC_LOG_DEBUG(("Start"));
234 server = conn == NULL ? NULL : conn->context;
235 memset(userhost, 0, sizeof(userhost));
236 if (sender->username)
237 snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
238 sender->username, sender->hostname);
240 if (flags & SILC_MESSAGE_FLAG_DATA) {
241 /* MIME object received, try to display it as well as we can */
242 char type[128], enc[128];
246 memset(type, 0, sizeof(type));
247 memset(enc, 0, sizeof(enc));
248 if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
249 enc, sizeof(enc) - 1, &data, &data_len))
252 /* Then figure out what we can display */
253 if (strstr(type, "text/") && !strstr(type, "text/t140") &&
254 !strstr(type, "text/vnd")) {
255 /* It is something textual, display it */
256 message = (const unsigned char *)data;
258 silc_emit_mime_sig(server, NULL, data, data_len,
259 enc, type, sender->nickname);
267 if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
268 char tmp[256], *cp, *dm = NULL;
270 memset(tmp, 0, sizeof(tmp));
272 if (message_len > sizeof(tmp) - 1) {
273 dm = silc_calloc(message_len + 1, sizeof(*dm));
277 silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
279 signal_emit("message private", 4, server, cp,
280 sender->nickname ? sender->nickname : "[<unknown>]",
281 sender->username ? userhost : NULL);
286 signal_emit("message private", 4, server, message,
287 sender->nickname ? sender->nickname : "[<unknown>]",
288 sender->username ? userhost : NULL);
291 /* Notify message to the client. The notify arguments are sent in the
292 same order as servers sends them. The arguments are same as received
293 from the server except for ID's. If ID is received application receives
294 the corresponding entry to the ID. For example, if Client ID is received
295 application receives SilcClientEntry. Also, if the notify type is
296 for channel the channel entry is sent to application (even if server
297 does not send it). */
299 void silc_notify(SilcClient client, SilcClientConnection conn,
300 SilcNotifyType type, ...)
303 SILC_SERVER_REC *server;
304 SILC_CHANNEL_REC *chanrec;
305 SILC_NICK_REC *nickrec;
306 SilcClientEntry client_entry, client_entry2;
307 SilcChannelEntry channel, channel2;
308 SilcServerEntry server_entry;
314 GSList *list1, *list_tmp;
316 SILC_LOG_DEBUG(("Start"));
320 server = conn == NULL ? NULL : conn->context;
323 case SILC_NOTIFY_TYPE_NONE:
324 /* Some generic notice from server */
325 printtext(server, NULL, MSGLEVEL_CRAP, "%s", (char *)va_arg(va, char *));
328 case SILC_NOTIFY_TYPE_INVITE:
330 * Invited or modified invite list.
333 SILC_LOG_DEBUG(("Notify: INVITE"));
335 channel = va_arg(va, SilcChannelEntry);
336 name = va_arg(va, char *);
337 client_entry = va_arg(va, SilcClientEntry);
339 memset(buf, 0, sizeof(buf));
340 snprintf(buf, sizeof(buf) - 1, "%s@%s",
341 client_entry->username, client_entry->hostname);
342 signal_emit("message invite", 4, server, channel ? channel->channel_name :
343 name, client_entry->nickname, buf);
346 case SILC_NOTIFY_TYPE_JOIN:
351 SILC_LOG_DEBUG(("Notify: JOIN"));
353 client_entry = va_arg(va, SilcClientEntry);
354 channel = va_arg(va, SilcChannelEntry);
356 if (client_entry == server->conn->local_entry) {
357 /* You joined to channel */
358 chanrec = silc_channel_find(server, channel->channel_name);
359 if (chanrec != NULL && !chanrec->joined)
360 chanrec->entry = channel;
362 chanrec = silc_channel_find_entry(server, channel);
363 if (chanrec != NULL) {
364 SilcChannelUser chu = silc_client_on_channel(channel, client_entry);
366 nickrec = silc_nicklist_insert(chanrec, chu, TRUE);
370 memset(buf, 0, sizeof(buf));
371 if (client_entry->username)
372 snprintf(buf, sizeof(buf) - 1, "%s@%s",
373 client_entry->username, client_entry->hostname);
374 signal_emit("message join", 4, server, channel->channel_name,
375 client_entry->nickname,
376 client_entry->username == NULL ? "" : buf);
379 case SILC_NOTIFY_TYPE_LEAVE:
384 SILC_LOG_DEBUG(("Notify: LEAVE"));
386 client_entry = va_arg(va, SilcClientEntry);
387 channel = va_arg(va, SilcChannelEntry);
389 memset(buf, 0, sizeof(buf));
390 if (client_entry->username)
391 snprintf(buf, sizeof(buf) - 1, "%s@%s",
392 client_entry->username, client_entry->hostname);
393 signal_emit("message part", 5, server, channel->channel_name,
394 client_entry->nickname, client_entry->username ?
395 buf : "", client_entry->nickname);
397 chanrec = silc_channel_find_entry(server, channel);
398 if (chanrec != NULL) {
399 nickrec = silc_nicklist_find(chanrec, client_entry);
401 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
405 case SILC_NOTIFY_TYPE_SIGNOFF:
410 SILC_LOG_DEBUG(("Notify: SIGNOFF"));
412 client_entry = va_arg(va, SilcClientEntry);
413 tmp = va_arg(va, char *);
415 silc_server_free_ftp(server, client_entry);
417 memset(buf, 0, sizeof(buf));
418 if (client_entry->username)
419 snprintf(buf, sizeof(buf) - 1, "%s@%s",
420 client_entry->username, client_entry->hostname);
421 signal_emit("message quit", 4, server, client_entry->nickname,
422 client_entry->username ? buf : "",
425 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
426 for (list_tmp = list1; list_tmp != NULL; list_tmp =
427 list_tmp->next->next) {
428 CHANNEL_REC *channel = list_tmp->data;
429 NICK_REC *nickrec = list_tmp->next->data;
431 nicklist_remove(channel, nickrec);
435 case SILC_NOTIFY_TYPE_TOPIC_SET:
440 SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
442 idtype = va_arg(va, int);
443 entry = va_arg(va, void *);
444 tmp = va_arg(va, char *);
445 channel = va_arg(va, SilcChannelEntry);
447 chanrec = silc_channel_find_entry(server, channel);
448 if (chanrec != NULL) {
449 g_free_not_null(chanrec->topic);
450 chanrec->topic = *tmp == '\0' ? NULL : g_strdup(tmp);
451 signal_emit("channel topic changed", 1, chanrec);
454 if (idtype == SILC_ID_CLIENT) {
455 client_entry = (SilcClientEntry)entry;
456 memset(buf, 0, sizeof(buf));
457 snprintf(buf, sizeof(buf) - 1, "%s@%s",
458 client_entry->username, client_entry->hostname);
459 signal_emit("message topic", 5, server, channel->channel_name,
460 tmp, client_entry->nickname, buf);
461 } else if (idtype == SILC_ID_SERVER) {
462 server_entry = (SilcServerEntry)entry;
463 signal_emit("message topic", 5, server, channel->channel_name,
464 tmp, server_entry->server_name,
465 server_entry->server_name);
466 } else if (idtype == SILC_ID_CHANNEL) {
467 channel = (SilcChannelEntry)entry;
468 signal_emit("message topic", 5, server, channel->channel_name,
469 tmp, channel->channel_name, channel->channel_name);
473 case SILC_NOTIFY_TYPE_NICK_CHANGE:
478 SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
480 client_entry = va_arg(va, SilcClientEntry);
481 client_entry2 = va_arg(va, SilcClientEntry);
483 if (!strcmp(client_entry->nickname, client_entry2->nickname))
486 memset(buf, 0, sizeof(buf));
487 snprintf(buf, sizeof(buf) - 1, "%s@%s",
488 client_entry2->username, client_entry2->hostname);
489 nicklist_rename_unique(SERVER(server),
490 client_entry, client_entry->nickname,
491 client_entry2, client_entry2->nickname);
492 signal_emit("message nick", 4, server, client_entry2->nickname,
493 client_entry->nickname, buf);
496 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
498 * Changed channel mode.
501 SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
503 idtype = va_arg(va, int);
504 entry = va_arg(va, void *);
505 mode = va_arg(va, SilcUInt32);
506 (void)va_arg(va, char *);
507 (void)va_arg(va, char *);
508 channel = va_arg(va, SilcChannelEntry);
510 tmp = silc_client_chmode(mode,
511 channel->channel_key ?
512 channel->channel_key->cipher->name : "",
514 silc_hmac_get_name(channel->hmac) : "");
516 chanrec = silc_channel_find_entry(server, channel);
517 if (chanrec != NULL) {
518 g_free_not_null(chanrec->mode);
519 chanrec->mode = g_strdup(tmp == NULL ? "" : tmp);
520 signal_emit("channel mode changed", 1, chanrec);
523 if (idtype == SILC_ID_CLIENT) {
524 client_entry = (SilcClientEntry)entry;
525 printformat_module("fe-common/silc", server, channel->channel_name,
526 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
527 channel->channel_name, tmp ? tmp : "removed all",
528 client_entry->nickname);
529 } else if (idtype == SILC_ID_SERVER) {
530 server_entry = (SilcServerEntry)entry;
531 printformat_module("fe-common/silc", server, channel->channel_name,
532 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
533 channel->channel_name, tmp ? tmp : "removed all",
534 server_entry->server_name);
535 } else if (idtype == SILC_ID_CHANNEL) {
536 channel2 = (SilcChannelEntry)entry;
537 printformat_module("fe-common/silc", server, channel->channel_name,
538 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
539 channel->channel_name, tmp ? tmp : "removed all",
540 channel2->channel_name);
546 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
548 * Changed user's mode on channel.
551 SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
553 idtype = va_arg(va, int);
554 entry = va_arg(va, void *);
555 mode = va_arg(va, SilcUInt32);
556 client_entry2 = va_arg(va, SilcClientEntry);
557 channel = va_arg(va, SilcChannelEntry);
559 tmp = silc_client_chumode(mode);
560 chanrec = silc_channel_find_entry(server, channel);
561 if (chanrec != NULL) {
564 if (client_entry2 == server->conn->local_entry)
565 chanrec->chanop = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
567 nick = silc_nicklist_find(chanrec, client_entry2);
569 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
570 nick->founder = (mode & SILC_CHANNEL_UMODE_CHANFO) != 0;
571 signal_emit("nick mode changed", 2, chanrec, nick);
575 if (idtype == SILC_ID_CLIENT) {
576 client_entry = (SilcClientEntry)entry;
577 printformat_module("fe-common/silc", server, channel->channel_name,
578 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
579 channel->channel_name, client_entry2->nickname,
580 tmp ? tmp : "removed all",
581 client_entry->nickname);
582 } else if (idtype == SILC_ID_SERVER) {
583 server_entry = (SilcServerEntry)entry;
584 printformat_module("fe-common/silc", server, channel->channel_name,
585 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
586 channel->channel_name, client_entry2->nickname,
587 tmp ? tmp : "removed all",
588 server_entry->server_name);
589 } else if (idtype == SILC_ID_CHANNEL) {
590 channel2 = (SilcChannelEntry)entry;
591 printformat_module("fe-common/silc", server, channel->channel_name,
592 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
593 channel->channel_name, client_entry2->nickname,
594 tmp ? tmp : "removed all",
595 channel2->channel_name);
598 if (mode & SILC_CHANNEL_UMODE_CHANFO)
599 printformat_module("fe-common/silc",
600 server, channel->channel_name, MSGLEVEL_CRAP,
601 SILCTXT_CHANNEL_FOUNDER,
602 channel->channel_name, client_entry2->nickname);
604 if (mode & SILC_CHANNEL_UMODE_QUIET && conn->local_entry == client_entry2)
605 printformat_module("fe-common/silc",
606 server, channel->channel_name, MSGLEVEL_CRAP,
607 SILCTXT_CHANNEL_QUIETED, channel->channel_name);
612 case SILC_NOTIFY_TYPE_MOTD:
617 SILC_LOG_DEBUG(("Notify: MOTD"));
619 tmp = va_arg(va, char *);
621 if (!settings_get_bool("skip_motd"))
622 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", tmp);
625 case SILC_NOTIFY_TYPE_KICKED:
627 * Someone was kicked from channel.
630 SILC_LOG_DEBUG(("Notify: KICKED"));
632 client_entry = va_arg(va, SilcClientEntry);
633 tmp = va_arg(va, char *);
634 client_entry2 = va_arg(va, SilcClientEntry);
635 channel = va_arg(va, SilcChannelEntry);
637 chanrec = silc_channel_find_entry(server, channel);
639 if (client_entry == conn->local_entry) {
640 printformat_module("fe-common/silc", server, channel->channel_name,
641 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
642 channel->channel_name,
643 client_entry ? client_entry2->nickname : "",
646 chanrec->kicked = TRUE;
647 channel_destroy((CHANNEL_REC *)chanrec);
650 printformat_module("fe-common/silc", server, channel->channel_name,
651 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
652 client_entry->nickname, channel->channel_name,
653 client_entry2 ? client_entry2->nickname : "",
657 SILC_NICK_REC *nickrec = silc_nicklist_find(chanrec, client_entry);
659 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
664 case SILC_NOTIFY_TYPE_KILLED:
666 * Someone was killed from the network.
669 SILC_LOG_DEBUG(("Notify: KILLED"));
671 client_entry = va_arg(va, SilcClientEntry);
672 tmp = va_arg(va, char *);
673 idtype = va_arg(va, int);
674 entry = va_arg(va, SilcClientEntry);
676 if (client_entry == conn->local_entry) {
677 if (idtype == SILC_ID_CLIENT) {
678 client_entry2 = (SilcClientEntry)entry;
679 printformat_module("fe-common/silc", server, NULL,
680 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
681 client_entry2 ? client_entry2->nickname : "",
683 } else if (idtype == SILC_ID_SERVER) {
684 server_entry = (SilcServerEntry)entry;
685 printformat_module("fe-common/silc", server, NULL,
686 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
687 server_entry->server_name, tmp ? tmp : "");
688 } else if (idtype == SILC_ID_CHANNEL) {
689 channel = (SilcChannelEntry)entry;
690 printformat_module("fe-common/silc", server, NULL,
691 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
692 channel->channel_name, tmp ? tmp : "");
695 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
696 for (list_tmp = list1; list_tmp != NULL; list_tmp =
697 list_tmp->next->next) {
698 CHANNEL_REC *channel = list_tmp->data;
699 NICK_REC *nickrec = list_tmp->next->data;
700 nicklist_remove(channel, nickrec);
703 if (idtype == SILC_ID_CLIENT) {
704 client_entry2 = (SilcClientEntry)entry;
705 printformat_module("fe-common/silc", server, NULL,
706 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
707 client_entry->nickname,
708 client_entry2 ? client_entry2->nickname : "",
710 } else if (idtype == SILC_ID_SERVER) {
711 server_entry = (SilcServerEntry)entry;
712 printformat_module("fe-common/silc", server, NULL,
713 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
714 client_entry->nickname,
715 server_entry->server_name, tmp ? tmp : "");
716 } else if (idtype == SILC_ID_CHANNEL) {
717 channel = (SilcChannelEntry)entry;
718 printformat_module("fe-common/silc", server, NULL,
719 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
720 client_entry->nickname,
721 channel->channel_name, tmp ? tmp : "");
726 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
729 case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
732 * Server has quit the network.
735 SilcClientEntry *clients;
736 SilcUInt32 clients_count;
738 SILC_LOG_DEBUG(("Notify: SIGNOFF"));
740 (void)va_arg(va, void *);
741 clients = va_arg(va, SilcClientEntry *);
742 clients_count = va_arg(va, SilcUInt32);
744 for (i = 0; i < clients_count; i++) {
745 memset(buf, 0, sizeof(buf));
746 if (clients[i]->username)
747 snprintf(buf, sizeof(buf) - 1, "%s@%s",
748 clients[i]->username, clients[i]->hostname);
749 signal_emit("message quit", 4, server, clients[i]->nickname,
750 clients[i]->username ? buf : "",
753 silc_server_free_ftp(server, clients[i]);
755 list1 = nicklist_get_same_unique(SERVER(server), clients[i]);
756 for (list_tmp = list1; list_tmp != NULL; list_tmp =
757 list_tmp->next->next) {
758 CHANNEL_REC *channel = list_tmp->data;
759 NICK_REC *nickrec = list_tmp->next->data;
760 nicklist_remove(channel, nickrec);
766 case SILC_NOTIFY_TYPE_ERROR:
768 SilcStatus error = va_arg(va, int);
770 silc_say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
771 "%s", silc_get_status_message(error));
775 case SILC_NOTIFY_TYPE_WATCH:
777 SilcNotifyType notify;
779 client_entry = va_arg(va, SilcClientEntry);
780 name = va_arg(va, char *); /* Maybe NULL */
781 mode = va_arg(va, SilcUInt32);
782 notify = va_arg(va, int);
784 if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
786 printformat_module("fe-common/silc", server, NULL,
787 MSGLEVEL_CRAP, SILCTXT_WATCH_NICK_CHANGE,
788 client_entry->nickname, name);
790 printformat_module("fe-common/silc", server, NULL,
791 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
792 client_entry->nickname);
793 } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
794 /* See if client was away and is now present */
795 if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
796 SILC_UMODE_BUSY | SILC_UMODE_PAGE |
797 SILC_UMODE_DETACHED)) &&
798 (client_entry->mode & SILC_UMODE_GONE ||
799 client_entry->mode & SILC_UMODE_INDISPOSED ||
800 client_entry->mode & SILC_UMODE_BUSY ||
801 client_entry->mode & SILC_UMODE_PAGE ||
802 client_entry->mode & SILC_UMODE_DETACHED)) {
803 printformat_module("fe-common/silc", server, NULL,
804 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
805 client_entry->nickname);
809 memset(buf, 0, sizeof(buf));
810 silc_get_umode_string(mode, buf, sizeof(buf) - 1);
811 printformat_module("fe-common/silc", server, NULL,
812 MSGLEVEL_CRAP, SILCTXT_WATCH_UMODE_CHANGE,
813 client_entry->nickname, buf);
815 } else if (notify == SILC_NOTIFY_TYPE_KILLED) {
816 printformat_module("fe-common/silc", server, NULL,
817 MSGLEVEL_CRAP, SILCTXT_WATCH_KILLED,
818 client_entry->nickname);
819 } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
820 notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF) {
821 printformat_module("fe-common/silc", server, NULL,
822 MSGLEVEL_CRAP, SILCTXT_WATCH_SIGNOFF,
823 client_entry->nickname);
824 } else if (notify == SILC_NOTIFY_TYPE_NONE) {
825 /* Client logged in to the network */
826 printformat_module("fe-common/silc", server, NULL,
827 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
828 client_entry->nickname);
835 printformat_module("fe-common/silc", server, NULL,
836 MSGLEVEL_CRAP, SILCTXT_UNKNOWN_NOTIFY, type);
843 /* Called to indicate that connection was either successfully established
844 or connecting failed. This is also the first time application receives
845 the SilcClientConnection object which it should save somewhere. */
847 void silc_connect(SilcClient client, SilcClientConnection conn,
848 SilcClientConnectionStatus status)
850 SILC_SERVER_REC *server = conn->context;
852 if (!server || server->disconnected) {
853 silc_client_close_connection(client, conn);
858 case SILC_CLIENT_CONN_SUCCESS:
859 /* We have successfully connected to server */
860 server->connected = TRUE;
861 signal_emit("event connected", 1, server);
864 case SILC_CLIENT_CONN_SUCCESS_RESUME:
865 /* We have successfully resumed old detached session */
866 server->connected = TRUE;
867 signal_emit("event connected", 1, server);
869 /* If we resumed old session check whether we need to update
871 if (strcmp(server->nick, conn->local_entry->nickname)) {
873 old = g_strdup(server->nick);
874 server_change_nick(SERVER(server), conn->local_entry->nickname);
875 nicklist_rename_unique(SERVER(server),
876 conn->local_entry, server->nick,
877 conn->local_entry, conn->local_entry->nickname);
878 signal_emit("message own_nick", 4, server, server->nick, old, "");
884 server->connection_lost = TRUE;
886 server->conn->context = NULL;
887 server_disconnect(SERVER(server));
892 /* Called to indicate that connection was disconnected to the server. */
894 void silc_disconnect(SilcClient client, SilcClientConnection conn,
895 SilcStatus status, const char *message)
897 SILC_SERVER_REC *server = conn->context;
899 SILC_LOG_DEBUG(("Start"));
901 if (!server || server->connection_lost)
904 if (server->conn && server->conn->local_entry) {
905 nicklist_rename_unique(SERVER(server),
906 server->conn->local_entry, server->nick,
907 server->conn->local_entry,
908 silc_client->username);
909 silc_change_nick(server, silc_client->username);
913 silc_say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
914 "Server closed connection: %s (%d) %s",
915 silc_get_status_message(status), status,
916 message ? message : "");
918 server->conn->context = NULL;
920 server->connection_lost = TRUE;
921 server_disconnect(SERVER(server));
924 /* Command handler. This function is called always in the command function.
925 If error occurs it will be called as well. `conn' is the associated
926 client connection. `cmd_context' is the command context that was
927 originally sent to the command. `success' is FALSE if error occured
928 during command. `command' is the command being processed. It must be
929 noted that this is not reply from server. This is merely called just
930 after application has called the command. Just to tell application
931 that the command really was processed. */
933 void silc_command(SilcClient client, SilcClientConnection conn,
934 SilcClientCommandContext cmd_context, bool success,
935 SilcCommand command, SilcStatus status)
937 SILC_SERVER_REC *server = conn->context;
939 SILC_LOG_DEBUG(("Start"));
942 silc_say_error("%s", silc_get_status_message(status));
948 case SILC_COMMAND_INVITE:
949 printformat_module("fe-common/silc", server, NULL,
950 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING,
951 cmd_context->argv[2],
952 (cmd_context->argv[1][0] == '*' ?
953 (char *)conn->current_channel->channel_name :
954 (char *)cmd_context->argv[1]));
957 case SILC_COMMAND_DETACH:
958 server->no_reconnect = TRUE;
966 /* Client info resolving callback when JOIN command reply is received.
967 This will cache all users on the channel. */
969 static void silc_client_join_get_users(SilcClient client,
970 SilcClientConnection conn,
971 SilcClientEntry *clients,
972 SilcUInt32 clients_count,
975 SilcChannelEntry channel = (SilcChannelEntry)context;
976 SilcHashTableList htl;
978 SILC_SERVER_REC *server = conn->context;
979 SILC_CHANNEL_REC *chanrec;
980 SilcClientEntry founder = NULL;
983 SILC_LOG_DEBUG(("Start, channel %s, %d users", channel->channel_name,
984 silc_hash_table_count(channel->user_list)));
989 chanrec = silc_channel_find(server, channel->channel_name);
993 silc_hash_table_list(channel->user_list, &htl);
994 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
995 if (!chu->client->nickname)
997 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
998 founder = chu->client;
999 silc_nicklist_insert(chanrec, chu, FALSE);
1001 silc_hash_table_list_reset(&htl);
1003 ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
1004 nicklist_set_own(CHANNEL(chanrec), ownnick);
1005 signal_emit("channel joined", 1, chanrec);
1006 chanrec->entry = channel;
1009 printformat_module("fe-common/silc", server, channel->channel_name,
1010 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
1011 channel->channel_name, chanrec->topic);
1013 fe_channels_nicklist(CHANNEL(chanrec), CHANNEL_NICKLIST_FLAG_ALL);
1016 if (founder == conn->local_entry)
1017 printformat_module("fe-common/silc",
1018 server, channel->channel_name, MSGLEVEL_CRAP,
1019 SILCTXT_CHANNEL_FOUNDER_YOU,
1020 channel->channel_name);
1022 printformat_module("fe-common/silc",
1023 server, channel->channel_name, MSGLEVEL_CRAP,
1024 SILCTXT_CHANNEL_FOUNDER,
1025 channel->channel_name, founder->nickname);
1031 SilcClientConnection conn;
1037 void silc_getkey_cb(bool success, void *context)
1039 GetkeyContext getkey = (GetkeyContext)context;
1040 char *entity = (getkey->id_type == SILC_ID_CLIENT ? "user" : "server");
1041 char *name = (getkey->id_type == SILC_ID_CLIENT ?
1042 ((SilcClientEntry)getkey->entry)->nickname :
1043 ((SilcServerEntry)getkey->entry)->server_name);
1046 printformat_module("fe-common/silc", NULL, NULL,
1047 MSGLEVEL_CRAP, SILCTXT_GETKEY_VERIFIED, entity, name);
1049 printformat_module("fe-common/silc", NULL, NULL,
1050 MSGLEVEL_CRAP, SILCTXT_GETKEY_DISCARD, entity, name);
1053 silc_free(getkey->fingerprint);
1057 /* Command reply handler. This function is called always in the command reply
1058 function. If error occurs it will be called as well. Normal scenario
1059 is that it will be called after the received command data has been parsed
1060 and processed. The function is used to pass the received command data to
1063 `conn' is the associated client connection. `cmd_payload' is the command
1064 payload data received from server and it can be ignored. It is provided
1065 if the application would like to re-parse the received command data,
1066 however, it must be noted that the data is parsed already by the library
1067 thus the payload can be ignored. `success' is FALSE if error occured.
1068 In this case arguments are not sent to the application. `command' is the
1069 command reply being processed. The function has variable argument list
1070 and each command defines the number and type of arguments it passes to the
1071 application (on error they are not sent). */
1074 silc_command_reply(SilcClient client, SilcClientConnection conn,
1075 SilcCommandPayload cmd_payload, bool success,
1076 SilcCommand command, SilcStatus status, ...)
1079 SILC_SERVER_REC *server = conn->context;
1080 SILC_CHANNEL_REC *chanrec;
1083 va_start(vp, status);
1085 SILC_LOG_DEBUG(("Start"));
1088 case SILC_COMMAND_WHOIS:
1090 char buf[1024], *nickname, *username, *realname, *nick;
1091 unsigned char *fingerprint;
1092 SilcUInt32 idle, mode;
1093 SilcBuffer channels, user_modes;
1094 SilcClientEntry client_entry;
1097 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
1098 /* Print the unknown nick for user */
1099 unsigned char *tmp =
1100 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1103 silc_say_error("%s: %s", tmp,
1104 silc_get_status_message(status));
1106 } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1107 /* Try to find the entry for the unknown client ID, since we
1108 might have, and print the nickname of it for user. */
1110 unsigned char *tmp =
1111 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1114 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
1117 client_entry = silc_client_get_client_by_id(client, conn,
1119 if (client_entry && client_entry->nickname)
1120 silc_say_error("%s: %s", client_entry->nickname,
1121 silc_get_status_message(status));
1122 silc_free(client_id);
1126 } else if (!success) {
1127 silc_say_error("WHOIS: %s", silc_get_status_message(status));
1131 client_entry = va_arg(vp, SilcClientEntry);
1132 nickname = va_arg(vp, char *);
1133 username = va_arg(vp, char *);
1134 realname = va_arg(vp, char *);
1135 channels = va_arg(vp, SilcBuffer);
1136 mode = va_arg(vp, SilcUInt32);
1137 idle = va_arg(vp, SilcUInt32);
1138 fingerprint = va_arg(vp, unsigned char *);
1139 user_modes = va_arg(vp, SilcBuffer);
1140 attrs = va_arg(vp, SilcDList);
1142 silc_parse_userfqdn(nickname, &nick, NULL);
1143 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1144 SILCTXT_WHOIS_USERINFO, nickname,
1145 client_entry->username, client_entry->hostname,
1146 nick, client_entry->nickname);
1147 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1148 SILCTXT_WHOIS_REALNAME, realname);
1151 if (channels && user_modes) {
1153 SilcDList list = silc_channel_payload_parse_list(channels->data,
1155 if (list && silc_get_mode_list(user_modes, silc_dlist_count(list),
1157 SilcChannelPayload entry;
1160 memset(buf, 0, sizeof(buf));
1161 silc_dlist_start(list);
1162 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
1163 SilcUInt32 name_len;
1164 char *m = silc_client_chumode_char(umodes[i++]);
1165 char *name = silc_channel_get_name(entry, &name_len);
1168 strncat(buf, m, strlen(m));
1169 strncat(buf, name, name_len);
1170 strncat(buf, " ", 1);
1174 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1175 SILCTXT_WHOIS_CHANNELS, buf);
1176 silc_channel_payload_list_free(list);
1182 memset(buf, 0, sizeof(buf));
1183 silc_get_umode_string(mode, buf, sizeof(buf - 1));
1184 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1185 SILCTXT_WHOIS_MODES, buf);
1188 if (idle && nickname) {
1189 memset(buf, 0, sizeof(buf));
1190 snprintf(buf, sizeof(buf) - 1, "%lu %s",
1191 idle > 60 ? (idle / 60) : idle,
1192 idle > 60 ? "minutes" : "seconds");
1194 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1195 SILCTXT_WHOIS_IDLE, buf);
1199 fingerprint = silc_fingerprint(fingerprint, 20);
1200 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1201 SILCTXT_WHOIS_FINGERPRINT, fingerprint);
1202 silc_free(fingerprint);
1206 silc_query_attributes_print(server, silc_client, conn, attrs,
1211 case SILC_COMMAND_IDENTIFY:
1213 SilcClientEntry client_entry;
1215 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
1216 /* Print the unknown nick for user */
1217 unsigned char *tmp =
1218 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1221 silc_say_error("%s: %s", tmp,
1222 silc_get_status_message(status));
1224 } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1225 /* Try to find the entry for the unknown client ID, since we
1226 might have, and print the nickname of it for user. */
1228 unsigned char *tmp =
1229 silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1232 SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len,
1235 client_entry = silc_client_get_client_by_id(client, conn,
1237 if (client_entry && client_entry->nickname)
1238 silc_say_error("%s: %s", client_entry->nickname,
1239 silc_get_status_message(status));
1240 silc_free(client_id);
1249 case SILC_COMMAND_WHOWAS:
1251 char *nickname, *username, *realname;
1253 if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
1254 status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1256 tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
1259 silc_say_error("%s: %s", tmp,
1260 silc_get_status_message(status));
1262 } else if (!success) {
1263 silc_say_error("WHOWAS: %s", silc_get_status_message(status));
1267 (void)va_arg(vp, SilcClientEntry);
1268 nickname = va_arg(vp, char *);
1269 username = va_arg(vp, char *);
1270 realname = va_arg(vp, char *);
1272 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1273 SILCTXT_WHOWAS_USERINFO, nickname, username,
1274 realname ? realname : "");
1278 case SILC_COMMAND_INVITE:
1280 SilcChannelEntry channel;
1282 SilcArgumentPayload args;
1288 channel = va_arg(vp, SilcChannelEntry);
1289 invite_list = va_arg(vp, char *);
1291 args = silc_command_get_args(cmd_payload);
1293 argc = silc_argument_get_arg_num(args);
1296 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1297 SILCTXT_CHANNEL_INVITE_LIST, channel->channel_name,
1300 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1301 SILCTXT_CHANNEL_NO_INVITE_LIST,
1302 channel->channel_name);
1306 case SILC_COMMAND_JOIN:
1308 char *channel, *mode, *topic;
1310 SilcChannelEntry channel_entry;
1311 SilcBuffer client_id_list;
1312 SilcUInt32 list_count;
1317 channel = va_arg(vp, char *);
1318 channel_entry = va_arg(vp, SilcChannelEntry);
1319 modei = va_arg(vp, SilcUInt32);
1320 (void)va_arg(vp, SilcUInt32);
1321 (void)va_arg(vp, unsigned char *);
1322 (void)va_arg(vp, unsigned char *);
1323 (void)va_arg(vp, unsigned char *);
1324 topic = va_arg(vp, char *);
1325 (void)va_arg(vp, unsigned char *);
1326 list_count = va_arg(vp, SilcUInt32);
1327 client_id_list = va_arg(vp, SilcBuffer);
1329 chanrec = silc_channel_find(server, channel);
1331 chanrec = silc_channel_create(server, channel, TRUE);
1334 g_free_not_null(chanrec->topic);
1335 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
1336 signal_emit("channel topic changed", 1, chanrec);
1339 mode = silc_client_chmode(modei,
1340 channel_entry->channel_key ?
1341 channel_entry->channel_key->cipher->name : "",
1342 channel_entry->hmac ?
1343 silc_hmac_get_name(channel_entry->hmac) : "");
1344 g_free_not_null(chanrec->mode);
1345 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
1346 signal_emit("channel mode changed", 1, chanrec);
1348 /* Resolve the client information */
1349 silc_client_get_clients_by_list(client, conn, list_count, client_id_list,
1350 silc_client_join_get_users,
1356 case SILC_COMMAND_NICK:
1359 SilcClientEntry client = va_arg(vp, SilcClientEntry);
1364 old = g_strdup(server->nick);
1365 server_change_nick(SERVER(server), client->nickname);
1366 nicklist_rename_unique(SERVER(server),
1367 server->conn->local_entry, server->nick,
1368 client, client->nickname);
1369 signal_emit("message own_nick", 4, server, server->nick, old, "");
1374 case SILC_COMMAND_LIST:
1383 (void)va_arg(vp, SilcChannelEntry);
1384 name = va_arg(vp, char *);
1385 topic = va_arg(vp, char *);
1386 usercount = va_arg(vp, int);
1388 if (status == SILC_STATUS_LIST_START ||
1389 status == SILC_STATUS_OK)
1390 printformat_module("fe-common/silc", server, NULL,
1391 MSGLEVEL_CRAP, SILCTXT_LIST_HEADER);
1394 snprintf(users, sizeof(users) - 1, "N/A");
1396 snprintf(users, sizeof(users) - 1, "%d", usercount);
1397 printformat_module("fe-common/silc", server, NULL,
1398 MSGLEVEL_CRAP, SILCTXT_LIST,
1399 name, users, topic ? topic : "");
1403 case SILC_COMMAND_UMODE:
1410 mode = va_arg(vp, SilcUInt32);
1412 if (mode & SILC_UMODE_SERVER_OPERATOR &&
1413 !(server->umode & SILC_UMODE_SERVER_OPERATOR))
1414 printformat_module("fe-common/silc", server, NULL,
1415 MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
1417 if (mode & SILC_UMODE_ROUTER_OPERATOR &&
1418 !(server->umode & SILC_UMODE_ROUTER_OPERATOR))
1419 printformat_module("fe-common/silc", server, NULL,
1420 MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
1422 server->umode = mode;
1423 signal_emit("user mode changed", 2, server, NULL);
1427 case SILC_COMMAND_OPER:
1431 server->umode |= SILC_UMODE_SERVER_OPERATOR;
1432 signal_emit("user mode changed", 2, server, NULL);
1434 printformat_module("fe-common/silc", server, NULL,
1435 MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
1438 case SILC_COMMAND_SILCOPER:
1442 server->umode |= SILC_UMODE_ROUTER_OPERATOR;
1443 signal_emit("user mode changed", 2, server, NULL);
1445 printformat_module("fe-common/silc", server, NULL,
1446 MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
1449 case SILC_COMMAND_USERS:
1451 SilcHashTableList htl;
1452 SilcChannelEntry channel;
1453 SilcChannelUser chu;
1458 channel = va_arg(vp, SilcChannelEntry);
1460 printformat_module("fe-common/silc", server, channel->channel_name,
1461 MSGLEVEL_CRAP, SILCTXT_USERS_HEADER,
1462 channel->channel_name);
1464 silc_hash_table_list(channel->user_list, &htl);
1465 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
1466 SilcClientEntry e = chu->client;
1467 char stat[5], *mode;
1472 memset(stat, 0, sizeof(stat));
1473 mode = silc_client_chumode_char(chu->mode);
1474 if (e->mode & SILC_UMODE_GONE)
1476 else if (e->mode & SILC_UMODE_INDISPOSED)
1478 else if (e->mode & SILC_UMODE_BUSY)
1480 else if (e->mode & SILC_UMODE_PAGE)
1482 else if (e->mode & SILC_UMODE_HYPER)
1484 else if (e->mode & SILC_UMODE_ROBOT)
1486 else if (e->mode & SILC_UMODE_ANONYMOUS)
1493 printformat_module("fe-common/silc", server, channel->channel_name,
1494 MSGLEVEL_CRAP, SILCTXT_USERS,
1496 e->username ? e->username : "",
1497 e->hostname ? e->hostname : "",
1498 e->realname ? e->realname : "");
1502 silc_hash_table_list_reset(&htl);
1506 case SILC_COMMAND_BAN:
1508 SilcChannelEntry channel;
1514 channel = va_arg(vp, SilcChannelEntry);
1515 ban_list = va_arg(vp, char *);
1518 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1519 SILCTXT_CHANNEL_BAN_LIST, channel->channel_name,
1522 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1523 SILCTXT_CHANNEL_NO_BAN_LIST,
1524 channel->channel_name);
1528 case SILC_COMMAND_GETKEY:
1532 SilcPublicKey public_key;
1535 GetkeyContext getkey;
1541 id_type = va_arg(vp, SilcUInt32);
1542 entry = va_arg(vp, void *);
1543 public_key = va_arg(vp, SilcPublicKey);
1546 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
1548 getkey = silc_calloc(1, sizeof(*getkey));
1549 getkey->entry = entry;
1550 getkey->id_type = id_type;
1551 getkey->client = client;
1552 getkey->conn = conn;
1553 getkey->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
1555 name = (id_type == SILC_ID_CLIENT ?
1556 ((SilcClientEntry)entry)->nickname :
1557 ((SilcServerEntry)entry)->server_name);
1559 silc_verify_public_key_internal(client, conn, name,
1560 (id_type == SILC_ID_CLIENT ?
1561 SILC_SOCKET_TYPE_CLIENT :
1562 SILC_SOCKET_TYPE_SERVER),
1563 pk, pk_len, SILC_SKE_PK_TYPE_SILC,
1564 silc_getkey_cb, getkey);
1567 printformat_module("fe-common/silc", server, NULL,
1568 MSGLEVEL_CRAP, SILCTXT_GETKEY_NOKEY);
1573 case SILC_COMMAND_INFO:
1575 SilcServerEntry server_entry;
1582 server_entry = va_arg(vp, SilcServerEntry);
1583 server_name = va_arg(vp, char *);
1584 server_info = va_arg(vp, char *);
1586 if (server_name && server_info )
1588 printtext(server, NULL, MSGLEVEL_CRAP, "Server: %s", server_name);
1589 printtext(server, NULL, MSGLEVEL_CRAP, "%s", server_info);
1594 case SILC_COMMAND_TOPIC:
1596 SilcChannelEntry channel;
1602 channel = va_arg(vp, SilcChannelEntry);
1603 topic = va_arg(vp, char *);
1606 chanrec = silc_channel_find_entry(server, channel);
1608 g_free_not_null(chanrec->topic);
1609 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
1610 signal_emit("channel topic changed", 1, chanrec);
1612 printformat_module("fe-common/silc", server, channel->channel_name,
1613 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
1614 channel->channel_name, topic);
1616 printformat_module("fe-common/silc", server, channel->channel_name,
1617 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC_NOT_SET,
1618 channel->channel_name);
1623 case SILC_COMMAND_WATCH:
1626 case SILC_COMMAND_STATS:
1628 SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops,
1629 my_router_ops, cell_clients, cell_channels, cell_servers,
1630 clients, channels, servers, routers, server_ops, router_ops;
1632 SilcBufferStruct buf;
1633 unsigned char *tmp_buf;
1635 const char *tmptime;
1636 int days, hours, mins, secs;
1641 tmp_buf = va_arg(vp, unsigned char *);
1642 buf_len = va_arg(vp, SilcUInt32);
1644 if (!tmp_buf || !buf_len) {
1645 printtext(server, NULL, MSGLEVEL_CRAP, "No statistics available");
1649 /* Get statistics structure */
1650 silc_buffer_set(&buf, tmp_buf, buf_len);
1651 silc_buffer_unformat(&buf,
1652 SILC_STR_UI_INT(&starttime),
1653 SILC_STR_UI_INT(&uptime),
1654 SILC_STR_UI_INT(&my_clients),
1655 SILC_STR_UI_INT(&my_channels),
1656 SILC_STR_UI_INT(&my_server_ops),
1657 SILC_STR_UI_INT(&my_router_ops),
1658 SILC_STR_UI_INT(&cell_clients),
1659 SILC_STR_UI_INT(&cell_channels),
1660 SILC_STR_UI_INT(&cell_servers),
1661 SILC_STR_UI_INT(&clients),
1662 SILC_STR_UI_INT(&channels),
1663 SILC_STR_UI_INT(&servers),
1664 SILC_STR_UI_INT(&routers),
1665 SILC_STR_UI_INT(&server_ops),
1666 SILC_STR_UI_INT(&router_ops),
1669 tmptime = silc_get_time(starttime);
1670 printformat_module("fe-common/silc", server, NULL,
1671 MSGLEVEL_CRAP, SILCTXT_STATS,
1672 "Local server start time", tmptime);
1674 days = uptime / (24 * 60 * 60);
1675 uptime -= days * (24 * 60 * 60);
1676 hours = uptime / (60 * 60);
1677 uptime -= hours * (60 * 60);
1679 uptime -= mins * 60;
1681 snprintf(tmp, sizeof(tmp) - 1, "%d days %d hours %d mins %d secs",
1682 days, hours, mins, secs);
1683 printformat_module("fe-common/silc", server, NULL,
1684 MSGLEVEL_CRAP, SILCTXT_STATS,
1685 "Local server uptime", tmp);
1687 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_clients);
1688 printformat_module("fe-common/silc", server, NULL,
1689 MSGLEVEL_CRAP, SILCTXT_STATS,
1690 "Local server clients", tmp);
1692 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_channels);
1693 printformat_module("fe-common/silc", server, NULL,
1694 MSGLEVEL_CRAP, SILCTXT_STATS,
1695 "Local server channels", tmp);
1697 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_server_ops);
1698 printformat_module("fe-common/silc", server, NULL,
1699 MSGLEVEL_CRAP, SILCTXT_STATS,
1700 "Local server operators", tmp);
1702 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_router_ops);
1703 printformat_module("fe-common/silc", server, NULL,
1704 MSGLEVEL_CRAP, SILCTXT_STATS,
1705 "Local router operators", tmp);
1707 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_clients);
1708 printformat_module("fe-common/silc", server, NULL,
1709 MSGLEVEL_CRAP, SILCTXT_STATS,
1710 "Local cell clients", tmp);
1712 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_channels);
1713 printformat_module("fe-common/silc", server, NULL,
1714 MSGLEVEL_CRAP, SILCTXT_STATS,
1715 "Local cell channels", tmp);
1717 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_servers);
1718 printformat_module("fe-common/silc", server, NULL,
1719 MSGLEVEL_CRAP, SILCTXT_STATS,
1720 "Local cell servers", tmp);
1722 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)clients);
1723 printformat_module("fe-common/silc", server, NULL,
1724 MSGLEVEL_CRAP, SILCTXT_STATS,
1725 "Total clients", tmp);
1727 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)channels);
1728 printformat_module("fe-common/silc", server, NULL,
1729 MSGLEVEL_CRAP, SILCTXT_STATS,
1730 "Total channels", tmp);
1732 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)servers);
1733 printformat_module("fe-common/silc", server, NULL,
1734 MSGLEVEL_CRAP, SILCTXT_STATS,
1735 "Total servers", tmp);
1737 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)routers);
1738 printformat_module("fe-common/silc", server, NULL,
1739 MSGLEVEL_CRAP, SILCTXT_STATS,
1740 "Total routers", tmp);
1742 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)server_ops);
1743 printformat_module("fe-common/silc", server, NULL,
1744 MSGLEVEL_CRAP, SILCTXT_STATS,
1745 "Total server operators", tmp);
1747 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)router_ops);
1748 printformat_module("fe-common/silc", server, NULL,
1749 MSGLEVEL_CRAP, SILCTXT_STATS,
1750 "Total router operators", tmp);
1761 SilcClientConnection conn;
1767 SilcSKEPKType pk_type;
1768 SilcVerifyPublicKey completion;
1772 static void verify_public_key_completion(const char *line, void *context)
1774 PublicKeyVerify verify = (PublicKeyVerify)context;
1776 if (line[0] == 'Y' || line[0] == 'y') {
1777 /* Call the completion */
1778 if (verify->completion)
1779 verify->completion(TRUE, verify->context);
1781 /* Save the key for future checking */
1782 silc_pkcs_save_public_key_data(verify->filename, verify->pk,
1783 verify->pk_len, SILC_PKCS_FILE_PEM);
1785 /* Call the completion */
1786 if (verify->completion)
1787 verify->completion(FALSE, verify->context);
1789 printformat_module("fe-common/silc", NULL, NULL,
1790 MSGLEVEL_CRAP, SILCTXT_PUBKEY_DISCARD,
1791 verify->entity_name ? verify->entity_name :
1795 silc_free(verify->filename);
1796 silc_free(verify->entity);
1797 silc_free(verify->entity_name);
1798 silc_free(verify->pk);
1802 /* Internal routine to verify public key. If the `completion' is provided
1803 it will be called to indicate whether public was verified or not. For
1804 server/router public key this will check for filename that includes the
1805 remote host's IP address and remote host's hostname. */
1808 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
1809 const char *name, SilcSocketType conn_type,
1810 unsigned char *pk, SilcUInt32 pk_len,
1811 SilcSKEPKType pk_type,
1812 SilcVerifyPublicKey completion, void *context)
1815 char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
1816 char *fingerprint, *babbleprint, *format;
1819 char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
1820 conn_type == SILC_SOCKET_TYPE_ROUTER) ?
1821 "server" : "client");
1822 PublicKeyVerify verify;
1824 if (pk_type != SILC_SKE_PK_TYPE_SILC) {
1825 printformat_module("fe-common/silc", NULL, NULL,
1826 MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED,
1829 completion(FALSE, context);
1833 pw = getpwuid(getuid());
1836 completion(FALSE, context);
1840 memset(filename, 0, sizeof(filename));
1841 memset(filename2, 0, sizeof(filename2));
1842 memset(file, 0, sizeof(file));
1844 if (conn_type == SILC_SOCKET_TYPE_SERVER ||
1845 conn_type == SILC_SOCKET_TYPE_ROUTER) {
1847 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
1848 conn->sock->ip, conn->sock->port);
1849 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
1850 get_irssi_dir(), entity, file);
1852 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
1853 conn->sock->hostname, conn->sock->port);
1854 snprintf(filename2, sizeof(filename2) - 1, "%s/%skeys/%s",
1855 get_irssi_dir(), entity, file);
1860 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
1861 name, conn->sock->port);
1862 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
1863 get_irssi_dir(), entity, file);
1868 /* Replace all whitespaces with `_'. */
1869 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
1870 for (i = 0; i < strlen(fingerprint); i++)
1871 if (fingerprint[i] == ' ')
1872 fingerprint[i] = '_';
1874 snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
1875 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
1876 get_irssi_dir(), entity, file);
1877 silc_free(fingerprint);
1882 /* Take fingerprint of the public key */
1883 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
1884 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
1886 verify = silc_calloc(1, sizeof(*verify));
1887 verify->client = client;
1888 verify->conn = conn;
1889 verify->filename = strdup(ipf);
1890 verify->entity = strdup(entity);
1891 verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ?
1892 (name ? strdup(name) : strdup(conn->sock->hostname))
1894 verify->pk = silc_calloc(pk_len, sizeof(*verify->pk));
1895 memcpy(verify->pk, pk, pk_len);
1896 verify->pk_len = pk_len;
1897 verify->pk_type = pk_type;
1898 verify->completion = completion;
1899 verify->context = context;
1901 /* Check whether this key already exists */
1902 if (stat(ipf, &st) < 0 && (!hostf || stat(hostf, &st) < 0)) {
1903 /* Key does not exist, ask user to verify the key and save it */
1905 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1906 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1907 verify->entity_name : entity);
1908 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1909 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1910 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1911 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1912 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
1913 SILCTXT_PUBKEY_ACCEPT);
1914 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
1917 silc_free(fingerprint);
1920 /* The key already exists, verify it. */
1921 SilcPublicKey public_key;
1922 unsigned char *encpk;
1923 SilcUInt32 encpk_len;
1925 /* Load the key file, try for both IP filename and hostname filename */
1926 if (!silc_pkcs_load_public_key(ipf, &public_key,
1927 SILC_PKCS_FILE_PEM) &&
1928 !silc_pkcs_load_public_key(ipf, &public_key,
1929 SILC_PKCS_FILE_BIN) &&
1930 (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key,
1931 SILC_PKCS_FILE_PEM) &&
1932 !silc_pkcs_load_public_key(hostf, &public_key,
1933 SILC_PKCS_FILE_BIN)))) {
1934 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1935 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1936 verify->entity_name : entity);
1937 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1938 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1939 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1940 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1941 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1942 SILCTXT_PUBKEY_COULD_NOT_LOAD, entity);
1943 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
1944 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
1945 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
1948 silc_free(fingerprint);
1952 /* Encode the key data */
1953 encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
1955 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1956 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1957 verify->entity_name : entity);
1958 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1959 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1960 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1961 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1962 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1963 SILCTXT_PUBKEY_MALFORMED, entity);
1964 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
1965 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
1966 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
1969 silc_free(fingerprint);
1973 /* Compare the keys */
1974 if (memcmp(encpk, pk, encpk_len)) {
1975 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1976 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
1977 verify->entity_name : entity);
1978 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1979 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
1980 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1981 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
1982 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1983 SILCTXT_PUBKEY_NO_MATCH, entity);
1984 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1985 SILCTXT_PUBKEY_MAYBE_EXPIRED, entity);
1986 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
1987 SILCTXT_PUBKEY_MITM_ATTACK, entity);
1989 /* Ask user to verify the key and save it */
1990 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
1991 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
1992 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
1995 silc_free(fingerprint);
1999 /* Local copy matched */
2001 completion(TRUE, context);
2002 silc_free(fingerprint);
2006 /* Verifies received public key. The `conn_type' indicates which entity
2007 (server, client etc.) has sent the public key. If user decides to trust
2008 the key may be saved as trusted public key for later use. The
2009 `completion' must be called after the public key has been verified. */
2012 silc_verify_public_key(SilcClient client, SilcClientConnection conn,
2013 SilcSocketType conn_type, unsigned char *pk,
2014 SilcUInt32 pk_len, SilcSKEPKType pk_type,
2015 SilcVerifyPublicKey completion, void *context)
2017 silc_verify_public_key_internal(client, conn, NULL, conn_type, pk,
2019 completion, context);
2022 /* Asks passphrase from user on the input line. */
2025 SilcAskPassphrase completion;
2029 void ask_passphrase_completion(const char *passphrase, void *context)
2031 AskPassphrase p = (AskPassphrase)context;
2032 if (passphrase && passphrase[0] == '\0')
2034 p->completion((unsigned char *)passphrase,
2035 passphrase ? strlen(passphrase) : 0, p->context);
2039 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
2040 SilcAskPassphrase completion, void *context)
2042 AskPassphrase p = silc_calloc(1, sizeof(*p));
2043 p->completion = completion;
2044 p->context = context;
2046 keyboard_entry_redirect((SIGNAL_FUNC)ask_passphrase_completion,
2047 "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
2051 SilcGetAuthMeth completion;
2053 } *InternalGetAuthMethod;
2055 /* Callback called when we've received the authentication method information
2056 from the server after we've requested it. This will get the authentication
2057 data from the user if needed. */
2059 static void silc_get_auth_method_callback(SilcClient client,
2060 SilcClientConnection conn,
2061 SilcAuthMethod auth_meth,
2064 InternalGetAuthMethod internal = (InternalGetAuthMethod)context;
2066 SILC_LOG_DEBUG(("Start"));
2068 switch (auth_meth) {
2069 case SILC_AUTH_NONE:
2070 /* No authentication required. */
2071 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
2073 case SILC_AUTH_PASSWORD:
2074 /* Do not ask the passphrase from user, the library will ask it if
2075 we do not provide it here. */
2076 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
2078 case SILC_AUTH_PUBLIC_KEY:
2079 /* Do not get the authentication data now, the library will generate
2080 it using our default key, if we do not provide it here. */
2081 /* XXX In the future when we support multiple local keys and multiple
2082 local certificates we will need to ask from user which one to use. */
2083 (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
2087 silc_free(internal);
2090 /* Find authentication method and authentication data by hostname and
2091 port. The hostname may be IP address as well. The found authentication
2092 method and authentication data is returned to `auth_meth', `auth_data'
2093 and `auth_data_len'. The function returns TRUE if authentication method
2094 is found and FALSE if not. `conn' may be NULL. */
2096 void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
2097 char *hostname, SilcUInt16 port,
2098 SilcGetAuthMeth completion, void *context)
2100 InternalGetAuthMethod internal;
2102 SILC_LOG_DEBUG(("Start"));
2104 /* XXX must resolve from configuration whether this connection has
2105 any specific authentication data */
2107 /* If we do not have this connection configured by the user in a
2108 configuration file then resolve the authentication method from the
2109 server for this session. */
2110 internal = silc_calloc(1, sizeof(*internal));
2111 internal->completion = completion;
2112 internal->context = context;
2114 silc_client_request_authentication_method(client, conn,
2115 silc_get_auth_method_callback,
2119 /* Notifies application that failure packet was received. This is called
2120 if there is some protocol active in the client. The `protocol' is the
2121 protocol context. The `failure' is opaque pointer to the failure
2122 indication. Note, that the `failure' is protocol dependant and application
2123 must explicitly cast it to correct type. Usually `failure' is 32 bit
2124 failure type (see protocol specs for all protocol failure types). */
2126 void silc_failure(SilcClient client, SilcClientConnection conn,
2127 SilcProtocol protocol, void *failure)
2129 SILC_LOG_DEBUG(("Start"));
2131 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
2132 SilcSKEStatus status = (SilcSKEStatus)failure;
2134 if (status == SILC_SKE_STATUS_BAD_VERSION)
2135 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2136 SILCTXT_KE_BAD_VERSION);
2137 if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
2138 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2139 SILCTXT_KE_UNSUPPORTED_PUBLIC_KEY);
2140 if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
2141 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2142 SILCTXT_KE_UNKNOWN_GROUP);
2143 if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
2144 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2145 SILCTXT_KE_UNKNOWN_CIPHER);
2146 if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
2147 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2148 SILCTXT_KE_UNKNOWN_PKCS);
2149 if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
2150 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2151 SILCTXT_KE_UNKNOWN_HASH_FUNCTION);
2152 if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
2153 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2154 SILCTXT_KE_UNKNOWN_HMAC);
2155 if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
2156 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2157 SILCTXT_KE_INCORRECT_SIGNATURE);
2158 if (status == SILC_SKE_STATUS_INVALID_COOKIE)
2159 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2160 SILCTXT_KE_INVALID_COOKIE);
2163 if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
2164 SilcUInt32 err = (SilcUInt32)failure;
2166 if (err == SILC_AUTH_FAILED)
2167 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2168 SILCTXT_AUTH_FAILED);
2172 /* Asks whether the user would like to perform the key agreement protocol.
2173 This is called after we have received an key agreement packet or an
2174 reply to our key agreement packet. This returns TRUE if the user wants
2175 the library to perform the key agreement protocol and FALSE if it is not
2176 desired (application may start it later by calling the function
2177 silc_client_perform_key_agreement). */
2179 int silc_key_agreement(SilcClient client, SilcClientConnection conn,
2180 SilcClientEntry client_entry, const char *hostname,
2181 SilcUInt16 port, SilcKeyAgreementCallback *completion,
2186 SILC_LOG_DEBUG(("Start"));
2188 /* We will just display the info on the screen and return FALSE and user
2189 will have to start the key agreement with a command. */
2192 snprintf(portstr, sizeof(portstr) - 1, "%d", port);
2195 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2196 SILCTXT_KEY_AGREEMENT_REQUEST, client_entry->nickname);
2198 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2199 SILCTXT_KEY_AGREEMENT_REQUEST_HOST,
2200 client_entry->nickname, hostname, portstr);
2208 /* Notifies application that file transfer protocol session is being
2209 requested by the remote client indicated by the `client_entry' from
2210 the `hostname' and `port'. The `session_id' is the file transfer
2211 session and it can be used to either accept or reject the file
2212 transfer request, by calling the silc_client_file_receive or
2213 silc_client_file_close, respectively. */
2215 void silc_ftp(SilcClient client, SilcClientConnection conn,
2216 SilcClientEntry client_entry, SilcUInt32 session_id,
2217 const char *hostname, SilcUInt16 port)
2219 SILC_SERVER_REC *server;
2221 FtpSession ftp = silc_calloc(1, sizeof(*ftp));
2223 SILC_LOG_DEBUG(("Start"));
2225 server = conn->context;
2227 ftp->client_entry = client_entry;
2228 ftp->session_id = session_id;
2231 silc_dlist_add(server->ftp_sessions, ftp);
2232 server->current_session = ftp;
2235 snprintf(portstr, sizeof(portstr) - 1, "%d", port);
2238 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2239 SILCTXT_FILE_REQUEST, client_entry->nickname);
2241 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2242 SILCTXT_FILE_REQUEST_HOST,
2243 client_entry->nickname, hostname, portstr);
2246 /* Delivers SILC session detachment data indicated by `detach_data' to the
2247 application. If application has issued SILC_COMMAND_DETACH command
2248 the client session in the SILC network is not quit. The client remains
2249 in the network but is detached. The detachment data may be used later
2250 to resume the session in the SILC Network. The appliation is
2251 responsible of saving the `detach_data', to for example in a file.
2253 The detachment data can be given as argument to the functions
2254 silc_client_connect_to_server, or silc_client_add_connection when
2255 creating connection to remote server, inside SilcClientConnectionParams
2256 structure. If it is provided the client library will attempt to resume
2257 the session in the network. After the connection is created
2258 successfully, the application is responsible of setting the user
2259 interface for user into the same state it was before detaching (showing
2260 same channels, channel modes, etc). It can do this by fetching the
2261 information (like joined channels) from the client library. */
2264 silc_detach(SilcClient client, SilcClientConnection conn,
2265 const unsigned char *detach_data, SilcUInt32 detach_data_len)
2269 /* Save the detachment data to file. */
2271 memset(file, 0, sizeof(file));
2272 snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
2273 silc_file_writefile(file, detach_data, detach_data_len);
2277 /* SILC client operations */
2278 SilcClientOperations ops = {
2280 silc_channel_message,
2281 silc_private_message,
2287 silc_get_auth_method,
2288 silc_verify_public_key,
2289 silc_ask_passphrase,