Added WHOIS to send multiple replies if multiple nicknames are
authorPekka Riikonen <priikone@silcnet.org>
Fri, 6 Oct 2000 08:10:23 +0000 (08:10 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 6 Oct 2000 08:10:23 +0000 (08:10 +0000)
found.
Added MOTD command and [motd] config section and server also sends
motd to client on connection now.
Fixed TOPIC command some more.

apps/silcd/command.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h

index ca16cf7324735b26c88f78ca8acbf528c34ad11f..c03fe0f1bfdae43723f5c6ad9bccf258abaf435f 100644 (file)
@@ -293,10 +293,12 @@ SILC_SERVER_CMD_FUNC(whois)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   char *tmp, *nick = NULL, *server_name = NULL;
-  unsigned int argc, count = 0, len;
+  unsigned int i, argc, count = 0, len, clients_count;
   SilcClientEntry entry;
   SilcBuffer packet;
   unsigned char *id_string;
+  SilcClientEntry *clients;
+  SilcCommandStatus status;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -345,10 +347,11 @@ SILC_SERVER_CMD_FUNC(whois)
     count = atoi(tmp);
   }
 
-  /* Then, make the query from our local client list */
-  entry = silc_idlist_find_client_by_nickname(server->local_list, 
-                                             nick, server_name);
-  if (!entry) {
+  /* Get all clients matching that nickname */
+  clients = silc_idlist_get_clients_by_nickname(server->local_list, 
+                                               nick, server_name,
+                                               &clients_count);
+  if (!clients) {
 
     /* If we are normal server and are connected to a router we will
        make global query from the router. */
@@ -380,70 +383,88 @@ SILC_SERVER_CMD_FUNC(whois)
  ok:
   /* XXX, works only for local server info */
 
-  /* Send WHOIS reply */
-  id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
-  tmp = silc_command_get_first_arg(cmd->payload, NULL);
 
-  /* XXX */
-  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
-    char nh[256], uh[256];
-    unsigned char idle[4];
-    SilcSocketConnection hsock;
+  status = SILC_STATUS_OK;
+  if (clients_count > 1)
+    status = SILC_STATUS_LIST_START;
 
-    memset(uh, 0, sizeof(uh));
-    memset(nh, 0, sizeof(nh));
+  for (i = 0; i < clients_count; i++) {
+    entry = clients[i];
 
-    strncat(nh, entry->nickname, strlen(entry->nickname));
-    strncat(nh, "@", 1);
-    len = entry->router ? strlen(entry->router->server_name) :
-      strlen(server->server_name);
-    strncat(nh, entry->router ? entry->router->server_name :
-           server->server_name, len);
+    if (count && i - 1 == count)
+      break;
 
-    strncat(uh, entry->username, strlen(entry->username));
-    strncat(uh, "@", 1);
-    hsock = (SilcSocketConnection)entry->connection;
-    len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
-    strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
+    if (clients_count > 2)
+      status = SILC_STATUS_LIST_ITEM;
 
-    SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
+    if (clients_count > 1 && i == clients_count - 1)
+      status = SILC_STATUS_LIST_END;
 
+    /* Send WHOIS reply */
+    id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
+    tmp = silc_command_get_first_arg(cmd->payload, NULL);
+    
     /* XXX */
-    if (entry->userinfo)
-      packet = 
-        silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
-                                            SILC_STATUS_OK, 5, 
-                                            2, id_string, SILC_ID_CLIENT_LEN,
-                                            3, nh, strlen(nh),
-                                            4, uh, strlen(uh),
-                                            5, entry->userinfo, 
-                                            strlen(entry->userinfo),
-                                            7, idle, 4);
-    else
+    if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+      char nh[256], uh[256];
+      unsigned char idle[4];
+      SilcSocketConnection hsock;
+
+      memset(uh, 0, sizeof(uh));
+      memset(nh, 0, sizeof(nh));
+      
+      strncat(nh, entry->nickname, strlen(entry->nickname));
+      strncat(nh, "@", 1);
+      len = entry->router ? strlen(entry->router->server_name) :
+       strlen(server->server_name);
+      strncat(nh, entry->router ? entry->router->server_name :
+             server->server_name, len);
+      
+      strncat(uh, entry->username, strlen(entry->username));
+      strncat(uh, "@", 1);
+      hsock = (SilcSocketConnection)entry->connection;
+      len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
+      strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
+      
+      SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
+      
+      /* XXX */
+      if (entry->userinfo)
+       packet = 
+         silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
+                                              status, 5, 
+                                              2, id_string, SILC_ID_CLIENT_LEN,
+                                              3, nh, strlen(nh),
+                                              4, uh, strlen(uh),
+                                              5, entry->userinfo, 
+                                              strlen(entry->userinfo),
+                                              7, idle, 4);
+      else
+       packet = 
+         silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
+                                              status, 4, 
+                                              2, id_string, SILC_ID_CLIENT_LEN,
+                                              3, nh, strlen(nh),
+                                              4, uh, strlen(uh),
+                                              7, idle, 4);
+      
+    } else {
+      /* XXX */
       packet = 
-        silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
-                                            SILC_STATUS_OK, 4
+       silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS, 
+                                            status, 3
                                             2, id_string, SILC_ID_CLIENT_LEN,
-                                            3, nh, strlen(nh),
-                                            4, uh, strlen(uh),
-                                            7, idle, 4);
-
-  } else {
-    /* XXX */
-    packet = 
-      silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS, 
-                                          SILC_STATUS_OK, 3, 
-                                          2, id_string, SILC_ID_CLIENT_LEN,
-                                          3, entry->nickname, 
-                                          strlen(entry->nickname),
-                                          4, tmp, strlen(tmp)); /* XXX */
-  }
-  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
-                         0, packet->data, packet->len, FALSE);
-
-  silc_free(id_string);
-  silc_buffer_free(packet);
-
+                                            3, entry->nickname, 
+                                            strlen(entry->nickname),
+                                            4, tmp, strlen(tmp)); /* XXX */
+    }
+    silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
+                           0, packet->data, packet->len, FALSE);
+    
+    silc_free(id_string);
+    silc_buffer_free(packet);
+  }
+    
  out:
   silc_server_command_free(cmd);
 }
@@ -694,7 +715,8 @@ SILC_SERVER_CMD_FUNC(topic)
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   SilcChannelID *channel_id;
   SilcChannelEntry channel;
-  unsigned char *tmp;
+  SilcBuffer packet;
+  unsigned char *tmp, *id_string;
   unsigned int argc;
 
   /* Check number of arguments */
@@ -719,6 +741,14 @@ SILC_SERVER_CMD_FUNC(topic)
   }
   channel_id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
 
+  /* Check whether the channel exists */
+  channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
+  if (!channel) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+                                         SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+    goto out;
+  }
+
   if (argc > 1) {
     /* Get the topic */
     tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
@@ -728,15 +758,15 @@ SILC_SERVER_CMD_FUNC(topic)
       goto out;
     }
 
-    /* Check whether the channel exists */
-    channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
-    if (!channel) {
+    if (strlen(tmp) > 256) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
       goto out;
     }
 
     /* Set the topic for channel */
+    if (channel->topic)
+      silc_free(channel->topic);
     channel->topic = strdup(tmp);
 
     /* Send notify about topic change to all clients on the channel */
@@ -750,9 +780,25 @@ SILC_SERVER_CMD_FUNC(topic)
   }
 
   /* Send the topic to client as reply packet */
-  silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
-                                      SILC_STATUS_OK,
-                                      2, tmp, strlen(tmp));
+  id_string = silc_id_id2str(channel_id, SILC_ID_CHANNEL);
+  if (channel->topic)
+    packet = silc_command_encode_reply_payload_va(SILC_COMMAND_TOPIC, 
+                                                 SILC_STATUS_OK, 2, 
+                                                 2, id_string, 
+                                                 SILC_ID_CHANNEL_LEN,
+                                                 3, channel->topic, 
+                                                 strlen(channel->topic));
+  else
+    packet = silc_command_encode_reply_payload_va(SILC_COMMAND_TOPIC, 
+                                                 SILC_STATUS_OK, 1, 
+                                                 2, id_string,
+                                                 SILC_ID_CHANNEL_LEN);
+  silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
+                         0, packet->data, packet->len, FALSE);
+
+  silc_free(id_string);
+  silc_buffer_free(packet);
+  silc_free(channel_id);
 
  out:
   silc_server_command_free(cmd);
@@ -1324,9 +1370,50 @@ SILC_SERVER_CMD_FUNC(join)
 
 SILC_SERVER_CMD_FUNC(motd)
 {
-
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcSocketConnection sock = cmd->sock;
+  unsigned int argc;
+  char *motd;
+  int motd_len;
+  
   SILC_LOG_DEBUG(("Start"));
 
+  argc = silc_command_get_arg_num(cmd->payload);
+  if (argc < 1) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  if (argc > 2) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
+                                         SILC_STATUS_ERR_TOO_MANY_PARAMS);
+    goto out;
+  }
+
+  /* XXX show currently only our motd */
+
+  if (server->config && server->config->motd && 
+      server->config->motd->motd_file) {
+
+    /* Send motd */
+    motd = silc_file_read(server->config->motd->motd_file, &motd_len);
+    if (!motd)
+      goto out;
+
+    motd[motd_len] = 0;
+    silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
+                                        SILC_STATUS_OK,
+                                        2, motd, motd_len);
+    goto out;
+  } else {
+    /* No motd */
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
+                                         SILC_STATUS_OK);
+  }
+
+ out:
+  silc_server_command_free(cmd);
 }
 
 SILC_SERVER_CMD_FUNC(umode)
index 97ee88544126bf3897a45cca39874ae45a0b6880..1df174e4c4245dec9958ccfbcbdb848e0463e6d4 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.8  2000/10/06 08:10:23  priikone
+ *     Added WHOIS to send multiple replies if multiple nicknames are
+ *     found.
+ *     Added MOTD command and [motd] config section and server also sends
+ *     motd to client on connection now.
+ *     Fixed TOPIC command some more.
+ *
  * Revision 1.7  2000/07/26 07:04:01  priikone
  *     Added server_find_by_id, replace_[server/client]_id.
  *
@@ -219,6 +226,38 @@ void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
   }
 }
 
+/* Returns all clients matching requested nickname. Number of clients is
+   returned to `clients_count'. Caller must free the returned table. */
+
+SilcClientEntry *
+silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
+                                   char *server, unsigned int *clients_count)
+{
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcClientEntry *clients;
+  int i;
+
+  if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
+    return NULL;
+
+  clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
+
+  i = 0;
+  silc_idcache_list_first(list, &id_cache);
+  clients[i++] = (SilcClientEntry)id_cache->context;
+
+  while (silc_idcache_list_next(list, &id_cache))
+    clients[i++] = (SilcClientEntry)id_cache->context;
+  
+  silc_idcache_list_free(list);
+  
+  if (clients_count)
+    *clients_count = i;
+
+  return clients;
+}
+
 /* Finds client entry by nickname. */
 
 SilcClientEntry
index e1f39ec1b7878f7351f9153a749969fea2732552..6a40147f6bce6f04be4029eeee15e509fb389d6c 100644 (file)
@@ -442,6 +442,9 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
                       SilcPKCS pkcs, SilcHmac hmac, 
                       SilcPublicKey public_key, void *connection);
 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
+SilcClientEntry *
+silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
+                                   char *server, unsigned int *clients_count);
 SilcClientEntry
 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
                                    char *server);
index e735125ff468c572a6df11a92f18001f5a071c38..f17de4f66a79401d66564c331b246d5caf506eb4 100644 (file)
@@ -2643,6 +2643,46 @@ void silc_server_channel_key(SilcServer server,
   silc_buffer_free(buffer);
 }
 
+/* Sends current motd to client */
+
+void silc_server_send_motd(SilcServer server,
+                          SilcSocketConnection sock)
+{
+  char *motd, *cp;
+  char line[256];
+  int i, motd_len;
+
+  if (server->config && server->config->motd && 
+      server->config->motd->motd_file) {
+
+    motd = silc_file_read(server->config->motd->motd_file, &motd_len);
+    if (!motd)
+      return;
+
+    /* Send motd */
+    i = 0;
+    cp = motd;
+    while(cp[i] != 0) {
+      if (cp[i++] == '\n') {
+       memset(line, 0, sizeof(line));
+       strncat(line, cp, i - 1);
+       cp += i;
+
+       if (i == 2)
+         line[0] = ' ';
+
+       silc_server_send_notify(server, sock, SILC_NOTIFY_TYPE_NONE, line);
+
+       if (!strlen(cp))
+         break;
+       i = 0;
+      }
+    }
+
+    silc_free(motd);
+  }
+}
+
 /* Sends error message. Error messages may or may not have any 
    implications. */
 
@@ -3114,7 +3154,8 @@ SilcClientEntry silc_server_new_client(SilcServer server,
                          "Your current nickname is %s",
                          client->nickname);
 
-  /* XXX Send motd */
+  /* Send motd */
+  silc_server_send_motd(server, sock);
 
   return client;
 }
index ae846d4297018d4fd8fb1aabd91f0733383726c7..ef80e69ee535254c34ccdc671502a723f1a5cf20 100644 (file)
@@ -113,6 +113,8 @@ void silc_server_channel_message(SilcServer server,
 void silc_server_channel_key(SilcServer server,
                             SilcSocketConnection sock,
                             SilcPacketContext *packet);
+void silc_server_send_motd(SilcServer server,
+                          SilcSocketConnection sock);
 void silc_server_send_error(SilcServer server,
                            SilcSocketConnection sock,
                            const char *fmt, ...);
index b6d44d6bed07d7e5ab9a22ce6a55dff8c66454f9..fc89baced403a8e8979e93e68c18893263bab274 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.4  2000/10/06 08:10:23  priikone
+ *     Added WHOIS to send multiple replies if multiple nicknames are
+ *     found.
+ *     Added MOTD command and [motd] config section and server also sends
+ *     motd to client on connection now.
+ *     Fixed TOPIC command some more.
+ *
  * Revision 1.3  2000/07/10 05:41:20  priikone
  *     Added missing token to administrative information.
  *
@@ -189,6 +196,8 @@ SilcConfigServerSection silc_config_server_sections[] = {
     SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION, 4 },
   { "[RedirectClient]", 
     SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT, 2 },
+  { "[motd]", 
+    SILC_CONFIG_SERVER_SECTION_TYPE_MOTD, 1 },
   
   { NULL, SILC_CONFIG_SERVER_SECTION_TYPE_NONE, 0 }
 };
@@ -249,6 +258,7 @@ void silc_config_server_free(SilcConfigServer config)
     silc_free(config->routers);
     silc_free(config->denied);
     silc_free(config->redirect);
+    silc_free(config->motd);
     silc_free(config);
   }
 }
@@ -980,6 +990,20 @@ int silc_config_server_parse_lines(SilcConfigServer config,
       check = TRUE;
       break;
 
+    case SILC_CONFIG_SERVER_SECTION_TYPE_MOTD:
+
+      if (!config->motd)
+       config->motd = silc_calloc(1, sizeof(*config->motd));
+
+      /* Get motd file */
+      ret = silc_config_get_token(line, &config->motd->motd_file);
+      if (ret < 0)
+       break;
+
+      check = TRUE;
+      checkmask |= (1L << pc->section->type);
+      break;
+
     case SILC_CONFIG_SERVER_SECTION_TYPE_NONE:
     default:
       /* Error */
index af017597958a826b3e3d01d5dee1570d4598fe72..5b7a1d54cd2bc70859ccc73b90a06565a9f4f5be 100644 (file)
@@ -133,6 +133,11 @@ typedef struct {
   unsigned short port;
 } SilcConfigServerSectionRedirectClient;
 
+/* Holds motd file */
+typedef struct {
+  char *motd_file;
+} SilcConfigServerSectionMotd;
+
 /* 
    SILC Server Config object. 
 
@@ -162,6 +167,7 @@ typedef struct {
   SilcConfigServerSectionAdminConnection *admins;
   SilcConfigServerSectionDenyConnection *denied;
   SilcConfigServerSectionRedirectClient *redirect;
+  SilcConfigServerSectionMotd *motd;
 } SilcConfigServerObject;
 
 typedef SilcConfigServerObject *SilcConfigServer;
@@ -183,6 +189,7 @@ typedef enum {
   SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION,
   SILC_CONFIG_SERVER_SECTION_TYPE_DENY_CONNECTION,
   SILC_CONFIG_SERVER_SECTION_TYPE_REDIRECT_CLIENT,
+  SILC_CONFIG_SERVER_SECTION_TYPE_MOTD,
 } SilcConfigServerSectionType;
 
 /* SILC Configuration Section structure. */