updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 25 Mar 2001 13:23:06 +0000 (13:23 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 25 Mar 2001 13:23:06 +0000 (13:23 +0000)
20 files changed:
CHANGES
README
apps/silc/client_ops.c
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/testi2.conf
doc/draft-riikonen-silc-spec-01.nroff
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silccore/silccommand.c
lib/silccore/silcnotify.c
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

diff --git a/CHANGES b/CHANGES
index c6c440a78453c4647ab84801c1380d5cc1da2edd..c835fdbefe44d9fd9110f0a8d44d724cbffc52f5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,39 @@
+Sun Mar 25 13:52:51 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Implemented the BAN command to the client library.
+
+       * The JOIN command in the server now checks the invite list
+         and the ban list.
+
+       * Changed the silc_command_reply_payload_encode_va and the
+         silc_command_payload_encode_va to support that if argument is
+         NULL it ignores and checks the next argument.  Affected file
+         lib/silccore/silccommand.c.
+
+       * Added silc_server_send_notify_ban to send the BAN notify
+         type between routers.
+
+       * Chaned the silc_notify_payload_encode to support that if 
+         argument is NULL it ignores and checks the next argument.
+         Affected file lib/silccore/silcnotify.c.
+
+       * Tested ban lists in router environment successfully.
+
+Sat Mar 24 14:47:25 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Implemented BAN command to the server, in silcd/command.[ch].
+
+       * Removed the BAN and INVITE_LIST modes from the CMODE command
+         in the server code.
+
+       * Added function silc_string_match to regex match two strings.
+         Affected files lib/silcutil/silcutil.[ch].
+
+Fri Mar 23 22:02:40 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Redefined parts of the SilcChannelEntry in the server to support
+         the new ban and invite lists.
+
 Fri Mar 23 16:25:11 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Redefined the INVITE command.  The same command can be used to
diff --git a/README b/README
index ac9e349f63e609888cacb77ff73bffef11620f88..215f04f96d85c82c3441986eb09f7c1fc59cffcf 100644 (file)
--- a/README
+++ b/README
@@ -86,12 +86,7 @@ SILC Commands
                l <limit>       Set/unset channel's user limit
                a <passphrase>  Set/unset passphrase for channel that must
                                be provided when joining to the channel.
-               b <username!nickname@server>    
-                               Add client to/remove client from ban list
-               I <username!nickname@server>    
-                               Add client to/remove client from invite list
-               c <cipher>
-                               Set/unset channel's cipher
+               c <cipher>      Set/unset channel's cipher
 
                Multiple modes can be set/unset at once if the modes does not
                require any arguments.  If mode requires an argument then only
index 690584b8be44206118dded0b790e8772637b9478..e71e8ac9bc90506aa5777ad1a96b0012a1d7629a 100644 (file)
@@ -712,8 +712,30 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
          silc_screen_print_bottom_line(app->screen, 0);
          break;
        }
+      }
       break;
+
+    case SILC_COMMAND_BAN:
+      {
+       SilcChannelEntry channel;
+       char *ban_list;
+
+       if (!success)
+         return;
+       
+       channel = va_arg(vp, SilcChannelEntry);
+       ban_list = va_arg(vp, char *);
+
+       if (ban_list)
+         silc_say(client, conn, "%s ban list: %s", channel->channel_name,
+                  ban_list);
+       else
+         silc_say(client, conn, "%s ban list not set", channel->channel_name);
       }
+      break;
+
+    default:
+      break;
     }
 }
 
index f92e8a39b30e6a646b2ee114a40dcde7781b8378..7bfbc62d63b79e0ce0195313cd5050b1dafc6053 100644 (file)
@@ -72,6 +72,7 @@ SilcServerCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
 
   { NULL, 0 },
 };
@@ -2569,43 +2570,73 @@ static void silc_server_command_join_channel(SilcServer server,
   SilcChannelClientEntry chl;
   SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
   unsigned short ident = silc_command_get_ident(cmd->payload);
+  char check[512];
 
   SILC_LOG_DEBUG(("Start"));
 
   if (!channel)
     return;
 
-  /* Get passphrase */
-  tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-  if (tmp) {
-    passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
-    memcpy(passphrase, tmp, tmp_len);
+  /* Get the client entry */
+  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+    client = (SilcClientEntry)sock->user_data;
+  } else {
+    client = silc_idlist_find_client_by_id(server->local_list, client_id, 
+                                          NULL);
+    if (!client)
+      goto out;
   }
-  
+
   /*
    * Check channel modes
    */
 
-  /* Check invite list if channel is invite-only channel */
-  if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
-    if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
-      /* Invite list is specified. Check whether client is invited in the
-        list. If not, then check whether it has been invited otherwise. */
-
-    } else {
-      /* XXX client must be invited to be able to join the channel */
+  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+    strncat(check, client->nickname, strlen(client->nickname));
+    if (!strchr(client->nickname, '@')) {
+      strncat(check, "@", 1);
+      strncat(check, server->server_name, strlen(server->server_name));
+    }
+    strncat(check, "!", 1);
+    strncat(check, client->username, strlen(client->username));
+    if (!strchr(client->username, '@')) {
+      strncat(check, "@", 1);
+      strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
     }
   }
 
-  /* Check ban list if set */
-  if (channel->mode & SILC_CHANNEL_MODE_BAN) {
+  /* Check invite list if channel is invite-only channel */
+  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
+      channel->mode & SILC_CHANNEL_MODE_INVITE && channel->invite_list) {
+    if (!silc_string_match(channel->invite_list, check)) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                           SILC_STATUS_ERR_NOT_INVITED);
+      goto out;
+    }
+  }
 
+  /* Check ban list if it exists. If the client's nickname, server,
+     username and/or hostname is in the ban list the access to the
+     channel is denied. */
+  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
+    if (silc_string_match(channel->ban_list, check)) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                             SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
+      goto out;
+    }
   }
 
+  /* Get passphrase */
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+  if (tmp) {
+    passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
+    memcpy(passphrase, tmp, tmp_len);
+  }
+  
   /* Check the channel passphrase if set. */
   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
-    if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
-                             strlen(channel->mode_data.passphrase))) {
+    if (!passphrase || memcmp(channel->passphrase, passphrase,
+                             strlen(channel->passphrase))) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                            SILC_STATUS_ERR_BAD_PASSWORD);
       goto out;
@@ -2615,7 +2646,7 @@ static void silc_server_command_join_channel(SilcServer server,
   /* Check user count limit if set. */
   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
     if (silc_list_count(channel->user_list) + 1 > 
-       channel->mode_data.user_limit) {
+       channel->user_limit) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                            SILC_STATUS_ERR_CHANNEL_IS_FULL);
       goto out;
@@ -2626,22 +2657,6 @@ static void silc_server_command_join_channel(SilcServer server,
    * Client is allowed to join to the channel. Make it happen.
    */
 
-  /* Get the client entry */
-  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
-    client = (SilcClientEntry)sock->user_data;
-  } else {
-    client = silc_idlist_find_client_by_id(server->local_list, client_id, 
-                                          NULL);
-    if (!client) {
-      /* XXX actually this is useless since router finds always cell's
-        local clients from its local lists. */
-      client = silc_idlist_find_client_by_id(server->global_list, client_id, 
-                                            NULL);
-      if (!client)
-       goto out;
-    }
-  }
-
   /* Check whether the client already is on the channel */
   if (silc_server_client_on_channel(client, channel)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
@@ -2689,39 +2704,31 @@ static void silc_server_command_join_channel(SilcServer server,
                                         channel->channel_key->cipher->name,
                                         channel->key_len / 8, channel->key);
   silc_free(tmp);
-  if (!channel->topic) {
-    reply = 
-      silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
-                                          SILC_STATUS_OK, ident, 9,
-                                          2, channel->channel_name,
-                                          strlen(channel->channel_name),
-                                          3, chidp->data, chidp->len,
-                                          4, clidp->data, clidp->len,
-                                          5, mode, 4,
-                                          6, tmp2, 4,
-                                          7, keyp->data, keyp->len,
-                                          12, tmp3, 4,
-                                          13, user_list->data, user_list->len,
-                                          14, mode_list->data, 
-                                          mode_list->len);
-  } else {
-    reply = 
-      silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
-                                          SILC_STATUS_OK, ident, 10, 
-                                          2, channel->channel_name, 
-                                          strlen(channel->channel_name),
-                                          3, chidp->data, chidp->len,
-                                          4, clidp->data, clidp->len,
-                                          5, mode, 4,
-                                          6, tmp2, 4,
-                                          7, keyp->data, keyp->len,
-                                          10, channel->topic, 
-                                          strlen(channel->topic),
-                                          12, tmp3, 4,
-                                          13, user_list->data, user_list->len,
-                                          14, mode_list->data, 
-                                          mode_list->len);
-  }
+  reply = 
+    silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
+                                        SILC_STATUS_OK, ident, 13,
+                                        2, channel->channel_name,
+                                        strlen(channel->channel_name),
+                                        3, chidp->data, chidp->len,
+                                        4, clidp->data, clidp->len,
+                                        5, mode, 4,
+                                        6, tmp2, 4,
+                                        7, keyp->data, keyp->len,
+                                        8, channel->ban_list, 
+                                        channel->ban_list ?
+                                        strlen(channel->ban_list) : 0,
+                                        9, channel->invite_list,
+                                        channel->invite_list ?
+                                        strlen(channel->invite_list) : 0,
+                                        10, channel->topic,
+                                        channel->topic ?
+                                        strlen(channel->topic) : 0,
+                                        11, channel->hmac->hmac->name,
+                                        strlen(channel->hmac->hmac->name),
+                                        12, tmp3, 4,
+                                        13, user_list->data, user_list->len,
+                                        14, mode_list->data, 
+                                        mode_list->len);
 
   /* Send command reply */
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
@@ -3338,12 +3345,12 @@ SILC_SERVER_CMD_FUNC(cmode)
       }
     } else {
       SILC_GET32_MSB(user_limit, tmp);
-      channel->mode_data.user_limit = user_limit;
+      channel->user_limit = user_limit;
     }
   } else {
     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
       /* User limit mode is unset. Remove user limit */
-      channel->mode_data.user_limit = 0;
+      channel->user_limit = 0;
   }
 
   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
@@ -3359,66 +3366,14 @@ SILC_SERVER_CMD_FUNC(cmode)
       }
 
       /* Save the passphrase */
-      channel->mode_data.passphrase = strdup(tmp);
+      channel->passphrase = strdup(tmp);
     }
   } else {
     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
       /* Passphrase mode is unset. remove the passphrase */
-      if (channel->mode_data.passphrase) {
-       silc_free(channel->mode_data.passphrase);
-       channel->mode_data.passphrase = NULL;
-      }
-    }
-  }
-
-  if (mode_mask & SILC_CHANNEL_MODE_BAN) {
-    if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
-      /* Ban list is specified for channel */
-
-      /* Get ban list */
-      tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
-      if (!tmp) {
-       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                  SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-       goto out;
-      }
-
-      /* XXX check that channel founder is not banned */
-
-      /* Save the ban list */
-      channel->mode_data.ban_list = strdup(tmp);
-    }
-  } else {
-    if (channel->mode & SILC_CHANNEL_MODE_BAN) {
-      /* Ban mode is unset. Remove the entire ban list */
-      if (channel->mode_data.ban_list) {
-       silc_free(channel->mode_data.ban_list);
-       channel->mode_data.ban_list = NULL;
-      }
-    }
-  }
-
-  if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
-    if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
-      /* Invite list is specified for channel */
-
-      /* Get invite list */
-      tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
-      if (!tmp) {
-       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                  SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-       goto out;
-      }
-
-      /* Save the invite linst */
-      channel->mode_data.invite_list = strdup(tmp);
-    }
-  } else {
-    if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
-      /* Invite list mode is unset. Remove the entire invite list */
-      if (channel->mode_data.invite_list) {
-       silc_free(channel->mode_data.invite_list);
-       channel->mode_data.invite_list = NULL;
+      if (channel->passphrase) {
+       silc_free(channel->passphrase);
+       channel->passphrase = NULL;
       }
     }
   }
@@ -3481,12 +3436,7 @@ SILC_SERVER_CMD_FUNC(cmode)
     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
       /* Cipher mode is unset. Remove the cipher and revert back to 
         default cipher */
-
-      if (channel->mode_data.cipher) {
-       silc_free(channel->mode_data.cipher);
-       channel->mode_data.cipher = NULL;
-       channel->mode_data.key_len = 0;
-      }
+      char *cipher = channel->channel_key->cipher->name;
 
       /* Generate new cipher and key for the channel */
 
@@ -3494,14 +3444,10 @@ SILC_SERVER_CMD_FUNC(cmode)
 
       /* Delete old cipher and allocate default one */
       silc_cipher_free(channel->channel_key);
-      if (!channel->cipher)
-       silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
-      else {
-       if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
-         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
-         goto out;
-       }
+      if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+                                  SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
+       goto out;
       }
 
       /* Re-generate channel key */
@@ -4422,3 +4368,139 @@ SILC_SERVER_CMD_FUNC(users)
  out:
   silc_server_command_free(cmd);
 }
+
+/* Server side of command BAN. This is used to manage the ban list of the
+   channel. To add clients and remove clients from the ban list. */
+
+SILC_SERVER_CMD_FUNC(ban)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcBuffer packet;
+  SilcChannelEntry channel;
+  SilcChannelClientEntry chl;
+  SilcChannelID *channel_id = NULL;
+  unsigned char *id, *add, *del;
+  unsigned int id_len, tmp_len;
+  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_BAN, cmd, 0, 3);
+
+  /* Get Channel ID */
+  id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+  if (id) {
+    channel_id = silc_id_payload_parse_id(id, id_len);
+    if (!channel_id) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
+      goto out;
+    }
+  }
+
+  /* Get channel entry. The server must know about the channel since the
+     client is expected to be on the channel. */
+  channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                          channel_id, NULL);
+  if (!channel) {
+    channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+      goto out;
+    }
+  }
+
+  /* Check whether this client is on the channel */
+  if (!silc_server_client_on_channel(client, channel)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NOT_ON_CHANNEL);
+    goto out;
+  }
+
+  /* Get entry to the channel user list */
+  silc_list_start(channel->user_list);
+  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+    if (chl->client == client)
+      break;
+
+  /* The client must be at least channel operator. */
+  if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+    goto out;
+  }
+
+  /* Get the new ban and add it to the ban list */
+  add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (add) {
+    if (!channel->ban_list)
+      channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
+    else
+      channel->ban_list = silc_realloc(channel->ban_list, 
+                                      sizeof(*channel->ban_list) * 
+                                      (tmp_len + 
+                                       strlen(channel->ban_list) + 2));
+    strncat(channel->ban_list, add, tmp_len);
+    strncat(channel->ban_list, ",", 1);
+  }
+
+  /* Get the ban to be removed and remove it from the list */
+  del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+  if (del && channel->ban_list) {
+    char *start, *end, *n;
+
+    if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
+      silc_free(channel->ban_list);
+      channel->ban_list = NULL;
+      goto out0;
+    }
+
+    start = strstr(channel->ban_list, del);
+    if (start && strlen(start) >= tmp_len) {
+      end = start + tmp_len;
+      n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
+      strncat(n, channel->ban_list, start - channel->ban_list);
+      strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
+                          end) - 1);
+      silc_free(channel->ban_list);
+      channel->ban_list = n;
+    }
+  }
+
+ out0:
+
+  /* Send the BAN notify type to our primary router. */
+  if (!server->standalone && (add || del))
+    silc_server_send_notify_ban(server, server->router->connection,
+                               server->server_type == SILC_ROUTER ?
+                               TRUE : FALSE, channel, add, del);
+
+  /* Send the reply back to the client */
+  if (channel->ban_list)
+    packet = 
+      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+                                          SILC_STATUS_OK, ident, 2,
+                                          2, id, id_len,
+                                          3, channel->ban_list, 
+                                          strlen(channel->ban_list) - 1);
+  else
+    packet = 
+      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+                                          SILC_STATUS_OK, ident, 1,
+                                          2, id, id_len);
+
+  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                         packet->data, packet->len, FALSE);
+    
+  silc_buffer_free(packet);
+
+ out:
+  if (channel_id)
+    silc_free(channel_id);
+  silc_server_command_free(cmd);
+}
index 8fc42e1ed2fa91b7e4fae50478e1b2da0ec02ed9..f8b7a5fe20088bef9c6b6de4a2ad3874b7637fb5 100644 (file)
@@ -154,5 +154,6 @@ SILC_SERVER_CMD_FUNC(shutdown);
 SILC_SERVER_CMD_FUNC(silcoper);
 SILC_SERVER_CMD_FUNC(leave);
 SILC_SERVER_CMD_FUNC(users);
+SILC_SERVER_CMD_FUNC(ban);
 
 #endif
index b693e2f3711bf1c6eb110b614f5dc8945afe1680..37c2838d8001511c1fc0e6722f9d56e140f84f2d 100644 (file)
@@ -724,6 +724,32 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     silc_free(id);
   }
 
+  /* Get the ban list */
+  tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
+  if (tmp) {
+    if (entry->ban_list)
+      silc_free(entry->ban_list);
+    entry->ban_list = silc_calloc(len, sizeof(*entry->ban_list));
+    memcpy(entry->ban_list, tmp, len);
+  }
+
+  /* Get the invite list */
+  tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
+  if (tmp) {
+    if (entry->invite_list)
+      silc_free(entry->invite_list);
+    entry->invite_list = silc_calloc(len, sizeof(*entry->invite_list));
+    memcpy(entry->invite_list, tmp, len);
+  }
+
+  /* Get the topic */
+  tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
+  if (tmp) {
+    if (entry->topic)
+      silc_free(entry->topic);
+    entry->topic = strdup(tmp);
+  }
+
   /* If channel was not created we know there is global users on the 
      channel. */
   entry->global_users = (created == 0 ? TRUE : FALSE);
index efca0dbf03cfd73ceee9a94840e641f6baba405d..1198e58af567fba7b9df9514e79700042771e27a 100644 (file)
@@ -211,8 +211,7 @@ typedef struct SilcChannelClientEntryStruct {
 
    char username
 
-       Client's (meaning user's) real name. This is defined in following 
-       manner:
+       Client's usename. This is defined in the following manner:
 
        Server type   List type      Contents
        ====================================================
@@ -390,15 +389,10 @@ struct SilcChannelEntryStruct {
   char *topic;
   char *cipher;
 
-  /* Data that is related to different channel modes. */
-  struct {
-    unsigned int user_limit;
-    unsigned char *passphrase;
-    unsigned char *ban_list;
-    unsigned char *invite_list;
-    unsigned char *cipher;
-    unsigned int key_len;
-  } mode_data;
+  unsigned int user_limit;
+  unsigned char *passphrase;
+  char *invite_list;
+  char *ban_list;
 
   /* List of users on channel */
   SilcList user_list;
index 16e9fa430f1d5f9ed0106329a393ffcd6bd70d94..a938e53c86a21d5fd1e5fb9030c7565ec5098e8c 100644 (file)
@@ -663,6 +663,74 @@ void silc_server_notify(SilcServer server,
 
     break;
 
+  case SILC_NOTIFY_TYPE_BAN:
+    /*
+     * Save the ban
+     */
+
+    SILC_LOG_DEBUG(("BAN notify"));
+    
+    /* Get Channel ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp)
+      goto out;
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!channel_id)
+      goto out;
+    
+    /* Get channel entry */
+    channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                              channel_id, NULL);
+      if (!channel) {
+       silc_free(channel_id);
+       goto out;
+      }
+    }
+    silc_free(channel_id);
+
+    /* Get the new ban and add it to the ban list */
+    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+    if (tmp) {
+      if (!channel->ban_list)
+       channel->ban_list = silc_calloc(tmp_len + 2, 
+                                       sizeof(*channel->ban_list));
+      else
+       channel->ban_list = silc_realloc(channel->ban_list, 
+                                        sizeof(*channel->ban_list) * 
+                                        (tmp_len + 
+                                         strlen(channel->ban_list) + 2));
+      strncat(channel->ban_list, tmp, tmp_len);
+      strncat(channel->ban_list, ",", 1);
+    }
+
+    /* Get the ban to be removed and remove it from the list */
+    tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+    if (tmp && channel->ban_list) {
+      char *start, *end, *n;
+      
+      if (!strcmp(channel->ban_list, tmp)) {
+       silc_free(channel->ban_list);
+       channel->ban_list = NULL;
+       break;
+      }
+      
+      start = strstr(channel->ban_list, tmp);
+      if (start && strlen(start) >= tmp_len) {
+       end = start + tmp_len;
+       n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
+       strncat(n, channel->ban_list, start - channel->ban_list);
+       strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
+                            end) - 1);
+       silc_free(channel->ban_list);
+       channel->ban_list = n;
+      }
+    }
+
+    break;
+
     /* Ignore rest of the notify types for now */
   case SILC_NOTIFY_TYPE_NONE:
   case SILC_NOTIFY_TYPE_MOTD:
index 7cd1767981447910a54c47e52a9d3c840c0afad8..2dba70f34e4a2c6e4ed17eb294bc92c1066eeea0 100644 (file)
@@ -1125,6 +1125,27 @@ void silc_server_send_notify_umode(SilcServer server,
   silc_buffer_free(idp);
 }
 
+/* Sends BAN notify type. This tells that `ban' has been either `add'ed
+   or `del'eted on the `channel. This function is used to send the packet
+   between routers as broadcast packet. */
+
+void silc_server_send_notify_ban(SilcServer server,
+                                SilcSocketConnection sock,
+                                int broadcast,
+                                SilcChannelEntry channel,
+                                char *add, char *del)
+{
+  SilcBuffer idp;
+
+  idp = silc_id_payload_encode((void *)channel->id, SILC_ID_CHANNEL);
+  silc_server_send_notify(server, sock, broadcast,
+                         SILC_NOTIFY_TYPE_BAN, 3,
+                         idp->data, idp->len,
+                         add, add ? strlen(add) : 0,
+                         del, del ? strlen(del) : 0);
+  silc_buffer_free(idp);
+}
+
 /* Sends notify message destined to specific entity. */
 
 void silc_server_send_notify_dest(SilcServer server,
index 29b349286c0f8baee00e9812aae211bcceec8f1a..b856e0e44bf01ad1a8efb8e8c6c085510467f70f 100644 (file)
@@ -174,6 +174,11 @@ void silc_server_send_notify_umode(SilcServer server,
                                   SilcClientID *client_id,
                                   unsigned int client_id_len,
                                   unsigned int mode_mask);
+void silc_server_send_notify_ban(SilcServer server,
+                                SilcSocketConnection sock,
+                                int broadcast,
+                                SilcChannelEntry channel,
+                                char *add, char *del);
 void silc_server_send_notify_dest(SilcServer server,
                                  SilcSocketConnection sock,
                                  int broadcast,
index 42ed3eae557fcc11cf459bdcbb77c8bacb6813ad..1eaa60712ab7aae1843e23183e8026d08547a0f6 100644 (file)
@@ -1,17 +1,23 @@
 [Cipher]
-rc6:../lib/silcsim/modules/rc6.sim.so:16:16
-twofish:../lib/silcsim/modules/twofish.sim.so:16:16
-mars:../lib/silcsim/modules/mars.sim.so:16:16
+aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16
+aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
+aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
+twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
+twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
+twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
+mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
+mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
+mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16
 none:../lib/silcsim/modules/none.sim.so:0:0
 
-[Hash] 
+[Hash]
 md5::64:16
 sha1::64:20
 
 [hmac]
 hmac-sha1-96:sha1:12
 hmac-md5-96:md5:12
-hmac-sha1:sha1:20
+hmac-sha1:sha1:20   
 hmac-md5:md5:16
 
 #[PKCS]
@@ -25,10 +31,10 @@ nobody:nobody
 Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
 
 [ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
 
 [ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.42.253:212.146.42.253:1334
 
 [Logging]
 infologfile:silcd2.log:10000
@@ -47,16 +53,13 @@ errorlogfile:silcd2.log:10000
 :::1336:1
 
 [AdminConnection]
-*:silc:silc:passwd:testi
+*:priikone:*:passwd:testi
 
 [ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.42.253:passwd:priikone:1333:1:1
 
 [RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.42.253:passwd:priikone:1335:1:1:0
 
 [DenyConnection]
 [RedirectClient]
-
-[motd]
-./motd
index 2f6582887c555fd8078272b7b213248bc54847e5..d641e083f55b5f31f5d99d2dad755cbc184de5f6 100644 (file)
@@ -2264,7 +2264,7 @@ List of all defined commands in SILC follows.
    7    SILC_COMMAND_INVITE
 
         Max Arguments:  4
-            Arguments:  (1) [<Client ID>]      (2) [<Channel ID>]
+            Arguments:  (1) [<Client ID>]      (2) <Channel ID>
                         (3) [<adding client>]  (4) [<removing client>]
 
         This command is used to invite other clients to join to the
@@ -2294,12 +2294,12 @@ List of all defined commands in SILC follows.
         nickname and hostname and add to the invite list before sending
         the notify packet.
         
-        When this command is given without any arguments then the command
-        merely returns the invite list of the channel.   This command must
-        fail if the requested channel does not exist, the requested
-        <Client ID> is already on the channel or if the channel is invite
-        only channel and the caller of this command does not have at least
-        channel operator privileges.
+        When this command is given with only <Channel ID> argument then
+        the command merely returns the invite list of the channel.   This
+        command must fail if the requested channel does not exist, the
+        requested <Client ID> is already on the channel or if the channel
+        is invite only channel and the caller of this command does not
+        have at least channel operator privileges.
 
         Reply messages to the command:
 
@@ -2551,7 +2551,7 @@ List of all defined commands in SILC follows.
             Arguments:  (1) <Status Payload>      (2) <channel> 
                         (3) <Channel ID>          (4) <Client ID>
                         (5) <channel mode mask>   (6) <created>
-                        (7) <Channel Key Payload> (8) [<ban mask>]
+                        (7) <Channel Key Payload> (8) [<ban list>]
                         (9) [<invite list>]       (10) [<topic>]
                         (11) [<hmac>]             (12) <list count>
                         (13) <Client ID list>     (14) <client mode list>
@@ -3162,7 +3162,7 @@ List of all defined commands in SILC follows.
    26   SILC_COMMAND_BAN
 
         Max Arguments:  3
-            Arguments:  (1) [<Channel ID>]       (2) [<adding client>]
+            Arguments:  (1) <Channel ID>         (2) [<adding client>]
                         (3) [<removing client>]
 
         This command is used to manage the ban list of the channel
@@ -3183,7 +3183,7 @@ List of all defined commands in SILC follows.
         from than one clients then the lists are an comma (`,') separated
         list.
 
-        If this command is executed without any arguments the command
+        If this command is executed without the ban arguments the command
         merely replies with the current ban list.
 
 
@@ -3202,6 +3202,7 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NOT_REGISTERED
             SILC_STATUS_ERR_TOO_MANY_PARAMS
             SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID
+            SILC_STATUS_ERR_NO_CHANNEL_ID
             SILC_STATUS_ERR_NOT_ON_CHANNEL
             SILC_STATUS_ERR_NO_CHANNEL_PRIV
 
index 002363fb305077eb4b8410759d1bd845275e2e3b..1ef9975d122c6d08c6b88315710a5b067fee61ff 100644 (file)
@@ -58,6 +58,7 @@ SilcClientCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 3),
   SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", SILC_CF_LAG | SILC_CF_REG, 2),
   SILC_CLIENT_CMD(users, USERS, "USERS", SILC_CF_LAG | SILC_CF_REG, 2),
+  SILC_CLIENT_CMD(ban, BAN, "BAN", SILC_CF_LAG | SILC_CF_REG, 3),
 
   { NULL, 0, NULL, 0, 0 },
 };
@@ -1180,26 +1181,6 @@ SILC_CLIENT_CMD_FUNC(cmode)
        mode &= ~SILC_CHANNEL_MODE_PASSPHRASE;
       }
       break;
-    case 'b':
-      if (add) {
-       mode |= SILC_CHANNEL_MODE_BAN;
-       type = 5;
-       arg = cmd->argv[3];
-       arg_len = cmd->argv_lens[3];
-      } else {
-       mode &= ~SILC_CHANNEL_MODE_BAN;
-      }
-      break;
-    case 'I':
-      if (add) {
-       mode |= SILC_CHANNEL_MODE_INVITE_LIST;
-       type = 6;
-       arg = cmd->argv[3];
-       arg_len = cmd->argv_lens[3];
-      } else {
-       mode &= ~SILC_CHANNEL_MODE_INVITE_LIST;
-      }
-      break;
     case 'c':
       if (add) {
        mode |= SILC_CHANNEL_MODE_CIPHER;
@@ -1963,3 +1944,80 @@ SILC_CLIENT_CMD_FUNC(users)
  out:
   silc_client_command_free(cmd);
 }
+
+/* Command BAN. This is used to manage the ban list of the channel. */
+
+SILC_CLIENT_CMD_FUNC(ban)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcChannelEntry channel;
+  SilcBuffer buffer, chidp;
+  int type = 0;
+  char *name, *ban = NULL;
+
+  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: /BAN <channel> "
+                  "[+|-[<nickname>[@<server>[!<username>[@hostname>]]]]]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argv[1][0] == '*') {
+    if (!conn->current_channel) {
+      cmd->client->ops->say(cmd->client, conn, "You are not on any channel");
+      COMMAND_ERROR;
+      goto out;
+    }
+
+    channel = conn->current_channel;
+  } else {
+    name = cmd->argv[1];
+
+    channel = silc_client_get_channel(cmd->client, conn, name);
+    if (!channel) {
+      cmd->client->ops->say(cmd->client, conn, "You are on that channel");
+      COMMAND_ERROR;
+      goto out;
+    }
+  }
+
+  if (cmd->argc == 3) {
+    if (cmd->argv[2][0] == '+')
+      type = 2;
+    else
+      type = 3;
+
+    ban = cmd->argv[2];
+    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);
+
+  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(chidp);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
index fad677509858c2500843ece9ac3dd30761b07410..64af6d8ca24c78fa2ec576b6439da4fe63c21f17 100644 (file)
@@ -153,5 +153,6 @@ SILC_CLIENT_CMD_FUNC(shutdown);
 SILC_CLIENT_CMD_FUNC(silcoper);
 SILC_CLIENT_CMD_FUNC(leave);
 SILC_CLIENT_CMD_FUNC(users);
+SILC_CLIENT_CMD_FUNC(ban);
 
 #endif
index 261578cf17a8b19cb0723088875106c39a41cda0..a97b23529fef89d2c432f04a57c6906f384b119c 100644 (file)
@@ -63,6 +63,7 @@ SilcClientCommandReply silc_command_reply_list[] =
   SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER),
   SILC_CLIENT_CMD_REPLY(leave, LEAVE),
   SILC_CLIENT_CMD_REPLY(users, USERS),
+  SILC_CLIENT_CMD_REPLY(ban, BAN),
 
   { NULL, 0 },
 };
@@ -679,7 +680,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
   if (!channel_id)
     goto out;
 
-  /* Get the channel name */
+  /* Get the channel entry */
   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
                                   SILC_ID_CHANNEL, &id_cache)) {
     silc_free(channel_id);
@@ -1646,3 +1647,56 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
   silc_client_command_reply_free(cmd);
 }
+
+SILC_CLIENT_CMD_REPLY_FUNC(ban)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+  SilcCommandStatus status;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcChannelEntry channel;
+  SilcChannelID *channel_id;
+  unsigned char *tmp;
+  unsigned int len;
+
+  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;
+  }
+
+  /* Take Channel ID */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (!tmp)
+    goto out;
+
+  channel_id = silc_id_payload_parse_id(tmp, len);
+  if (!channel_id)
+    goto out;
+
+  /* Get the channel entry */
+  if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
+                                  SILC_ID_CHANNEL, &id_cache)) {
+    silc_free(channel_id);
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+  
+  channel = (SilcChannelEntry)id_cache->context;
+
+  /* Get the ban list */
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+
+  /* Notify application */
+  COMMAND_REPLY((ARGS, channel, tmp));
+
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN);
+
+ out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_BAN);
+  silc_client_command_reply_free(cmd);
+}
index de788130172d2f8716bc61094ec33ffebbbeddb9..f1ebd1c3c3d20a6f8754e4b1c8c53a06e87fa954 100644 (file)
@@ -98,5 +98,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown);
 SILC_CLIENT_CMD_REPLY_FUNC(silcoper);
 SILC_CLIENT_CMD_REPLY_FUNC(leave);
 SILC_CLIENT_CMD_REPLY_FUNC(users);
+SILC_CLIENT_CMD_REPLY_FUNC(ban);
 
 #endif
index 3185fe305cb064810752a2e2d6ea7b5e54206f37..784bd5bb47bc2be746b52621dcf5657b9d797f39 100644 (file)
@@ -195,7 +195,7 @@ SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
   unsigned int x_len;
   unsigned int x_type;
   SilcBuffer buffer;
-  int i;
+  int i, k;
 
   va_start(ap, argc);
 
@@ -203,21 +203,25 @@ SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
   argv_lens = silc_calloc(argc, sizeof(unsigned int));
   argv_types = silc_calloc(argc, sizeof(unsigned int));
 
-  for (i = 0; i < argc; i++) {
+  for (i = 0, k = 0; i < argc; i++) {
     x_type = va_arg(ap, unsigned int);
     x = va_arg(ap, unsigned char *);
     x_len = va_arg(ap, unsigned int);
 
-    argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
-    memcpy(argv[i], x, x_len);
-    argv_lens[i] = x_len;
-    argv_types[i] = x_type;
+    if (!x_type || !x || !x_len)
+      continue;
+
+    argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+    memcpy(argv[k], x, x_len);
+    argv_lens[k] = x_len;
+    argv_types[k] = x_type;
+    k++;
   }
 
-  buffer = silc_command_payload_encode(cmd, argc, argv
-                                      argv_lens, argv_types, ident);
+  buffer = silc_command_payload_encode(cmd, k, argv, argv_lens
+                                      argv_types, ident);
 
-  for (i = 0; i < argc; i++)
+  for (i = 0; i < k; i++)
     silc_free(argv[i]);
   silc_free(argv);
   silc_free(argv_lens);
@@ -238,27 +242,31 @@ SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd,
   unsigned int x_len;
   unsigned int x_type;
   SilcBuffer buffer;
-  int i;
+  int i, k;
 
   argv = silc_calloc(argc, sizeof(unsigned char *));
   argv_lens = silc_calloc(argc, sizeof(unsigned int));
   argv_types = silc_calloc(argc, sizeof(unsigned int));
 
-  for (i = 0; i < argc; i++) {
+  for (i = 0, k = 0; i < argc; i++) {
     x_type = va_arg(ap, unsigned int);
     x = va_arg(ap, unsigned char *);
     x_len = va_arg(ap, unsigned int);
 
-    argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
-    memcpy(argv[i], x, x_len);
-    argv_lens[i] = x_len;
-    argv_types[i] = x_type;
+    if (!x_type || !x || !x_len)
+      continue;
+
+    argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+    memcpy(argv[k], x, x_len);
+    argv_lens[k] = x_len;
+    argv_types[k] = x_type;
+    k++;
   }
 
-  buffer = silc_command_payload_encode(cmd, argc, argv
-                                      argv_lens, argv_types, ident);
+  buffer = silc_command_payload_encode(cmd, k, argv, argv_lens
+                                      argv_types, ident);
 
-  for (i = 0; i < argc; i++)
+  for (i = 0; i < k; i++)
     silc_free(argv[i]);
   silc_free(argv);
   silc_free(argv_lens);
@@ -286,7 +294,7 @@ silc_command_reply_payload_encode_va(SilcCommand cmd,
   unsigned int x_len;
   unsigned int x_type;
   SilcBuffer buffer;
-  int i;
+  int i, k;
 
   va_start(ap, argc);
 
@@ -301,21 +309,25 @@ silc_command_reply_payload_encode_va(SilcCommand cmd,
   argv_lens[0] = sizeof(status_data);
   argv_types[0] = 1;
 
-  for (i = 1; i < argc; i++) {
+  for (i = 1, k = 1; i < argc; i++) {
     x_type = va_arg(ap, unsigned int);
     x = va_arg(ap, unsigned char *);
     x_len = va_arg(ap, unsigned int);
 
-    argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
-    memcpy(argv[i], x, x_len);
-    argv_lens[i] = x_len;
-    argv_types[i] = x_type;
+    if (!x_type || !x || !x_len)
+      continue;
+
+    argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+    memcpy(argv[k], x, x_len);
+    argv_lens[k] = x_len;
+    argv_types[k] = x_type;
+    k++;
   }
 
-  buffer = silc_command_payload_encode(cmd, argc, argv
-                                      argv_lens, argv_types, ident);
+  buffer = silc_command_payload_encode(cmd, k, argv, argv_lens
+                                      argv_types, ident);
 
-  for (i = 0; i < argc; i++)
+  for (i = 0; i < k; i++)
     silc_free(argv[i]);
   silc_free(argv);
   silc_free(argv_lens);
index d1e739b18e2862f1b18310174b796dde5610bda6..d8f80ca25d28024cd7efd44a343724fd2bfeed56 100644 (file)
@@ -83,27 +83,31 @@ SilcBuffer silc_notify_payload_encode(SilcNotifyType type, unsigned int argc,
   unsigned int *argv_lens = NULL, *argv_types = NULL;
   unsigned char *x;
   unsigned int x_len;
-  int i, len = 0;
+  int i, k, len = 0;
 
   if (argc) {
     argv = silc_calloc(argc, sizeof(unsigned char *));
     argv_lens = silc_calloc(argc, sizeof(unsigned int));
     argv_types = silc_calloc(argc, sizeof(unsigned int));
     
-    for (i = 0; i < argc; i++) {
+    for (i = 0, k = 0; i < argc; i++) {
       x = va_arg(ap, unsigned char *);
       x_len = va_arg(ap, unsigned int);
+
+      if (!x || !x_len)
+       continue;
       
-      argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
-      memcpy(argv[i], x, x_len);
-      argv_lens[i] = x_len;
-      argv_types[i] = i + 1;
+      argv[k] = silc_calloc(x_len + 1, sizeof(unsigned char));
+      memcpy(argv[k], x, x_len);
+      argv_lens[k] = x_len;
+      argv_types[k] = i + 1;
+      k++;
     }
 
-    args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
+    args = silc_argument_payload_encode(k, argv, argv_lens, argv_types);
     len = args->len;
 
-    for (i = 0; i < argc; i++)
+    for (i = 0; i < k; i++)
       silc_free(argv[i]);
     silc_free(argv);
     silc_free(argv_lens);
@@ -116,10 +120,10 @@ SilcBuffer silc_notify_payload_encode(SilcNotifyType type, unsigned int argc,
   silc_buffer_format(buffer,
                     SILC_STR_UI_SHORT(type),
                     SILC_STR_UI_SHORT(len),
-                    SILC_STR_UI_CHAR(argc),
+                    SILC_STR_UI_CHAR(k),
                     SILC_STR_END);
 
-  if (argc) {
+  if (k) {
     silc_buffer_pull(buffer, 5);
     silc_buffer_format(buffer,
                       SILC_STR_UI_XNSTRING(args->data, args->len),
index c6d9dd308a4eb205a48874bf21e3c8fb2f6278ac..ba4b9cc7bcbd39226373bb6d0a492d55714143cb 100644 (file)
@@ -602,26 +602,21 @@ int silc_string_compare(char *string1, char *string2)
 }
 
 /* Inspects the `string' for wildcards and returns regex string that can
-   be used by the GNU regex library. This has a lot overhead but luckily
-   this is used only for short strings. */
+   be used by the GNU regex library. A comma (`,') in the `string' means
+   that the string is list. */
 
 char *silc_string_regexify(const char *string)
 {
   int i, len, count;
   char *regex;
 
-  /* If there is no wildcards then we don't need to regexify the string. */
-  if (!strchr(string, '*') && !strchr(string, '?'))
-    return strdup(string);
-
   len = strlen(string);
-  count = 0;
-
+  count = 4;
   for (i = 0; i < len; i++)
     if (string[i] == '*' || string[i] == '?')
       count++;
 
-  regex = silc_calloc(len + count + 4, sizeof(*regex));
+  regex = silc_calloc(len + count, sizeof(*regex));
 
   count = 0;
   regex[count] = '(';
@@ -631,6 +626,10 @@ char *silc_string_regexify(const char *string)
     if (string[i] == '*' || string[i] == '?') {
       regex[count] = '.';
       count++;
+    } else if (string[i] == ',') {
+      regex[count] = '|';
+      count++;
+      continue;
     }
 
     regex[count] = string[i];
@@ -656,9 +655,9 @@ char *silc_string_regex_combine(const char *string1, const char *string2)
   len2 = strlen(string2);
 
   tmp = silc_calloc(2 + len1 + len2, sizeof(*tmp));
-  memcpy(tmp, string1, len1 - 2);
-  memcpy(tmp, "|", 1);
-  memcpy(tmp, string2 + 1, len2 - 1);
+  strncat(tmp, string1, len1 - 2);
+  strncat(tmp, "|", 1);
+  strncat(tmp, string2 + 1, len2 - 1);
 
   return tmp;
 }
@@ -680,3 +679,18 @@ int silc_string_regex_match(const char *regex, const char *string)
 
   return ret;
 }
+
+/* Do regex match to the two strings `string1' and `string2'. If the
+   `string2' matches the `string1' this returns TRUE. */
+
+int silc_string_match(const char *string1, const char *string2)
+{
+  char *s1;
+  int ret = FALSE;
+
+  s1 = silc_string_regexify(string1);
+  ret = silc_string_regex_match(s1, string2);
+  silc_free(s1);
+
+  return ret;
+}
index d58909e03b14116408e1966b8e076155b01698b6..dc6196769afef3667dfc29d98b4780d50da74e70 100644 (file)
@@ -47,5 +47,6 @@ char *silc_id_render(void *id, unsigned short type);
 int silc_string_compare(char *string1, char *string2);
 char *silc_string_regexify(const char *string);
 int silc_string_regex_match(const char *regex, const char *string);
+int silc_string_match(const char *string1, const char *string2);
 
 #endif