updates.
[silc.git] / lib / silcclient / command.c
index ffa55d5c744dce2481e7d41348d4c6268bcb1dc0..ee12b1ea27fe48ede6136042b0603ae49cf9006e 100644 (file)
@@ -195,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);
   }
 }
@@ -365,6 +367,12 @@ SILC_CLIENT_CMD_FUNC(nick)
     goto out;
   }
 
+  if (cmd->argc < 2) {
+    cmd->client->ops->say(cmd->client, conn, "Usage: /NICK <nickname>");
+    COMMAND_ERROR;
+    goto out;
+  }
+
   if (!strcmp(conn->nickname, cmd->argv[1]))
     goto out;
 
@@ -428,7 +436,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);
     }
@@ -498,7 +506,7 @@ SILC_CLIENT_CMD_FUNC(topic)
   }
 
   /* 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)) {
     cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
     COMMAND_ERROR;
     goto out;
@@ -509,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);
@@ -610,10 +619,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++;
@@ -788,6 +793,20 @@ SILC_CLIENT_CMD_FUNC(kill)
   silc_buffer_free(buffer);
   silc_buffer_free(idp);
 
+  /* Remove the client entry from the local cache. */
+  silc_idcache_del_by_context(conn->client_cache, target);
+  if (target->nickname)
+    silc_free(target->nickname);
+  if (target->server)
+    silc_free(target->server);
+  if (target->id)
+    silc_free(target->id);
+  if (target->send_key)
+    silc_cipher_free(target->send_key);
+  if (target->receive_key)
+    silc_cipher_free(target->receive_key);
+  silc_free(target);
+
   /* Notify application */
   COMMAND;
 
@@ -862,7 +881,8 @@ SILC_CLIENT_CMD_FUNC(ping)
   /* 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);
@@ -927,12 +947,12 @@ SILC_CLIENT_CMD_FUNC(join)
   }
 
   /* See if we have joined to the requested channel already */
-  if (silc_idcache_find_by_data_one(conn->channel_cache, cmd->argv[1],
+  if (silc_idcache_find_by_name_one(conn->channel_cache, cmd->argv[1],
                                    &id_cache)) {
+#if 0
     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
@@ -1205,6 +1225,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, 
+              "Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
+         COMMAND_ERROR;
+         goto out;
+       }
        ll = atoi(cmd->argv[3]);
        SILC_PUT32_MSB(ll, tmp);
        arg = tmp;
@@ -1217,6 +1243,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, 
+              "Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
+         COMMAND_ERROR;
+         goto out;
+       }
        arg = cmd->argv[3];
        arg_len = cmd->argv_lens[3];
       } else {
@@ -1227,6 +1259,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, 
+              "Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
+         COMMAND_ERROR;
+         goto out;
+       }
        arg = cmd->argv[3];
        arg_len = cmd->argv_lens[3];
       } else {
@@ -1237,6 +1275,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, 
+              "Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
+         COMMAND_ERROR;
+         goto out;
+       }
        arg = cmd->argv[3];
        arg_len = cmd->argv_lens[3];
       } else {
@@ -1248,6 +1292,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, 
+              "Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
+         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,
@@ -1272,11 +1323,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);
 
@@ -1519,7 +1565,7 @@ SILC_CLIENT_CMD_FUNC(kick)
   }
 
   /* 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)) {
     cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
     COMMAND_ERROR;
     goto out;
@@ -1574,15 +1620,44 @@ SILC_CLIENT_CMD_FUNC(kick)
   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) {
+    /* Pulic key auth XXX TODO */
+    auth = NULL;
+  } else {
+    /* Encode the 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;
+  uint32 auth_data_len = 0;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -1604,19 +1679,41 @@ SILC_CLIENT_CMD_FUNC(oper)
     goto out;
   } else {
     /* 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(auth_data, auth_data_len, context);
 
+  memset(auth_data, 0, auth_data_len);
+  silc_free(auth_data);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
+
+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) {
+    /* Pulic key auth XXX TODO */
+    auth = NULL;
+  } else {
     /* Encode the 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);
@@ -1625,14 +1722,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. */
@@ -1641,9 +1733,8 @@ SILC_CLIENT_CMD_FUNC(silcoper)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer;
   unsigned char *auth_data;
-  SilcBuffer auth;
+  uint32 auth_data_len = 0;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -1665,28 +1756,15 @@ SILC_CLIENT_CMD_FUNC(silcoper)
     goto out;
   } else {
     /* 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_client_command_silcoper_send(auth_data, auth_data_len, context);
 
-  silc_buffer_free(buffer);
-  silc_buffer_free(auth);
-  memset(auth_data, 0, strlen(auth_data));
+  memset(auth_data, 0, auth_data_len);
   silc_free(auth_data);
 
   /* Notify application */
@@ -1933,7 +2011,7 @@ SILC_CLIENT_CMD_FUNC(leave)
   }
 
   /* 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)) {
     cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
     COMMAND_ERROR;
     goto out;
@@ -1950,21 +2028,18 @@ 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);
+  /* Notify application */
+  COMMAND;
 
   conn->current_channel = NULL;
 
-  silc_idcache_del_by_id(conn->channel_cache, SILC_ID_CHANNEL, channel->id);
+  silc_idcache_del_by_id(conn->channel_cache, 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;
-
  out:
   silc_client_command_free(cmd);
 }
@@ -2011,7 +2086,7 @@ SILC_CLIENT_CMD_FUNC(users)
   }
 
   /* 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)) {
     /* XXX should resolve the channel ID; LIST command */
     cmd->client->ops->say(cmd->client, conn, 
                          "You are not on that channel", name);