+
+/* Register all default commands provided by the client library for the
+ application. */
+
+void silc_client_commands_register(SilcClient client)
+{
+ silc_list_init(client->internal->commands, struct SilcClientCommandStruct,
+ next);
+
+ SILC_CLIENT_CMD(whois, WHOIS, "WHOIS", 5);
+ SILC_CLIENT_CMD(whowas, WHOWAS, "WHOWAS", 3);
+ SILC_CLIENT_CMD(identify, IDENTIFY, "IDENTIFY", 3);
+ SILC_CLIENT_CMD(nick, NICK, "NICK", 2);
+ SILC_CLIENT_CMD(list, LIST, "LIST", 2);
+ SILC_CLIENT_CMD(topic, TOPIC, "TOPIC", 3);
+ SILC_CLIENT_CMD(invite, INVITE, "INVITE", 3);
+ SILC_CLIENT_CMD(quit, QUIT, "QUIT", 2);
+ SILC_CLIENT_CMD(kill, KILL, "KILL", 4);
+ SILC_CLIENT_CMD(info, INFO, "INFO", 2);
+ SILC_CLIENT_CMD(stats, STATS, "STATS", 0);
+ SILC_CLIENT_CMD(ping, PING, "PING", 2);
+ SILC_CLIENT_CMD(oper, OPER, "OPER", 3);
+ SILC_CLIENT_CMD(join, JOIN, "JOIN", 9);
+ SILC_CLIENT_CMD(motd, MOTD, "MOTD", 2);
+ SILC_CLIENT_CMD(umode, UMODE, "UMODE", 2);
+ SILC_CLIENT_CMD(cmode, CMODE, "CMODE", 6);
+ SILC_CLIENT_CMD(cumode, CUMODE, "CUMODE", 9);
+ SILC_CLIENT_CMD(kick, KICK, "KICK", 4);
+ SILC_CLIENT_CMD(ban, BAN, "BAN", 3);
+ SILC_CLIENT_CMD(detach, DETACH, "DETACH", 0);
+ SILC_CLIENT_CMD(watch, WATCH, "WATCH", 3);
+ SILC_CLIENT_CMD(silcoper, SILCOPER, "SILCOPER", 3);
+ SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", 2);
+ SILC_CLIENT_CMD(users, USERS, "USERS", 2);
+ SILC_CLIENT_CMD(getkey, GETKEY, "GETKEY", 2);
+ SILC_CLIENT_CMD(service, SERVICE, "SERVICE", 10);
+
+ SILC_CLIENT_CMD(connect, PRIV_CONNECT, "CONNECT", 3);
+ SILC_CLIENT_CMD(close, PRIV_CLOSE, "CLOSE", 3);
+ SILC_CLIENT_CMD(shutdown, PRIV_SHUTDOWN, "SHUTDOWN", 1);
+}
+
+/* Unregister all commands. */
+
+void silc_client_commands_unregister(SilcClient client)
+{
+ SILC_CLIENT_CMDU(whois, WHOIS, "WHOIS");
+ SILC_CLIENT_CMDU(whowas, WHOWAS, "WHOWAS");
+ SILC_CLIENT_CMDU(identify, IDENTIFY, "IDENTIFY");
+ SILC_CLIENT_CMDU(nick, NICK, "NICK");
+ SILC_CLIENT_CMDU(list, LIST, "LIST");
+ SILC_CLIENT_CMDU(topic, TOPIC, "TOPIC");
+ SILC_CLIENT_CMDU(invite, INVITE, "INVITE");
+ SILC_CLIENT_CMDU(quit, QUIT, "QUIT");
+ SILC_CLIENT_CMDU(kill, KILL, "KILL");
+ SILC_CLIENT_CMDU(info, INFO, "INFO");
+ SILC_CLIENT_CMDU(stats, STATS, "STATS");
+ SILC_CLIENT_CMDU(ping, PING, "PING");
+ SILC_CLIENT_CMDU(oper, OPER, "OPER");
+ SILC_CLIENT_CMDU(join, JOIN, "JOIN");
+ SILC_CLIENT_CMDU(motd, MOTD, "MOTD");
+ SILC_CLIENT_CMDU(umode, UMODE, "UMODE");
+ SILC_CLIENT_CMDU(cmode, CMODE, "CMODE");
+ SILC_CLIENT_CMDU(cumode, CUMODE, "CUMODE");
+ SILC_CLIENT_CMDU(kick, KICK, "KICK");
+ SILC_CLIENT_CMDU(ban, BAN, "BAN");
+ SILC_CLIENT_CMDU(detach, DETACH, "DETACH");
+ SILC_CLIENT_CMDU(watch, WATCH, "WATCH");
+ SILC_CLIENT_CMDU(silcoper, SILCOPER, "SILCOPER");
+ SILC_CLIENT_CMDU(leave, LEAVE, "LEAVE");
+ SILC_CLIENT_CMDU(users, USERS, "USERS");
+ SILC_CLIENT_CMDU(getkey, GETKEY, "GETKEY");
+ SILC_CLIENT_CMDU(service, SERVICE, "SERVICE");
+
+ SILC_CLIENT_CMDU(connect, PRIV_CONNECT, "CONNECT");
+ SILC_CLIENT_CMDU(close, PRIV_CLOSE, "CLOSE");
+ SILC_CLIENT_CMDU(shutdown, PRIV_SHUTDOWN, "SHUTDOWN");
+}
+
+/**** Client side incoming command handling **********************************/
+
+void silc_client_command_process_whois(SilcClient client,
+ SilcSocketConnection sock,
+ SilcCommandPayload payload,
+ SilcArgumentPayload args);
+
+/* Client is able to receive some command packets even though they are
+ special case. Server may send WHOIS command to the client to retrieve
+ Requested Attributes information for WHOIS query the server is
+ processing. This function currently handles only the WHOIS command,
+ but if in the future for commands may arrive then this can be made
+ to support other commands too. */
+
+void silc_client_command_process(SilcClient client,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcCommandPayload payload;
+ SilcCommand command;
+ SilcArgumentPayload args;
+
+ /* Get command payload from packet */
+ payload = silc_command_payload_parse(packet->buffer->data,
+ packet->buffer->len);
+ if (!payload) {
+ /* Silently ignore bad reply packet */
+ SILC_LOG_DEBUG(("Bad command packet"));
+ return;
+ }
+
+ /* Get arguments */
+ args = silc_command_get_args(payload);
+
+ /* Get the command */
+ command = silc_command_get(payload);
+ switch (command) {
+
+ case SILC_COMMAND_WHOIS:
+ /* Ignore everything if requested by application */
+ if (client->internal->params->ignore_requested_attributes)
+ break;
+
+ silc_client_command_process_whois(client, sock, payload, args);
+ break;
+
+ default:
+ break;
+ }
+
+ silc_command_payload_free(payload);
+}
+
+void silc_client_command_process_whois(SilcClient client,
+ SilcSocketConnection sock,
+ SilcCommandPayload payload,
+ SilcArgumentPayload args)
+{
+ SilcDList attrs;
+ unsigned char *tmp;
+ SilcUInt32 tmp_len;
+ SilcBuffer buffer, packet;
+
+ SILC_LOG_DEBUG(("Received WHOIS command"));
+
+ /* Try to take the Requested Attributes */
+ tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (!tmp)
+ return;
+
+ attrs = silc_attribute_payload_parse(tmp, tmp_len);
+ if (!attrs)
+ return;
+
+ /* Process requested attributes */
+ buffer = silc_client_attributes_process(client, sock, attrs);
+ if (!buffer) {
+ silc_attribute_payload_list_free(attrs);
+ return;
+ }
+
+ /* Send the attributes back */
+ 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);
+ silc_buffer_free(packet);
+ silc_buffer_free(buffer);
+}