updates.
[silc.git] / apps / silcd / command.c
index afb9e5394e9f8c6e8e789113d783209bd9951dbe..06e5b96d7717fed78c6d947714f6f5bb70300415 100644 (file)
@@ -29,11 +29,11 @@ static int silc_server_is_registered(SilcServer server,
 static void 
 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
                                      SilcCommand command,
-                                     SilcCommandStatus status);
+                                     SilcStatus status);
 static void 
 silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     SilcCommand command,
-                                    SilcCommandStatus status,
+                                    SilcStatus status,
                                     SilcUInt32 arg_type,
                                     const unsigned char *arg,
                                     SilcUInt32 arg_len);
@@ -389,7 +389,7 @@ silc_server_command_pending_check(SilcServer server,
 static void 
 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
                                      SilcCommand command,
-                                     SilcCommandStatus status)
+                                     SilcStatus status)
 {
   SilcBuffer buffer;
 
@@ -411,7 +411,7 @@ silc_server_command_send_status_reply(SilcServerCommandContext cmd,
 static void 
 silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     SilcCommand command,
-                                    SilcCommandStatus status,
+                                    SilcStatus status,
                                     SilcUInt32 arg_type,
                                     const unsigned char *arg,
                                     SilcUInt32 arg_len)
@@ -533,10 +533,11 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
 
   /* Get the max count of reply messages allowed */
   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
-  if (tmp)
-    *count = atoi(tmp);
-  else
+  if (tmp) {
+    SILC_GET32_MSB(*count, tmp);
+  } else {
     *count = 0;
+  }
 
   return TRUE;
 }
@@ -701,9 +702,9 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
   SilcServer server = cmd->server;
   char *tmp;
   int i, k, len, valid_count;
-  SilcBuffer packet, idp, channels;
+  SilcBuffer packet, idp, channels, umode_list = NULL;
   SilcClientEntry entry;
-  SilcCommandStatus status;
+  SilcStatus status;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char nh[256], uh[256];
   unsigned char idle[4], mode[4];
@@ -782,7 +783,12 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
       strncat(uh, hsock->hostname, len);
     }
 
-    channels = silc_server_get_client_channel_list(server, entry);
+    if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
+      channels = silc_server_get_client_channel_list(server, entry, FALSE, 
+                                                    FALSE, &umode_list);
+    else
+      channels = silc_server_get_client_channel_list(server, entry, TRUE, 
+                                                    TRUE, &umode_list);
 
     if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
       fingerprint = entry->data.fingerprint;
@@ -797,7 +803,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
 
     packet = 
       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
-                                          status, 0, ident, 8
+                                          status, 0, ident, 9
                                           2, idp->data, idp->len,
                                           3, nh, strlen(nh),
                                           4, uh, strlen(uh),
@@ -808,7 +814,10 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
                                           7, mode, 4,
                                           8, idle, 4,
                                           9, fingerprint,
-                                          fingerprint ? 20 : 0);
+                                          fingerprint ? 20 : 0,
+                                          10, umode_list ? umode_list->data :
+                                          NULL, umode_list ? umode_list->len :
+                                          0);
 
     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
                            0, packet->data, packet->len, FALSE);
@@ -817,6 +826,10 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     silc_buffer_free(idp);
     if (channels)
       silc_buffer_free(channels);
+    if (umode_list) {
+      silc_buffer_free(umode_list);
+      umode_list = NULL;
+    }
 
     k++;
   }
@@ -1021,10 +1034,11 @@ silc_server_command_whowas_parse(SilcServerCommandContext cmd,
 
   /* Get the max count of reply messages allowed */
   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
-  if (tmp)
-    *count = atoi(tmp);
-  else
+  if (tmp) {
+    SILC_GET32_MSB(*count, tmp);
+  } else {
     *count = 0;
+  }
 
   return TRUE;
 }
@@ -1083,7 +1097,7 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
   int i, k, count = 0, len;
   SilcBuffer packet, idp;
   SilcClientEntry entry = NULL;
-  SilcCommandStatus status;
+  SilcStatus status;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char nh[256], uh[256];
   int valid_count;
@@ -1575,10 +1589,11 @@ silc_server_command_identify_parse(SilcServerCommandContext cmd,
   
   /* Get the max count of reply messages allowed */
   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
-  if (tmp)
-    *count = atoi(tmp);
-  else
+  if (tmp) {
+    SILC_GET32_MSB(*count, tmp);
+  } else {
     *count = 0;
+  }
 
   return 1;
 }
@@ -1737,7 +1752,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
   SilcServer server = cmd->server;
   int i, k, len, valid_count;
   SilcBuffer packet, idp;
-  SilcCommandStatus status;
+  SilcStatus status;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char nh[256], uh[256];
   SilcSocketConnection hsock;
@@ -2088,7 +2103,7 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
   int i, k;
   SilcBuffer packet, idp;
   SilcChannelEntry entry;
-  SilcCommandStatus status;
+  SilcStatus status;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char *topic;
   unsigned char usercount[4];
@@ -2457,7 +2472,7 @@ SILC_SERVER_CMD_FUNC(invite)
     }
 
     /* Get the client entry */
-    dest = silc_server_get_client_resolve(server, dest_id, &resolve);
+    dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
     if (!dest) {
       if (server->server_type != SILC_SERVER || !resolve) {
        silc_server_command_send_status_reply(
@@ -3074,7 +3089,8 @@ static void silc_server_command_join_channel(SilcServer server,
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     client = (SilcClientEntry)sock->user_data;
   } else {
-    client = silc_server_get_client_resolve(server, client_id, &resolve);
+    client = silc_server_get_client_resolve(server, client_id, FALSE, 
+                                           &resolve);
     if (!client) {
       if (cmd->pending)
        goto out;
@@ -4673,6 +4689,19 @@ SILC_TASK_CALLBACK(silc_server_command_detach_cb)
   silc_free(q);
 }
 
+SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
+{
+  QuitInternal q = (QuitInternal)context;
+  SilcClientEntry client = (SilcClientEntry)q->sock;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (client->mode & SILC_UMODE_DETACHED)
+    silc_server_free_client_data(q->server, NULL, client, TRUE,
+                                "Detach timeout");
+  silc_free(q);
+}
+
 /* Server side of DETACH command.  Detached the client from the network
    by closing the connection but preserving the session. */
 
@@ -4683,6 +4712,12 @@ SILC_SERVER_CMD_FUNC(detach)
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   QuitInternal q;
 
+  if (server->config->detach_disabled) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
+                                         SILC_STATUS_ERR_UNKNOWN_COMMAND);
+    goto out;
+  }
+
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
 
@@ -4702,6 +4737,16 @@ SILC_SERVER_CMD_FUNC(detach)
   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
                         q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 
+  if (server->config->detach_timeout) {
+    q = silc_calloc(1, sizeof(*q));
+    q->server = server;
+    q->sock = (void *)client;
+    silc_schedule_task_add(server->schedule, 0, 
+                          silc_server_command_detach_timeout,
+                          q, server->config->detach_timeout * 60,
+                          0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+  }
+
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
                                        SILC_STATUS_OK);
@@ -5062,7 +5107,7 @@ SILC_SERVER_CMD_FUNC(users)
     channel = silc_idlist_find_channel_by_name(server->local_list, 
                                               channel_name, NULL);
 
-  if (!channel || channel->disabled) {
+  if (!channel || channel->disabled || !channel->users_resolved) {
     if (server->server_type != SILC_ROUTER && !server->standalone &&
        !cmd->pending) {
       SilcBuffer tmpbuf;
@@ -5102,20 +5147,13 @@ SILC_SERVER_CMD_FUNC(users)
   }
 
   /* If the channel is private or secret do not send anything, unless the
-     user requesting this command is on the channel. */
+     user requesting this command is on the channel or is server */
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
        && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
                                          NULL)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
-      goto out;
-    }
-  } else {
-    if (channel->mode & 
-       (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
   }
@@ -5198,7 +5236,8 @@ SILC_SERVER_CMD_FUNC(getkey)
                                             client_id, TRUE, NULL);
     
     if ((!client && !cmd->pending && !server->standalone) ||
-       (client && !client->connection && !cmd->pending) ||
+       (client && !client->connection && !cmd->pending &&
+        !(client->mode & SILC_UMODE_DETACHED)) ||
        (client && !client->data.public_key && !cmd->pending)) {
       SilcBuffer tmpbuf;
       SilcUInt16 old_ident;