Support for SILC 1.2 INVITE and BAN commands. Client supports
[silc.git] / lib / silcclient / command.c
index 66e51786d1fce744d30d5e97cb74cb58d01046a3..ed94414ddf2e3a23b273f6aab8ffae69e3c7ec41 100644 (file)
@@ -132,7 +132,7 @@ bool silc_client_command_call(SilcClient client,
       argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
       argv[argc] = silc_memdup(arg, strlen(arg));
       argv_lens[argc] = strlen(arg);
-      argv_types[argc] = argc + 1;
+      argv_types[argc] = argc;
       argc++;
       arg = va_arg(va, char *);
     }
@@ -258,6 +258,7 @@ void silc_client_command_free(SilcClientCommandContext ctx)
 
     for (i = 0; i < ctx->argc; i++)
       silc_free(ctx->argv[i]);
+    silc_free(ctx->argv);
     silc_free(ctx->argv_lens);
     silc_free(ctx->argv_types);
     silc_free(ctx);
@@ -623,10 +624,10 @@ SILC_CLIENT_CMD_FUNC(invite)
   SilcClientConnection conn = cmd->conn;
   SilcClientEntry client_entry = NULL;
   SilcChannelEntry channel;
-  SilcBuffer buffer, clidp, chidp;
-  SilcUInt32 type = 0;
+  SilcBuffer buffer, clidp, chidp, args = NULL;
   char *nickname = NULL, *name;
   char *invite = NULL;
+  unsigned char action[1];
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -689,35 +690,48 @@ SILC_CLIENT_CMD_FUNC(invite)
       invite = cmd->argv[2];
       invite++;
       if (cmd->argv[2][0] == '+')
-       type = 3;
+       action[0] = 0x00;
       else
-       type = 4;
+       action[0] = 0x01;
     }
   }
 
+  if (invite) {
+    args = silc_buffer_alloc_size(2);
+    silc_buffer_format(args,
+                      SILC_STR_UI_SHORT(1),
+                      SILC_STR_END);
+    args = silc_argument_payload_encode_one(args, invite, strlen(invite), 1);
+  }
+
   /* Send the command */
   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   if (client_entry) {
     clidp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
     buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE, 
-                                           ++conn->cmd_ident, 3,
+                                           ++conn->cmd_ident, 4,
                                            1, chidp->data, chidp->len,
                                            2, clidp->data, clidp->len,
-                                           type, invite, invite ?
-                                           strlen(invite) : 0);
+                                           3, args ? action : NULL,
+                                           args ? 1 : 0,
+                                           4, args ? args->data : NULL,
+                                           args ? args->len : 0);
     silc_buffer_free(clidp);
   } else {
     buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE, 
-                                           ++conn->cmd_ident, 2,
+                                           ++conn->cmd_ident, 3,
                                            1, chidp->data, chidp->len,
-                                           type, invite, invite ?
-                                           strlen(invite) : 0);
+                                           3, args ? action : NULL,
+                                           args ? 1 : 0,
+                                           4, args ? args->data : NULL,
+                                           args ? args->len : 0);
   }
 
   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(chidp);
+  silc_buffer_free(args),
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -845,9 +859,9 @@ SILC_CLIENT_CMD_FUNC(kill)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClient client = cmd->client;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer, idp;
+  SilcBuffer buffer, idp, auth = NULL;
   SilcClientEntry target;
-  char *nickname = NULL;
+  char *nickname = NULL, *comment = NULL;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -857,7 +871,7 @@ SILC_CLIENT_CMD_FUNC(kill)
 
   if (cmd->argc < 2) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-       "Usage: /KILL <nickname> [<comment>]");
+       "Usage: /KILL <nickname> [<comment>] [-pubkey]");
     COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
@@ -887,22 +901,35 @@ SILC_CLIENT_CMD_FUNC(kill)
     goto out;
   }
 
+  if (cmd->argc >= 3) {
+    if (strcasecmp(cmd->argv[2], "-pubkey"))
+      comment = cmd->argv[2];
+
+    if (!strcasecmp(cmd->argv[2], "-pubkey") ||
+       (cmd->argc >= 4 && !strcasecmp(cmd->argv[3], "-pubkey"))) {
+      /* Encode the public key authentication payload */
+      auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
+                                               cmd->client->private_key,
+                                               cmd->client->rng,
+                                               client->sha1hash,
+                                               target->id, SILC_ID_CLIENT);
+    }
+  }
+
   /* Send the KILL command to the server */
   idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
-  if (cmd->argc == 2)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 
-                                           ++conn->cmd_ident, 1, 
-                                           1, idp->data, idp->len);
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 
-                                           ++conn->cmd_ident, 2, 
-                                           1, idp->data, idp->len,
-                                           2, cmd->argv[2], 
-                                           strlen(cmd->argv[2]));
+  buffer =
+    silc_command_payload_encode_va(SILC_COMMAND_KILL, 
+                                  ++conn->cmd_ident, 3, 
+                                  1, idp->data, idp->len,
+                                  2, comment, comment ? strlen(comment) : 0,
+                                  3, auth ? auth->data : NULL,
+                                  auth ? auth->len : 0);
   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);
+  silc_buffer_free(auth);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -996,7 +1023,7 @@ SILC_CLIENT_CMD_FUNC(ping)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer;
+  SilcBuffer buffer, idp;
   void *id;
   int i;
 
@@ -1006,14 +1033,15 @@ SILC_CLIENT_CMD_FUNC(ping)
     goto out;
   }
 
+  idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER); 
+
   /* Send the command */
   buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 0, 1, 
-                                         1, conn->remote_id_data, 
-                                         silc_id_get_len(conn->remote_id,
-                                                         SILC_ID_SERVER));
+                                         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);
 
   id = silc_id_str2id(conn->remote_id_data, conn->remote_id_data_len,
                      SILC_ID_SERVER);
@@ -1530,13 +1558,13 @@ SILC_CLIENT_CMD_FUNC(cmode)
      that requires an argument. */
   if (type && arg) {
     buffer = 
-      silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 3, 
+      silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 3,
                                     1, chidp->data, chidp->len, 
                                     2, modebuf, sizeof(modebuf),
                                     type, arg, arg_len);
   } else {
     buffer = 
-      silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 2, 
+      silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 2,
                                     1, chidp->data, chidp->len, 
                                     2, modebuf, sizeof(modebuf));
   }
@@ -1975,9 +2003,9 @@ SILC_CLIENT_CMD_FUNC(ban)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
   SilcChannelEntry channel;
-  SilcBuffer buffer, chidp;
-  int type = 0;
+  SilcBuffer buffer, chidp, args = NULL;
   char *name, *ban = NULL;
+  unsigned char action[1];
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -2012,25 +2040,37 @@ SILC_CLIENT_CMD_FUNC(ban)
 
   if (cmd->argc == 3) {
     if (cmd->argv[2][0] == '+')
-      type = 2;
+      action[0] = 0x00;
     else
-      type = 3;
+      action[0] = 0x01;
 
     ban = cmd->argv[2];
     ban++;
   }
 
+  if (ban) {
+    args = silc_buffer_alloc_size(2);
+    silc_buffer_format(args,
+                      SILC_STR_UI_SHORT(1),
+                      SILC_STR_END);
+    args = silc_argument_payload_encode_one(args, ban, strlen(ban), 1);
+  }
+
   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
 
   /* Send the command */
   buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 
-                                         ++conn->cmd_ident, 2,
+                                         ++conn->cmd_ident, 3,
                                          1, chidp->data, chidp->len,
-                                         type, ban, ban ? strlen(ban) : 0);
+                                         2, args ? action : NULL,
+                                         args ? 1 : 0,
+                                         3, args ? args->data : NULL,
+                                         args ? args->len : 0);
   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(chidp);
+  silc_buffer_free(args);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2548,7 +2588,7 @@ void silc_client_commands_register(SilcClient client)
   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", 3);
+  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);