updates.
[silc.git] / lib / silcclient / command.c
index 48a0fa56231cd50841b5b8f375d6fd1d5731c718..f04e4510aaff84f3c8d490c76b0bb5cbe4bf70df 100644 (file)
@@ -324,7 +324,7 @@ SILC_CLIENT_CMD_FUNC(nick_change)
     (SilcClientCommandReplyContext)context2;
   SilcCommandStatus status;
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
+  silc_command_get_status(reply->payload, &status, NULL);
   if (status == SILC_STATUS_OK) {
     /* Set the nickname */
     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
@@ -664,7 +664,7 @@ SILC_TASK_CALLBACK(silc_client_command_quit_cb)
 
   /* Close connection */
   q->client->internal->ops->disconnect(q->client, q->conn);
-  silc_client_close_connection(q->client, NULL, q->conn->sock->user_data);
+  silc_client_close_connection(q->client, q->conn->sock->user_data);
 
   silc_free(q);
 }
@@ -751,7 +751,7 @@ SILC_CLIENT_CMD_FUNC(kill_remove)
     (SilcClientCommandReplyContext)context2;
   SilcCommandStatus status;
 
-  SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
+  silc_command_get_status(reply->payload, &status, NULL);
   if (status == SILC_STATUS_OK) {
     /* Remove with timeout */
     silc_schedule_task_add(cmd->client->schedule, cmd->conn->sock->sock,
@@ -950,8 +950,8 @@ SILC_CLIENT_CMD_FUNC(join)
   SilcClientConnection conn = cmd->conn;
   SilcChannelEntry channel;
   SilcBuffer buffer, idp, auth = NULL;
-  char *name, *passphrase = NULL, *cipher = NULL, *hmac = NULL;
-  int i;
+  char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
+  int i, passphrase_len = 0;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -997,7 +997,18 @@ SILC_CLIENT_CMD_FUNC(join)
       }
       i++;
     } else {
-      passphrase = cmd->argv[i];
+      /* Passphrases must be UTF-8 encoded, so encode if it is not */
+      if (!silc_utf8_valid(cmd->argv[i], cmd->argv_lens[i])) {
+       passphrase_len = silc_utf8_encoded_len(cmd->argv[i], 
+                                              cmd->argv_lens[i], 0);
+       pu8 = silc_calloc(passphrase_len, sizeof(*pu8));
+       passphrase_len = silc_utf8_encode(cmd->argv[i], cmd->argv_lens[i],
+                                         0, pu8, passphrase_len);
+       passphrase = pu8;
+      } else {
+       passphrase = strdup(cmd->argv[i]);
+       passphrase_len = cmd->argv_lens[i];
+      }
     }
   }
 
@@ -1006,8 +1017,7 @@ SILC_CLIENT_CMD_FUNC(join)
     silc_command_payload_encode_va(SILC_COMMAND_JOIN, 0, 6,
                                   1, name, strlen(name),
                                   2, idp->data, idp->len,
-                                  3, passphrase, 
-                                  passphrase ? strlen(passphrase) : 0,
+                                  3, passphrase, passphrase_len,
                                   4, cipher, cipher ? strlen(cipher) : 0,
                                   5, hmac, hmac ? strlen(hmac) : 0,
                                   6, auth ? auth->data : NULL,
@@ -1018,6 +1028,7 @@ SILC_CLIENT_CMD_FUNC(join)
   silc_buffer_free(idp);
   if (auth)
     silc_buffer_free(auth);
+  silc_free(passphrase);
 
   /* Notify application */
   COMMAND;
@@ -1132,6 +1143,42 @@ SILC_CLIENT_CMD_FUNC(umode)
       else
        mode &= ~SILC_UMODE_GONE;
       break;
+    case 'i':
+      if (add)
+       mode |= SILC_UMODE_INDISPOSED;
+      else
+       mode &= ~SILC_UMODE_INDISPOSED;
+      break;
+    case 'b':
+      if (add)
+       mode |= SILC_UMODE_BUSY;
+      else
+       mode &= ~SILC_UMODE_BUSY;
+      break;
+    case 'p':
+      if (add)
+       mode |= SILC_UMODE_PAGE;
+      else
+       mode &= ~SILC_UMODE_PAGE;
+      break;
+    case 'h':
+      if (add)
+       mode |= SILC_UMODE_HYPER;
+      else
+       mode &= ~SILC_UMODE_HYPER;
+      break;
+    case 't':
+      if (add)
+       mode |= SILC_UMODE_ROBOT;
+      else
+       mode &= ~SILC_UMODE_ROBOT;
+      break;
+    case 'P':
+      if (add)
+       mode |= SILC_UMODE_BLOCK_PRIVMSG;
+      else
+       mode &= ~SILC_UMODE_BLOCK_PRIVMSG;
+      break;
     default:
       COMMAND_ERROR;
       goto out;
@@ -1254,6 +1301,18 @@ SILC_CLIENT_CMD_FUNC(cmode)
       else
        mode &= ~SILC_CHANNEL_MODE_TOPIC;
       break;
+    case 'm':
+      if (add)
+       mode |= SILC_CHANNEL_MODE_SILENCE_USERS;
+      else
+       mode &= ~SILC_CHANNEL_MODE_SILENCE_USERS;
+      break;
+    case 'M':
+      if (add)
+       mode |= SILC_CHANNEL_MODE_SILENCE_OPERS;
+      else
+       mode &= ~SILC_CHANNEL_MODE_SILENCE_OPERS;
+      break;
     case 'l':
       if (add) {
        int ll;
@@ -1485,6 +1544,7 @@ SILC_CLIENT_CMD_FUNC(cumode)
       if (add) {
        mode |= SILC_CHANNEL_UMODE_CHANFO;
        mode |= SILC_CHANNEL_UMODE_CHANOP;
+       mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
       } else {
        mode = SILC_CHANNEL_UMODE_NONE;
       }
@@ -1515,6 +1575,12 @@ SILC_CLIENT_CMD_FUNC(cumode)
       else
        mode &= ~SILC_CHANNEL_UMODE_CHANOP;
       break;
+    case 'b':
+      if (add)
+       mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
+      else
+       mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
+      break;
     default:
       COMMAND_ERROR;
       goto out;
@@ -1720,7 +1786,8 @@ SILC_CLIENT_CMD_FUNC(oper)
 }
 
 static void silc_client_command_silcoper_send(unsigned char *data,
-                                             SilcUInt32 data_len, void *context)
+                                             SilcUInt32 data_len, 
+                                             void *context)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
@@ -1787,54 +1854,6 @@ SILC_CLIENT_CMD_FUNC(silcoper)
   silc_client_command_free(cmd);
 }
 
-/* CONNECT command. Connects the server to another server. */
-
-SILC_CLIENT_CMD_FUNC(connect)
-{
-  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-  SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer;
-  unsigned char port[4];
-  SilcUInt32 tmp;
-
-  if (!cmd->conn) {
-    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc < 2) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-       "Usage: /CONNECT <server> [<port>]");
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc == 3) {
-    tmp = atoi(cmd->argv[2]);
-    SILC_PUT32_MSB(tmp, port);
-  }
-
-  if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CONNECT, 0, 2, 
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]),
-                                           2, port, 4);
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CONNECT, 0, 1,
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]));
-  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 BAN. This is used to manage the ban list of the channel. */
 
 SILC_CLIENT_CMD_FUNC(ban)
@@ -1894,14 +1913,10 @@ SILC_CLIENT_CMD_FUNC(ban)
   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
 
   /* Send the command */
-  if (ban)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 2, 
-                                           1, chidp->data, chidp->len,
-                                           type, ban, strlen(ban));
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 1, 
-                                           1, chidp->data, chidp->len);
-
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 
+                                         ++conn->cmd_ident, 2,
+                                         1, chidp->data, chidp->len,
+                                         type, ban, ban ? strlen(ban) : 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);
@@ -1914,15 +1929,13 @@ SILC_CLIENT_CMD_FUNC(ban)
   silc_client_command_free(cmd);
 }
 
-/* CLOSE command. Close server connection to the remote server */
-SILC_CLIENT_CMD_FUNC(close)
+/* Command DETACH. This is used to detach from the server */
+
+SILC_CLIENT_CMD_FUNC(detach)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
   SilcBuffer buffer;
-  unsigned char port[4];
-  SilcUInt32 tmp;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -1930,28 +1943,9 @@ SILC_CLIENT_CMD_FUNC(close)
     goto out;
   }
 
-  if (cmd->argc < 2) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-       "Usage: /CLOSE <server> [<port>]");
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc == 3) {
-    tmp = atoi(cmd->argv[2]);
-    SILC_PUT32_MSB(tmp, port);
-  }
-
-  if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CLOSE, 0, 2, 
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]),
-                                           2, port, 4);
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CLOSE, 0, 1,
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]));
-  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_DETACH,
+                                         ++conn->cmd_ident, 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);
 
@@ -1961,29 +1955,6 @@ SILC_CLIENT_CMD_FUNC(close)
  out:
   silc_client_command_free(cmd);
 }
-/* SHUTDOWN command. Shutdowns the server. */
-
-SILC_CLIENT_CMD_FUNC(shutdown)
-{
-  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-
-  if (!cmd->conn) {
-    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  /* Send the command */
-  silc_client_command_send(cmd->client, cmd->conn, 
-                          SILC_COMMAND_SHUTDOWN, 0, 0);
-
-  /* Notify application */
-  COMMAND;
-
- out:
-  silc_client_command_free(cmd);
-}
 
 /* LEAVE command. Leaves a channel. Client removes itself from a channel. */
 
@@ -2167,12 +2138,11 @@ SILC_CLIENT_CMD_FUNC(getkey)
       } else {
        SilcClientCommandReplyContext reply = 
          (SilcClientCommandReplyContext)context2;
-       SilcCommandStatus status;
-       unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
-       SILC_GET16_MSB(status, tmp);
-       
+       SilcCommandStatus error;
+
        /* If nickname was not found, then resolve the server. */
-       if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       silc_command_get_status(reply->payload, NULL, &error);
+       if (error == SILC_STATUS_ERR_NO_SUCH_NICK) {
          /* This sends the IDENTIFY command to resolve the server. */
          silc_client_command_register(client, SILC_COMMAND_IDENTIFY, 
                                       NULL, NULL,
@@ -2190,11 +2160,11 @@ SILC_CLIENT_CMD_FUNC(getkey)
 
        /* If server was not found, then we've resolved both nickname and
           server and did not find anybody. */
-       if (status == SILC_STATUS_ERR_NO_SUCH_SERVER) {
+       if (error == SILC_STATUS_ERR_NO_SUCH_SERVER) {
          SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s", 
             silc_client_command_status_message(SILC_STATUS_ERR_NO_SUCH_NICK));
          SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s", 
-           silc_client_command_status_message(status));
+           silc_client_command_status_message(error));
          COMMAND_ERROR;
          goto out;
        }
@@ -2286,6 +2256,129 @@ bool silc_client_command_unregister(SilcClient client,
   return FALSE;
 }
 
+/* Private range commands, specific to this implementation (and compatible
+   with SILC Server). */
+
+/* CONNECT command. Connects the server to another server. */
+
+SILC_CLIENT_CMD_FUNC(connect)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer;
+  unsigned char port[4];
+  SilcUInt32 tmp;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
+       "Usage: /CONNECT <server> [<port>]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc == 3) {
+    tmp = atoi(cmd->argv[2]);
+    SILC_PUT32_MSB(tmp, port);
+  }
+
+  if (cmd->argc == 3)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 2, 
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]),
+                                           2, port, 4);
+  else
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 1,
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]));
+  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);
+}
+
+
+/* CLOSE command. Close server connection to the remote server */
+SILC_CLIENT_CMD_FUNC(close)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer;
+  unsigned char port[4];
+  SilcUInt32 tmp;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
+       "Usage: /CLOSE <server> [<port>]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc == 3) {
+    tmp = atoi(cmd->argv[2]);
+    SILC_PUT32_MSB(tmp, port);
+  }
+
+  if (cmd->argc == 3)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 2, 
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]),
+                                           2, port, 4);
+  else
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 1,
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]));
+  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);
+}
+/* SHUTDOWN command. Shutdowns the server. */
+
+SILC_CLIENT_CMD_FUNC(shutdown)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  /* Send the command */
+  silc_client_command_send(cmd->client, cmd->conn, 
+                          SILC_COMMAND_PRIV_SHUTDOWN, 0, 0);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
+
 /* Register all default commands provided by the client library for the
    application. */
 
@@ -2304,7 +2397,6 @@ void silc_client_commands_register(SilcClient client)
   SILC_CLIENT_CMD(quit, QUIT, "QUIT", 2);
   SILC_CLIENT_CMD(kill, KILL, "KILL", 3);
   SILC_CLIENT_CMD(info, INFO, "INFO", 2);
-  SILC_CLIENT_CMD(connect, CONNECT, "CONNECT", 3);
   SILC_CLIENT_CMD(ping, PING, "PING", 2);
   SILC_CLIENT_CMD(oper, OPER, "OPER", 3);
   SILC_CLIENT_CMD(join, JOIN, "JOIN", 9);
@@ -2314,12 +2406,15 @@ void silc_client_commands_register(SilcClient client)
   SILC_CLIENT_CMD(cumode, CUMODE, "CUMODE", 5);
   SILC_CLIENT_CMD(kick, KICK, "KICK", 4);
   SILC_CLIENT_CMD(ban, BAN, "BAN", 3);
-  SILC_CLIENT_CMD(close, CLOSE, "CLOSE", 3);
-  SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN", 1);
+  SILC_CLIENT_CMD(detach, DETACH, "DETACH", 0);
   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(connect, PRIV_CONNECT, "CONNECT", 3);
+  SILC_CLIENT_CMD(close, PRIV_CLOSE, "CLOSE", 3);
+  SILC_CLIENT_CMD(shutdown, PRIV_SHUTDOWN, "SHUTDOWN", 1);
 }
 
 /* Unregister all commands. */
@@ -2336,7 +2431,6 @@ void silc_client_commands_unregister(SilcClient client)
   SILC_CLIENT_CMDU(quit, QUIT, "QUIT");
   SILC_CLIENT_CMDU(kill, KILL, "KILL");
   SILC_CLIENT_CMDU(info, INFO, "INFO");
-  SILC_CLIENT_CMDU(connect, CONNECT, "CONNECT");
   SILC_CLIENT_CMDU(ping, PING, "PING");
   SILC_CLIENT_CMDU(oper, OPER, "OPER");
   SILC_CLIENT_CMDU(join, JOIN, "JOIN");
@@ -2346,10 +2440,13 @@ void silc_client_commands_unregister(SilcClient client)
   SILC_CLIENT_CMDU(cumode, CUMODE, "CUMODE");
   SILC_CLIENT_CMDU(kick, KICK, "KICK");
   SILC_CLIENT_CMDU(ban, BAN, "BAN");
-  SILC_CLIENT_CMDU(close, CLOSE, "CLOSE");
-  SILC_CLIENT_CMDU(shutdown, SHUTDOWN, "SHUTDOWN");
+  SILC_CLIENT_CMDU(detach, DETACH, "DETACH");
   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(connect, PRIV_CONNECT, "CONNECT");
+  SILC_CLIENT_CMDU(close, PRIV_CLOSE, "CLOSE");
+  SILC_CLIENT_CMDU(shutdown, PRIV_SHUTDOWN, "SHUTDOWN");
 }