5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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.
21 * Command reply functions are "the otherside" of the command functions.
22 * Reply to a command sent by server is handled by these functions.
27 * Revision 1.5 2000/07/06 07:14:36 priikone
28 * Fixes to NAMES command handling.
29 * Fixes when leaving from channel.
31 * Revision 1.4 2000/07/05 06:12:34 priikone
32 * Tweaked NAMES command reply for better. Should now show users
33 * joined to a channel.
35 * Revision 1.3 2000/07/04 08:27:14 priikone
36 * Changes to LEAVE command -- more consistent now and does error
37 * handling better. Added INVITE, PING and part of NAMES commands.
38 * SilcPacketContext is included into command structure.
40 * Revision 1.2 2000/07/03 05:49:49 priikone
41 * Implemented LEAVE command. Minor bug fixes.
43 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
44 * Imported from internal CVS/Added Log headers.
49 #include "clientincludes.h"
51 /* Client command reply list. */
52 SilcClientCommandReply silc_command_reply_list[] =
54 SILC_CLIENT_CMD_REPLY(whois, WHOIS),
55 SILC_CLIENT_CMD_REPLY(whowas, WHOWAS),
56 SILC_CLIENT_CMD_REPLY(identify, IDENTIFY),
57 SILC_CLIENT_CMD_REPLY(nick, NICK),
58 SILC_CLIENT_CMD_REPLY(list, LIST),
59 SILC_CLIENT_CMD_REPLY(topic, TOPIC),
60 SILC_CLIENT_CMD_REPLY(invite, INVITE),
61 SILC_CLIENT_CMD_REPLY(quit, QUIT),
62 SILC_CLIENT_CMD_REPLY(kill, KILL),
63 SILC_CLIENT_CMD_REPLY(info, INFO),
64 SILC_CLIENT_CMD_REPLY(away, AWAY),
65 SILC_CLIENT_CMD_REPLY(connect, CONNECT),
66 SILC_CLIENT_CMD_REPLY(ping, PING),
67 SILC_CLIENT_CMD_REPLY(oper, OPER),
68 SILC_CLIENT_CMD_REPLY(join, JOIN),
69 SILC_CLIENT_CMD_REPLY(motd, MOTD),
70 SILC_CLIENT_CMD_REPLY(umode, UMODE),
71 SILC_CLIENT_CMD_REPLY(cmode, CMODE),
72 SILC_CLIENT_CMD_REPLY(kick, KICK),
73 SILC_CLIENT_CMD_REPLY(restart, RESTART),
74 SILC_CLIENT_CMD_REPLY(close, CLOSE),
75 SILC_CLIENT_CMD_REPLY(die, DIE),
76 SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER),
77 SILC_CLIENT_CMD_REPLY(leave, LEAVE),
78 SILC_CLIENT_CMD_REPLY(names, NAMES),
83 /* Status message structure. Messages are defined below. */
85 SilcCommandStatus status;
87 } SilcCommandStatusMessage;
89 /* Status messages returned by the server */
90 #define STAT(x) SILC_STATUS_ERR_##x
91 const SilcCommandStatusMessage silc_command_status_messages[] = {
93 { STAT(NO_SUCH_NICK), "No such nickname" },
94 { STAT(NO_SUCH_CHANNEL), "No such channel" },
95 { STAT(NO_SUCH_SERVER), "No such server" },
96 { STAT(TOO_MANY_TARGETS), "Duplicate recipients. No message delivered" },
97 { STAT(NO_RECIPIENT), "No recipient given" },
98 { STAT(UNKNOWN_COMMAND), "Unknown command" },
99 { STAT(WILDCARDS), "Unknown command" },
100 { STAT(NO_CLIENT_ID), "No Client ID given" },
101 { STAT(NO_CHANNEL_ID), "No Channel ID given" },
102 { STAT(NO_SERVER_ID), "No Server ID given" },
103 { STAT(BAD_CLIENT_ID), "Bad Client ID" },
104 { STAT(BAD_CHANNEL_ID), "Bad Channel ID" },
105 { STAT(NO_SUCH_CLIENT_ID), "No such Client ID" },
106 { STAT(NO_SUCH_CHANNEL_ID),"No such Channel ID" },
107 { STAT(NICKNAME_IN_USE), "Nickname already exists" },
108 { STAT(NOT_ON_CHANNEL), "You are not on that channel" },
109 { STAT(USER_ON_CHANNEL), "User already on channel" },
110 { STAT(NOT_REGISTERED), "You have not registered" },
111 { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
112 { STAT(TOO_MANY_PARAMS), "Too many parameters" },
113 { STAT(PERM_DENIED), "Your host is not among the privileged" },
114 { STAT(BANNED_FROM_SERVER),"You are banned from this server" },
115 { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" },
116 { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" },
117 { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" },
118 { STAT(BANNED_FROM_CHANNEL), "Cannot join channel. You have been banned" },
119 { STAT(UNKNOWN_MODE), "Unknown mode" },
120 { STAT(NOT_YOU), "Cannot change mode for other users" },
121 { STAT(NO_CHANNEL_PRIV), "Permission denied. You are not channel operator" },
122 { STAT(NO_SERVER_PRIV), "Permission denied. You are not server operator" },
123 { STAT(NO_ROUTER_PRIV), "Permission denied. You are not SILC operator" },
124 { STAT(BAD_NICKNAME), "Bad nickname" },
125 { STAT(BAD_CHANNEL), "Bad channel name" },
126 { STAT(AUTH_FAILED), "Authentication failed" },
131 /* Process received command reply. */
133 void silc_client_command_reply_process(SilcClient client,
134 SilcSocketConnection sock,
135 SilcPacketContext *packet)
137 SilcBuffer buffer = packet->buffer;
138 SilcClientCommandReplyContext ctx;
139 SilcCommandPayload payload;
141 /* Get command reply payload from packet */
142 payload = silc_command_parse_payload(buffer);
144 /* Silently ignore bad reply packet */
145 SILC_LOG_DEBUG(("Bad command reply packet"));
149 /* Allocate command reply context. This must be free'd by the
150 command reply routine receiving it. */
151 ctx = silc_calloc(1, sizeof(*ctx));
152 ctx->client = client;
154 ctx->payload = payload;
155 ctx->packet = packet;
157 /* Check for pending commands and mark to be exeucted */
158 SILC_CLIENT_COMMAND_CHECK_PENDING(ctx);
160 /* Execute command reply */
161 SILC_CLIENT_COMMAND_REPLY_EXEC(ctx);
164 /* Returns status message string */
167 silc_client_command_status_message(SilcCommandStatus status)
171 for (i = 0; silc_command_status_messages[i].message; i++) {
172 if (silc_command_status_messages[i].status == status)
176 if (silc_command_status_messages[i].message == NULL)
179 return silc_command_status_messages[i].message;
182 /* Free command reply context and its internals. */
184 void silc_client_command_reply_free(SilcClientCommandReplyContext cmd)
187 silc_command_free_payload(cmd->payload);
192 /* Received reply for WHOIS command. This maybe called several times
193 for one WHOIS command as server may reply with list of results. */
195 SILC_CLIENT_CMD_REPLY_FUNC(whois)
197 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
198 SilcClient client = cmd->client;
199 SilcCommandStatus status;
202 SILC_LOG_DEBUG(("Start"));
204 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
205 SILC_GET16_MSB(status, tmp);
206 if (status != SILC_STATUS_OK) {
207 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
208 /* Take nickname which may be provided */
209 tmp = silc_command_get_arg_type(cmd->payload, 3, NULL);
211 silc_say(cmd->client, "%s: %s", tmp,
212 silc_client_command_status_message(status));
214 silc_say(cmd->client, "%s",
215 silc_client_command_status_message(status));
218 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
223 /* Display one whois reply */
224 if (status == SILC_STATUS_OK) {
227 unsigned char *id_data;
228 char *nickname = NULL, *username = NULL;
229 char *realname = NULL;
232 memset(buf, 0, sizeof(buf));
234 argc = silc_command_get_arg_num(cmd->payload);
235 id_data = silc_command_get_arg_type(cmd->payload, 2, NULL);
237 nickname = silc_command_get_arg_type(cmd->payload, 3, &len);
239 strncat(buf, nickname, len);
240 strncat(buf, " is ", 4);
243 username = silc_command_get_arg_type(cmd->payload, 4, &len);
245 strncat(buf, username, len);
248 realname = silc_command_get_arg_type(cmd->payload, 5, &len);
250 strncat(buf, " (", 2);
251 strncat(buf, realname, len);
252 strncat(buf, ")", 1);
256 /* Save received Client ID to ID cache */
257 /* XXX Maybe should not be saved as /MSG will get confused */
258 id = silc_id_str2id(id_data, SILC_ID_CLIENT);
259 client->current_win->client_id_cache_count[(int)nickname[0] - 32] =
260 silc_idcache_add(&client->current_win->
261 client_id_cache[(int)nickname[0] - 32],
262 client->current_win->
263 client_id_cache_count[(int)nickname[0] - 32],
264 strdup(nickname), SILC_ID_CLIENT, id, NULL);
267 silc_say(cmd->client, "%s", buf);
270 if (status == SILC_STATUS_LIST_START) {
274 if (status == SILC_STATUS_LIST_END) {
278 SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_WHOIS);
281 silc_client_command_reply_free(cmd);
284 SILC_CLIENT_CMD_REPLY_FUNC(whowas)
288 /* Received reply for IDENTIFY command. This maybe called several times
289 for one IDENTIFY command as server may reply with list of results.
290 This is totally silent and does not print anything on screen. */
292 SILC_CLIENT_CMD_REPLY_FUNC(identify)
294 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
295 SilcClientWindow win = (SilcClientWindow)cmd->sock->user_data;
296 SilcClientEntry client_entry;
297 SilcCommandStatus status;
300 SILC_LOG_DEBUG(("Start"));
302 #define CIDC(x) win->client_id_cache[(x) - 32]
303 #define CIDCC(x) win->client_id_cache_count[(x) - 32]
305 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
306 SILC_GET16_MSB(status, tmp);
307 if (status != SILC_STATUS_OK) {
308 if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
309 /* Take nickname which may be provided */
310 tmp = silc_command_get_arg_type(cmd->payload, 3, NULL);
312 silc_say(cmd->client, "%s: %s", tmp,
313 silc_client_command_status_message(status));
315 silc_say(cmd->client, "%s",
316 silc_client_command_status_message(status));
319 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
324 /* Display one whois reply */
325 if (status == SILC_STATUS_OK) {
326 unsigned char *id_data;
329 id_data = silc_command_get_arg_type(cmd->payload, 2, NULL);
330 nickname = silc_command_get_arg_type(cmd->payload, 3, NULL);
332 /* Allocate client entry */
333 client_entry = silc_calloc(1, sizeof(*client_entry));
334 client_entry->id = silc_id_str2id(id_data, SILC_ID_CLIENT);
335 client_entry->nickname = strdup(nickname);
337 /* Save received Client ID to ID cache */
339 silc_idcache_add(&CIDC(nickname[0]), CIDCC(nickname[0]),
340 client_entry->nickname, SILC_ID_CLIENT,
341 client_entry->id, client_entry);
344 if (status == SILC_STATUS_LIST_START) {
348 if (status == SILC_STATUS_LIST_END) {
352 SILC_CLIENT_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
355 silc_client_command_reply_free(cmd);
360 /* Received reply for command NICK. If everything went without errors
361 we just received our new Client ID. */
363 SILC_CLIENT_CMD_REPLY_FUNC(nick)
365 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
366 SilcClientWindow win = (SilcClientWindow)cmd->sock->user_data;
367 SilcCommandStatus status;
368 unsigned char *tmp, *id_string;
371 SILC_LOG_DEBUG(("Start"));
373 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
374 SILC_GET16_MSB(status, tmp);
375 if (status != SILC_STATUS_OK) {
376 silc_say(cmd->client, "Cannot set nickname: %s",
377 silc_client_command_status_message(status));
381 argc = silc_command_get_arg_num(cmd->payload);
382 if (argc < 2 || argc > 2) {
383 silc_say(cmd->client, "Cannot set nickname: bad reply to command");
387 /* Take received Client ID */
388 id_string = silc_command_get_arg_type(cmd->payload, 2, NULL);
389 silc_client_receive_new_id(cmd->client, cmd->sock, id_string);
391 /* Update nickname on screen */
392 cmd->client->screen->bottom_line->nickname = win->nickname;
393 silc_screen_print_bottom_line(cmd->client->screen, 0);
396 silc_client_command_reply_free(cmd);
399 SILC_CLIENT_CMD_REPLY_FUNC(list)
403 SILC_CLIENT_CMD_REPLY_FUNC(topic)
407 /* Received reply to invite command. */
409 SILC_CLIENT_CMD_REPLY_FUNC(invite)
411 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
412 SilcCommandStatus status;
415 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
416 SILC_GET16_MSB(status, tmp);
417 if (status != SILC_STATUS_OK) {
418 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
419 silc_client_command_reply_free(cmd);
423 silc_client_command_reply_free(cmd);
426 SILC_CLIENT_CMD_REPLY_FUNC(quit)
430 SILC_CLIENT_CMD_REPLY_FUNC(kill)
434 SILC_CLIENT_CMD_REPLY_FUNC(info)
438 SILC_CLIENT_CMD_REPLY_FUNC(away)
442 SILC_CLIENT_CMD_REPLY_FUNC(connect)
446 /* Received reply to PING command. The reply time is shown to user. */
448 SILC_CLIENT_CMD_REPLY_FUNC(ping)
450 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
451 SilcClientWindow win = (SilcClientWindow)cmd->sock->user_data;
452 SilcCommandStatus status;
456 time_t diff, curtime;
458 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
459 SILC_GET16_MSB(status, tmp);
460 if (status != SILC_STATUS_OK) {
461 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
465 curtime = time(NULL);
466 id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
468 for (i = 0; i < win->ping_count; i++) {
469 if (!SILC_ID_SERVER_COMPARE(win->ping[i].dest_id, id)) {
470 diff = curtime - win->ping[i].start_time;
471 silc_say(cmd->client, "Ping reply from %s: %d second%s",
472 win->ping[i].dest_name, diff, diff == 1 ? "" : "s");
474 win->ping[i].start_time = 0;
475 silc_free(win->ping[i].dest_id);
476 win->ping[i].dest_id = NULL;
477 silc_free(win->ping[i].dest_name);
478 win->ping[i].dest_name = NULL;
484 silc_client_command_reply_free(cmd);
487 SILC_CLIENT_CMD_REPLY_FUNC(oper)
491 /* Received reply for JOIN command. */
493 SILC_CLIENT_CMD_REPLY_FUNC(join)
495 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
496 SilcClient client = cmd->client;
497 SilcCommandStatus status;
498 unsigned int argc, mode;
499 unsigned char *id_string;
500 char *topic, *tmp, *channel_name;
502 SILC_LOG_DEBUG(("Start"));
504 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
505 SILC_GET16_MSB(status, tmp);
506 if (status != SILC_STATUS_OK) {
507 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
511 argc = silc_command_get_arg_num(cmd->payload);
512 if (argc < 3 || argc > 4) {
513 silc_say(cmd->client, "Cannot join channel: Bad reply packet");
517 /* Get channel name */
518 tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
520 silc_say(cmd->client, "Cannot join channel: Bad reply packet");
523 channel_name = strdup(tmp);
526 id_string = silc_command_get_arg_type(cmd->payload, 3, NULL);
528 silc_say(cmd->client, "Cannot join channel: Bad reply packet");
532 /* Get channel mode */
533 tmp = silc_command_get_arg_type(cmd->payload, 4, NULL);
535 SILC_GET32_MSB(mode, tmp);
540 topic = silc_command_get_arg_type(cmd->payload, 5, NULL);
542 /* Save received Channel ID */
543 silc_client_new_channel_id(cmd->client, cmd->sock, channel_name,
546 /* Print channel name on screen */
547 client->screen->bottom_line->channel = channel_name;
548 silc_screen_print_bottom_line(client->screen, 0);
551 silc_say(client, "Topic for %s: %s", channel_name, topic);
554 silc_client_command_reply_free(cmd);
557 SILC_CLIENT_CMD_REPLY_FUNC(motd)
561 SILC_CLIENT_CMD_REPLY_FUNC(umode)
565 SILC_CLIENT_CMD_REPLY_FUNC(cmode)
569 SILC_CLIENT_CMD_REPLY_FUNC(kick)
573 SILC_CLIENT_CMD_REPLY_FUNC(restart)
577 SILC_CLIENT_CMD_REPLY_FUNC(close)
581 SILC_CLIENT_CMD_REPLY_FUNC(die)
585 SILC_CLIENT_CMD_REPLY_FUNC(silcoper)
589 /* Reply to LEAVE command. */
591 SILC_CLIENT_CMD_REPLY_FUNC(leave)
593 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
594 SilcClient client = cmd->client;
595 SilcCommandStatus status;
598 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
599 SILC_GET16_MSB(status, tmp);
600 if (status != SILC_STATUS_OK)
601 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
603 silc_client_command_reply_free(cmd);
606 /* Reply to NAMES command. Received list of client names on the channel
609 SILC_CLIENT_CMD_REPLY_FUNC(names)
611 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
612 SilcClientWindow win = (SilcClientWindow)cmd->sock->user_data;
613 SilcCommandStatus status;
614 SilcIDCache *id_cache = NULL;
615 SilcChannelEntry channel;
616 SilcChannelID *channel_id = NULL;
617 SilcBuffer client_id_list;
620 int i, len1, len2, list_count = 0;
622 SILC_LOG_DEBUG(("Start"));
624 #define CIDC(x) win->channel_id_cache[(x)]
625 #define CIDCC(x) win->channel_id_cache_count[(x)]
626 #define CLC(x) win->client_id_cache[(x) - 32]
627 #define CLCC(x) win->client_id_cache_count[(x) - 32]
629 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
630 SILC_GET16_MSB(status, tmp);
631 if (status != SILC_STATUS_OK) {
632 silc_say(cmd->client, "%s", silc_client_command_status_message(status));
637 tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
639 silc_say(cmd->client, "Cannot get user list: Bad reply packet");
642 channel_id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
644 /* Get the name list of the channel */
645 name_list = silc_command_get_arg_type(cmd->payload, 3, &len1);
647 silc_say(cmd->client, "Cannot get user list: Bad reply packet");
651 /* Get Client ID list */
652 tmp = silc_command_get_arg_type(cmd->payload, 4, &len2);
654 silc_say(cmd->client, "Cannot get user list: Bad reply packet");
658 client_id_list = silc_buffer_alloc(len2);
659 silc_buffer_pull_tail(client_id_list, len2);
660 silc_buffer_put(client_id_list, tmp, len2);
662 /* Get the channel name */
663 for (i = 0; i < 96; i++) {
666 if (silc_idcache_find_by_id(CIDC(i), CIDCC(i), (void *)channel_id,
667 SILC_ID_CHANNEL, &id_cache))
673 channel = (SilcChannelEntry)id_cache->context;
675 /* If there is pending command we know that user has called this command
676 and we will handle the name list differently. */
678 /* We will resolve all the necessary information about the people
679 on the channel. Only after that will we display the user list. */
680 for (i = 0; i < len1; i++) {
684 silc_client_command_pending_del(SILC_COMMAND_NAMES);
686 /* there is no pending callback it means that this command reply
687 has been received without calling the command, ie. server has sent
688 the reply without getting the command from us first. This happens
689 with SILC servers that sends NAMES reply after joining to a channel. */
691 /* Remove commas from list */
692 for (i = 0; i < len1; i++)
693 if (name_list[i] == ',') {
698 silc_say(cmd->client, "Users on %s: %s", channel->channel_name, name_list);
701 /* Cache the received name list and client ID's. This cache expires
702 whenever server sends notify message to channel. It means to things;
703 some user has joined or leaved the channel. */
704 for (i = 0; i < list_count; i++) {
705 int nick_len = strcspn(name_list, " ");
706 char *nickname = silc_calloc(nick_len, sizeof(*nickname));
707 SilcClientID *client_id;
708 SilcClientEntry client;
710 memcpy(nickname, name_list, nick_len);
711 client_id = silc_id_str2id(client_id_list->data, SILC_ID_CLIENT_LEN);
712 silc_buffer_pull(client_id_list, SILC_ID_CLIENT_LEN);
714 client = silc_calloc(1, sizeof(*client));
715 client->id = client_id;
716 client->nickname = nickname;
718 CLCC(nickname[0]) = silc_idcache_add(&CLC(nickname[0]), CLCC(nickname[0]),
719 nickname, SILC_ID_CLIENT,
720 client_id, (void *)client);
722 name_list = name_list + nick_len + 1;
725 silc_buffer_free(client_id_list);
729 silc_free(channel_id);
730 silc_client_command_reply_free(cmd);
737 /* Private message received. This processes the private message and
738 finally displays it on the screen. */
740 SILC_CLIENT_CMD_REPLY_FUNC(msg)
742 SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
743 SilcClient client = cmd->client;
744 SilcBuffer buffer = (SilcBuffer)cmd->context;
745 unsigned short nick_len;
746 unsigned char *nickname, *message;
747 SilcIDCache *id_cache;
748 unsigned char *id_string;
752 silc_buffer_unformat(buffer,
753 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
755 silc_buffer_pull(buffer, 2 + nick_len);
758 /* Get ID of the sender */
759 id_string = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char *));
760 silc_buffer_push(buffer, SILC_ID_CLIENT_LEN + SILC_ID_CLIENT_LEN);
761 memcpy(id_string, buffer->data, SILC_ID_CLIENT_LEN);
762 silc_buffer_pull(buffer, SILC_ID_CLIENT_LEN + SILC_ID_CLIENT_LEN);
763 id = silc_id_str2id(id_string, SILC_ID_CLIENT);
764 silc_free(id_string);
766 /* Nickname should be verified if we don't have it in the cache */
767 if (silc_idcache_find_by_data(client->current_win->
768 client_id_cache[nickname[0] - 32],
769 client->current_win->
770 client_id_cache_count[nickname[0] - 32],
771 nickname, &id_cache) == FALSE) {
773 SilcClientCommandContext ctx;
776 /* Private message from unknown source, try to resolve it. */
783 message = silc_calloc(buffer->len + 1, sizeof(char));
784 memcpy(message, buffer->data, buffer->len);
785 silc_print(client, "*%s* %s", nickname, message);
786 memset(message, 0, buffer->len);