update.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 19 Mar 2001 17:54:34 +0000 (17:54 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 19 Mar 2001 17:54:34 +0000 (17:54 +0000)
CHANGES
README
apps/silc/client_ops.c
apps/silc/screen.c
apps/silc/screen.h
apps/silcd/command.c
doc/draft-riikonen-silc-spec-01.nroff
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/idlist.h

diff --git a/CHANGES b/CHANGES
index 47a58cafaacbee6b26f5ae867222cf50e1634c74..9ee79cc3e38ef4b6b5e3538de1e8c159d2fbc558 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,20 @@
+Mon Mar 19 18:43:06 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Fixed the mode printing on the user interface on joining.
+         Affected file silc/client_ops.c.
+
+       * Implemented the UMODE command and user modes in general to the
+         client library and to the user interface.
+
+       * Implemented the UMODE command to the server.
+
+       * The server now sends UNKNOWN_COMMAND error status if client sends
+         unknown command.  Affected file silcd/command.c.
+
+       * All server commands now handle the command identifier the right
+         way when sending the command reply to the client.  The client can
+         use to identify the command replies with the identifier.
+
 Mon Mar 19 16:13:07 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added silc_server_get_client_route to resolve the route to
diff --git a/README b/README
index 559ae953419e3fda2ad3dbafb76d9ba95072bfac..97e58a3786ea4d2d544d8339acf752e6c712347f 100644 (file)
--- a/README
+++ b/README
@@ -118,6 +118,8 @@ Following commands has been, at least partly, implemented:
                                Set/unset channel operator.  Requires that 
                                you are channel operator or channel founder.
 
+       /UMODE  +|-<modes>
+
        /MSG    <nickname> <message>
 
                Sends private message to remote client.  Support for
index f2096c6662546c0bd6bc2ef62d5c46fc92a418aa..a37129d74d09255205f65aa48e53ab6ba5a90ddb 100644 (file)
@@ -114,6 +114,20 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     snprintf(message, sizeof(message), "%s (%s) has joined channel %s", 
             client_entry->nickname, client_entry->username, 
             channel_entry->channel_name);
+    if (client_entry == conn->local_entry) {
+      SilcChannelUser chu;
+
+      silc_list_start(channel_entry->clients);
+      while ((chu = silc_list_get(channel_entry->clients)) != SILC_LIST_END) {
+       if (chu->client == client_entry) {
+         if (app->screen->bottom_line->mode)
+           silc_free(app->screen->bottom_line->mode);
+         app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode);
+         silc_screen_print_bottom_line(app->screen, 0);
+         break;
+       }
+      }
+    }
     break;
 
   case SILC_NOTIFY_TYPE_LEAVE:
@@ -547,6 +561,56 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
       }
       break;
 
+    case SILC_COMMAND_UMODE:
+      {
+       unsigned int mode;
+
+       if (!success)
+         return;
+
+       mode = va_arg(vp, unsigned int);
+
+       if (!mode && app->screen->bottom_line->umode) {
+         silc_free(app->screen->bottom_line->umode);
+         app->screen->bottom_line->umode = NULL;
+       }
+
+       if (mode & SILC_UMODE_SERVER_OPERATOR) {
+         if (app->screen->bottom_line->umode)
+           silc_free(app->screen->bottom_line->umode);
+         app->screen->bottom_line->umode = strdup("Server Operator");;
+       }
+
+       if (mode & SILC_UMODE_ROUTER_OPERATOR) {
+         if (app->screen->bottom_line->umode)
+           silc_free(app->screen->bottom_line->umode);
+         app->screen->bottom_line->umode = strdup("SILC Operator");;
+       }
+
+       silc_screen_print_bottom_line(app->screen, 0);
+      }
+      break;
+
+    case SILC_COMMAND_OPER:
+      if (status == SILC_STATUS_OK) {
+       conn->local_entry->mode |= SILC_UMODE_SERVER_OPERATOR;
+       if (app->screen->bottom_line->umode)
+         silc_free(app->screen->bottom_line->umode);
+       app->screen->bottom_line->umode = strdup("Server Operator");;
+       silc_screen_print_bottom_line(app->screen, 0);
+      }
+      break;
+
+    case SILC_COMMAND_SILCOPER:
+      if (status == SILC_STATUS_OK) {
+       conn->local_entry->mode |= SILC_UMODE_ROUTER_OPERATOR;
+       if (app->screen->bottom_line->umode)
+         silc_free(app->screen->bottom_line->umode);
+       app->screen->bottom_line->umode = strdup("SILC Operator");;
+       silc_screen_print_bottom_line(app->screen, 0);
+      }
+      break;
+
     case SILC_COMMAND_USERS:
       if (!success)
        return;
@@ -557,8 +621,7 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
        if (chu->client == conn->local_entry) {
          if (app->screen->bottom_line->mode)
            silc_free(app->screen->bottom_line->mode);
-         app->screen->bottom_line->mode = 
-           silc_client_chumode_char(chu->mode);
+         app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode);
          silc_screen_print_bottom_line(app->screen, 0);
          break;
        }
index dba669258178f72b5f6f179b0ce7f635334afa56..8fb8a8104c783451788845f54b1712d6d3856d22 100644 (file)
@@ -215,6 +215,14 @@ void silc_screen_print_bottom_line(SilcScreen screen, int win_index)
     strncat(buf, ")", 2);
   }
 
+  if (line->umode) {
+    len = strlen(line->umode);
+    strncat(buf, " [", 2);
+    strncat(buf, line->umode, len > SILC_SCREEN_MAX_UMODE_LEN ?
+           SILC_SCREEN_MAX_UMODE_LEN : len);
+    strncat(buf, "]", 2);
+  }
+
   if (line->away)
     strncat(buf, " (away)", 8);
 
index ffa89ffd511fa656f78f8c3e89850e7f634056ce..7f082d5b599316042d9830a2cc2776805b12c0e6 100644 (file)
@@ -27,6 +27,7 @@ typedef struct {
   char *connection;
   char *channel;
   char *channel_mode;
+  char *umode;
   int away;
 } *SilcScreenBottomLine;
 
@@ -77,6 +78,9 @@ typedef SilcScreenObject *SilcScreen;
 /* Maximum length of connection name that will be shown on the screen */
 #define SILC_SCREEN_MAX_CONN_LEN 20
 
+/* Maximum length of user mode that will be shown on the screen */
+#define SILC_SCREEN_MAX_UMODE_LEN 20
+
 /* Macros */
 
 /* Macro used to insert typed character into the buffer. The character
index 0cded085d1121da73102d33eb43359cb7af5238f..215d0cbdb9456cac4c9ae19f4dc94e2006e89eae 100644 (file)
@@ -150,6 +150,7 @@ void silc_server_command_process(SilcServer server,
 {
   SilcServerCommandContext ctx;
   SilcServerCommand *cmd;
+  SilcCommand command;
 
   /* Allocate command context. This must be free'd by the
      command routine receiving it. */
@@ -169,14 +170,16 @@ void silc_server_command_process(SilcServer server,
     return;
   }
   ctx->args = silc_command_get_args(ctx->payload);
-  
+
   /* Get the command */
+  command = silc_command_get(ctx->payload);
   for (cmd = silc_command_list; cmd->cb; cmd++)
-    if (cmd->cmd == silc_command_get(ctx->payload))
+    if (cmd->cmd == command)
       break;
 
   if (cmd == NULL) {
-    SILC_LOG_ERROR(("Unknown command, packet dropped"));
+    silc_server_command_send_status_reply(ctx, command,
+                                         SILC_STATUS_ERR_UNKNOWN_COMMAND);
     silc_server_command_free(ctx);
     return;
   }
@@ -351,7 +354,10 @@ silc_server_command_send_status_reply(SilcServerCommandContext cmd,
 
   SILC_LOG_DEBUG(("Sending command status %d", status));
 
-  buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
+  buffer = 
+    silc_command_reply_payload_encode_va(command, status, 
+                                        silc_command_get_ident(cmd->payload),
+                                        0);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0, 
                          buffer->data, buffer->len, FALSE);
@@ -373,8 +379,10 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
 
   SILC_LOG_DEBUG(("Sending command status %d", status));
 
-  buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
-                                               arg_type, arg, arg_len);
+  buffer = 
+    silc_command_reply_payload_encode_va(command, status, 
+                                        silc_command_get_ident(cmd->payload),
+                                        1, arg_type, arg, arg_len);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0, 
                          buffer->data, buffer->len, FALSE);
@@ -1629,6 +1637,7 @@ SILC_SERVER_CMD_FUNC(nick)
   SilcBuffer packet, nidp, oidp;
   SilcClientID *new_id;
   char *nick;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
 
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
@@ -1693,7 +1702,7 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Send the new Client ID as reply command back to client */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
-                                               SILC_STATUS_OK, 0, 1, 
+                                               SILC_STATUS_OK, ident, 1, 
                                                2, nidp->data, nidp->len);
   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
                          0, packet->data, packet->len, FALSE);
@@ -1724,6 +1733,7 @@ SILC_SERVER_CMD_FUNC(topic)
   SilcBuffer packet, idp;
   unsigned char *tmp;
   unsigned int argc, tmp_len;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
 
@@ -1811,13 +1821,13 @@ SILC_SERVER_CMD_FUNC(topic)
   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
   if (channel->topic)
     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
-                                                 SILC_STATUS_OK, 0, 2, 
+                                                 SILC_STATUS_OK, ident, 2, 
                                                  2, idp->data, idp->len,
                                                  3, channel->topic, 
                                                  strlen(channel->topic));
   else
     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
-                                                 SILC_STATUS_OK, 0, 1, 
+                                                 SILC_STATUS_OK, ident, 1, 
                                                  2, idp->data, idp->len);
   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
                          0, packet->data, packet->len, FALSE);
@@ -2631,8 +2641,70 @@ SILC_SERVER_CMD_FUNC(motd)
   silc_server_command_free(cmd);
 }
 
+/* Server side of command UMODE. Client can use this command to set/unset
+   user mode. Client actually cannot set itself to be as server/router
+   operator so this can be used only to unset the modes. */
+
 SILC_SERVER_CMD_FUNC(umode)
 {
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcBuffer packet;
+  unsigned char *tmp_mask;
+  unsigned int mask;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
+
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+    goto out;
+
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
+
+  /* Get the client's mode mask */
+  tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
+  if (!tmp_mask) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  SILC_GET32_MSB(mask, tmp_mask);
+
+  /* 
+   * Change the mode 
+   */
+
+  if (mask & SILC_UMODE_SERVER_OPERATOR) {
+    /* Cannot operator mode */
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+                                         SILC_STATUS_ERR_PERM_DENIED);
+    goto out;
+  } else {
+    if (client->mode & SILC_UMODE_SERVER_OPERATOR)
+      /* Remove the server operator rights */
+      client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
+  }
+
+  if (mask & SILC_UMODE_ROUTER_OPERATOR) {
+    /* Cannot operator mode */
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+                                         SILC_STATUS_ERR_PERM_DENIED);
+    goto out;
+  } else {
+    if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
+      /* Remove the router operator rights */
+      client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
+  }
+
+  /* Send command reply to sender */
+  packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
+                                               SILC_STATUS_OK, ident, 1,
+                                               2, tmp_mask, 4);
+  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                         packet->data, packet->len, FALSE);
+  silc_buffer_free(packet);
+
+ out:
+  silc_server_command_free(cmd);
 }
 
 /* Checks that client has rights to add or remove channel modes. If any
@@ -2703,6 +2775,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   SilcBuffer packet, cidp;
   unsigned char *tmp, *tmp_id, *tmp_mask;
   unsigned int argc, mode_mask, tmp_len, tmp_len2;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -3055,7 +3128,7 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
-                                               SILC_STATUS_OK, 0, 1,
+                                               SILC_STATUS_OK, ident, 1,
                                                2, tmp_mask, 4);
   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          packet->data, packet->len, FALSE);
@@ -3084,6 +3157,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
   unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
   int notify = FALSE;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
 
@@ -3249,7 +3323,7 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
-                                               SILC_STATUS_OK, 0, 2,
+                                               SILC_STATUS_OK, ident, 2,
                                                2, tmp_mask, 4,
                                                3, tmp_id, tmp_len);
   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
index ec7ba80c3850985242061157dac1f386875d3b5a..3129a44390fda84f56baf2b2845be64222940694 100644 (file)
@@ -2621,8 +2621,8 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID
             SILC_STATUS_ERR_BAD_CLIENT_ID
             SILC_STATUS_ERR_NOT_YOU
+            SILC_STATUS_ERR_PERM_DENIED
             SILC_STATUS_ERR_UNKNOWN_MODE
-            SILC_STATUS_ERR_NO_RECIPIENT
             SILC_STATUS_ERR_NO_CLIENT_ID
 
 
@@ -2830,7 +2830,6 @@ List of all defined commands in SILC follows.
         all clients on the channel by sending SILC_NOTIFY_TYPE_CMODE_CHANGE
         notify type.
 
-
         Reply messages to the command:
 
         Max Arguments:  2
@@ -2894,7 +2893,6 @@ List of all defined commands in SILC follows.
               client on the channel.  Channel founder and channel operator
               may set/unset (promote/demote) this mode.
 
-
         Reply messages to the command:
 
         Max Arguments:  3
@@ -3340,8 +3338,8 @@ List of all defined command status messages following.
 
    31   SILC_STATUS_ERR_PERM_DENIED
 
-        "Your host is not among the privileged".  The client tried to
-        register on server that does not allow this host to connect.
+        "Permission denied".  Generic permission denied error status
+        to indicate disallowed access.
 
    32   SILC_STATUS_ERR_BANNED_FROM_SERVER
 
index f6dca33316e8e9cba3d61259cebb3fbef7e2a8f9..7c90c184b63da344dbea59b10fc70b8caf4225be 100644 (file)
@@ -928,11 +928,91 @@ SILC_CLIENT_CMD_FUNC(motd)
   silc_client_command_free(cmd);
 }
 
-/* UMODE. Set user mode in SILC. */
+/* UMODE. Set/unset user mode in SILC. This is used mainly to unset the
+   modes as client cannot set itself server/router operator privileges. */
 
 SILC_CLIENT_CMD_FUNC(umode)
 {
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer, idp;
+  unsigned char *cp, modebuf[4];
+  unsigned int mode, add, len;
+  int i;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    cmd->client->ops->say(cmd->client, conn, 
+                 "Usage: /UMODE +|-<modes>");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  mode = conn->local_entry->mode;
+
+  /* Are we adding or removing mode */
+  if (cmd->argv[1][0] == '-')
+    add = FALSE;
+  else
+    add = TRUE;
+
+  /* Parse mode */
+  cp = cmd->argv[1] + 1;
+  len = strlen(cp);
+  for (i = 0; i < len; i++) {
+    switch(cp[i]) {
+    case 'a':
+      if (add) {
+       mode = 0;
+       mode |= SILC_UMODE_SERVER_OPERATOR;
+       mode |= SILC_UMODE_ROUTER_OPERATOR;
+      } else {
+       mode = SILC_UMODE_NONE;
+      }
+      break;
+    case 's':
+      if (add)
+       mode |= SILC_UMODE_SERVER_OPERATOR;
+      else
+       mode &= ~SILC_UMODE_SERVER_OPERATOR;
+      break;
+    case 'r':
+      if (add)
+       mode |= SILC_UMODE_ROUTER_OPERATOR;
+      else
+       mode &= ~SILC_UMODE_ROUTER_OPERATOR;
+      break;
+    default:
+      COMMAND_ERROR;
+      goto out;
+      break;
+    }
+  }
 
+  idp = silc_id_payload_encode(conn->local_id, SILC_ID_CLIENT);
+  SILC_PUT32_MSB(mode, modebuf);
+
+  /* Send the command packet. We support sending only one mode at once
+     that requires an argument. */
+  buffer = 
+    silc_command_payload_encode_va(SILC_COMMAND_UMODE, ++conn->cmd_ident, 2, 
+                                  1, idp->data, idp->len, 
+                                  2, modebuf, sizeof(modebuf));
+  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);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
 }
 
 /* CMODE command. Sets channel mode. Modes that does not require any arguments
index a2e3e1c42b187ced3c93ebcd4b310ba49792421e..d0f898a9283e873565c7ce9157c33944d9c65c27 100644 (file)
@@ -90,7 +90,7 @@ const SilcCommandStatusMessage silc_command_status_messages[] = {
   { STAT(NOT_REGISTERED),    "You have not registered" },
   { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
   { STAT(TOO_MANY_PARAMS),   "Too many parameters" },
-  { STAT(PERM_DENIED),       "Your host is not among the privileged" },
+  { STAT(PERM_DENIED),       "Permission denied" },
   { STAT(BANNED_FROM_SERVER),"You are banned from this server" },
   { STAT(BAD_PASSWORD),      "Cannot join channel. Incorrect password" },
   { STAT(CHANNEL_IS_FULL),   "Cannot join channel. Channel is full" },
@@ -696,10 +696,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill)
   COMMAND_REPLY((ARGS));
 
   /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE);
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL);
 
  out:
-  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE);
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KILL);
   silc_client_command_reply_free(cmd);
 }
 
@@ -1059,8 +1059,43 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd)
   silc_client_command_reply_free(cmd);
 }
 
+/* Received reply tot he UMODE command. Save the current user mode */
+
 SILC_CLIENT_CMD_REPLY_FUNC(umode)
 {
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+  SilcCommandStatus status;
+  unsigned char *tmp;
+  unsigned int mode;
+
+  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
+  SILC_GET16_MSB(status, tmp);
+  if (status != SILC_STATUS_OK) {
+    cmd->client->ops->say(cmd->client, conn,
+            "%s", silc_client_command_status_message(status));
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+  if (!tmp) {
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  SILC_GET32_MSB(mode, tmp);
+  conn->local_entry->mode = mode;
+
+  /* Notify application */
+  COMMAND_REPLY((ARGS, mode));
+
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE);
+
+ out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_UMODE);
+  silc_client_command_reply_free(cmd);
 }
 
 /* Received reply for CMODE command. */
index 513a52ef29090af8f9947e02410013bd4120dc3f..b9f832ad97cc2f6755cf389eee95d9425ee41688 100644 (file)
@@ -31,6 +31,7 @@ typedef struct SilcClientEntryStruct {
   char *server;                        /* SILC server name */
   char *realname;              /* Realname (userinfo) */
   unsigned int num;
+  unsigned int mode;           /* User mode in SILC */
   SilcClientID *id;            /* The Client ID */
   SilcCipher send_key;         /* Private message key for sending */
   SilcCipher receive_key;      /* Private message key for receiving */