X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcclient%2Fcommand.c;h=b449b1150ed9da09d1d1eccd113d1f948bf63754;hb=017dec75a98209fbef49eb496c2269b0c49e736d;hp=db3946ca272aea406fe4c5d13a02c7aa7442d6d4;hpb=72cfa31520ebc0058763a30e21c13f6e9a964aa0;p=silc.git diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index db3946ca..b449b115 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -57,12 +57,13 @@ SilcClientCommand silc_command_list[] = SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 3), SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", SILC_CF_LAG | SILC_CF_REG, 2), SILC_CLIENT_CMD(users, USERS, "USERS", SILC_CF_LAG | SILC_CF_REG, 2), + SILC_CLIENT_CMD(getkey, GETKEY, "GETKEY", SILC_CF_LAG | SILC_CF_REG, 2), { NULL, 0, NULL, 0, 0 }, }; #define SILC_NOT_CONNECTED(x, c) \ - x->ops->say((x), (c), \ + x->ops->say((x), (c), SILC_CLIENT_MESSAGE_ERROR, \ "You are not connected to a server, use /SERVER to connect"); /* Command operation that is called at the end of all commands. @@ -194,6 +195,8 @@ void silc_client_command_free(SilcClientCommandContext ctx) for (i = 0; i < ctx->argc; i++) silc_free(ctx->argv[i]); + silc_free(ctx->argv_lens); + silc_free(ctx->argv_types); silc_free(ctx); } } @@ -216,16 +219,6 @@ static void silc_client_command_destructor(void *context) silc_client_command_free((SilcClientCommandContext)context); } -/* silc_client_get_client completion callback */ -void silc_client_command_completion(SilcClient client, - SilcClientConnection conn, - SilcClientEntry clients, - uint32 clients_count, - void *context) -{ - -} - /* Command WHOIS. This command is used to query information about specific user. */ @@ -241,10 +234,13 @@ SILC_CLIENT_CMD_FUNC(whois) goto out; } - if (cmd->argc < 2 || cmd->argc > 3) { - cmd->client->ops->say(cmd->client, conn, - "Usage: /WHOIS [@] []"); - COMMAND_ERROR; + /* Given without arguments fetches client's own information */ + if (cmd->argc < 2) { + buffer = silc_id_payload_encode(cmd->conn->local_id, SILC_ID_CLIENT); + silc_client_send_command(cmd->client, cmd->conn, SILC_COMMAND_WHOIS, + ++conn->cmd_ident, + 1, 3, buffer->data, buffer->len); + silc_buffer_free(buffer); goto out; } @@ -283,7 +279,7 @@ SILC_CLIENT_CMD_FUNC(whowas) } if (cmd->argc < 2 || cmd->argc > 3) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /WHOWAS [@] []"); COMMAND_ERROR; goto out; @@ -324,23 +320,27 @@ SILC_CLIENT_CMD_FUNC(identify) } if (cmd->argc < 2 || cmd->argc > 3) { - cmd->client->ops->say(cmd->client, conn, - "Usage: /IDENTIFY [@] []"); COMMAND_ERROR; goto out; } - buffer = silc_command_payload_encode(SILC_COMMAND_IDENTIFY, - cmd->argc - 1, ++cmd->argv, - ++cmd->argv_lens, ++cmd->argv_types, - ++conn->cmd_ident); + if (cmd->argc == 2) + buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY, + ++conn->cmd_ident, 1, + 1, cmd->argv[1], + cmd->argv_lens[1]); + else + buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY, + ++conn->cmd_ident, 2, + 1, cmd->argv[1], + cmd->argv_lens[1], + 4, cmd->argv[2], + cmd->argv_lens[2]); + silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, buffer->data, buffer->len, TRUE); silc_buffer_free(buffer); - cmd->argv--; - cmd->argv_lens--; - cmd->argv_types--; /* Notify application */ COMMAND; @@ -364,21 +364,27 @@ SILC_CLIENT_CMD_FUNC(nick) goto out; } + if (cmd->argc < 2) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /NICK "); + COMMAND_ERROR; + goto out; + } + if (!strcmp(conn->nickname, cmd->argv[1])) goto out; /* Show current nickname */ if (cmd->argc < 2) { if (cmd->conn) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Your nickname is %s on server %s", conn->nickname, conn->remote_host); } else { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Your nickname is %s", conn->nickname); } - /* XXX Notify application */ COMMAND; goto out; } @@ -427,7 +433,7 @@ SILC_CLIENT_CMD_FUNC(list) name = cmd->argv[1]; /* Get the Channel ID of the channel */ - if (silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) { + if (silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) { channel = (SilcChannelEntry)id_cache->context; idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); } @@ -473,7 +479,7 @@ SILC_CLIENT_CMD_FUNC(topic) } if (cmd->argc < 2 || cmd->argc > 3) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /TOPIC []"); COMMAND_ERROR; goto out; @@ -481,7 +487,8 @@ SILC_CLIENT_CMD_FUNC(topic) if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -491,14 +498,16 @@ SILC_CLIENT_CMD_FUNC(topic) } if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on that channel"); COMMAND_ERROR; goto out; } /* Get the Channel ID of the channel */ - if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); + if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on that channel"); COMMAND_ERROR; goto out; } @@ -508,14 +517,15 @@ SILC_CLIENT_CMD_FUNC(topic) /* Send TOPIC command to the server */ idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); if (cmd->argc > 2) - buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC, 0, 2, + buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC, + ++conn->cmd_ident, 2, 1, idp->data, idp->len, 2, cmd->argv[2], strlen(cmd->argv[2])); else - buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC, 1, - 1, idp->data, idp->len, - 0); + buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC, + ++conn->cmd_ident, 1, + 1, idp->data, idp->len); silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, buffer->data, buffer->len, TRUE); silc_buffer_free(buffer); @@ -539,8 +549,8 @@ SILC_CLIENT_CMD_FUNC(invite) SilcClientEntry client_entry = NULL; SilcChannelEntry channel; SilcBuffer buffer, clidp, chidp; - uint32 num = 0, type = 0; - char *nickname = NULL, *server = NULL, *name; + uint32 type = 0; + char *nickname = NULL, *name; char *invite = NULL; if (!cmd->conn) { @@ -550,7 +560,7 @@ SILC_CLIENT_CMD_FUNC(invite) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /INVITE [[@server>]" "[+|-[[@[![@hostname>]]]]]"); COMMAND_ERROR; @@ -559,7 +569,8 @@ SILC_CLIENT_CMD_FUNC(invite) if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -570,7 +581,8 @@ SILC_CLIENT_CMD_FUNC(invite) channel = silc_client_get_channel(cmd->client, conn, name); if (!channel) { - cmd->client->ops->say(cmd->client, conn, "You are on that channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are on that channel"); COMMAND_ERROR; goto out; } @@ -579,20 +591,16 @@ SILC_CLIENT_CMD_FUNC(invite) /* Parse the typed nickname. */ if (cmd->argc == 3) { if (cmd->argv[2][0] != '+' && cmd->argv[2][0] != '-') { - if (!silc_parse_nickname(cmd->argv[2], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, "Bad nickname"); - COMMAND_ERROR; - goto out; - } - + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[2], &nickname); + else + nickname = strdup(cmd->argv[2]); + /* Find client entry */ client_entry = silc_idlist_get_client(client, conn, nickname, - server, num, TRUE); + cmd->argv[2], TRUE); if (!client_entry) { - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); if (cmd->pending) { COMMAND_ERROR; @@ -609,10 +617,6 @@ SILC_CLIENT_CMD_FUNC(invite) cmd->pending = 1; return; } - - cmd->client->ops->say(cmd->client, conn, - "Inviting %s to channel %s", cmd->argv[2], - channel->channel_name); } else { invite = cmd->argv[2]; invite++; @@ -651,10 +655,7 @@ SILC_CLIENT_CMD_FUNC(invite) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -705,9 +706,9 @@ SILC_CLIENT_CMD_FUNC(quit) q->conn = cmd->conn; /* We quit the connection with little timeout */ - silc_task_register(cmd->client->timeout_queue, cmd->conn->sock->sock, - silc_client_command_quit_cb, (void *)q, - 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + silc_schedule_task_add(cmd->client->schedule, cmd->conn->sock->sock, + silc_client_command_quit_cb, (void *)q, + 1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); /* Notify application */ COMMAND; @@ -722,11 +723,11 @@ SILC_CLIENT_CMD_FUNC(quit) SILC_CLIENT_CMD_FUNC(kill) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; SilcBuffer buffer, idp; SilcClientEntry target; - uint32 num = 0; - char *nickname = NULL, *server = NULL; + char *nickname = NULL; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -735,26 +736,23 @@ SILC_CLIENT_CMD_FUNC(kill) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /KILL []"); COMMAND_ERROR; goto out; } /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[1], &nickname); + else + nickname = strdup(cmd->argv[1]); /* Get the target client */ target = silc_idlist_get_client(cmd->client, conn, nickname, - server, num, TRUE); + cmd->argv[1], TRUE); if (!target) { silc_free(nickname); - if (server) - silc_free(server); if (cmd->pending) { COMMAND_ERROR; @@ -791,10 +789,7 @@ SILC_CLIENT_CMD_FUNC(kill) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -847,7 +842,6 @@ SILC_CLIENT_CMD_FUNC(ping) SilcBuffer buffer; void *id; int i; - char *name = NULL; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -855,13 +849,11 @@ SILC_CLIENT_CMD_FUNC(ping) goto out; } - if (cmd->argc == 1 || !strcmp(cmd->argv[1], conn->remote_host)) - name = strdup(conn->remote_host); - /* Send the command */ buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 0, 1, 1, conn->remote_id_data, - SILC_ID_SERVER_LEN); + silc_id_get_len(conn->remote_id, + SILC_ID_SERVER)); silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 0, NULL, NULL, buffer->data, buffer->len, TRUE); silc_buffer_free(buffer); @@ -879,7 +871,7 @@ SILC_CLIENT_CMD_FUNC(ping) if (conn->ping[i].dest_id == NULL) { conn->ping[i].start_time = time(NULL); conn->ping[i].dest_id = id; - conn->ping[i].dest_name = name; + conn->ping[i].dest_name = strdup(conn->remote_host); conn->ping_count++; break; } @@ -889,7 +881,7 @@ SILC_CLIENT_CMD_FUNC(ping) conn->ping = silc_realloc(conn->ping, sizeof(*conn->ping) * (i + 1)); conn->ping[i].start_time = time(NULL); conn->ping[i].dest_id = id; - conn->ping[i].dest_name = name; + conn->ping[i].dest_name = strdup(conn->remote_host); conn->ping_count++; } @@ -900,10 +892,6 @@ SILC_CLIENT_CMD_FUNC(ping) silc_client_command_free(cmd); } -SILC_CLIENT_CMD_FUNC(notice) -{ -} - /* Command JOIN. Joins to a channel. */ SILC_CLIENT_CMD_FUNC(join) @@ -919,24 +907,10 @@ SILC_CLIENT_CMD_FUNC(join) goto out; } - if (cmd->argc < 2) { - /* Show channels currently joined to */ - - goto out; - } - /* See if we have joined to the requested channel already */ - if (silc_idcache_find_by_data_one(conn->channel_cache, cmd->argv[1], - &id_cache)) { - cmd->client->ops->say(cmd->client, conn, - "You are talking to channel %s", cmd->argv[1]); - conn->current_channel = (SilcChannelEntry)id_cache->context; -#if 0 - cmd->client->screen->bottom_line->channel = cmd->argv[1]; - silc_screen_print_bottom_line(cmd->client->screen, 0); -#endif + if (silc_idcache_find_by_name_one(conn->channel_cache, cmd->argv[1], + &id_cache)) goto out; - } idp = silc_id_payload_encode(conn->local_id, SILC_ID_CLIENT); @@ -988,7 +962,7 @@ SILC_CLIENT_CMD_FUNC(motd) } if (cmd->argc < 1 || cmd->argc > 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /MOTD []"); COMMAND_ERROR; goto out; @@ -1033,7 +1007,7 @@ SILC_CLIENT_CMD_FUNC(umode) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /UMODE +|-"); COMMAND_ERROR; goto out; @@ -1128,7 +1102,7 @@ SILC_CLIENT_CMD_FUNC(cmode) } if (cmd->argc < 3) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /CMODE +|- [{ }]"); COMMAND_ERROR; goto out; @@ -1136,7 +1110,8 @@ SILC_CLIENT_CMD_FUNC(cmode) if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -1147,7 +1122,8 @@ SILC_CLIENT_CMD_FUNC(cmode) channel = silc_client_get_channel(cmd->client, conn, name); if (!channel) { - cmd->client->ops->say(cmd->client, conn, "You are on that channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are on that channel"); COMMAND_ERROR; goto out; } @@ -1204,6 +1180,12 @@ SILC_CLIENT_CMD_FUNC(cmode) int ll; mode |= SILC_CHANNEL_MODE_ULIMIT; type = 3; + if (cmd->argc < 4) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CMODE +|- [{ }]"); + COMMAND_ERROR; + goto out; + } ll = atoi(cmd->argv[3]); SILC_PUT32_MSB(ll, tmp); arg = tmp; @@ -1216,6 +1198,12 @@ SILC_CLIENT_CMD_FUNC(cmode) if (add) { mode |= SILC_CHANNEL_MODE_PASSPHRASE; type = 4; + if (cmd->argc < 4) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CMODE +|- [{ }]"); + COMMAND_ERROR; + goto out; + } arg = cmd->argv[3]; arg_len = cmd->argv_lens[3]; } else { @@ -1226,6 +1214,12 @@ SILC_CLIENT_CMD_FUNC(cmode) if (add) { mode |= SILC_CHANNEL_MODE_CIPHER; type = 5; + if (cmd->argc < 4) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CMODE +|- [{ }]"); + COMMAND_ERROR; + goto out; + } arg = cmd->argv[3]; arg_len = cmd->argv_lens[3]; } else { @@ -1236,6 +1230,12 @@ SILC_CLIENT_CMD_FUNC(cmode) if (add) { mode |= SILC_CHANNEL_MODE_HMAC; type = 6; + if (cmd->argc < 4) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CMODE +|- [{ }]"); + COMMAND_ERROR; + goto out; + } arg = cmd->argv[3]; arg_len = cmd->argv_lens[3]; } else { @@ -1247,6 +1247,13 @@ SILC_CLIENT_CMD_FUNC(cmode) mode |= SILC_CHANNEL_MODE_FOUNDER_AUTH; type = 7; + if (cmd->argc < 4) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /CMODE +|- [{ }]"); + COMMAND_ERROR; + goto out; + } + if (!strcasecmp(cmd->argv[3], "-pubkey")) { auth = silc_auth_public_key_auth_generate(cmd->client->public_key, cmd->client->private_key, @@ -1271,11 +1278,6 @@ SILC_CLIENT_CMD_FUNC(cmode) } } - if (type && cmd->argc < 3) { - COMMAND_ERROR; - goto out; - } - chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL); SILC_PUT32_MSB(mode, modebuf); @@ -1313,6 +1315,7 @@ SILC_CLIENT_CMD_FUNC(cmode) SILC_CLIENT_CMD_FUNC(cumode) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; SilcChannelEntry channel; SilcChannelUser chu; @@ -1320,8 +1323,7 @@ SILC_CLIENT_CMD_FUNC(cumode) SilcBuffer buffer, clidp, chidp, auth = NULL; unsigned char *name, *cp, modebuf[4]; uint32 mode = 0, add, len; - char *nickname = NULL, *server = NULL; - uint32 num = 0; + char *nickname = NULL; int i; if (!cmd->conn) { @@ -1331,7 +1333,7 @@ SILC_CLIENT_CMD_FUNC(cumode) } if (cmd->argc < 4) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /CUMODE +|- [@]"); COMMAND_ERROR; goto out; @@ -1339,7 +1341,8 @@ SILC_CLIENT_CMD_FUNC(cumode) if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -1350,23 +1353,25 @@ SILC_CLIENT_CMD_FUNC(cumode) channel = silc_client_get_channel(cmd->client, conn, name); if (!channel) { - cmd->client->ops->say(cmd->client, conn, "You are on that channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are on that channel"); COMMAND_ERROR; goto out; } } /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[3], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[3], &nickname); + else + nickname = strdup(cmd->argv[3]); /* Find client entry */ - client_entry = silc_idlist_get_client(cmd->client, conn, - nickname, server, num, TRUE); + client_entry = silc_idlist_get_client(cmd->client, conn, nickname, + cmd->argv[3], TRUE); if (!client_entry) { + silc_free(nickname); + if (cmd->pending) { COMMAND_ERROR; goto out; @@ -1383,9 +1388,10 @@ SILC_CLIENT_CMD_FUNC(cumode) return; } + /* Get the current mode */ while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) { if (chu->client == client_entry) { - chu->mode = mode; + mode = chu->mode; break; } } @@ -1466,10 +1472,7 @@ SILC_CLIENT_CMD_FUNC(cumode) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } @@ -1478,14 +1481,14 @@ SILC_CLIENT_CMD_FUNC(cumode) SILC_CLIENT_CMD_FUNC(kick) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClient client = cmd->client; SilcClientConnection conn = cmd->conn; SilcIDCacheEntry id_cache = NULL; SilcChannelEntry channel; SilcBuffer buffer, idp, idp2; SilcClientEntry target; char *name; - uint32 num = 0; - char *nickname = NULL, *server = NULL; + char *nickname = NULL; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -1494,7 +1497,7 @@ SILC_CLIENT_CMD_FUNC(kick) } if (cmd->argc < 3) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /KICK []"); COMMAND_ERROR; goto out; @@ -1502,7 +1505,8 @@ SILC_CLIENT_CMD_FUNC(kick) if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -1512,14 +1516,16 @@ SILC_CLIENT_CMD_FUNC(kick) } if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on that channel"); COMMAND_ERROR; goto out; } /* Get the Channel ID of the channel */ - if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); + if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on that channel"); COMMAND_ERROR; goto out; } @@ -1527,17 +1533,17 @@ SILC_CLIENT_CMD_FUNC(kick) channel = (SilcChannelEntry)id_cache->context; /* Parse the typed nickname. */ - if (!silc_parse_nickname(cmd->argv[2], &nickname, &server, &num)) { - cmd->client->ops->say(cmd->client, conn, "Bad nickname"); - COMMAND_ERROR; - goto out; - } + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[2], &nickname); + else + nickname = strdup(cmd->argv[2]); /* Get the target client */ target = silc_idlist_get_client(cmd->client, conn, nickname, - server, num, FALSE); + cmd->argv[2], FALSE); if (!target) { - cmd->client->ops->say(cmd->client, conn, "No such client: %s", + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "No such client: %s", cmd->argv[2]); COMMAND_ERROR; goto out; @@ -1566,22 +1572,50 @@ SILC_CLIENT_CMD_FUNC(kick) COMMAND; out: - if (nickname) - silc_free(nickname); - if (server) - silc_free(server); + silc_free(nickname); silc_client_command_free(cmd); } +static void silc_client_command_oper_send(unsigned char *data, + uint32 data_len, void *context) +{ + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcBuffer buffer, auth; + + if (cmd->argc >= 3) { + /* Encode the public key authentication payload */ + auth = silc_auth_public_key_auth_generate(cmd->client->public_key, + cmd->client->private_key, + conn->hash, + conn->local_id, + SILC_ID_CLIENT); + } else { + /* Encode the password authentication payload */ + auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0, + data, data_len); + } + + buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER, 0, 2, + 1, cmd->argv[1], + strlen(cmd->argv[1]), + 2, auth->data, auth->len); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, + 0, NULL, NULL, buffer->data, buffer->len, TRUE); + + silc_buffer_free(buffer); + silc_buffer_free(auth); + + /* Notify application */ + COMMAND; +} + /* OPER command. Used to obtain server operator privileges. */ SILC_CLIENT_CMD_FUNC(oper) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClientConnection conn = cmd->conn; - SilcBuffer buffer; - unsigned char *auth_data; - SilcBuffer auth; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -1590,32 +1624,47 @@ SILC_CLIENT_CMD_FUNC(oper) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, - "Usage: /OPER []"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /OPER [-pubkey]"); COMMAND_ERROR; goto out; } - if (cmd->argc == 3) { - /* XXX Get public key */ - auth_data = NULL; - COMMAND_ERROR; - goto out; - } else { + if (cmd->argc < 3) { /* Get passphrase */ + cmd->client->ops->ask_passphrase(cmd->client, conn, + silc_client_command_oper_send, + context); + return; + } - auth_data = cmd->client->ops->ask_passphrase(cmd->client, conn); - if (!auth_data) { - COMMAND_ERROR; - goto out; - } + silc_client_command_oper_send(NULL, 0, context); + + out: + silc_client_command_free(cmd); +} - /* Encode the authentication payload */ +static void silc_client_command_silcoper_send(unsigned char *data, + uint32 data_len, void *context) +{ + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcBuffer buffer, auth; + + if (cmd->argc >= 3) { + /* Encode the public key authentication payload */ + auth = silc_auth_public_key_auth_generate(cmd->client->public_key, + cmd->client->private_key, + conn->hash, + conn->local_id, + SILC_ID_CLIENT); + } else { + /* Encode the password authentication payload */ auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0, - auth_data, strlen(auth_data)); + data, data_len); } - buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER, 0, 2, + buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER, 0, 2, 1, cmd->argv[1], strlen(cmd->argv[1]), 2, auth->data, auth->len); @@ -1624,14 +1673,9 @@ SILC_CLIENT_CMD_FUNC(oper) silc_buffer_free(buffer); silc_buffer_free(auth); - memset(auth_data, 0, strlen(auth_data)); - silc_free(auth_data); /* Notify application */ COMMAND; - - out: - silc_client_command_free(cmd); } /* SILCOPER command. Used to obtain router operator privileges. */ @@ -1640,9 +1684,6 @@ SILC_CLIENT_CMD_FUNC(silcoper) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClientConnection conn = cmd->conn; - SilcBuffer buffer; - unsigned char *auth_data; - SilcBuffer auth; if (!cmd->conn) { SILC_NOT_CONNECTED(cmd->client, cmd->conn); @@ -1651,45 +1692,21 @@ SILC_CLIENT_CMD_FUNC(silcoper) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, - "Usage: /SILCOPER []"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /SILCOPER [-pubkey]"); COMMAND_ERROR; goto out; } - if (cmd->argc == 3) { - /* XXX Get public key */ - auth_data = NULL; - COMMAND_ERROR; - goto out; - } else { + if (cmd->argc < 3) { /* Get passphrase */ - - auth_data = cmd->client->ops->ask_passphrase(cmd->client, conn); - if (!auth_data) { - COMMAND_ERROR; - goto out; - } - - /* Encode the authentication payload */ - auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0, - auth_data, strlen(auth_data)); + cmd->client->ops->ask_passphrase(cmd->client, conn, + silc_client_command_silcoper_send, + context); + return; } - buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER, 0, 2, - 1, cmd->argv[1], - strlen(cmd->argv[1]), - 2, auth->data, auth->len); - silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, - 0, NULL, NULL, buffer->data, buffer->len, TRUE); - - silc_buffer_free(buffer); - silc_buffer_free(auth); - memset(auth_data, 0, strlen(auth_data)); - silc_free(auth_data); - - /* Notify application */ - COMMAND; + silc_client_command_silcoper_send(NULL, 0, context); out: silc_client_command_free(cmd); @@ -1712,7 +1729,7 @@ SILC_CLIENT_CMD_FUNC(connect) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /CONNECT []"); COMMAND_ERROR; goto out; @@ -1761,7 +1778,7 @@ SILC_CLIENT_CMD_FUNC(ban) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /BAN " "[+|-[[@[![@hostname>]]]]]"); COMMAND_ERROR; @@ -1770,7 +1787,8 @@ SILC_CLIENT_CMD_FUNC(ban) if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -1781,7 +1799,8 @@ SILC_CLIENT_CMD_FUNC(ban) channel = silc_client_get_channel(cmd->client, conn, name); if (!channel) { - cmd->client->ops->say(cmd->client, conn, "You are on that channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are on that channel"); COMMAND_ERROR; goto out; } @@ -1837,7 +1856,7 @@ SILC_CLIENT_CMD_FUNC(close) } if (cmd->argc < 2) { - cmd->client->ops->say(cmd->client, conn, + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, "Usage: /CLOSE []"); COMMAND_ERROR; goto out; @@ -1909,14 +1928,16 @@ SILC_CLIENT_CMD_FUNC(leave) } if (cmd->argc != 2) { - cmd->client->ops->say(cmd->client, conn, "Usage: /LEAVE "); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /LEAVE "); COMMAND_ERROR; goto out; } if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -1925,15 +1946,10 @@ SILC_CLIENT_CMD_FUNC(leave) name = cmd->argv[1]; } - if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); - COMMAND_ERROR; - goto out; - } - /* Get the Channel ID of the channel */ - if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); + if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) { + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on that channel"); COMMAND_ERROR; goto out; } @@ -1949,21 +1965,14 @@ SILC_CLIENT_CMD_FUNC(leave) silc_buffer_free(buffer); silc_buffer_free(idp); - /* We won't talk anymore on this channel */ - cmd->client->ops->say(cmd->client, conn, "You have left channel %s", name); - - conn->current_channel = NULL; - - silc_idcache_del_by_id(conn->channel_cache, SILC_ID_CHANNEL, channel->id); - silc_free(channel->channel_name); - silc_free(channel->id); - silc_free(channel->key); - silc_cipher_free(channel->channel_key); - silc_free(channel); - /* Notify application */ COMMAND; + if (conn->current_channel == channel) + conn->current_channel = NULL; + + silc_client_del_channel(cmd->client, cmd->conn, channel); + out: silc_client_command_free(cmd); } @@ -1975,9 +1984,7 @@ SILC_CLIENT_CMD_FUNC(users) { SilcClientCommandContext cmd = (SilcClientCommandContext)context; SilcClientConnection conn = cmd->conn; - SilcIDCacheEntry id_cache = NULL; - SilcChannelEntry channel; - SilcBuffer buffer, idp; + SilcBuffer buffer; char *name; if (!cmd->conn) { @@ -1987,14 +1994,16 @@ SILC_CLIENT_CMD_FUNC(users) } if (cmd->argc != 2) { - cmd->client->ops->say(cmd->client, conn, "Usage: /USERS "); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /USERS "); COMMAND_ERROR; goto out; } if (cmd->argv[1][0] == '*') { if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on any channel"); + cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, + "You are not on any channel"); COMMAND_ERROR; goto out; } @@ -2003,49 +2012,104 @@ SILC_CLIENT_CMD_FUNC(users) name = cmd->argv[1]; } - if (!conn->current_channel) { - cmd->client->ops->say(cmd->client, conn, "You are not on that channel"); + /* Send USERS command to the server */ + buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, + ++conn->cmd_ident, 1, + 2, name, strlen(name)); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, + NULL, 0, NULL, NULL, buffer->data, + buffer->len, TRUE); + silc_buffer_free(buffer); + + /* Notify application */ + COMMAND; + + out: + silc_client_command_free(cmd); +} + +/* Command GETKEY. Used to fetch remote client's public key. */ + +SILC_CLIENT_CMD_FUNC(getkey) +{ + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcClient client = cmd->client; + SilcClientEntry client_entry = NULL; + SilcServerEntry server_entry = NULL; + char *nickname = NULL; + SilcBuffer idp, buffer; + + if (!cmd->conn) { + SILC_NOT_CONNECTED(cmd->client, cmd->conn); COMMAND_ERROR; goto out; } - /* Get the Channel ID of the channel */ - if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) { - /* XXX should resolve the channel ID; LIST command */ - cmd->client->ops->say(cmd->client, conn, - "You are not on that channel", name); + if (cmd->argc < 2) { + client->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO, + "Usage: /GETKEY "); COMMAND_ERROR; goto out; } - channel = (SilcChannelEntry)id_cache->context; + /* Parse the typed nickname. */ + if (client->params->nickname_parse) + client->params->nickname_parse(cmd->argv[1], &nickname); + else + nickname = strdup(cmd->argv[1]); - if (!cmd->pending) { - /* Send USERS command to the server */ - idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL); - buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, - ++conn->cmd_ident, 1, - 1, idp->data, idp->len); - silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, - NULL, 0, NULL, NULL, buffer->data, - buffer->len, TRUE); - silc_buffer_free(buffer); - silc_buffer_free(idp); + /* Find client entry */ + client_entry = silc_idlist_get_client(client, conn, nickname, cmd->argv[1], + FALSE); + if (!client_entry) { + /* Check whether user requested server actually */ + server_entry = silc_client_get_server(client, conn, cmd->argv[1]); + + if (!server_entry) { + /* No. what ever user wants we don't have it, so resolve it. We + will try to resolve both client and server, one of them is + bound to be wrong. */ + + /* This will send the IDENTIFY command */ + silc_idlist_get_client(client, conn, nickname, cmd->argv[1], TRUE); + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, + conn->cmd_ident, + silc_client_command_destructor, + silc_client_command_getkey, + silc_client_command_dup(cmd)); + + /* This sends the INFO command to resolve the server. */ + silc_client_send_command(client, conn, SILC_COMMAND_INFO, + ++conn->cmd_ident, 1, + 1, cmd->argv[1], cmd->argv_lens[1]); + silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, + conn->cmd_ident, + silc_client_command_destructor, + silc_client_command_getkey, + silc_client_command_dup(cmd)); + + cmd->pending = 1; + silc_free(nickname); + return; + } - /* Register pending callback which will recall this command callback with - same context and reprocesses the command. When reprocessing we actually - display the information on the screen. */ - silc_client_command_pending(conn, SILC_COMMAND_USERS, conn->cmd_ident, - silc_client_command_destructor, - silc_client_command_users, - silc_client_command_dup(cmd)); - cmd->pending = TRUE; - return; + idp = silc_id_payload_encode(server_entry->server_id, SILC_ID_SERVER); + } else { + idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT); } + buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY, 0, 1, + 1, idp->data, idp->len); + silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, + 0, NULL, NULL, buffer->data, buffer->len, TRUE); + silc_buffer_free(buffer); + silc_buffer_free(idp); + /* Notify application */ COMMAND; out: + silc_free(nickname); silc_client_command_free(cmd); }