X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fcommand.c;h=85e33fe38217f0fe7b17c6c70a97270b1d3e2aca;hb=52e57c880aba9c5e89f59d962eb9af75670b76e0;hp=b1d233fc8c1a7f3f0ac6d4ec48104ed7366e8ae1;hpb=81f0294584576e6cff50ebcfd7160017dbf7ba97;p=silc.git diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index b1d233fc..85e33fe3 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2006 Pekka Riikonen + Copyright (C) 1997 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -119,13 +119,36 @@ static void silc_client_command_resolve_continue(SilcClient client, if (status != SILC_STATUS_OK) silc_fsm_next(&cmd->thread, silc_client_command_continue_error); - if (clients) - silc_dlist_uninit(clients); - /* Continue with the command */ SILC_FSM_CALL_CONTINUE(&cmd->thread); } +/* Dummy command callback. Nothing interesting to do here. Use this when + you just send command but don't care about reply. */ + +SilcBool silc_client_command_called_dummy(SilcClient client, + SilcClientConnection conn, + SilcCommand command, + SilcStatus status, + SilcStatus error, + void *context, + va_list ap) +{ + return FALSE; +} + +/* Dummy resolving callback. Nothing interesting to do here. Use this + when you just resolve entires but don't care about reply. */ + +void silc_client_command_resolve_dummy(SilcClient client, + SilcClientConnection conn, + SilcStatus status, + SilcDList clients, + void *context) +{ + /* Nothing */ +} + /* Register command to client */ static SilcBool @@ -203,7 +226,14 @@ static void silc_client_command_destructor(SilcFSMThread thread, void *fsm_context, void *destructor_context) { - silc_client_command_free(fsm_context); + SilcClientCommandContext cmd = fsm_context; + SilcClientConnection conn = cmd->conn; + + /* Removes commands that aren't waiting for reply but are waiting + for something. They may not have been removed yet. */ + silc_list_del(conn->internal->pending_commands, cmd); + + silc_client_command_free(cmd); } /* Add a command pending a command reply. Used internally by the library. */ @@ -254,6 +284,9 @@ static SilcUInt16 silc_client_command_send_vap(SilcClient client, SILC_LOG_DEBUG(("Send command %s", silc_get_command_name(command))); + if (conn->internal->disconnected) + return 0; + if (!cmd->cmd_ident) cmd->cmd_ident = silc_client_cmd_ident(conn); @@ -297,6 +330,9 @@ silc_client_command_send_arg_array(SilcClient client, SILC_LOG_DEBUG(("Send command %s", silc_get_command_name(command))); + if (conn->internal->disconnected) + return 0; + if (!cmd->cmd_ident) cmd->cmd_ident = silc_client_cmd_ident(conn); @@ -380,7 +416,7 @@ SilcUInt16 silc_client_command_call(SilcClient client, char *arg; if (!conn) { - client->internal->ops->say(client, NULL, SILC_CLIENT_MESSAGE_ERROR, + client->internal->ops->say(client, NULL, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "You are not connected to a server, please connect to server"); return 0; } @@ -600,6 +636,7 @@ SILC_FSM_STATE(silc_client_command_whois) unsigned char count[4], *tmp = NULL; SilcBool details = FALSE, nick = FALSE; unsigned char *pubkey = NULL; + char *nickname = NULL; int i; /* Given without arguments fetches client's own information */ @@ -660,7 +697,7 @@ SILC_FSM_STATE(silc_client_command_whois) SilcPublicKey pk; if (!silc_pkcs_load_public_key(pubkey, &pk)) { - SAY(client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load public key %s, check the filename", pubkey); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); @@ -690,14 +727,22 @@ SILC_FSM_STATE(silc_client_command_whois) SILC_ATTRIBUTE_USER_PUBLIC_KEY, SILC_ATTRIBUTE_FLAG_VALID, &obj, sizeof(obj)); + silc_free(obj.data); + } + + if (nick) { + silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname); + if (!nickname) + nickname = strdup(cmd->argv[1]); } /* Send command */ silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, - 3, 1, nick ? cmd->argv[1] : NULL, - nick ? cmd->argv_lens[1] : 0, + 3, 1, nick ? nickname : NULL, + nick ? strlen(nickname) : 0, 2, tmp ? tmp : NULL, tmp ? 4 : 0, 3, silc_buffer_datalen(attrs)); + silc_free(nickname); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -787,7 +832,7 @@ SILC_FSM_STATE(silc_client_command_identify) SILC_FSM_STATE(silc_client_command_nick) { - SilcClientCommandContext cmd = fsm_context; + SilcClientCommandContext cmd2, cmd = fsm_context; SilcClientConnection conn = cmd->conn; if (cmd->argc < 2) { @@ -815,6 +860,19 @@ SILC_FSM_STATE(silc_client_command_nick) goto out; } + /* If JOIN command is active, wait for it to finish before sending NICK. + To avoid problems locally with changing IDs while joining, we do this. */ + silc_mutex_lock(conn->internal->lock); + silc_list_start(conn->internal->pending_commands); + while ((cmd2 = silc_list_get(conn->internal->pending_commands))) { + if (cmd2->cmd == SILC_COMMAND_JOIN) { + silc_mutex_unlock(conn->internal->lock); + silc_fsm_next_later(fsm, silc_client_command_nick, 0, 300000); + return SILC_FSM_WAIT; + } + } + silc_mutex_unlock(conn->internal->lock); + if (cmd->argv_lens[1] > 128) cmd->argv_lens[1] = 128; @@ -841,7 +899,8 @@ SILC_FSM_STATE(silc_client_command_list) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; - SilcChannelEntry channel; + SilcClient client = conn->client; + SilcChannelEntry channel = NULL; SilcBuffer idp = NULL; if (cmd->argc == 2) { @@ -858,6 +917,7 @@ SILC_FSM_STATE(silc_client_command_list) 1, 1, silc_buffer_datalen(idp)); silc_buffer_free(idp); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -875,9 +935,10 @@ SILC_FSM_STATE(silc_client_command_topic) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; + SilcClient client = conn->client; SilcChannelEntry channel; SilcBuffer idp; - char *name; + char *name, tmp[512]; if (cmd->argc < 2 || cmd->argc > 3) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -892,7 +953,15 @@ SILC_FSM_STATE(silc_client_command_topic) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -921,6 +990,7 @@ SILC_FSM_STATE(silc_client_command_topic) 1, silc_buffer_datalen(idp)); silc_buffer_free(idp); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -944,7 +1014,7 @@ SILC_FSM_STATE(silc_client_command_invite) SilcClientConnection conn = cmd->conn; SilcClient client = conn->client; SilcClientEntry client_entry = NULL; - SilcChannelEntry channel; + SilcChannelEntry channel = NULL; SilcBuffer clidp, chidp, args = NULL; SilcPublicKey pubkey = NULL; SilcDList clients = NULL; @@ -967,6 +1037,7 @@ SILC_FSM_STATE(silc_client_command_invite) } channel = conn->current_channel; + silc_client_ref_channel(client, conn, channel); } else { name = cmd->argv[1]; @@ -980,19 +1051,15 @@ SILC_FSM_STATE(silc_client_command_invite) /* Parse the typed nickname. */ if (cmd->argc == 3) { if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') { - if (client->internal->params->nickname_parse) - client->internal->params->nickname_parse(cmd->argv[2], &nickname); - else - nickname = strdup(cmd->argv[2]); + silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname); /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[2]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[2], + FALSE); if (!clients) /* Resolve client information */ SILC_FSM_CALL(silc_client_get_clients( - client, conn, nickname, - cmd->argv[2], + client, conn, nickname, NULL, silc_client_command_resolve_continue, cmd)); @@ -1048,6 +1115,7 @@ SILC_FSM_STATE(silc_client_command_invite) silc_buffer_free(args); silc_free(nickname); silc_client_list_free(client, conn, clients); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -1069,19 +1137,17 @@ SILC_FSM_STATE(silc_client_command_quit_final) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; - SilcClient client = conn->client; + + SILC_LOG_DEBUG(("Quitting")); /* Notify application */ COMMAND(SILC_STATUS_OK); - /* Call connection callback */ - conn->callback(client, conn, SILC_CLIENT_CONN_DISCONNECTED, - 0, NULL, conn->callback_context); - /* Signal to close connection */ + conn->internal->status = SILC_CLIENT_CONN_DISCONNECTED; if (!conn->internal->disconnected) { conn->internal->disconnected = TRUE; - SILC_FSM_SEMA_POST(&conn->internal->wait_event); + SILC_FSM_EVENT_SIGNAL(&conn->internal->wait_event); } return SILC_FSM_FINISH; @@ -1110,7 +1176,6 @@ SILC_FSM_STATE(silc_client_command_quit) /********************************** KILL ************************************/ - /* Command KILL. Router operator can use this command to remove an client fromthe SILC Network. */ @@ -1132,20 +1197,14 @@ SILC_FSM_STATE(silc_client_command_kill) } /* Parse the typed nickname. */ - if (client->internal->params->nickname_parse) - client->internal->params->nickname_parse(cmd->argv[1], &nickname); - else - nickname = strdup(cmd->argv[1]); - if (!nickname) + if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname)) return SILC_FSM_FINISH; /* Get the target client */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[1]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[1], FALSE); if (!clients) /* Resolve client information */ - SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, - cmd->argv[1], + SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, NULL, silc_client_command_resolve_continue, cmd)); @@ -1268,9 +1327,10 @@ SILC_FSM_STATE(silc_client_command_ping) SILC_FSM_STATE(silc_client_command_join) { - SilcClientCommandContext cmd = fsm_context; + SilcClientCommandContext cmd2, cmd = fsm_context; SilcClientConnection conn = cmd->conn; - SilcChannelEntry channel; + SilcClient client = conn->client; + SilcChannelEntry channel = NULL; SilcBuffer auth = NULL, cauth = NULL; char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL; int i, passphrase_len = 0; @@ -1285,6 +1345,19 @@ SILC_FSM_STATE(silc_client_command_join) if (channel && silc_client_on_channel(channel, conn->local_entry)) goto out; + /* If NICK command is active, wait for it to finish before sending JOIN. + To avoid problems locally with changing IDs while joining, we do this. */ + silc_mutex_lock(conn->internal->lock); + silc_list_start(conn->internal->pending_commands); + while ((cmd2 = silc_list_get(conn->internal->pending_commands))) { + if (cmd2->cmd == SILC_COMMAND_NICK) { + silc_mutex_unlock(conn->internal->lock); + silc_fsm_next_later(fsm, silc_client_command_join, 0, 300000); + return SILC_FSM_WAIT; + } + } + silc_mutex_unlock(conn->internal->lock); + if (cmd->argv_lens[1] > 256) cmd->argv_lens[1] = 256; @@ -1316,7 +1389,7 @@ SILC_FSM_STATE(silc_client_command_join) } if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass, &pubkey, &privkey)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load key pair, check your arguments"); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -1368,6 +1441,7 @@ SILC_FSM_STATE(silc_client_command_join) if (passphrase) memset(passphrase, 0, strlen(passphrase)); silc_free(passphrase); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -1377,6 +1451,7 @@ SILC_FSM_STATE(silc_client_command_join) return SILC_FSM_CONTINUE; out: + silc_client_unref_channel(client, conn, channel); return SILC_FSM_FINISH; } @@ -1564,7 +1639,7 @@ SILC_FSM_STATE(silc_client_command_cmode) SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; SilcClient client = conn->client; - SilcChannelEntry channel; + SilcChannelEntry channel = NULL; SilcBuffer chidp, auth = NULL, pk = NULL; unsigned char *name, *cp, modebuf[4], tmp[4], *arg = NULL; SilcUInt32 mode, add, type, len, arg_len = 0; @@ -1584,6 +1659,7 @@ SILC_FSM_STATE(silc_client_command_cmode) } channel = conn->current_channel; + silc_client_ref_channel(client, conn, channel); } else { name = cmd->argv[1]; @@ -1733,7 +1809,7 @@ SILC_FSM_STATE(silc_client_command_cmode) pass = cmd->argv[5]; if (!silc_load_key_pair(cmd->argv[3], cmd->argv[4], pass, &pubkey, &privkey)) { - SAY(client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load key pair, check your arguments"); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -1768,10 +1844,14 @@ SILC_FSM_STATE(silc_client_command_cmode) NULL, NULL, 1, 1, silc_buffer_datalen(chidp)); silc_buffer_free(chidp); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); - goto out; + + /** Wait for command reply */ + silc_fsm_next(fsm, silc_client_command_reply_wait); + return SILC_FSM_CONTINUE; } if (cmd->argc >= 4) { @@ -1785,7 +1865,7 @@ SILC_FSM_STATE(silc_client_command_cmode) if (cmd->argv[k][0] == '+') chadd = TRUE; if (!silc_pkcs_load_public_key(cmd->argv[k] + 1, &chpk)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load public key %s, check the filename", cmd->argv[k]); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); @@ -1837,6 +1917,7 @@ SILC_FSM_STATE(silc_client_command_cmode) silc_buffer_free(chidp); silc_buffer_free(auth); silc_buffer_free(pk); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -1846,6 +1927,7 @@ SILC_FSM_STATE(silc_client_command_cmode) return SILC_FSM_CONTINUE; out: + silc_client_unref_channel(client, conn, channel); return SILC_FSM_FINISH; } @@ -1858,7 +1940,7 @@ SILC_FSM_STATE(silc_client_command_cumode) SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; SilcClient client = conn->client; - SilcChannelEntry channel; + SilcChannelEntry channel = NULL; SilcChannelUser chu; SilcClientEntry client_entry; SilcBuffer clidp, chidp, auth = NULL; @@ -1882,6 +1964,7 @@ SILC_FSM_STATE(silc_client_command_cumode) } channel = conn->current_channel; + silc_client_ref_channel(client, conn, channel); } else { name = cmd->argv[1]; @@ -1893,17 +1976,13 @@ SILC_FSM_STATE(silc_client_command_cumode) } /* Parse the typed nickname. */ - if (client->internal->params->nickname_parse) - client->internal->params->nickname_parse(cmd->argv[3], &nickname); - else - nickname = strdup(cmd->argv[3]); + silc_client_nickname_parse(client, conn, cmd->argv[3], &nickname); /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[3]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[3], FALSE); if (!clients) /* Resolve client information */ - SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, cmd->argv[3], + SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, NULL, silc_client_command_resolve_continue, cmd)); @@ -1947,7 +2026,7 @@ SILC_FSM_STATE(silc_client_command_cumode) pass = cmd->argv[6]; if (!silc_load_key_pair(cmd->argv[4], cmd->argv[5], pass, &pubkey, &privkey)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load key pair, check your arguments"); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -2019,6 +2098,7 @@ SILC_FSM_STATE(silc_client_command_cumode) silc_buffer_free(auth); silc_free(nickname); silc_client_list_free(client, conn, clients); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -2028,6 +2108,7 @@ SILC_FSM_STATE(silc_client_command_cumode) return SILC_FSM_CONTINUE; out: + silc_client_unref_channel(client, conn, channel); silc_client_list_free(client, conn, clients); silc_free(nickname); return SILC_FSM_FINISH; @@ -2042,12 +2123,11 @@ SILC_FSM_STATE(silc_client_command_kick) SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; SilcClient client = conn->client; - SilcChannelEntry channel; + SilcChannelEntry channel = NULL; SilcBuffer idp, idp2; SilcClientEntry target; SilcDList clients = NULL; - char *name; - char *nickname = NULL; + char *name, tmp[512]; if (cmd->argc < 3) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -2061,7 +2141,15 @@ SILC_FSM_STATE(silc_client_command_kick) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -2078,15 +2166,8 @@ SILC_FSM_STATE(silc_client_command_kick) goto out; } - /* Parse the typed nickname. */ - if (client->internal->params->nickname_parse) - client->internal->params->nickname_parse(cmd->argv[2], &nickname); - else - nickname = strdup(cmd->argv[2]); - /* Get the target client */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[2]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[2], FALSE); if (!clients) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, "No such client: %s", cmd->argv[2]); @@ -2110,8 +2191,8 @@ SILC_FSM_STATE(silc_client_command_kick) silc_buffer_free(idp); silc_buffer_free(idp2); - silc_free(nickname); silc_client_list_free(client, conn, clients); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -2121,7 +2202,7 @@ SILC_FSM_STATE(silc_client_command_kick) return SILC_FSM_CONTINUE; out: - silc_free(nickname); + silc_client_unref_channel(client, conn, channel); return SILC_FSM_FINISH; } @@ -2134,7 +2215,7 @@ typedef struct { /* Ask passphrase callback */ -static void silc_client_command_oper_cb(unsigned char *data, +static void silc_client_command_oper_cb(const unsigned char *data, SilcUInt32 data_len, void *context) { SilcClientCommandContext cmd = context; @@ -2205,6 +2286,8 @@ SILC_FSM_STATE(silc_client_command_oper) return SILC_FSM_FINISH; } + silc_fsm_next(fsm, silc_client_command_oper_send); + /* Get passphrase */ if (cmd->argc < 3) { oper = silc_calloc(1, sizeof(*oper)); @@ -2216,7 +2299,6 @@ SILC_FSM_STATE(silc_client_command_oper) silc_client_command_oper_cb, cmd)); } - silc_fsm_next(fsm, silc_client_command_oper_send); return SILC_FSM_CONTINUE; } @@ -2235,6 +2317,8 @@ SILC_FSM_STATE(silc_client_command_silcoper) return SILC_FSM_FINISH; } + silc_fsm_next(fsm, silc_client_command_oper_send); + /* Get passphrase */ if (cmd->argc < 3) { oper = silc_calloc(1, sizeof(*oper)); @@ -2246,7 +2330,6 @@ SILC_FSM_STATE(silc_client_command_silcoper) silc_client_command_oper_cb, cmd)); } - silc_fsm_next(fsm, silc_client_command_oper_send); return SILC_FSM_CONTINUE; } @@ -2258,6 +2341,7 @@ SILC_FSM_STATE(silc_client_command_ban) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; + SilcClient client = conn->client; SilcChannelEntry channel; SilcBuffer chidp, args = NULL; char *name, *ban = NULL; @@ -2279,6 +2363,7 @@ SILC_FSM_STATE(silc_client_command_ban) } channel = conn->current_channel; + silc_client_ref_channel(client, conn, channel); } else { name = cmd->argv[1]; @@ -2328,6 +2413,7 @@ SILC_FSM_STATE(silc_client_command_ban) silc_buffer_free(chidp); silc_buffer_free(args); + silc_client_unref_channel(client, conn, channel); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -2396,7 +2482,7 @@ SILC_FSM_STATE(silc_client_command_watch) SilcBuffer buffer; if (!silc_pkcs_load_public_key(pubkey, &pk)) { - SAY(conn->client, conn, SILC_CLIENT_MESSAGE_ERROR, + SAY(conn->client, conn, SILC_CLIENT_MESSAGE_COMMAND_ERROR, "Could not load public key %s, check the filename", pubkey); COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); goto out; @@ -2413,6 +2499,12 @@ SILC_FSM_STATE(silc_client_command_watch) silc_pkcs_public_key_free(pk); } + /* If watching by nickname, resolve all users with that nickname so that + we get their information immediately. */ + if (type == 2) + silc_client_get_clients(conn->client, conn, cmd->argv[2], NULL, + silc_client_command_resolve_dummy, NULL); + /* Send the commmand */ silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 2, 1, silc_buffer_datalen(conn->internal-> @@ -2442,9 +2534,10 @@ SILC_FSM_STATE(silc_client_command_leave) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; + SilcClient client = conn->client; SilcChannelEntry channel; SilcBuffer idp; - char *name; + char *name, tmp[512]; if (cmd->argc != 2) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -2458,7 +2551,15 @@ SILC_FSM_STATE(silc_client_command_leave) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -2484,6 +2585,8 @@ SILC_FSM_STATE(silc_client_command_leave) if (conn->current_channel == channel) conn->current_channel = NULL; + silc_client_unref_channel(client, conn, channel); + /** Wait for command reply */ silc_fsm_next(fsm, silc_client_command_reply_wait); return SILC_FSM_CONTINUE; @@ -2501,7 +2604,7 @@ SILC_FSM_STATE(silc_client_command_users) { SilcClientCommandContext cmd = fsm_context; SilcClientConnection conn = cmd->conn; - char *name; + char *name, tmp[512]; if (cmd->argc != 2) { SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO, @@ -2515,7 +2618,15 @@ SILC_FSM_STATE(silc_client_command_users) COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL); goto out; } - name = conn->current_channel->channel_name; + + if (conn->client->internal->params->full_channel_names) + silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name); + else + silc_snprintf(tmp, sizeof(tmp), "%s%s%s", + conn->current_channel->channel_name, + conn->current_channel->server[0] ? "@" : "", + conn->current_channel->server); + name = tmp; } else { name = cmd->argv[1]; } @@ -2547,7 +2658,6 @@ SILC_FSM_STATE(silc_client_command_getkey) SilcClientEntry client_entry; SilcServerEntry server_entry; SilcDList clients; - char *nickname = NULL; SilcBuffer idp; if (cmd->argc < 2) { @@ -2557,19 +2667,8 @@ SILC_FSM_STATE(silc_client_command_getkey) return SILC_FSM_FINISH; } - /* Parse the typed nickname. */ - if (client->internal->params->nickname_parse) - client->internal->params->nickname_parse(cmd->argv[1], &nickname); - else - nickname = strdup(cmd->argv[1]); - if (!nickname) { - COMMAND_ERROR(SILC_STATUS_ERR_RESOURCE_LIMIT); - return SILC_FSM_FINISH; - } - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, - cmd->argv[1]); + clients = silc_client_get_clients_local(client, conn, cmd->argv[1], FALSE); if (!clients) { /* Check whether user requested server */ server_entry = silc_client_get_server(client, conn, cmd->argv[1]); @@ -2607,7 +2706,6 @@ SILC_FSM_STATE(silc_client_command_getkey) 1, silc_buffer_datalen(idp)); silc_buffer_free(idp); - silc_free(nickname); /* Notify application */ COMMAND(SILC_STATUS_OK); @@ -2736,7 +2834,6 @@ static void silc_client_command_process_whois(SilcClient client, SilcCommandPayload payload, SilcArgumentPayload args) { -#if 0 SilcDList attrs; unsigned char *tmp; SilcUInt32 tmp_len; @@ -2760,18 +2857,25 @@ static void silc_client_command_process_whois(SilcClient client, return; } - /* Send the attributes back */ + /* Send the attributes back in COMMAND_REPLY packet */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS, SILC_STATUS_OK, 0, silc_command_get_ident(payload), - 1, 11, buffer->data, buffer->len); - silc_client_packet_send(client, sock, SILC_PACKET_COMMAND_REPLY, - NULL, 0, NULL, NULL, packet->data, - packet->len, TRUE); + 1, 11, buffer->data, + silc_buffer_len(buffer)); + if (!packet) { + silc_buffer_free(buffer); + return; + } + + SILC_LOG_DEBUG(("Sending back requested WHOIS attributes")); + + silc_packet_send(conn->stream, SILC_PACKET_COMMAND_REPLY, 0, + silc_buffer_datalen(packet)); + silc_buffer_free(packet); silc_buffer_free(buffer); -#endif /* 0 */ } /* Client is able to receive some command packets even though they are @@ -2807,7 +2911,7 @@ SILC_FSM_STATE(silc_client_command) case SILC_COMMAND_WHOIS: /* Ignore everything if requested by application */ - if (client->internal->params->ignore_requested_attributes) + if (conn->internal->params.ignore_requested_attributes) break; silc_client_command_process_whois(client, conn, payload, args);