5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2007 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"
32 #include "silc-cmdqueue.h"
38 #include "special-vars.h"
39 #include "fe-common/core/printtext.h"
40 #include "fe-common/core/fe-channels.h"
41 #include "fe-common/core/keyboard.h"
42 #include "fe-common/core/window-items.h"
43 #include "fe-common/silc/module-formats.h"
48 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
49 const char *name, SilcConnectionType conn_type,
50 SilcPublicKey public_key,
51 SilcVerifyPublicKey completion, void *context);
53 char *silc_get_session_filename(SILC_SERVER_REC *server)
55 char *file, *expanded;
57 expanded = parse_special_string(settings_get_str("session_filename"),
58 SERVER(server), NULL, "", NULL, 0);
60 file = silc_calloc(1, strlen(expanded) + 255);
61 snprintf(file, strlen(expanded) + 255, "%s/%s", get_irssi_dir(), expanded);
67 static void silc_get_umode_string(SilcUInt32 mode, char *buf,
70 if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
71 (mode & SILC_UMODE_ROUTER_OPERATOR)) {
72 strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
74 (mode & SILC_UMODE_ROUTER_OPERATOR) ?
75 "[SILC operator]" : "[unknown mode]");
77 if (mode & SILC_UMODE_GONE)
78 strcat(buf, " [away]");
79 if (mode & SILC_UMODE_INDISPOSED)
80 strcat(buf, " [indisposed]");
81 if (mode & SILC_UMODE_BUSY)
82 strcat(buf, " [busy]");
83 if (mode & SILC_UMODE_PAGE)
84 strcat(buf, " [page to reach]");
85 if (mode & SILC_UMODE_HYPER)
86 strcat(buf, " [hyper active]");
87 if (mode & SILC_UMODE_ROBOT)
88 strcat(buf, " [robot]");
89 if (mode & SILC_UMODE_ANONYMOUS)
90 strcat(buf, " [anonymous]");
91 if (mode & SILC_UMODE_BLOCK_PRIVMSG)
92 strcat(buf, " [blocks private messages]");
93 if (mode & SILC_UMODE_DETACHED)
94 strcat(buf, " [detached]");
95 if (mode & SILC_UMODE_REJECT_WATCHING)
96 strcat(buf, " [rejects watching]");
97 if (mode & SILC_UMODE_BLOCK_INVITE)
98 strcat(buf, " [blocks invites]");
101 /* converts an utf-8 string to current locale */
102 char * silc_convert_utf8_string(const char *str)
104 int message_len = (str != NULL ? strlen(str) : 0);
105 char *message = silc_calloc(message_len + 1, sizeof(*message));
107 g_return_val_if_fail(message != NULL, NULL);
114 if (!silc_term_utf8() && silc_utf8_valid(str, message_len))
115 silc_utf8_decode(str, message_len, SILC_STRING_LOCALE,
116 message, message_len);
118 strcpy(message, str);
123 /* print "nick appears as" message to every channel of a server */
125 silc_print_nick_change_channel(SILC_SERVER_REC *server, const char *channel,
126 const char *newnick, const char *oldnick,
129 if (ignore_check(SERVER(server), oldnick, address,
130 channel, newnick, MSGLEVEL_NICKS))
133 printformat_module("fe-common/silc", server, channel, MSGLEVEL_NICKS,
134 SILCTXT_CHANNEL_APPEARS,
135 oldnick, newnick, channel, address);
139 silc_print_nick_change(SILC_SERVER_REC *server, const char *newnick,
140 const char *oldnick, const char *address)
142 GSList *tmp, *windows;
144 /* Print to each channel/query where the nick is.
145 Don't print more than once to the same window. */
148 for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
149 CHANNEL_REC *channel = tmp->data;
150 WINDOW_REC *window = window_item_window((WI_ITEM_REC *) channel);
152 if (nicklist_find(channel, newnick) == NULL ||
153 g_slist_find(windows, window) != NULL)
156 windows = g_slist_append(windows, window);
157 silc_print_nick_change_channel(server, channel->visible_name,
158 newnick, oldnick, address);
161 g_slist_free(windows);
164 static void silc_parse_channel_public_keys(SILC_SERVER_REC *server,
165 SilcChannelEntry channel_entry,
166 SilcDList channel_pubkeys)
168 SilcArgumentDecodedList e;
169 SilcPublicKey pubkey;
170 SilcSILCPublicKey silc_pubkey;
171 SilcUInt32 pk_len, type;
173 char *fingerprint, *babbleprint;
176 printformat_module("fe-common/silc", server, NULL,
177 MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST,
178 channel_entry->channel_name);
180 silc_dlist_start(channel_pubkeys);
181 while ((e = silc_dlist_get(channel_pubkeys))) {
182 pubkey = e->argument;
185 if (silc_pkcs_get_type(pubkey) != SILC_PKCS_SILC)
188 pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
192 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
193 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
194 silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, pubkey);
196 printformat_module("fe-common/silc", server, NULL,
197 MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST_ENTRY,
198 c++, channel_entry->channel_name,
199 type == 0x00 ? "Added" : "Removed",
200 silc_pubkey->identifier.realname ?
201 silc_pubkey->identifier.realname : "",
202 fingerprint, babbleprint);
204 silc_free(fingerprint);
205 silc_free(babbleprint);
210 void silc_say(SilcClient client, SilcClientConnection conn,
211 SilcClientMessageType type, char *msg, ...)
213 SILC_SERVER_REC *server;
217 server = conn == NULL ? NULL : conn->context;
220 str = g_strdup_vprintf(msg, va);
221 printtext(server, NULL, MSGLEVEL_CRAP, "%s", str);
226 void silc_say_error(char *msg, ...)
232 str = g_strdup_vprintf(msg, va);
233 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s", str);
239 /* Try to verify a message using locally stored public key data */
241 int verify_message_signature(SilcClientEntry sender,
242 SilcMessagePayload message)
245 char file[256], filename[256];
246 char *fingerprint, *fingerprint2;
247 const unsigned char *pk_data;
248 SilcUInt32 pk_datalen;
250 int ret = SILC_MSG_SIGNED_VERIFIED, i;
252 /* get public key from the signature payload and compare it with the
253 one stored in the client entry */
254 pk = silc_message_signed_get_public_key(message, &pk_data, &pk_datalen);
257 fingerprint = silc_hash_fingerprint(NULL, pk_data, pk_datalen);
259 if (sender->fingerprint[0]) {
260 fingerprint2 = silc_fingerprint(sender->fingerprint,
261 sizeof(sender->fingerprint));
262 if (strcmp(fingerprint, fingerprint2)) {
263 /* since the public key differs from the senders public key, the
264 verification _failed_ */
265 silc_pkcs_public_key_free(pk);
266 silc_free(fingerprint);
267 ret = SILC_MSG_SIGNED_UNKNOWN;
269 silc_free(fingerprint2);
271 } else if (sender->fingerprint[0])
272 fingerprint = silc_fingerprint(sender->fingerprint,
273 sizeof(sender->fingerprint));
275 /* no idea, who or what signed that message ... */
276 return SILC_MSG_SIGNED_UNKNOWN;
278 /* search our local client key cache */
279 for (i = 0; i < strlen(fingerprint); i++)
280 if (fingerprint[i] == ' ')
281 fingerprint[i] = '_';
283 snprintf(file, sizeof(file) - 1, "clientkey_%s.pub", fingerprint);
284 snprintf(filename, sizeof(filename) - 1, "%s/clientkeys/%s",
285 get_irssi_dir(), file);
286 silc_free(fingerprint);
288 if (stat(filename, &st) < 0)
289 /* we don't have the public key cached ... use the one from the sig */
290 ret = SILC_MSG_SIGNED_UNKNOWN;
292 SilcPublicKey cached_pk=NULL;
294 /* try to load the file */
295 if (!silc_pkcs_load_public_key(filename, &cached_pk)) {
296 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
297 SILCTXT_PUBKEY_COULD_NOT_LOAD, "client");
299 return SILC_MSG_SIGNED_UNKNOWN;
301 ret = SILC_MSG_SIGNED_UNKNOWN;
306 silc_pkcs_public_key_free(pk);
311 /* the public key is now in pk, our "level of trust" in ret */
312 if ((pk) && silc_message_signed_verify(message, pk,
313 sha1hash) != SILC_AUTH_OK)
314 ret = SILC_MSG_SIGNED_FAILED;
317 silc_pkcs_public_key_free(pk);
322 char *silc_unescape_data(const char *escaped_data, SilcUInt32 *length)
325 int i = 0, j = 0, len = strlen(escaped_data);
327 data = silc_calloc(len, sizeof(char));
330 ptr = memchr(escaped_data + i, 1, len - i);
332 int inc = (ptr - escaped_data) - i;
333 memcpy(data + j, escaped_data + i, inc);
336 data[j++] = *(ptr + 1) - 1;
338 memcpy(data + j, escaped_data + i, len - i);
348 char *silc_escape_data(const char *data, SilcUInt32 len)
350 char *escaped_data, *ptr, *ptr0, *ptr1;
353 escaped_data = silc_calloc(2 * len, sizeof(char));
356 ptr0 = memchr(data + i, 0, len - i);
357 ptr1 = memchr(data + i, 1, len - i);
359 ptr = (ptr0 < ptr1 ? (ptr0 ? ptr0 : ptr1) : (ptr1 ? ptr1 : ptr0));
362 int inc = (ptr - data) - i;
364 memcpy(escaped_data + j, data + i, inc);
367 escaped_data[j++] = 1;
368 escaped_data[j++] = *(data + i++) + 1;
370 memcpy(escaped_data + j, data + i, len - i);
379 void silc_emit_mime_sig(SILC_SERVER_REC *server, WI_ITEM_REC *item,
380 const char *data, SilcUInt32 data_len,
381 const char *nick, int verified)
385 escaped_data = silc_escape_data(data, data_len);
387 signal_emit("mime", 5, server, item, escaped_data, nick, verified);
389 silc_free(escaped_data);
393 /* Message for a channel. The `sender' is the nickname of the sender
394 received in the packet. The `channel_name' is the name of the channel. */
396 void silc_channel_message(SilcClient client, SilcClientConnection conn,
397 SilcClientEntry sender, SilcChannelEntry channel,
398 SilcMessagePayload payload,
399 SilcChannelPrivateKey key,
400 SilcMessageFlags flags, const unsigned char *message,
401 SilcUInt32 message_len)
403 SILC_SERVER_REC *server;
405 SILC_CHANNEL_REC *chanrec;
408 SILC_LOG_DEBUG(("Start"));
413 server = conn == NULL ? NULL : conn->context;
414 chanrec = silc_channel_find_entry(server, channel);
418 nick = silc_nicklist_find(chanrec, sender);
420 /* We didn't find client but it clearly exists, add it. */
421 SilcChannelUser chu = silc_client_on_channel(channel, sender);
423 nick = silc_nicklist_insert(chanrec, chu, FALSE);
428 /* If the messages is digitally signed, verify it, if possible. */
429 if (flags & SILC_MESSAGE_FLAG_SIGNED) {
430 if (!settings_get_bool("ignore_message_signatures")) {
431 verified = verify_message_signature(sender, payload);
433 flags &= ~SILC_MESSAGE_FLAG_SIGNED;
437 if (flags & SILC_MESSAGE_FLAG_DATA) {
438 silc_emit_mime_sig(server, (WI_ITEM_REC *)chanrec, message, message_len,
439 nick == NULL ? NULL : nick->nick,
440 flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
447 if (flags & SILC_MESSAGE_FLAG_ACTION)
448 if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
449 char tmp[256], *cp, *dm = NULL;
450 memset(tmp, 0, sizeof(tmp));
452 if(message_len > sizeof(tmp) - 1) {
453 dm = silc_calloc(message_len + 1, sizeof(*dm));
456 silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
458 if (flags & SILC_MESSAGE_FLAG_SIGNED)
459 signal_emit("message silc signed_action", 6, server, cp, nick->nick,
460 nick->host, channel->channel_name, verified);
462 signal_emit("message silc action", 5, server, cp, nick->nick,
463 nick->host, channel->channel_name);
466 if (flags & SILC_MESSAGE_FLAG_SIGNED)
467 signal_emit("message silc signed_action", 6, server, message,
468 nick->nick, nick->host, channel->channel_name, verified);
470 signal_emit("message silc action", 5, server, message,
471 nick->nick, nick->host, channel->channel_name);
473 else if (flags & SILC_MESSAGE_FLAG_NOTICE)
474 if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
475 char tmp[256], *cp, *dm = NULL;
476 memset(tmp, 0, sizeof(tmp));
478 if(message_len > sizeof(tmp) - 1) {
479 dm = silc_calloc(message_len + 1, sizeof(*dm));
482 silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
484 if (flags & SILC_MESSAGE_FLAG_SIGNED)
485 signal_emit("message silc signed_notice", 6, server, cp, nick->nick,
486 nick->host, channel->channel_name, verified);
488 signal_emit("message silc notice", 5, server, cp, nick->nick,
489 nick->host, channel->channel_name);
492 if (flags & SILC_MESSAGE_FLAG_SIGNED)
493 signal_emit("message silc signed_notice", 6, server, message,
494 nick->nick, nick->host, channel->channel_name, verified);
496 signal_emit("message silc notice", 5, server, message,
497 nick->nick, nick->host, channel->channel_name);
500 if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
501 char tmp[256], *cp, *dm = NULL;
503 memset(tmp, 0, sizeof(tmp));
505 if (message_len > sizeof(tmp) - 1) {
506 dm = silc_calloc(message_len + 1, sizeof(*dm));
510 silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
512 if (flags & SILC_MESSAGE_FLAG_SIGNED)
513 signal_emit("message signed_public", 6, server, cp,
514 nick == NULL ? "[<unknown>]" : nick->nick,
515 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
516 chanrec->name, verified);
518 signal_emit("message public", 6, server, cp,
519 nick == NULL ? "[<unknown>]" : nick->nick,
520 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
521 chanrec->name, nick);
526 if (flags & SILC_MESSAGE_FLAG_SIGNED)
527 signal_emit("message signed_public", 6, server, message,
528 nick == NULL ? "[<unknown>]" : nick->nick,
529 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
530 chanrec->name, verified);
532 signal_emit("message public", 6, server, message,
533 nick == NULL ? "[<unknown>]" : nick->nick,
534 nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
535 chanrec->name, nick);
539 /* Private message to the client. The `sender' is the nickname of the
540 sender received in the packet. */
542 void silc_private_message(SilcClient client, SilcClientConnection conn,
543 SilcClientEntry sender, SilcMessagePayload payload,
544 SilcMessageFlags flags,
545 const unsigned char *message,
546 SilcUInt32 message_len)
548 SILC_SERVER_REC *server;
552 SILC_LOG_DEBUG(("Start"));
554 server = conn == NULL ? NULL : conn->context;
555 memset(userhost, 0, sizeof(userhost));
556 if (sender->username[0])
557 snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
558 sender->username, sender->hostname);
560 /* If the messages is digitally signed, verify it, if possible. */
561 if (flags & SILC_MESSAGE_FLAG_SIGNED) {
562 if (!settings_get_bool("ignore_message_signatures")) {
563 verified = verify_message_signature(sender, payload);
565 flags &= ~SILC_MESSAGE_FLAG_SIGNED;
569 if (flags & SILC_MESSAGE_FLAG_DATA) {
570 silc_emit_mime_sig(server,
571 sender->nickname[0] ?
572 (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) :
574 message, message_len,
575 sender->nickname[0] ? sender->nickname : "[<unknown>]",
576 flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
583 if (flags & SILC_MESSAGE_FLAG_ACTION)
584 if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
585 char tmp[256], *cp, *dm = NULL;
586 memset(tmp, 0, sizeof(tmp));
588 if(message_len > sizeof(tmp) - 1) {
589 dm = silc_calloc(message_len + 1, sizeof(*dm));
592 silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
594 if (flags & SILC_MESSAGE_FLAG_SIGNED)
595 signal_emit("message silc signed_private_action", 6, server, cp,
596 sender->nickname[0] ? sender->nickname : "[<unknown>]",
597 sender->username[0] ? userhost : NULL,
600 signal_emit("message silc private_action", 5, server, cp,
601 sender->nickname[0] ? sender->nickname : "[<unknown>]",
602 sender->username[0] ? userhost : NULL, NULL);
605 if (flags & SILC_MESSAGE_FLAG_SIGNED)
606 signal_emit("message silc signed_private_action", 6, server, message,
607 sender->nickname[0] ? sender->nickname : "[<unknown>]",
608 sender->username[0] ? userhost : NULL,
611 signal_emit("message silc private_action", 5, server, message,
612 sender->nickname[0] ? sender->nickname : "[<unknown>]",
613 sender->username[0] ? userhost : NULL, NULL);
615 else if (flags & SILC_MESSAGE_FLAG_NOTICE)
616 if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
617 char tmp[256], *cp, *dm = NULL;
618 memset(tmp, 0, sizeof(tmp));
620 if(message_len > sizeof(tmp) - 1) {
621 dm = silc_calloc(message_len + 1, sizeof(*dm));
624 silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
626 if (flags & SILC_MESSAGE_FLAG_SIGNED)
627 signal_emit("message silc signed_private_notice", 6, server, cp,
628 sender->nickname[0] ? sender->nickname : "[<unknown>]",
629 sender->username[0] ? userhost : NULL,
632 signal_emit("message silc private_notice", 5, server, cp,
633 sender->nickname[0] ? sender->nickname : "[<unknown>]",
634 sender->username[0] ? userhost : NULL, NULL);
637 if (flags & SILC_MESSAGE_FLAG_SIGNED)
638 signal_emit("message silc signed_private_notice", 6, server, message,
639 sender->nickname[0] ? sender->nickname : "[<unknown>]",
640 sender->username[0] ? userhost : NULL,
643 signal_emit("message silc private_notice", 5, server, message,
644 sender->nickname[0] ? sender->nickname : "[<unknown>]",
645 sender->username[0] ? userhost : NULL, NULL);
648 if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
649 char tmp[256], *cp, *dm = NULL;
651 memset(tmp, 0, sizeof(tmp));
653 if (message_len > sizeof(tmp) - 1) {
654 dm = silc_calloc(message_len + 1, sizeof(*dm));
658 silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
660 if (flags & SILC_MESSAGE_FLAG_SIGNED)
661 signal_emit("message signed_private", 5, server, cp,
662 sender->nickname[0] ? sender->nickname : "[<unknown>]",
663 sender->username[0] ? userhost : NULL, verified);
665 signal_emit("message private", 4, server, cp,
666 sender->nickname[0] ? sender->nickname : "[<unknown>]",
667 sender->username[0] ? userhost : NULL);
672 if (flags & SILC_MESSAGE_FLAG_SIGNED)
673 signal_emit("message signed_private", 5, server, message,
674 sender->nickname[0] ? sender->nickname : "[<unknown>]",
675 sender->username[0] ? userhost : NULL, verified);
677 signal_emit("message private", 4, server, message,
678 sender->nickname[0] ? sender->nickname : "[<unknown>]",
679 sender->username[0] ? userhost : NULL);
683 /* Notify message to the client. The notify arguments are sent in the
684 same order as servers sends them. The arguments are same as received
685 from the server except for ID's. If ID is received application receives
686 the corresponding entry to the ID. For example, if Client ID is received
687 application receives SilcClientEntry. Also, if the notify type is
688 for channel the channel entry is sent to application (even if server
689 does not send it). */
691 void silc_notify(SilcClient client, SilcClientConnection conn,
692 SilcNotifyType type, ...)
695 SILC_SERVER_REC *server;
696 SILC_CHANNEL_REC *chanrec;
697 SILC_NICK_REC *nickrec;
698 SilcClientEntry client_entry, client_entry2;
699 SilcChannelEntry channel, channel2;
700 SilcServerEntry server_entry;
705 char *name, *tmp, *cipher, *hmac;
706 GSList *list1, *list_tmp;
707 SilcDList chpks, clients;
709 SILC_LOG_DEBUG(("Start"));
713 server = conn == NULL ? NULL : conn->context;
716 case SILC_NOTIFY_TYPE_NONE:
717 /* Some generic notice from server */
718 printtext(server, NULL, MSGLEVEL_CRAP, "%s", (char *)va_arg(va, char *));
721 case SILC_NOTIFY_TYPE_INVITE:
723 * Invited or modified invite list.
726 SILC_LOG_DEBUG(("Notify: INVITE"));
728 channel = va_arg(va, SilcChannelEntry);
729 name = va_arg(va, char *);
730 client_entry = va_arg(va, SilcClientEntry);
732 silc_snprintf(buf, sizeof(buf) - 1, "%s@%s",
733 client_entry->username, client_entry->hostname);
734 signal_emit("message invite", 4, server, name,
735 client_entry->nickname, buf);
738 case SILC_NOTIFY_TYPE_JOIN:
743 SILC_LOG_DEBUG(("Notify: JOIN"));
745 client_entry = va_arg(va, SilcClientEntry);
746 channel = va_arg(va, SilcChannelEntry);
748 if (client_entry == server->conn->local_entry) {
749 /* You joined to channel */
750 chanrec = silc_channel_find(server, channel->channel_name);
752 chanrec = silc_channel_create(server, channel->channel_name,
753 channel->channel_name, TRUE);
754 if (!chanrec->joined)
755 chanrec->entry = channel;
757 chanrec = silc_channel_find_entry(server, channel);
758 if (chanrec != NULL) {
759 SilcChannelUser chu = silc_client_on_channel(channel, client_entry);
761 nickrec = silc_nicklist_insert(chanrec, chu, TRUE);
765 memset(buf, 0, sizeof(buf));
766 if (client_entry->username[0])
767 snprintf(buf, sizeof(buf) - 1, "%s@%s",
768 client_entry->username, client_entry->hostname);
769 signal_emit("message join", 4, server, channel->channel_name,
770 client_entry->nickname,
771 !client_entry->username[0] ? "" : buf);
773 /* If there are multiple same nicknames on channel now, tell it to user. */
774 if (client_entry != server->conn->local_entry) {
778 silc_client_nickname_parse(client, conn, client_entry->nickname, &nick);
779 clients = silc_client_get_clients_local(client, conn, nick, TRUE);
780 if (!clients || silc_dlist_count(clients) < 2) {
782 silc_client_list_free(client, conn, clients);
785 silc_dlist_start(clients);
786 while ((client_entry2 = silc_dlist_get(clients)))
787 if (silc_client_on_channel(channel, client_entry2))
790 silc_snprintf(tmp, sizeof(tmp), "%d", silc_dlist_count(clients));
791 printformat_module("fe-common/silc", server, channel->channel_name,
792 MSGLEVEL_CRAP, SILCTXT_CHANNEL_MANY_NICKS,
794 printformat_module("fe-common/silc", server, channel->channel_name,
795 MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
796 buf, client_entry->nickname);
798 silc_client_list_free(client, conn, clients);
803 case SILC_NOTIFY_TYPE_LEAVE:
808 SILC_LOG_DEBUG(("Notify: LEAVE"));
810 client_entry = va_arg(va, SilcClientEntry);
811 channel = va_arg(va, SilcChannelEntry);
813 memset(buf, 0, sizeof(buf));
814 if (client_entry->username)
815 snprintf(buf, sizeof(buf) - 1, "%s@%s",
816 client_entry->username, client_entry->hostname);
817 signal_emit("message part", 5, server, channel->channel_name,
818 client_entry->nickname, client_entry->username[0] ?
819 buf : "", client_entry->nickname);
821 chanrec = silc_channel_find_entry(server, channel);
822 if (chanrec != NULL) {
823 nickrec = silc_nicklist_find(chanrec, client_entry);
825 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
828 /* If there is only one client with this same nickname on channel now
829 change it to the base format if it is formatted nickname. */
831 silc_client_nickname_parse(client, conn, client_entry->nickname, &name);
832 clients = silc_client_get_clients_local(client, conn, name, TRUE);
833 if (!clients || silc_dlist_count(clients) != 2) {
835 silc_client_list_free(client, conn, clients);
838 silc_dlist_start(clients);
839 client_entry2 = silc_dlist_get(clients);
840 if (client_entry2 == client_entry)
841 client_entry2 = silc_dlist_get(clients);
842 if (silc_client_on_channel(channel, client_entry2)) {
843 silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname);
844 silc_client_nickname_format(client, conn, client_entry2, TRUE);
845 if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) {
846 nicklist_rename_unique(SERVER(server), client_entry2, buf,
847 client_entry2, client_entry2->nickname);
848 printformat_module("fe-common/silc", server, channel->channel_name,
849 MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
850 buf, client_entry2->nickname);
853 silc_client_list_free(client, conn, clients);
858 case SILC_NOTIFY_TYPE_SIGNOFF:
863 SILC_LOG_DEBUG(("Notify: SIGNOFF"));
865 client_entry = va_arg(va, SilcClientEntry);
866 tmp = va_arg(va, char *);
867 channel = va_arg(va, SilcChannelEntry);
869 silc_server_free_ftp(server, client_entry);
871 memset(buf, 0, sizeof(buf));
872 if (client_entry->username)
873 snprintf(buf, sizeof(buf) - 1, "%s@%s",
874 client_entry->username, client_entry->hostname);
875 signal_emit("message quit", 4, server, client_entry->nickname,
876 client_entry->username[0] ? buf : "", tmp ? tmp : "");
878 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
879 for (list_tmp = list1; list_tmp != NULL; list_tmp =
880 list_tmp->next->next) {
881 CHANNEL_REC *channel = list_tmp->data;
882 NICK_REC *nickrec = list_tmp->next->data;
884 nicklist_remove(channel, nickrec);
887 /* If there is only one client with this same nickname on channel now
888 change it to the base format if it is formatted nickname. */
890 silc_client_nickname_parse(client, conn, client_entry->nickname, &name);
891 clients = silc_client_get_clients_local(client, conn, name, TRUE);
892 if (!clients || silc_dlist_count(clients) != 2) {
894 silc_client_list_free(client, conn, clients);
897 silc_dlist_start(clients);
898 client_entry2 = silc_dlist_get(clients);
899 if (client_entry2 == client_entry)
900 client_entry2 = silc_dlist_get(clients);
901 if (silc_client_on_channel(channel, client_entry2)) {
902 silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname);
903 silc_client_nickname_format(client, conn, client_entry2, TRUE);
904 if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) {
905 nicklist_rename_unique(SERVER(server), client_entry2, buf,
906 client_entry2, client_entry2->nickname);
907 printformat_module("fe-common/silc", server, channel->channel_name,
908 MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS,
909 buf, client_entry2->nickname);
912 silc_client_list_free(client, conn, clients);
917 case SILC_NOTIFY_TYPE_TOPIC_SET:
922 SILC_LOG_DEBUG(("Notify: TOPIC_SET"));
924 idtype = va_arg(va, int);
925 entry = va_arg(va, void *);
926 tmp = va_arg(va, char *);
927 channel = va_arg(va, SilcChannelEntry);
929 chanrec = silc_channel_find_entry(server, channel);
930 if (chanrec != NULL) {
931 char tmp2[256], *cp, *dm = NULL;
933 g_free_not_null(chanrec->topic);
934 if (tmp && !silc_term_utf8() && silc_utf8_valid(tmp, strlen(tmp))) {
935 memset(tmp2, 0, sizeof(tmp2));
937 if (strlen(tmp) > sizeof(tmp2) - 1) {
938 dm = silc_calloc(strlen(tmp) + 1, sizeof(*dm));
942 silc_utf8_decode(tmp, strlen(tmp), SILC_STRING_LANGUAGE,
947 chanrec->topic = *tmp == '\0' ? NULL : g_strdup(tmp);
948 signal_emit("channel topic changed", 1, chanrec);
953 if (idtype == SILC_ID_CLIENT) {
954 client_entry = (SilcClientEntry)entry;
955 memset(buf, 0, sizeof(buf));
956 snprintf(buf, sizeof(buf) - 1, "%s@%s",
957 client_entry->username, client_entry->hostname);
958 signal_emit("message topic", 5, server, channel->channel_name,
959 tmp, client_entry->nickname, buf);
960 } else if (idtype == SILC_ID_SERVER) {
961 server_entry = (SilcServerEntry)entry;
962 signal_emit("message topic", 5, server, channel->channel_name,
963 tmp, server_entry->server_name,
964 server_entry->server_name);
965 } else if (idtype == SILC_ID_CHANNEL) {
966 channel = (SilcChannelEntry)entry;
967 signal_emit("message topic", 5, server, channel->channel_name,
968 tmp, channel->channel_name, channel->channel_name);
972 case SILC_NOTIFY_TYPE_NICK_CHANGE:
977 SILC_LOG_DEBUG(("Notify: NICK_CHANGE"));
979 client_entry = va_arg(va, SilcClientEntry);
980 name = va_arg(va, char *); /* old nickname */
982 if (!strcmp(client_entry->nickname, name))
985 memset(buf, 0, sizeof(buf));
986 snprintf(buf, sizeof(buf) - 1, "%s@%s",
987 client_entry->username, client_entry->hostname);
988 nicklist_rename_unique(SERVER(server),
990 client_entry, client_entry->nickname);
991 signal_emit("message nick", 4, server, client_entry->nickname, name, buf);
994 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
996 * Changed channel mode.
999 SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
1001 idtype = va_arg(va, int);
1002 entry = va_arg(va, void *);
1003 mode = va_arg(va, SilcUInt32);
1004 cipher = va_arg(va, char *); /* cipher */
1005 hmac = va_arg(va, char *); /* hmac */
1006 (void)va_arg(va, char *); /* passphrase */
1007 (void)va_arg(va, SilcPublicKey); /* founder key */
1008 chpks = va_arg(va, SilcDList); /* channel public keys */
1009 channel = va_arg(va, SilcChannelEntry);
1011 tmp = silc_client_chmode(mode, cipher ? cipher : "",
1014 chanrec = silc_channel_find_entry(server, channel);
1015 if (chanrec != NULL) {
1016 g_free_not_null(chanrec->mode);
1017 chanrec->mode = g_strdup(tmp == NULL ? "" : tmp);
1018 signal_emit("channel mode changed", 1, chanrec);
1021 if (idtype == SILC_ID_CLIENT) {
1022 client_entry = (SilcClientEntry)entry;
1023 printformat_module("fe-common/silc", server, channel->channel_name,
1024 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
1025 channel->channel_name, tmp ? tmp : "removed all",
1026 client_entry->nickname);
1027 } else if (idtype == SILC_ID_SERVER) {
1028 server_entry = (SilcServerEntry)entry;
1029 printformat_module("fe-common/silc", server, channel->channel_name,
1030 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
1031 channel->channel_name, tmp ? tmp : "removed all",
1032 server_entry->server_name);
1033 } else if (idtype == SILC_ID_CHANNEL) {
1034 channel2 = (SilcChannelEntry)entry;
1035 printformat_module("fe-common/silc", server, channel->channel_name,
1036 MSGLEVEL_MODES, SILCTXT_CHANNEL_CMODE,
1037 channel->channel_name, tmp ? tmp : "removed all",
1038 channel2->channel_name);
1041 /* Print the channel public key list */
1043 silc_parse_channel_public_keys(server, channel, chpks);
1048 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1050 * Changed user's mode on channel.
1053 SILC_LOG_DEBUG(("Notify: CUMODE_CHANGE"));
1055 idtype = va_arg(va, int);
1056 entry = va_arg(va, void *);
1057 mode = va_arg(va, SilcUInt32);
1058 client_entry2 = va_arg(va, SilcClientEntry);
1059 channel = va_arg(va, SilcChannelEntry);
1061 tmp = silc_client_chumode(mode);
1062 chanrec = silc_channel_find_entry(server, channel);
1063 if (chanrec != NULL) {
1064 SILC_NICK_REC *nick;
1066 if (client_entry2 == server->conn->local_entry)
1067 chanrec->chanop = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
1069 nick = silc_nicklist_find(chanrec, client_entry2);
1071 nick->op = (mode & SILC_CHANNEL_UMODE_CHANOP) != 0;
1072 nick->founder = (mode & SILC_CHANNEL_UMODE_CHANFO) != 0;
1073 signal_emit("nick mode changed", 2, chanrec, nick);
1077 if (idtype == SILC_ID_CLIENT) {
1078 client_entry = (SilcClientEntry)entry;
1079 printformat_module("fe-common/silc", server, channel->channel_name,
1080 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
1081 channel->channel_name, client_entry2->nickname,
1082 tmp ? tmp : "removed all",
1083 client_entry->nickname);
1084 } else if (idtype == SILC_ID_SERVER) {
1085 server_entry = (SilcServerEntry)entry;
1086 printformat_module("fe-common/silc", server, channel->channel_name,
1087 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
1088 channel->channel_name, client_entry2->nickname,
1089 tmp ? tmp : "removed all",
1090 server_entry->server_name);
1091 } else if (idtype == SILC_ID_CHANNEL) {
1092 channel2 = (SilcChannelEntry)entry;
1093 printformat_module("fe-common/silc", server, channel->channel_name,
1094 MSGLEVEL_MODES, SILCTXT_CHANNEL_CUMODE,
1095 channel->channel_name, client_entry2->nickname,
1096 tmp ? tmp : "removed all",
1097 channel2->channel_name);
1100 if (mode & SILC_CHANNEL_UMODE_CHANFO)
1101 printformat_module("fe-common/silc",
1102 server, channel->channel_name, MSGLEVEL_CRAP,
1103 SILCTXT_CHANNEL_FOUNDER,
1104 channel->channel_name, client_entry2->nickname);
1106 if (mode & SILC_CHANNEL_UMODE_QUIET && conn->local_entry == client_entry2)
1107 printformat_module("fe-common/silc",
1108 server, channel->channel_name, MSGLEVEL_CRAP,
1109 SILCTXT_CHANNEL_QUIETED, channel->channel_name);
1114 case SILC_NOTIFY_TYPE_MOTD:
1119 SILC_LOG_DEBUG(("Notify: MOTD"));
1121 tmp = va_arg(va, char *);
1123 if (!settings_get_bool("skip_motd"))
1124 printtext_multiline(server, NULL, MSGLEVEL_CRAP, "%s", tmp);
1127 case SILC_NOTIFY_TYPE_KICKED:
1129 * Someone was kicked from channel.
1132 SILC_LOG_DEBUG(("Notify: KICKED"));
1134 client_entry = va_arg(va, SilcClientEntry);
1135 tmp = va_arg(va, char *);
1136 client_entry2 = va_arg(va, SilcClientEntry);
1137 channel = va_arg(va, SilcChannelEntry);
1139 chanrec = silc_channel_find_entry(server, channel);
1141 if (client_entry == conn->local_entry) {
1142 printformat_module("fe-common/silc", server, channel->channel_name,
1143 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED_YOU,
1144 channel->channel_name,
1145 client_entry ? client_entry2->nickname : "",
1148 chanrec->kicked = TRUE;
1149 channel_destroy((CHANNEL_REC *)chanrec);
1152 printformat_module("fe-common/silc", server, channel->channel_name,
1153 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KICKED,
1154 client_entry->nickname, channel->channel_name,
1155 client_entry2 ? client_entry2->nickname : "",
1159 SILC_NICK_REC *nickrec = silc_nicklist_find(chanrec, client_entry);
1160 if (nickrec != NULL)
1161 nicklist_remove(CHANNEL(chanrec), NICK(nickrec));
1166 case SILC_NOTIFY_TYPE_KILLED:
1168 * Someone was killed from the network.
1171 SILC_LOG_DEBUG(("Notify: KILLED"));
1173 client_entry = va_arg(va, SilcClientEntry);
1174 tmp = va_arg(va, char *);
1175 idtype = va_arg(va, int);
1176 entry = va_arg(va, SilcClientEntry);
1178 if (client_entry == conn->local_entry) {
1179 if (idtype == SILC_ID_CLIENT) {
1180 client_entry2 = (SilcClientEntry)entry;
1181 printformat_module("fe-common/silc", server, NULL,
1182 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
1183 client_entry2 ? client_entry2->nickname : "",
1185 } else if (idtype == SILC_ID_SERVER) {
1186 server_entry = (SilcServerEntry)entry;
1187 printformat_module("fe-common/silc", server, NULL,
1188 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
1189 server_entry->server_name, tmp ? tmp : "");
1190 } else if (idtype == SILC_ID_CHANNEL) {
1191 channel = (SilcChannelEntry)entry;
1192 printformat_module("fe-common/silc", server, NULL,
1193 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU,
1194 channel->channel_name, tmp ? tmp : "");
1197 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
1198 for (list_tmp = list1; list_tmp != NULL; list_tmp =
1199 list_tmp->next->next) {
1200 CHANNEL_REC *channel = list_tmp->data;
1201 NICK_REC *nickrec = list_tmp->next->data;
1202 nicklist_remove(channel, nickrec);
1205 if (idtype == SILC_ID_CLIENT) {
1206 client_entry2 = (SilcClientEntry)entry;
1207 printformat_module("fe-common/silc", server, NULL,
1208 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
1209 client_entry->nickname,
1210 client_entry2 ? client_entry2->nickname : "",
1212 } else if (idtype == SILC_ID_SERVER) {
1213 server_entry = (SilcServerEntry)entry;
1214 printformat_module("fe-common/silc", server, NULL,
1215 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
1216 client_entry->nickname,
1217 server_entry->server_name, tmp ? tmp : "");
1218 } else if (idtype == SILC_ID_CHANNEL) {
1219 channel = (SilcChannelEntry)entry;
1220 printformat_module("fe-common/silc", server, NULL,
1221 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
1222 client_entry->nickname,
1223 channel->channel_name, tmp ? tmp : "");
1228 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1231 case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
1234 * Server has quit the network.
1238 SILC_LOG_DEBUG(("Notify: SERVER_SIGNOFF"));
1240 (void)va_arg(va, void *);
1241 clients = va_arg(va, SilcDList);
1243 silc_dlist_start(clients);
1244 while ((client_entry = silc_dlist_get(clients))) {
1245 memset(buf, 0, sizeof(buf));
1247 /* Print only if we have the nickname. If this client has just quit
1248 when we were only resolving it, it is possible we don't have the
1250 if (client_entry->nickname[0]) {
1251 if (client_entry->username[0])
1252 snprintf(buf, sizeof(buf) - 1, "%s@%s",
1253 client_entry->username, client_entry->hostname);
1254 signal_emit("message quit", 4, server, client_entry->nickname,
1255 client_entry->username[0] ? buf : "",
1259 silc_server_free_ftp(server, client_entry);
1261 list1 = nicklist_get_same_unique(SERVER(server), client_entry);
1262 for (list_tmp = list1; list_tmp != NULL; list_tmp =
1263 list_tmp->next->next) {
1264 CHANNEL_REC *channel = list_tmp->data;
1265 NICK_REC *nickrec = list_tmp->next->data;
1266 nicklist_remove(channel, nickrec);
1272 case SILC_NOTIFY_TYPE_ERROR:
1274 SilcStatus error = va_arg(va, int);
1276 silc_say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
1277 "%s", silc_get_status_message(error));
1281 case SILC_NOTIFY_TYPE_WATCH:
1283 SilcNotifyType notify;
1285 client_entry = va_arg(va, SilcClientEntry);
1286 name = va_arg(va, char *); /* Maybe NULL */
1287 mode = va_arg(va, SilcUInt32);
1288 notify = va_arg(va, int);
1290 if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
1292 printformat_module("fe-common/silc", server, NULL,
1293 MSGLEVEL_CRAP, SILCTXT_WATCH_NICK_CHANGE,
1294 client_entry->nickname, name);
1296 printformat_module("fe-common/silc", server, NULL,
1297 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
1298 client_entry->nickname);
1299 } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
1300 /* See if client was away and is now present */
1301 if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
1302 SILC_UMODE_BUSY | SILC_UMODE_PAGE |
1303 SILC_UMODE_DETACHED)) &&
1304 (client_entry->mode & SILC_UMODE_GONE ||
1305 client_entry->mode & SILC_UMODE_INDISPOSED ||
1306 client_entry->mode & SILC_UMODE_BUSY ||
1307 client_entry->mode & SILC_UMODE_PAGE ||
1308 client_entry->mode & SILC_UMODE_DETACHED)) {
1309 printformat_module("fe-common/silc", server, NULL,
1310 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
1311 client_entry->nickname);
1315 memset(buf, 0, sizeof(buf));
1316 silc_get_umode_string(mode, buf, sizeof(buf) - 1);
1317 printformat_module("fe-common/silc", server, NULL,
1318 MSGLEVEL_CRAP, SILCTXT_WATCH_UMODE_CHANGE,
1319 client_entry->nickname, buf);
1321 } else if (notify == SILC_NOTIFY_TYPE_KILLED) {
1322 printformat_module("fe-common/silc", server, NULL,
1323 MSGLEVEL_CRAP, SILCTXT_WATCH_KILLED,
1324 client_entry->nickname);
1325 } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
1326 notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF) {
1327 printformat_module("fe-common/silc", server, NULL,
1328 MSGLEVEL_CRAP, SILCTXT_WATCH_SIGNOFF,
1329 client_entry->nickname);
1330 } else if (notify == SILC_NOTIFY_TYPE_NONE) {
1331 /* Client logged in to the network */
1332 printformat_module("fe-common/silc", server, NULL,
1333 MSGLEVEL_CRAP, SILCTXT_WATCH_PRESENT,
1334 client_entry->nickname);
1340 /* Unknown notify */
1341 printformat_module("fe-common/silc", server, NULL,
1342 MSGLEVEL_CRAP, SILCTXT_UNKNOWN_NOTIFY, type);
1349 /* Command handler. This function is called always in the command function.
1350 If error occurs it will be called as well. `conn' is the associated
1351 client connection. `cmd_context' is the command context that was
1352 originally sent to the command. `success' is FALSE if error occured
1353 during command. `command' is the command being processed. It must be
1354 noted that this is not reply from server. This is merely called just
1355 after application has called the command. Just to tell application
1356 that the command really was processed. */
1358 static SilcBool cmode_list_chpks = FALSE;
1360 void silc_command(SilcClient client, SilcClientConnection conn,
1361 SilcBool success, SilcCommand command, SilcStatus status,
1362 SilcUInt32 argc, unsigned char **argv)
1364 SILC_SERVER_REC *server = conn->context;
1366 SILC_LOG_DEBUG(("Start"));
1369 silc_say_error("%s", silc_get_status_message(status));
1375 case SILC_COMMAND_INVITE:
1377 printformat_module("fe-common/silc", server, NULL,
1378 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING,
1380 (argv[1][0] == '*' ?
1381 (char *)conn->current_channel->channel_name :
1385 case SILC_COMMAND_DETACH:
1386 server->no_reconnect = TRUE;
1389 case SILC_COMMAND_CMODE:
1390 if (argc == 3 && !strcmp(argv[2], "+C"))
1391 cmode_list_chpks = TRUE;
1393 cmode_list_chpks = FALSE;
1403 SilcClientConnection conn;
1408 void silc_getkey_cb(bool success, void *context)
1410 GetkeyContext getkey = (GetkeyContext)context;
1411 char *entity = (getkey->id_type == SILC_ID_CLIENT ? "user" : "server");
1412 char *name = (getkey->id_type == SILC_ID_CLIENT ?
1413 ((SilcClientEntry)getkey->entry)->nickname :
1414 ((SilcServerEntry)getkey->entry)->server_name);
1415 SilcPublicKey public_key = (getkey->id_type == SILC_ID_CLIENT ?
1416 ((SilcClientEntry)getkey->entry)->public_key :
1417 ((SilcServerEntry)getkey->entry)->public_key);
1418 SilcSILCPublicKey silc_pubkey;
1420 silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
1423 if (getkey->id_type == SILC_ID_CLIENT)
1424 printformat_module("fe-common/silc", NULL, NULL,
1425 MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED_CLIENT,
1427 silc_pubkey->identifier.realname ?
1428 silc_pubkey->identifier.realname : "",
1429 silc_pubkey->identifier.email ?
1430 silc_pubkey->identifier.email : "");
1432 printformat_module("fe-common/silc", NULL, NULL,
1433 MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED,
1436 printformat_module("fe-common/silc", NULL, NULL,
1437 MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOTVERIFIED,
1442 * XXX: What if the connection or client went away? They're not even
1443 * refcounted and we don't have a way to cancel the input callback. Bad!
1445 switch (getkey->id_type)
1447 case SILC_ID_CLIENT:
1448 silc_client_unref_client(getkey->client, getkey->conn, (SilcClientEntry)getkey->entry);
1451 case SILC_ID_SERVER:
1452 silc_client_unref_server(getkey->client, getkey->conn, (SilcServerEntry)getkey->entry);
1459 /* Parse an invite or ban list */
1460 void silc_parse_inviteban_list(SilcClient client,
1461 SilcClientConnection conn,
1462 SILC_SERVER_REC *server,
1463 SilcChannelEntry channel,
1464 const char *list_type,
1465 SilcArgumentPayload list)
1468 SilcUInt32 type, len;
1469 SILC_CHANNEL_REC *chanrec = silc_channel_find_entry(server, channel);
1470 int counter=0, resolving = FALSE;
1472 if (!silc_argument_get_arg_num(list)) {
1473 printformat_module("fe-common/silc", server,
1474 (chanrec ? chanrec->visible_name : NULL),
1475 MSGLEVEL_CRAP, SILCTXT_CHANNEL_NO_INVITEBAN_LIST,
1476 channel->channel_name, list_type);
1480 printformat_module("fe-common/silc", server,
1481 (chanrec ? chanrec->visible_name : NULL),
1482 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_LIST,
1483 channel->channel_name, list_type);
1485 /* Parse the list */
1486 tmp = silc_argument_get_first_arg(list, &type, &len);
1491 /* An invite string */
1495 if (tmp[len-1] == ',')
1498 list = g_strsplit(tmp, ",", -1);
1500 printformat_module("fe-common/silc", server,
1501 (chanrec ? chanrec->visible_name : NULL),
1502 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_STRING,
1503 ++counter, channel->channel_name, list_type,
1512 char *fingerprint, *babbleprint;
1514 /* tmp is Public Key Payload, take public key from it. */
1515 fingerprint = silc_hash_fingerprint(NULL, tmp + 4, len - 4);
1516 babbleprint = silc_hash_babbleprint(NULL, tmp + 4, len - 4);
1518 printformat_module("fe-common/silc", server,
1519 (chanrec ? chanrec->visible_name : NULL),
1520 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_PUBKEY,
1521 ++counter, channel->channel_name, list_type,
1522 fingerprint, babbleprint);
1529 SilcClientEntry client_entry;
1532 if (!silc_id_payload_parse_id(tmp, len, &id)) {
1533 silc_say_error("Invalid data in %s list encountered", list_type);
1537 client_entry = silc_client_get_client_by_id(client, conn,
1540 printformat_module("fe-common/silc", server,
1541 (chanrec ? chanrec->visible_name : NULL),
1542 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_STRING,
1543 ++counter, channel->channel_name, list_type,
1544 client_entry->nickname);
1545 silc_client_unref_client(client, conn, client_entry);
1548 silc_client_get_client_by_id_resolve(client, conn, &id.u.client_id,
1556 silc_say_error("Unkown type in %s list: %u (len %u)",
1557 list_type, type, len);
1560 tmp = silc_argument_get_next_arg(list, &type, &len);
1564 printformat_module("fe-common/silc", server,
1565 (chanrec ? chanrec->visible_name : NULL),
1566 MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_REGET,
1567 list_type, channel->channel_name);
1570 /* Command reply handler. This function is called always in the command reply
1571 function. If error occurs it will be called as well. Normal scenario
1572 is that it will be called after the received command data has been parsed
1573 and processed. The function is used to pass the received command data to
1576 `conn' is the associated client connection. `cmd_payload' is the command
1577 payload data received from server and it can be ignored. It is provided
1578 if the application would like to re-parse the received command data,
1579 however, it must be noted that the data is parsed already by the library
1580 thus the payload can be ignored. `success' is FALSE if error occured.
1581 In this case arguments are not sent to the application. `command' is the
1582 command reply being processed. The function has variable argument list
1583 and each command defines the number and type of arguments it passes to the
1584 application (on error they are not sent). */
1586 void silc_command_reply(SilcClient client, SilcClientConnection conn,
1587 SilcCommand command, SilcStatus status,
1588 SilcStatus error, va_list vp)
1590 SILC_SERVER_REC *server = conn->context;
1591 SILC_CHANNEL_REC *chanrec;
1593 SILC_LOG_DEBUG(("Start"));
1596 case SILC_COMMAND_WHOIS:
1598 char buf[1024], *nickname, *username, *realname, *nick;
1599 unsigned char *fingerprint;
1600 SilcUInt32 idle, mode, *user_modes;
1602 SilcClientEntry client_entry;
1605 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
1606 /* Print the unknown nick for user */
1607 char *tmp = va_arg(vp, char *);
1609 silc_say_error("%s: %s", tmp, silc_get_status_message(status));
1611 } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
1612 /* Try to find the entry for the unknown client ID, since we
1613 might have, and print the nickname of it for user. */
1614 SilcClientID *id = va_arg(vp, SilcClientID *);
1616 client_entry = silc_client_get_client_by_id(client, conn, id);
1617 if (client_entry && client_entry->nickname[0])
1618 silc_say_error("%s: %s", client_entry->nickname,
1619 silc_get_status_message(status));
1620 silc_client_unref_client(client, conn, client_entry);
1623 } else if (SILC_STATUS_IS_ERROR(status)) {
1624 silc_say_error("WHOIS: %s", silc_get_status_message(status));
1628 client_entry = va_arg(vp, SilcClientEntry);
1629 nickname = va_arg(vp, char *);
1630 username = va_arg(vp, char *);
1631 realname = va_arg(vp, char *);
1632 channels = va_arg(vp, SilcDList);
1633 mode = va_arg(vp, SilcUInt32);
1634 idle = va_arg(vp, SilcUInt32);
1635 fingerprint = va_arg(vp, unsigned char *);
1636 user_modes = va_arg(vp, SilcUInt32 *);
1637 attrs = va_arg(vp, SilcDList);
1639 silc_client_nickname_parse(client, conn, client_entry->nickname, &nick);
1640 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1641 SILCTXT_WHOIS_USERINFO, nickname,
1642 client_entry->username, client_entry->hostname,
1643 nick, client_entry->nickname);
1644 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1645 SILCTXT_WHOIS_REALNAME, realname);
1648 if (channels && user_modes) {
1649 SilcChannelPayload entry;
1652 memset(buf, 0, sizeof(buf));
1653 silc_dlist_start(channels);
1654 while ((entry = silc_dlist_get(channels))) {
1655 SilcUInt32 name_len;
1656 char *m = silc_client_chumode_char(user_modes[i++]);
1657 char *name = silc_channel_get_name(entry, &name_len);
1660 silc_strncat(buf, sizeof(buf) - 1, m, strlen(m));
1661 silc_strncat(buf, sizeof(buf) - 1, name, name_len);
1662 silc_strncat(buf, sizeof(buf) - 1, " ", 1);
1666 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1667 SILCTXT_WHOIS_CHANNELS, buf);
1671 memset(buf, 0, sizeof(buf));
1672 silc_get_umode_string(mode, buf, sizeof(buf - 1));
1673 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1674 SILCTXT_WHOIS_MODES, buf);
1677 if (idle && nickname) {
1678 memset(buf, 0, sizeof(buf));
1679 snprintf(buf, sizeof(buf) - 1, "%lu %s",
1680 idle > 60 ? (idle / 60) : idle,
1681 idle > 60 ? "minutes" : "seconds");
1683 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1684 SILCTXT_WHOIS_IDLE, buf);
1688 fingerprint = silc_fingerprint(fingerprint, 20);
1689 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1690 SILCTXT_WHOIS_FINGERPRINT, fingerprint);
1691 silc_free(fingerprint);
1695 silc_query_attributes_print(server, silc_client, conn, attrs,
1700 case SILC_COMMAND_WHOWAS:
1702 char *nickname, *username, *realname;
1704 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
1705 char *tmp = va_arg(vp, char *);
1707 silc_say_error("%s: %s", tmp,
1708 silc_get_status_message(status));
1710 } else if (SILC_STATUS_IS_ERROR(status)) {
1711 silc_say_error("WHOWAS: %s", silc_get_status_message(status));
1715 (void)va_arg(vp, SilcClientEntry);
1716 nickname = va_arg(vp, char *);
1717 username = va_arg(vp, char *);
1718 realname = va_arg(vp, char *);
1720 printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
1721 SILCTXT_WHOWAS_USERINFO, nickname, username,
1722 realname ? realname : "");
1726 case SILC_COMMAND_INVITE:
1728 SilcChannelEntry channel;
1729 SilcArgumentPayload invite_list;
1731 if (SILC_STATUS_IS_ERROR(status))
1734 channel = va_arg(vp, SilcChannelEntry);
1735 invite_list = va_arg(vp, SilcArgumentPayload);
1738 silc_parse_inviteban_list(client, conn, server, channel,
1739 "invite", invite_list);
1743 case SILC_COMMAND_JOIN:
1745 char *channel, *mode, *topic, *cipher, *hmac;
1747 SilcHashTableList *user_list;
1748 SilcChannelEntry channel_entry;
1749 SilcChannelUser chu;
1750 SilcClientEntry founder = NULL;
1753 if (SILC_STATUS_IS_ERROR(status)) {
1754 if (status == SILC_STATUS_ERR_NO_SUCH_SERVER) {
1755 char *tmp = va_arg(vp, char *);
1757 silc_say_error("JOIN: %s: %s", tmp,
1758 silc_get_status_message(status));
1761 if (status == SILC_STATUS_ERR_NO_SUCH_CHANNEL) {
1762 char *tmp = va_arg(vp, char *);
1764 silc_say_error("JOIN: %s: %s", tmp,
1765 silc_get_status_message(status));
1768 silc_say_error("JOIN: %s", silc_get_status_message(status));
1772 channel = va_arg(vp, char *);
1773 channel_entry = va_arg(vp, SilcChannelEntry);
1774 modei = va_arg(vp, SilcUInt32);
1775 user_list = va_arg(vp, SilcHashTableList *);
1776 topic = va_arg(vp, char *);
1777 cipher = va_arg(vp, char *);
1778 hmac = va_arg(vp, char *);
1780 chanrec = silc_channel_find(server, channel);
1782 chanrec = silc_channel_create(server, channel, channel, TRUE);
1785 char tmp[256], *cp, *dm = NULL;
1786 g_free_not_null(chanrec->topic);
1788 if (!silc_term_utf8() && silc_utf8_valid(topic, strlen(topic))) {
1789 memset(tmp, 0, sizeof(tmp));
1791 if (strlen(topic) > sizeof(tmp) - 1) {
1792 dm = silc_calloc(strlen(topic) + 1, sizeof(*dm));
1796 silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE,
1801 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
1802 signal_emit("channel topic changed", 1, chanrec);
1807 mode = silc_client_chmode(modei, cipher ? cipher : "", hmac ? hmac : "");
1808 g_free_not_null(chanrec->mode);
1809 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
1810 signal_emit("channel mode changed", 1, chanrec);
1813 while (silc_hash_table_get(user_list, NULL, (void *)&chu)) {
1814 if (!chu->client->nickname[0])
1816 if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
1817 founder = chu->client;
1818 silc_nicklist_insert(chanrec, chu, FALSE);
1821 ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
1824 nicklist_set_own(CHANNEL(chanrec), ownnick);
1825 chanrec->entry = channel_entry;
1826 signal_emit("channel joined", 1, chanrec);
1829 printformat_module("fe-common/silc", server,
1830 channel_entry->channel_name,
1831 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
1832 channel_entry->channel_name, chanrec->topic);
1835 if (founder == conn->local_entry) {
1836 printformat_module("fe-common/silc",
1837 server, channel_entry->channel_name,
1838 MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER_YOU,
1839 channel_entry->channel_name);
1840 signal_emit("nick mode changed", 2, chanrec, ownnick);
1842 printformat_module("fe-common/silc",
1843 server, channel_entry->channel_name,
1844 MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER,
1845 channel_entry->channel_name, founder->nickname);
1851 case SILC_COMMAND_NICK:
1854 SilcClientEntry client_entry = va_arg(vp, SilcClientEntry);
1857 if (SILC_STATUS_IS_ERROR(status)) {
1858 silc_say_error("NICK: %s", silc_get_status_message(status));
1862 nicks = nicklist_get_same(SERVER(server), client_entry->nickname);
1863 if ((nicks != NULL) &&
1864 (strcmp(SERVER(server)->nick, client_entry->nickname))) {
1866 SilcClientEntry collider, old;
1868 old = ((SILC_NICK_REC *)(nicks->next->data))->silc_user->client;
1869 collider = silc_client_get_client_by_id(client, conn, &old->id);
1870 if (collider != client_entry) {
1871 memset(buf, 0, sizeof(buf));
1872 snprintf(buf, sizeof(buf) - 1, "%s@%s",
1873 collider->username, collider->hostname);
1874 nicklist_rename_unique(SERVER(server),
1876 collider, collider->nickname);
1877 silc_print_nick_change(server, collider->nickname,
1878 client_entry->nickname, buf);
1880 silc_client_unref_client(client, conn, collider);
1884 g_slist_free(nicks);
1886 old = g_strdup(server->nick);
1887 server_change_nick(SERVER(server), client_entry->nickname);
1888 nicklist_rename_unique(SERVER(server),
1889 server->conn->local_entry, server->nick,
1890 client_entry, client_entry->nickname);
1891 signal_emit("message own_nick", 4, server, server->nick, old, "");
1894 /* when connecting to a server, the last thing we receive
1895 is a SILC_COMMAND_LIST reply. Since we enable queueing
1896 during the connection, we can now safely disable it again */
1897 silc_queue_disable(conn);
1901 case SILC_COMMAND_LIST:
1906 char tmp[256], *cp, *dm = NULL;
1908 if (SILC_STATUS_IS_ERROR(status))
1911 (void)va_arg(vp, SilcChannelEntry);
1912 name = va_arg(vp, char *);
1913 topic = va_arg(vp, char *);
1914 usercount = va_arg(vp, int);
1916 if (topic && !silc_term_utf8() &&
1917 silc_utf8_valid(topic, strlen(topic))) {
1918 memset(tmp, 0, sizeof(tmp));
1920 if (strlen(topic) > sizeof(tmp) - 1) {
1921 dm = silc_calloc(strlen(topic) + 1, sizeof(*dm));
1925 silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE,
1930 if (status == SILC_STATUS_LIST_START ||
1931 status == SILC_STATUS_OK)
1932 printformat_module("fe-common/silc", server, NULL,
1933 MSGLEVEL_CRAP, SILCTXT_LIST_HEADER);
1936 snprintf(users, sizeof(users) - 1, "N/A");
1938 snprintf(users, sizeof(users) - 1, "%d", usercount);
1939 printformat_module("fe-common/silc", server, NULL,
1940 MSGLEVEL_CRAP, SILCTXT_LIST,
1941 name, users, topic ? topic : "");
1946 case SILC_COMMAND_UMODE:
1951 if (SILC_STATUS_IS_ERROR(status))
1954 mode = va_arg(vp, SilcUInt32);
1956 if (mode & SILC_UMODE_SERVER_OPERATOR &&
1957 !(server->umode & SILC_UMODE_SERVER_OPERATOR))
1958 printformat_module("fe-common/silc", server, NULL,
1959 MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
1961 if (mode & SILC_UMODE_ROUTER_OPERATOR &&
1962 !(server->umode & SILC_UMODE_ROUTER_OPERATOR))
1963 printformat_module("fe-common/silc", server, NULL,
1964 MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
1966 if ((mode & SILC_UMODE_GONE) != (server->umode & SILC_UMODE_GONE)) {
1967 if (mode & SILC_UMODE_GONE) {
1968 if ((server->away_reason != NULL) && (server->away_reason[0] != '\0'))
1969 reason = g_strdup(server->away_reason);
1971 reason = g_strdup("away");
1973 reason = g_strdup("");
1975 silc_set_away(reason, server);
1980 server->umode = mode;
1981 signal_emit("user mode changed", 2, server, NULL);
1985 case SILC_COMMAND_OPER:
1986 if (SILC_STATUS_IS_ERROR(status)) {
1987 silc_say_error("OPER: %s", silc_get_status_message(status));
1991 server->umode |= SILC_UMODE_SERVER_OPERATOR;
1992 signal_emit("user mode changed", 2, server, NULL);
1994 printformat_module("fe-common/silc", server, NULL,
1995 MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
1998 case SILC_COMMAND_SILCOPER:
1999 if (SILC_STATUS_IS_ERROR(status)) {
2000 silc_say_error("SILCOPER: %s", silc_get_status_message(status));
2004 server->umode |= SILC_UMODE_ROUTER_OPERATOR;
2005 signal_emit("user mode changed", 2, server, NULL);
2007 printformat_module("fe-common/silc", server, NULL,
2008 MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
2011 case SILC_COMMAND_USERS:
2013 SilcHashTableList htl;
2014 SilcChannelEntry channel;
2015 SilcChannelUser chu;
2017 if (SILC_STATUS_IS_ERROR(status)) {
2018 silc_say_error("USERS: %s", silc_get_status_message(status));
2022 channel = va_arg(vp, SilcChannelEntry);
2024 printformat_module("fe-common/silc", server, channel->channel_name,
2025 MSGLEVEL_CRAP, SILCTXT_USERS_HEADER,
2026 channel->channel_name);
2028 silc_hash_table_list(channel->user_list, &htl);
2029 while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
2030 SilcClientEntry e = chu->client;
2031 char stat[5], *mode;
2033 if (!e->nickname[0])
2036 memset(stat, 0, sizeof(stat));
2037 mode = silc_client_chumode_char(chu->mode);
2038 if (e->mode & SILC_UMODE_GONE)
2040 else if (e->mode & SILC_UMODE_INDISPOSED)
2042 else if (e->mode & SILC_UMODE_BUSY)
2044 else if (e->mode & SILC_UMODE_PAGE)
2046 else if (e->mode & SILC_UMODE_HYPER)
2048 else if (e->mode & SILC_UMODE_ROBOT)
2050 else if (e->mode & SILC_UMODE_ANONYMOUS)
2057 printformat_module("fe-common/silc", server, channel->channel_name,
2058 MSGLEVEL_CRAP, SILCTXT_USERS,
2060 e->username[0] ? e->username : "",
2061 e->hostname[0] ? e->hostname : "",
2062 e->realname ? e->realname : "");
2066 silc_hash_table_list_reset(&htl);
2070 case SILC_COMMAND_BAN:
2072 SilcChannelEntry channel;
2073 SilcArgumentPayload invite_list;
2075 if (SILC_STATUS_IS_ERROR(status))
2078 channel = va_arg(vp, SilcChannelEntry);
2079 invite_list = va_arg(vp, SilcArgumentPayload);
2082 silc_parse_inviteban_list(client, conn, server, channel,
2083 "ban", invite_list);
2087 case SILC_COMMAND_GETKEY:
2091 SilcPublicKey public_key;
2092 GetkeyContext getkey;
2095 if (SILC_STATUS_IS_ERROR(status)) {
2096 silc_say_error("GETKEY: %s", silc_get_status_message(status));
2100 id_type = va_arg(vp, SilcUInt32);
2101 entry = va_arg(vp, void *);
2102 public_key = va_arg(vp, SilcPublicKey);
2105 getkey = silc_calloc(1, sizeof(*getkey));
2106 getkey->entry = entry;
2107 getkey->id_type = id_type;
2108 getkey->client = client;
2109 getkey->conn = conn;
2111 name = (id_type == SILC_ID_CLIENT ?
2112 ((SilcClientEntry)entry)->nickname :
2113 ((SilcServerEntry)entry)->server_name);
2117 case SILC_ID_CLIENT:
2118 name = ((SilcClientEntry)entry)->nickname;
2119 silc_client_ref_client(client, conn, (SilcClientEntry)entry);
2122 case SILC_ID_SERVER:
2123 name = ((SilcServerEntry)entry)->server_name;
2124 silc_client_ref_server(client, conn, (SilcServerEntry)entry);
2128 silc_verify_public_key_internal(client, conn, name,
2129 (id_type == SILC_ID_CLIENT ?
2132 public_key, silc_getkey_cb, getkey);
2134 printformat_module("fe-common/silc", server, NULL,
2135 MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOKEY);
2140 case SILC_COMMAND_INFO:
2142 SilcServerEntry server_entry;
2146 if (SILC_STATUS_IS_ERROR(status))
2149 server_entry = va_arg(vp, SilcServerEntry);
2150 server_name = va_arg(vp, char *);
2151 server_info = va_arg(vp, char *);
2153 if (server_name && server_info )
2155 printtext(server, NULL, MSGLEVEL_CRAP, "Server: %s", server_name);
2156 printtext(server, NULL, MSGLEVEL_CRAP, "%s", server_info);
2161 case SILC_COMMAND_TOPIC:
2163 SilcChannelEntry channel;
2165 char tmp[256], *cp, *dm = NULL;
2167 if (SILC_STATUS_IS_ERROR(status))
2170 channel = va_arg(vp, SilcChannelEntry);
2171 topic = va_arg(vp, char *);
2173 if (topic && !silc_term_utf8() &&
2174 silc_utf8_valid(topic, strlen(topic))) {
2175 memset(tmp, 0, sizeof(tmp));
2177 if (strlen(topic) > sizeof(tmp) - 1) {
2178 dm = silc_calloc(strlen(topic) + 1, sizeof(*dm));
2182 silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE,
2188 chanrec = silc_channel_find_entry(server, channel);
2190 g_free_not_null(chanrec->topic);
2191 chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic);
2192 signal_emit("channel topic changed", 1, chanrec);
2194 printformat_module("fe-common/silc", server, channel->channel_name,
2195 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC,
2196 channel->channel_name, topic);
2198 printformat_module("fe-common/silc", server, channel->channel_name,
2199 MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC_NOT_SET,
2200 channel->channel_name);
2206 case SILC_COMMAND_WATCH:
2209 case SILC_COMMAND_STATS:
2211 SilcClientStats *cstats;
2213 const char *tmptime;
2214 int days, hours, mins, secs;
2216 if (SILC_STATUS_IS_ERROR(status))
2219 cstats = va_arg(vp, SilcClientStats *);
2221 printtext(server, NULL, MSGLEVEL_CRAP, "No statistics available");
2225 tmptime = silc_time_string(cstats->starttime);
2226 printformat_module("fe-common/silc", server, NULL,
2227 MSGLEVEL_CRAP, SILCTXT_STATS,
2228 "Local server start time", tmptime);
2230 days = cstats->uptime / (24 * 60 * 60);
2231 cstats->uptime -= days * (24 * 60 * 60);
2232 hours = cstats->uptime / (60 * 60);
2233 cstats->uptime -= hours * (60 * 60);
2234 mins = cstats->uptime / 60;
2235 cstats->uptime -= mins * 60;
2236 secs = cstats->uptime;
2237 snprintf(tmp, sizeof(tmp) - 1, "%d days %d hours %d mins %d secs",
2238 days, hours, mins, secs);
2239 printformat_module("fe-common/silc", server, NULL,
2240 MSGLEVEL_CRAP, SILCTXT_STATS,
2241 "Local server uptime", tmp);
2243 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_clients);
2244 printformat_module("fe-common/silc", server, NULL,
2245 MSGLEVEL_CRAP, SILCTXT_STATS,
2246 "Local server clients", tmp);
2248 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_channels);
2249 printformat_module("fe-common/silc", server, NULL,
2250 MSGLEVEL_CRAP, SILCTXT_STATS,
2251 "Local server channels", tmp);
2253 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_server_ops);
2254 printformat_module("fe-common/silc", server, NULL,
2255 MSGLEVEL_CRAP, SILCTXT_STATS,
2256 "Local server operators", tmp);
2258 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_router_ops);
2259 printformat_module("fe-common/silc", server, NULL,
2260 MSGLEVEL_CRAP, SILCTXT_STATS,
2261 "Local router operators", tmp);
2263 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_clients);
2264 printformat_module("fe-common/silc", server, NULL,
2265 MSGLEVEL_CRAP, SILCTXT_STATS,
2266 "Local cell clients", tmp);
2268 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_channels);
2269 printformat_module("fe-common/silc", server, NULL,
2270 MSGLEVEL_CRAP, SILCTXT_STATS,
2271 "Local cell channels", tmp);
2273 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_servers);
2274 printformat_module("fe-common/silc", server, NULL,
2275 MSGLEVEL_CRAP, SILCTXT_STATS,
2276 "Local cell servers", tmp);
2278 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->clients);
2279 printformat_module("fe-common/silc", server, NULL,
2280 MSGLEVEL_CRAP, SILCTXT_STATS,
2281 "Total clients", tmp);
2283 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->channels);
2284 printformat_module("fe-common/silc", server, NULL,
2285 MSGLEVEL_CRAP, SILCTXT_STATS,
2286 "Total channels", tmp);
2288 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->servers);
2289 printformat_module("fe-common/silc", server, NULL,
2290 MSGLEVEL_CRAP, SILCTXT_STATS,
2291 "Total servers", tmp);
2293 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->routers);
2294 printformat_module("fe-common/silc", server, NULL,
2295 MSGLEVEL_CRAP, SILCTXT_STATS,
2296 "Total routers", tmp);
2298 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->server_ops);
2299 printformat_module("fe-common/silc", server, NULL,
2300 MSGLEVEL_CRAP, SILCTXT_STATS,
2301 "Total server operators", tmp);
2303 snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->router_ops);
2304 printformat_module("fe-common/silc", server, NULL,
2305 MSGLEVEL_CRAP, SILCTXT_STATS,
2306 "Total router operators", tmp);
2310 case SILC_COMMAND_CMODE:
2312 SilcChannelEntry channel_entry;
2315 channel_entry = va_arg(vp, SilcChannelEntry);
2316 (void)va_arg(vp, SilcUInt32);
2317 (void)va_arg(vp, SilcPublicKey);
2318 chpks = va_arg(vp, SilcDList);
2320 if (SILC_STATUS_IS_ERROR(status) || !cmode_list_chpks ||
2321 !channel_entry || !channel_entry->channel_name)
2324 /* Print the channel public key list */
2326 silc_parse_channel_public_keys(server, channel_entry, chpks);
2328 printformat_module("fe-common/silc", server, NULL,
2329 MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST,
2330 channel_entry->channel_name);
2335 case SILC_COMMAND_LEAVE:
2337 if (SILC_STATUS_IS_ERROR(status))
2340 /* We might be cycling, so disable queueing again */
2341 silc_queue_disable(conn);
2345 case SILC_COMMAND_DETACH:
2347 /* Save the detachment data to file. */
2351 if (SILC_STATUS_IS_ERROR(status))
2354 detach = va_arg(vp, SilcBuffer);
2355 file = silc_get_session_filename(server);
2356 silc_file_writefile(file, silc_buffer_data(detach),
2357 silc_buffer_len(detach));
2362 case SILC_COMMAND_KILL:
2364 SilcClientEntry client_entry;
2366 if (SILC_STATUS_IS_ERROR(status)) {
2367 silc_say_error("KILL: %s", silc_get_status_message(status));
2371 client_entry = va_arg(vp, SilcClientEntry);
2372 if (!client_entry || !client_entry->nickname[0])
2375 /* Print this only if the killed client isn't joined on channels.
2376 If it is, we receive KILLED notify and we'll print this there. */
2377 if (!silc_hash_table_count(client_entry->channels))
2378 printformat_module("fe-common/silc", server, NULL,
2379 MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED,
2380 client_entry->nickname,
2381 conn->local_entry->nickname, "");
2388 SilcClientConnection conn;
2392 SilcPublicKey public_key;
2393 SilcVerifyPublicKey completion;
2397 static void verify_public_key_completion(const char *line, void *context)
2399 PublicKeyVerify verify = (PublicKeyVerify)context;
2401 if (line[0] == 'Y' || line[0] == 'y') {
2402 /* Call the completion */
2403 if (verify->completion)
2404 verify->completion(TRUE, verify->context);
2406 /* Save the key for future checking */
2407 silc_pkcs_save_public_key(verify->filename, verify->public_key,
2408 SILC_PKCS_FILE_BASE64);
2410 /* Call the completion */
2411 if (verify->completion)
2412 verify->completion(FALSE, verify->context);
2414 printformat_module("fe-common/silc", NULL, NULL,
2415 MSGLEVEL_CRAP, SILCTXT_PUBKEY_DISCARD,
2416 verify->entity_name ? verify->entity_name :
2420 silc_free(verify->filename);
2421 silc_free(verify->entity);
2422 silc_free(verify->entity_name);
2426 /* Internal routine to verify public key. If the `completion' is provided
2427 it will be called to indicate whether public was verified or not. For
2428 server/router public key this will check for filename that includes the
2429 remote host's IP address and remote host's hostname. */
2432 silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
2434 SilcConnectionType conn_type,
2435 SilcPublicKey public_key,
2436 SilcVerifyPublicKey completion, void *context)
2438 PublicKeyVerify verify;
2439 char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
2440 char *fingerprint, *babbleprint, *format;
2441 SilcPublicKey local_pubkey;
2442 SilcSILCPublicKey silc_pubkey;
2444 const char *hostname, *ip;
2449 char *entity = ((conn_type == SILC_CONN_SERVER ||
2450 conn_type == SILC_CONN_ROUTER) ?
2451 "server" : "client");
2454 if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) {
2455 printformat_module("fe-common/silc", NULL, NULL,
2456 MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED,
2457 entity, silc_pkcs_get_type(public_key));
2459 completion(FALSE, context);
2463 /* Encode public key */
2464 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
2467 completion(FALSE, context);
2471 silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
2473 pw = getpwuid(getuid());
2476 completion(FALSE, context);
2481 memset(filename, 0, sizeof(filename));
2482 memset(filename2, 0, sizeof(filename2));
2483 memset(file, 0, sizeof(file));
2485 /* Get remote host information */
2486 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream),
2487 NULL, &hostname, &ip, &port);
2489 if (conn_type == SILC_CONN_SERVER ||
2490 conn_type == SILC_CONN_ROUTER) {
2492 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, ip, port);
2493 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
2494 get_irssi_dir(), entity, file);
2496 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
2498 snprintf(filename2, sizeof(filename2) - 1, "%s/%skeys/%s",
2499 get_irssi_dir(), entity, file);
2504 snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
2506 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
2507 get_irssi_dir(), entity, file);
2512 /* Replace all whitespaces with `_'. */
2513 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
2514 for (i = 0; i < strlen(fingerprint); i++)
2515 if (fingerprint[i] == ' ')
2516 fingerprint[i] = '_';
2518 snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
2519 snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s",
2520 get_irssi_dir(), entity, file);
2521 silc_free(fingerprint);
2526 /* Take fingerprint of the public key */
2527 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
2528 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
2530 verify = silc_calloc(1, sizeof(*verify));
2531 verify->client = client;
2532 verify->conn = conn;
2533 verify->filename = strdup(ipf);
2534 verify->entity = strdup(entity);
2535 verify->entity_name = (conn_type != SILC_CONN_CLIENT ?
2536 (name ? strdup(name) : strdup(hostname))
2538 verify->public_key = public_key;
2539 verify->completion = completion;
2540 verify->context = context;
2542 /* Check whether this key already exists */
2543 if (stat(ipf, &st) < 0 && (!hostf || stat(hostf, &st) < 0)) {
2544 /* Key does not exist, ask user to verify the key and save it */
2546 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2547 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
2548 verify->entity_name : entity);
2549 if (conn_type == SILC_CONN_CLIENT && name &&
2550 silc_pubkey->identifier.realname)
2551 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2552 SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
2553 silc_pubkey->identifier.realname,
2554 silc_pubkey->identifier.email ?
2555 silc_pubkey->identifier.email : "");
2556 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2557 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
2558 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2559 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
2560 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
2561 SILCTXT_PUBKEY_ACCEPT);
2562 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
2565 silc_free(fingerprint);
2566 silc_free(babbleprint);
2570 /* The key already exists, verify it. */
2571 unsigned char *encpk;
2572 SilcUInt32 encpk_len;
2574 /* Load the key file, try for both IP filename and hostname filename */
2575 if (!silc_pkcs_load_public_key(ipf, &local_pubkey) &&
2576 (!hostf || (!silc_pkcs_load_public_key(hostf, &local_pubkey)))) {
2577 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2578 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
2579 verify->entity_name : entity);
2580 if (conn_type == SILC_CONN_CLIENT && name &&
2581 silc_pubkey->identifier.realname)
2582 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2583 SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
2584 silc_pubkey->identifier.realname,
2585 silc_pubkey->identifier.email ?
2586 silc_pubkey->identifier.email : "");
2587 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2588 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
2589 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2590 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
2591 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2592 SILCTXT_PUBKEY_COULD_NOT_LOAD, entity);
2593 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
2594 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
2595 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
2598 silc_free(fingerprint);
2599 silc_free(babbleprint);
2604 /* Encode the key data */
2605 encpk = silc_pkcs_public_key_encode(local_pubkey, &encpk_len);
2607 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2608 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
2609 verify->entity_name : entity);
2610 if (conn_type == SILC_CONN_CLIENT && name &&
2611 silc_pubkey->identifier.realname)
2612 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2613 SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
2614 silc_pubkey->identifier.realname,
2615 silc_pubkey->identifier.email ?
2616 silc_pubkey->identifier.email : "");
2617 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2618 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
2619 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2620 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
2621 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2622 SILCTXT_PUBKEY_MALFORMED, entity);
2623 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
2624 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
2625 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
2628 silc_free(fingerprint);
2629 silc_free(babbleprint);
2633 silc_pkcs_public_key_free(local_pubkey);
2635 /* Compare the keys */
2636 if (memcmp(encpk, pk, encpk_len)) {
2637 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2638 SILCTXT_PUBKEY_RECEIVED,verify->entity_name ?
2639 verify->entity_name : entity);
2640 if (conn_type == SILC_CONN_CLIENT && name &&
2641 silc_pubkey->identifier.realname)
2642 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2643 SILCTXT_PUBKEY_RECEIVED_CLIENT, name,
2644 silc_pubkey->identifier.realname,
2645 silc_pubkey->identifier.email ?
2646 silc_pubkey->identifier.email : "");
2647 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2648 SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint);
2649 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2650 SILCTXT_PUBKEY_BABBLEPRINT, babbleprint);
2651 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2652 SILCTXT_PUBKEY_NO_MATCH, entity);
2653 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2654 SILCTXT_PUBKEY_MAYBE_EXPIRED, entity);
2655 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2656 SILCTXT_PUBKEY_MITM_ATTACK, entity);
2658 /* Ask user to verify the key and save it */
2659 format = format_get_text("fe-common/silc", NULL, NULL, NULL,
2660 SILCTXT_PUBKEY_ACCEPT_ANYWAY);
2661 keyboard_entry_redirect((SIGNAL_FUNC)verify_public_key_completion,
2664 silc_free(fingerprint);
2665 silc_free(babbleprint);
2671 /* Local copy matched */
2673 completion(TRUE, context);
2675 silc_free(fingerprint);
2676 silc_free(babbleprint);
2677 silc_free(verify->filename);
2678 silc_free(verify->entity);
2679 silc_free(verify->entity_name);
2685 /* Verifies received public key. The `conn_type' indicates which entity
2686 (server, client etc.) has sent the public key. If user decides to trust
2687 the key may be saved as trusted public key for later use. The
2688 `completion' must be called after the public key has been verified. */
2691 silc_verify_public_key(SilcClient client, SilcClientConnection conn,
2692 SilcConnectionType conn_type,
2693 SilcPublicKey public_key,
2694 SilcVerifyPublicKey completion, void *context)
2696 silc_verify_public_key_internal(client, conn, NULL, conn_type, public_key,
2697 completion, context);
2700 /* Asks passphrase from user on the input line. */
2703 SilcAskPassphrase completion;
2707 void ask_passphrase_completion(const char *passphrase, void *context)
2709 AskPassphrase p = (AskPassphrase)context;
2710 if (passphrase && passphrase[0] == '\0')
2712 p->completion((unsigned char *)passphrase,
2713 passphrase ? strlen(passphrase) : 0, p->context);
2717 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
2718 SilcAskPassphrase completion, void *context)
2720 AskPassphrase p = silc_calloc(1, sizeof(*p));
2721 p->completion = completion;
2722 p->context = context;
2724 keyboard_entry_redirect((SIGNAL_FUNC)ask_passphrase_completion,
2725 "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
2729 SilcGetAuthMeth completion;
2733 static void silc_get_auth_ask_passphrase(const unsigned char *passphrase,
2734 SilcUInt32 passphrase_len,
2737 GetAuthMethod a = context;
2738 a->completion(passphrase ? SILC_AUTH_PASSWORD : SILC_AUTH_NONE,
2739 passphrase, passphrase_len, a->context);
2743 /* Find authentication data by hostname and port. The hostname may be IP
2746 void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
2747 char *hostname, SilcUInt16 port,
2748 SilcAuthMethod auth_meth,
2749 SilcGetAuthMeth completion, void *context)
2751 SERVER_SETUP_REC *setup;
2753 SILC_LOG_DEBUG(("Start"));
2755 if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
2756 /* Returning NULL will cause library to use our private key configured
2757 for this connection */
2758 completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
2762 /* Check whether we find the password for this server in our
2763 configuration. If it's set, always send it server. */
2764 setup = server_setup_find_port(hostname, port);
2765 if (setup && setup->password) {
2766 completion(SILC_AUTH_PASSWORD, setup->password, strlen(setup->password),
2771 /* Didn't find password. If server wants it, ask it from user. */
2772 if (auth_meth == SILC_AUTH_PASSWORD) {
2774 a = silc_calloc(1, sizeof(*a));
2776 a->completion = completion;
2777 a->context = context;
2778 silc_ask_passphrase(client, conn, silc_get_auth_ask_passphrase, a);
2783 /* No authentication */
2784 completion(SILC_AUTH_NONE, NULL, 0, context);
2787 /* Asks whether the user would like to perform the key agreement protocol.
2788 This is called after we have received an key agreement packet or an
2789 reply to our key agreement packet. This returns TRUE if the user wants
2790 the library to perform the key agreement protocol and FALSE if it is not
2791 desired (application may start it later by calling the function
2792 silc_client_perform_key_agreement). */
2794 void silc_key_agreement(SilcClient client, SilcClientConnection conn,
2795 SilcClientEntry client_entry, const char *hostname,
2796 SilcUInt16 protocol, SilcUInt16 port)
2798 char portstr[12], protostr[5];
2800 SILC_LOG_DEBUG(("Start"));
2802 /* We will just display the info on the screen and return FALSE and user
2803 will have to start the key agreement with a command. */
2806 snprintf(portstr, sizeof(portstr) - 1, "%d", port);
2807 snprintf(protostr, sizeof(protostr) - 1, "%s", protocol == 1 ? "UDP" :
2812 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2813 SILCTXT_KEY_AGREEMENT_REQUEST, client_entry->nickname);
2815 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2816 SILCTXT_KEY_AGREEMENT_REQUEST_HOST,
2817 client_entry->nickname, hostname, portstr, protostr);
2820 /* Notifies application that file transfer protocol session is being
2821 requested by the remote client indicated by the `client_entry' from
2822 the `hostname' and `port'. The `session_id' is the file transfer
2823 session and it can be used to either accept or reject the file
2824 transfer request, by calling the silc_client_file_receive or
2825 silc_client_file_close, respectively. */
2827 void silc_ftp(SilcClient client, SilcClientConnection conn,
2828 SilcClientEntry client_entry, SilcUInt32 session_id,
2829 const char *hostname, SilcUInt16 port)
2831 SILC_SERVER_REC *server;
2833 FtpSession ftp = NULL;
2835 SILC_LOG_DEBUG(("Start"));
2837 server = conn->context;
2839 silc_dlist_start(server->ftp_sessions);
2840 while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) {
2841 if (ftp->client_entry == client_entry &&
2842 ftp->session_id == session_id) {
2843 server->current_session = ftp;
2847 if (ftp == SILC_LIST_END) {
2848 ftp = silc_calloc(1, sizeof(*ftp));
2849 ftp->client_entry = client_entry;
2850 ftp->session_id = session_id;
2853 silc_dlist_add(server->ftp_sessions, ftp);
2854 server->current_session = ftp;
2858 snprintf(portstr, sizeof(portstr) - 1, "%d", port);
2861 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2862 SILCTXT_FILE_REQUEST, client_entry->nickname);
2864 printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
2865 SILCTXT_FILE_REQUEST_HOST,
2866 client_entry->nickname, hostname, portstr);
2869 /* SILC client operations */
2870 SilcClientOperations ops = {
2872 silc_channel_message,
2873 silc_private_message,
2877 silc_get_auth_method,
2878 silc_verify_public_key,
2879 silc_ask_passphrase,