Merged silc_1_1_branch to trunk.
[silc.git] / lib / silcclient / command.c
index a5ba076ec23cb79c7132c29ef04ed93576303cfa..85e33fe38217f0fe7b17c6c70a97270b1d3e2aca 100644 (file)
@@ -123,6 +123,32 @@ static void silc_client_command_resolve_continue(SilcClient client,
   SILC_FSM_CALL_CONTINUE(&cmd->thread);
 }
 
+/* Dummy command callback.  Nothing interesting to do here.  Use this when
+   you just send command but don't care about reply. */
+
+SilcBool silc_client_command_called_dummy(SilcClient client,
+                                         SilcClientConnection conn,
+                                         SilcCommand command,
+                                         SilcStatus status,
+                                         SilcStatus error,
+                                         void *context,
+                                         va_list ap)
+{
+  return FALSE;
+}
+
+/* Dummy resolving callback.  Nothing interesting to do here.  Use this
+   when you just resolve entires but don't care about reply. */
+
+void silc_client_command_resolve_dummy(SilcClient client,
+                                      SilcClientConnection conn,
+                                      SilcStatus status,
+                                      SilcDList clients,
+                                      void *context)
+{
+  /* Nothing */
+}
+
 /* Register command to client */
 
 static SilcBool
@@ -610,6 +636,7 @@ SILC_FSM_STATE(silc_client_command_whois)
   unsigned char count[4], *tmp = NULL;
   SilcBool details = FALSE, nick = FALSE;
   unsigned char *pubkey = NULL;
+  char *nickname = NULL;
   int i;
 
   /* Given without arguments fetches client's own information */
@@ -700,14 +727,22 @@ SILC_FSM_STATE(silc_client_command_whois)
                                           SILC_ATTRIBUTE_USER_PUBLIC_KEY,
                                           SILC_ATTRIBUTE_FLAG_VALID,
                                           &obj, sizeof(obj));
+    silc_free(obj.data);
+  }
+
+  if (nick) {
+    silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname);
+    if (!nickname)
+      nickname = strdup(cmd->argv[1]);
   }
 
   /* Send command */
   silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL,
-                             3, 1, nick ? cmd->argv[1] : NULL,
-                             nick ? cmd->argv_lens[1] : 0,
+                             3, 1, nick ? nickname : NULL,
+                             nick ? strlen(nickname) : 0,
                              2, tmp ? tmp : NULL, tmp ? 4 : 0,
                              3, silc_buffer_datalen(attrs));
+  silc_free(nickname);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -903,7 +938,7 @@ SILC_FSM_STATE(silc_client_command_topic)
   SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer idp;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc < 2 || cmd->argc > 3) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -918,7 +953,15 @@ SILC_FSM_STATE(silc_client_command_topic)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -1011,13 +1054,12 @@ SILC_FSM_STATE(silc_client_command_invite)
       silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname);
 
       /* Find client entry */
-      clients = silc_client_get_clients_local(client, conn, nickname,
-                                             cmd->argv[2]);
+      clients = silc_client_get_clients_local(client, conn, cmd->argv[2],
+                                             FALSE);
       if (!clients)
        /* Resolve client information */
        SILC_FSM_CALL(silc_client_get_clients(
-                                     client, conn, nickname,
-                                     cmd->argv[2],
+                                     client, conn, nickname, NULL,
                                      silc_client_command_resolve_continue,
                                      cmd));
 
@@ -1159,12 +1201,10 @@ SILC_FSM_STATE(silc_client_command_kill)
     return SILC_FSM_FINISH;
 
   /* Get the target client */
-  clients = silc_client_get_clients_local(client, conn, nickname,
-                                         cmd->argv[1]);
+  clients = silc_client_get_clients_local(client, conn, cmd->argv[1], FALSE);
   if (!clients)
     /* Resolve client information */
-    SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname,
-                                         cmd->argv[1],
+    SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, NULL,
                                          silc_client_command_resolve_continue,
                                          cmd));
 
@@ -1804,10 +1844,14 @@ SILC_FSM_STATE(silc_client_command_cmode)
                                      NULL, NULL, 1,
                                      1, silc_buffer_datalen(chidp));
          silc_buffer_free(chidp);
+         silc_client_unref_channel(client, conn, channel);
 
          /* Notify application */
          COMMAND(SILC_STATUS_OK);
-         goto out;
+
+         /** Wait for command reply */
+         silc_fsm_next(fsm, silc_client_command_reply_wait);
+         return SILC_FSM_CONTINUE;
        }
 
        if (cmd->argc >= 4) {
@@ -1935,11 +1979,10 @@ SILC_FSM_STATE(silc_client_command_cumode)
   silc_client_nickname_parse(client, conn, cmd->argv[3], &nickname);
 
   /* Find client entry */
-  clients = silc_client_get_clients_local(client, conn, nickname,
-                                         cmd->argv[3]);
+  clients = silc_client_get_clients_local(client, conn, cmd->argv[3], FALSE);
   if (!clients)
     /* Resolve client information */
-    SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, cmd->argv[3],
+    SILC_FSM_CALL(silc_client_get_clients(client, conn, nickname, NULL,
                                          silc_client_command_resolve_continue,
                                          cmd));
 
@@ -2084,8 +2127,7 @@ SILC_FSM_STATE(silc_client_command_kick)
   SilcBuffer idp, idp2;
   SilcClientEntry target;
   SilcDList clients = NULL;
-  char *name;
-  char *nickname = NULL;
+  char *name, tmp[512];
 
   if (cmd->argc < 3) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -2099,7 +2141,15 @@ SILC_FSM_STATE(silc_client_command_kick)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -2116,12 +2166,8 @@ SILC_FSM_STATE(silc_client_command_kick)
     goto out;
   }
 
-  /* Parse the typed nickname. */
-  silc_client_nickname_parse(client, conn, cmd->argv[2], &nickname);
-
   /* Get the target client */
-  clients = silc_client_get_clients_local(client, conn, nickname,
-                                         cmd->argv[2]);
+  clients = silc_client_get_clients_local(client, conn, cmd->argv[2], FALSE);
   if (!clients) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
        "No such client: %s", cmd->argv[2]);
@@ -2145,7 +2191,6 @@ SILC_FSM_STATE(silc_client_command_kick)
 
   silc_buffer_free(idp);
   silc_buffer_free(idp2);
-  silc_free(nickname);
   silc_client_list_free(client, conn, clients);
   silc_client_unref_channel(client, conn, channel);
 
@@ -2158,7 +2203,6 @@ SILC_FSM_STATE(silc_client_command_kick)
 
  out:
   silc_client_unref_channel(client, conn, channel);
-  silc_free(nickname);
   return SILC_FSM_FINISH;
 }
 
@@ -2171,7 +2215,7 @@ typedef struct {
 
 /* Ask passphrase callback */
 
-static void silc_client_command_oper_cb(unsigned char *data,
+static void silc_client_command_oper_cb(const unsigned char *data,
                                        SilcUInt32 data_len, void *context)
 {
   SilcClientCommandContext cmd = context;
@@ -2242,6 +2286,8 @@ SILC_FSM_STATE(silc_client_command_oper)
     return SILC_FSM_FINISH;
   }
 
+  silc_fsm_next(fsm, silc_client_command_oper_send);
+
   /* Get passphrase */
   if (cmd->argc < 3) {
     oper = silc_calloc(1, sizeof(*oper));
@@ -2253,7 +2299,6 @@ SILC_FSM_STATE(silc_client_command_oper)
                                      silc_client_command_oper_cb, cmd));
   }
 
-  silc_fsm_next(fsm, silc_client_command_oper_send);
   return SILC_FSM_CONTINUE;
 }
 
@@ -2272,6 +2317,8 @@ SILC_FSM_STATE(silc_client_command_silcoper)
     return SILC_FSM_FINISH;
   }
 
+  silc_fsm_next(fsm, silc_client_command_oper_send);
+
   /* Get passphrase */
   if (cmd->argc < 3) {
     oper = silc_calloc(1, sizeof(*oper));
@@ -2283,7 +2330,6 @@ SILC_FSM_STATE(silc_client_command_silcoper)
                                      silc_client_command_oper_cb, cmd));
   }
 
-  silc_fsm_next(fsm, silc_client_command_oper_send);
   return SILC_FSM_CONTINUE;
 }
 
@@ -2453,6 +2499,12 @@ SILC_FSM_STATE(silc_client_command_watch)
     silc_pkcs_public_key_free(pk);
   }
 
+  /* If watching by nickname, resolve all users with that nickname so that
+     we get their information immediately. */
+  if (type == 2)
+    silc_client_get_clients(conn->client, conn, cmd->argv[2], NULL,
+                           silc_client_command_resolve_dummy, NULL);
+
   /* Send the commmand */
   silc_client_command_send_va(conn, cmd, cmd->cmd, NULL, NULL, 2,
                              1, silc_buffer_datalen(conn->internal->
@@ -2485,7 +2537,7 @@ SILC_FSM_STATE(silc_client_command_leave)
   SilcClient client = conn->client;
   SilcChannelEntry channel;
   SilcBuffer idp;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc != 2) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -2499,7 +2551,15 @@ SILC_FSM_STATE(silc_client_command_leave)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -2544,7 +2604,7 @@ SILC_FSM_STATE(silc_client_command_users)
 {
   SilcClientCommandContext cmd = fsm_context;
   SilcClientConnection conn = cmd->conn;
-  char *name;
+  char *name, tmp[512];
 
   if (cmd->argc != 2) {
     SAY(conn->client, conn, SILC_CLIENT_MESSAGE_INFO,
@@ -2558,7 +2618,15 @@ SILC_FSM_STATE(silc_client_command_users)
       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
-    name = conn->current_channel->channel_name;
+
+    if (conn->client->internal->params->full_channel_names)
+      silc_snprintf(tmp, sizeof(tmp), conn->current_channel->channel_name);
+    else
+      silc_snprintf(tmp, sizeof(tmp), "%s%s%s",
+                   conn->current_channel->channel_name,
+                   conn->current_channel->server[0] ? "@" : "",
+                   conn->current_channel->server);
+    name = tmp;
   } else {
     name = cmd->argv[1];
   }
@@ -2590,7 +2658,6 @@ SILC_FSM_STATE(silc_client_command_getkey)
   SilcClientEntry client_entry;
   SilcServerEntry server_entry;
   SilcDList clients;
-  char *nickname = NULL;
   SilcBuffer idp;
 
   if (cmd->argc < 2) {
@@ -2600,15 +2667,8 @@ SILC_FSM_STATE(silc_client_command_getkey)
     return SILC_FSM_FINISH;
   }
 
-  /* Parse the typed nickname. */
-  if (!silc_client_nickname_parse(client, conn, cmd->argv[1], &nickname)) {
-    COMMAND_ERROR(SILC_STATUS_ERR_RESOURCE_LIMIT);
-    return SILC_FSM_FINISH;
-  }
-
   /* Find client entry */
-  clients = silc_client_get_clients_local(client, conn, nickname,
-                                         cmd->argv[1]);
+  clients = silc_client_get_clients_local(client, conn, cmd->argv[1], FALSE);
   if (!clients) {
     /* Check whether user requested server */
     server_entry = silc_client_get_server(client, conn, cmd->argv[1]);
@@ -2646,7 +2706,6 @@ SILC_FSM_STATE(silc_client_command_getkey)
                              1, silc_buffer_datalen(idp));
 
   silc_buffer_free(idp);
-  silc_free(nickname);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2775,7 +2834,6 @@ static void silc_client_command_process_whois(SilcClient client,
                                              SilcCommandPayload payload,
                                              SilcArgumentPayload args)
 {
-#if 0
   SilcDList attrs;
   unsigned char *tmp;
   SilcUInt32 tmp_len;
@@ -2799,18 +2857,25 @@ static void silc_client_command_process_whois(SilcClient client,
     return;
   }
 
-  /* Send the attributes back */
+  /* Send the attributes back in COMMAND_REPLY packet */
   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);
+                                        1, 11, buffer->data,
+                                        silc_buffer_len(buffer));
+  if (!packet) {
+    silc_buffer_free(buffer);
+    return;
+  }
+
+  SILC_LOG_DEBUG(("Sending back requested WHOIS attributes"));
+
+  silc_packet_send(conn->stream, SILC_PACKET_COMMAND_REPLY, 0,
+                  silc_buffer_datalen(packet));
+
   silc_buffer_free(packet);
   silc_buffer_free(buffer);
-#endif /* 0 */
 }
 
 /* Client is able to receive some command packets even though they are