Started implementing protocol version 1.1 and narrowing down
authorPekka Riikonen <priikone@silcnet.org>
Wed, 3 Apr 2002 18:27:43 +0000 (18:27 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 3 Apr 2002 18:27:43 +0000 (18:27 +0000)
TODO list, see CHANGES.

31 files changed:
CHANGES
TODO
apps/irssi/docs/help/in/cmode.in
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/client_ops.h
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/protocol.c
apps/silcd/server_util.c
doc/draft-riikonen-silc-commands-03.nroff
doc/draft-riikonen-silc-pp-05.nroff
doc/draft-riikonen-silc-spec-05.nroff
doc/example_silcd.conf.in
lib/silcclient/client_channel.c
lib/silcclient/client_notify.c
lib/silcclient/client_ops_example.c
lib/silcclient/client_prvmsg.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/silcclient.h
lib/silccore/silcchannel.h
lib/silccore/silccommand.h
lib/silccore/silcmode.h
lib/silcutil/silcutil.c
prepare

diff --git a/CHANGES b/CHANGES
index a372c867d8a1931f72ef48d5f9f2c7fe6ce51119..299db091a746c76abf534389c6622aad3e0907eb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,76 @@
+Wed Apr  3 16:24:51 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Upgraded the protocol version to 1.1, updated protocol specs
+         and software.
+
+       * Added the nickname as new argument to NICK_CHANGE notify and
+         added it to protocol specs and implemented it to client and
+         server.  Protocol TODO #3.  Affected files are silcd/idlist.[ch],
+         silcd/command.c, silcd/packet_receive.c, packet_send.[ch], and
+         lib/silcclient/client_notify.c.
+
+       * Added the killer's client ID to the KILLED notify and added
+         it to protocol specs and implemented it to client and server.
+         Protocol TODO #13.  Affected files are silcd/command.c,
+         silcd/packet_receive.c, packet_send.[ch], 
+         lib/silcclient/client_notify.c, irssi/src/silc/core/client_ops.c.
+         The killer's client entry is now returned to application in
+         the `notify' client operation.
+
+       * Fixed the Max Argument fields that had too large value set
+         in the protocol specs.  Protocol TODO #14.
+
+       * Added the LEAVE command reply to return the ID of parted
+         channel.  Updated protocol specs and implemented it to the
+         client and server.  Protocol TODO #15.  Affected files are
+         silcd/command.c, lib/silcclient/command_reply.c.  The channel
+         entry is now returned to application in the `command_reply'
+         client operation.
+
+       * Rewrote the version SKE version checking in client libary
+         and in server to use the silc_parse_version_string.  Affected
+         files are lib/silcclient/protocol.c, silcd/protocol.c.
+
+       * Added SILC_STATUS_ERR_NO_CHANNEL_FOPRIV error status to few
+         commands that was missing it, and updated protocol specs and
+         the server implementation.  Protocol TODO #10.  The affected
+         file is silcd/command.c.
+
+       * Defined new message flags SILC_MESSAGE_FLAG_REPLY to be
+         generic reply to a generic request (REQUEST flag), and
+         SILC_MESSAGE_FLAG_DATA to send any kind of data in a generic
+         way.  A draft-riikonen-silc-flags-payloads-00.txt is written
+         to define the payload for DATA flag.  Added the flags to
+         the implementation.  Protocol TODO #9.  Affected file is
+         lib/silccore/silcchannel.h.
+
+         Changed the client library to return the message length
+         to application as well in the channel_message and private_message
+         client operations.  Affected files are 
+         lib/silcclient/client_prvmsg, lib/silcclient/client_channel.c,
+         lib/silcclient/silcclient.h, irssi/src/silc/core/client_ops.c,
+         and lib/silcclient/client_ops_example.c.
+
+       * Added two new channel modes: SILC_CMODE_SILENCE_USERS
+         and SILC_CMODE_SILENCE_OPERS which can be used to moderate
+         the channel.  Updated protocol specs and impelemented this
+         to client and server.  Protocol TODO #6.  Affected files are
+         silcd/packet_receive.c, server_util.c, lib/silcclient/command.c,
+         lib/silcclient/client_channel.c, lib/silccore/silcmode.h.
+
+         Added new options m and M to CMODE command in Irssi SILC
+         client to set these modes.
+
+       * Deprecated all administrative commands from SILC protocol
+         since they are highly implementation specific commands.
+         Updated protocol specs.  Moved the old commands in 
+         implementations to private range of command types.  Affected
+         files are silcd/command.c, lib/silcclient/command.c and
+         lib/silcclient/command_reply.c.  Protocol TODO #8.
+
+       * Fixed a bug in server where sending unknown command crashes
+         the server.  Affected file silcd/command.c.
+
 Wed Apr  3 09:57:47 CEST 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SILC_PROTOCOLVERSION macro to check protocol version
diff --git a/TODO b/TODO
index d7ff4d8eb3d146811b16c4786ea78a071de06c4a..7c8615e57892e1fa15ed606392b445d5a25c47c6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -16,10 +16,6 @@ TODO/bugs In SILC Client Library
 
  o Additions to do after protocol version 1.1:
 
-       o Fix the NICK_CHANGE notify handling not to create new entry
-         for the changed client, but take the nickname from the notify
-         (removes need for resolving as well).  Protocol TODO entry 3.
-
        o Add support for list of errors in command replies.  Protocol
          TODO entry 1.
 
@@ -44,7 +40,6 @@ TODO/bugs In SILC Server
 
        o JOIN (check that joining is allowed)
        o SIGNOFF (maybe should check that notifier owns the client)
-       o KILLED (check that killling is allowed (Protocol TODO #13))
 
  o Backup router related issues (Fix this to 1.0):
 
@@ -128,13 +123,6 @@ describe new stuff to be added to protocol versions 1.x.
     *after* sending successfully found entries (this way receiver may
     ignore them).  To be included in protocol version 1.1.
 
- 3. Define the NICK_CHANGE notify to send the changed nickname as a new
-    third argument.  This will make the NICK_CHANGE notify handling easier
-    in the receiver's end (client primarily) since it removes the
-    requirement that receiver must resolve (using IDENTIFY or WHOIS) the
-    new Client ID received in the notify (because of the new nickname is
-    unknown).  To be included in protocol version 1.1.
-
  4. Add "request parameters" or similar to the WHOIS command, which can
     be used to request various parameters (something not returned by
     standard WHOIS command) about clients (info that could be fetched
@@ -148,10 +136,6 @@ describe new stuff to be added to protocol versions 1.x.
  5. Inviting and banning by public key should be made possible.  To be
     included in protocol version 1.x.
 
- 6. Add perhaps SILENCE_USERS, SILENCE_OPERS channel user modes which
-    can be used to silence (moderate) normal users and opers (this set
-    only by founder).  To be included in protocol version 1.1.
-
  7. Channel Message Payload needs slight redesining to include the IV
     field to the MAC generation of the payload.  It is authenticated
     by the packet's MAC but not by the payload's MAC.  Since the IV
@@ -159,40 +143,11 @@ describe new stuff to be added to protocol versions 1.x.
     payload MAC and not alone by packet MAC.  To be included in protocol 
     version 1.1.
 
- 8. Remove the administrative commands from the protocol all together.
-    It does not make sense for the protocol to define how a server is
-    reconnected or shutdown, since they are implementation and 
-    configuration issues.  Besides protocol provides only limited set of
-    administrative commands and cannot define all that one could imagine.
-    To be included in protocol version 1.1.
-
- 9. Add SILC_MESAGE_FLAG_REPLY for being other side to the
-    SILC_MESSAGE_FLAG_REQUEST.  Add generic SILC_MESSAGE_FLAG_DATA, which
-    can include generic payload, which can include generic data.  The
-    payload definition is left out for now.  To be included in protocol
-    version 1.1.
-
- 10. Check command reply error status types in various commands,
-     specifically NO_FOPRIV is missing from many commands.  To be 
-     included in protocol version 1.1.
-
  11. Change the wording in Private Message Key Payload definition to
      describe the problems of trusting the payload, and to indicate that
      the receiver may not accept the key in the payload, and to describe
      other means of distributing a key.
 
- 13. Add the killer's client ID to the KILLED notify.  To be included in 
-     protocol version 1.1.
-
- 14. The length of Arguments Num field in Notify Payload and Command
-     Payload enforces that total of 256 arguments can be associated
-     to a such payload.  However, command-xx draft specified much higher
-     values, and these should be fixed.
-
- 15. The LEAVE command reply should return the Channel ID of the channel
-     that was parted.
-
  16. Add STATS command after all to the protocol for providing practically
      same information client gets when connects to a server.  Normal
      server would send this to router always when received from client.
-
index 4370809edcd99d912e4aed7176d89159b4dd53f3..b9e49b81ec652fe01370e8a0ffc00bf8dd2411de 100644 (file)
@@ -13,6 +13,12 @@ option(s).  The following modes are available:
     i               Set/unset channel as invite only channel
     t               Set/unset that only channel operator or 
                     founder may set channel topic
+    m               Set/unset user silencing.  Normal users
+                    are not able to talk on channel.  Only
+                    channel founder may set this mode
+    M               Set/unset operator silencing.  Operators
+                    are not able to talk on channel.  Only
+                    channel founder may set this mode
     l <limit>       Set/unset channel's user limit
     a <passphrase>  Set/unset passphrase for channel that must
                     be provided when joining to the channel.
index 6ac3306f20b9d3efe41801fcaab49fa664a86fc2..a886132904715ac1ede6f8100a27073f2d4c1cbb 100644 (file)
@@ -43,10 +43,10 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "ban_list", "channel {channel $0} ban list: $1", 2, { 0, 0 } },
        { "no_ban_list", "channel {channel $0} ban list not set", 1, { 0 } },
        { "inviting", "Inviting {nick $0} to channel {channel $1}", 2, { 0, 0 } },
-       { "kicked_you", "You have been kicked off channel {channel $0} by {nick $1} ($2)", 3, { 0, 0 } },
-       { "kicked", "{nick $0} has been kicked off channel {channel $1} by {nick $2} ($3)", 4, { 0, 0, 0 } },
-       { "killed_you", "You have been killed from the SILC Network", 0 },
-       { "killed", "{nick $0} has been killed from the SILC Network ($1)", 2, { 0, 0 } },
+       { "kicked_you", "You have been kicked off channel {channel $0} by {nick $1} ($2)", 3, { 0, 0, 0 } },
+       { "kicked", "{nick $0} has been kicked off channel {channel $1} by {nick $2} ($3)", 4, { 0, 0, 0, 0 } },
+       { "killed_you", "You have been killed from the SILC Network by {nick $0} ($1)", 2, { 0, 0 } },
+       { "killed", "{nick $0} has been killed from the SILC Network by {nick $1} ($2)", 3, { 0, 0, 0 } },
 
        /* WHOIS, WHOWAS and USERS (alias WHO) messages */
        { NULL, "Who Queries", 0 },
index 14699048500478f3200ec886f8e639697272fd5e..a4008b78c8882fa13f610e7f8adee69dfe35e743 100644 (file)
@@ -81,7 +81,8 @@ void silc_say_error(char *msg, ...)
 
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcChannelEntry channel,
-                         SilcMessageFlags flags, char *msg)
+                         SilcMessageFlags flags, const unsigned char *message,
+                         SilcUInt32 message_len)
 {
   SILC_SERVER_REC *server;
   SILC_NICK_REC *nick;
@@ -89,7 +90,7 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
   
   SILC_LOG_DEBUG(("Start"));
 
-  if (!msg)
+  if (!message)
     return;
 
   server = conn == NULL ? NULL : conn->context;
@@ -108,13 +109,13 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
   if (flags & SILC_MESSAGE_FLAG_ACTION)
     printformat_module("fe-common/silc", server, channel->channel_name,
                       MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION, 
-                       nick == NULL ? "[<unknown>]" : nick->nick, msg);
+                       nick == NULL ? "[<unknown>]" : nick->nick, message);
   else if (flags & SILC_MESSAGE_FLAG_NOTICE)
     printformat_module("fe-common/silc", server, channel->channel_name,
                       MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE, 
-                       nick == NULL ? "[<unknown>]" : nick->nick, msg);
+                       nick == NULL ? "[<unknown>]" : nick->nick, message);
   else
-    signal_emit("message public", 6, server, msg,
+    signal_emit("message public", 6, server, message,
                nick == NULL ? "[<unknown>]" : nick->nick,
                nick == NULL ? "" : nick->host == NULL ? "" : nick->host,
                chanrec->name, nick);
@@ -125,7 +126,8 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
 
 void silc_private_message(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcMessageFlags flags,
-                         char *msg)
+                         const unsigned char *message,
+                         SilcUInt32 message_len)
 {
   SILC_SERVER_REC *server;
   char userhost[256];
@@ -137,7 +139,7 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
   if (sender->username)
     snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
             sender->username, sender->hostname);
-  signal_emit("message private", 4, server, msg,
+  signal_emit("message private", 4, server, message,
              sender->nickname ? sender->nickname : "[<unknown>]",
              sender->username ? userhost : NULL);
 }
@@ -516,10 +518,12 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     client_entry = va_arg(va, SilcClientEntry);
     tmp = va_arg(va, char *);
+    client_entry2 = va_arg(va, SilcClientEntry);
   
     if (client_entry == conn->local_entry) {
       printformat_module("fe-common/silc", server, NULL,
                         MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED_YOU, 
+                        client_entry2 ? client_entry2->nickname : "",
                         tmp ? tmp : "");
     } else {
       list1 = nicklist_get_same_unique(SERVER(server), client_entry);
@@ -533,6 +537,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
       printformat_module("fe-common/silc", server, NULL,
                         MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, 
                         client_entry->nickname,
+                        client_entry2 ? client_entry2->nickname : "",
                         tmp ? tmp : "");
     }
     break;
index 69682f69b8157ace526dfff601ebfcc159d3a70c..f7031fdb106340b4065c4dd954d9fb1957eaa685 100644 (file)
@@ -27,10 +27,14 @@ void silc_say_error(char *msg, ...);
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, 
                          SilcChannelEntry channel, 
-                         SilcMessageFlags flags, char *msg);
+                         SilcMessageFlags flags, 
+                         const unsigned char *message,
+                         SilcUInt32 message_len);
 void silc_private_message(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, 
-                         SilcMessageFlags flags, char *msg);
+                         SilcMessageFlags flags, 
+                         const unsigned char *message,
+                         SilcUInt32 message_len);
 void silc_notify(SilcClient client, SilcClientConnection conn, 
                 SilcNotifyType type, ...);
 void silc_command(SilcClient client, SilcClientConnection conn, 
index 7000a9ad52b5be825a4b64b1cd0b705e46a338ae..ba345af6c5490c57d617570b90149cd90c2a78b2 100644 (file)
@@ -56,8 +56,6 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(connect, CONNECT, 
-                 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
@@ -67,16 +65,19 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
-  SILC_SERVER_CMD(close, CLOSE,
-                 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
-  SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
-                 SILC_CF_OPER),
   SILC_SERVER_CMD(silcoper, SILCOPER,
                  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(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
 
+  SILC_SERVER_CMD(connect, PRIV_CONNECT, 
+                 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
+  SILC_SERVER_CMD(close, PRIV_CLOSE,
+                 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
+  SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
+                 SILC_CF_OPER),
+
   { NULL, 0 },
 };
 
@@ -205,7 +206,7 @@ void silc_server_command_process(SilcServer server,
     if (cmd->cmd == command)
       break;
 
-  if (cmd == NULL) {
+  if (!cmd || !cmd->cb) {
     silc_server_command_send_status_reply(ctx, command,
                                          SILC_STATUS_ERR_UNKNOWN_COMMAND);
     silc_server_command_free(ctx);
@@ -2027,7 +2028,7 @@ SILC_SERVER_CMD_FUNC(nick)
     silc_server_send_notify_nick_change(server, server->router->connection, 
                                        server->server_type == SILC_SERVER ? 
                                        FALSE : TRUE, client->id,
-                                       new_id);
+                                       new_id, nick);
 
   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
@@ -2051,9 +2052,11 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Send NICK_CHANGE notify to the client's channels */
   silc_server_send_notify_on_channels(server, NULL, client, 
-                                     SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
+                                     SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
                                      oidp->data, oidp->len, 
-                                     nidp->data, nidp->len);
+                                     nidp->data, nidp->len,
+                                     client->nickname, 
+                                     strlen(client->nickname));
 
  send_reply:
   /* Send the new Client ID as reply command back to client */
@@ -2671,6 +2674,7 @@ SILC_SERVER_CMD_FUNC(kill)
   SilcClientID *client_id;
   unsigned char *tmp, *comment;
   SilcUInt32 tmp_len, tmp_len2;
+  SilcBuffer killer;
   bool local;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
@@ -2724,7 +2728,7 @@ SILC_SERVER_CMD_FUNC(kill)
   /* Get comment */
   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
   if (tmp_len2 > 128)
-    comment = NULL;
+    tmp_len2 = 128;
 
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
@@ -2737,22 +2741,24 @@ SILC_SERVER_CMD_FUNC(kill)
   /* Send KILLED notify to the channels. It is not sent to the client
      as it will be sent differently destined directly to the client and not
      to the channel. */
+  killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   silc_server_send_notify_on_channels(server, remote_client, 
                                      remote_client, SILC_NOTIFY_TYPE_KILLED,
-                                     comment ? 2 : 1,
-                                     tmp, tmp_len,
-                                     comment, comment ? tmp_len2 : 0);
+                                     3, tmp, tmp_len,
+                                     comment, comment ? tmp_len2 : 0,
+                                     killer->data, killer->len);
+  silc_buffer_free(killer);
 
   /* Send KILLED notify to primary route */
   if (!server->standalone)
     silc_server_send_notify_killed(server, server->router->connection, TRUE,
-                                  remote_client->id, comment);
+                                  remote_client->id, comment, client->id);
 
   /* Send KILLED notify to the client directly */
   silc_server_send_notify_killed(server, remote_client->connection ? 
                                 remote_client->connection : 
                                 remote_client->router->connection, FALSE,
-                                remote_client->id, comment);
+                                remote_client->id, comment, client->id);
 
   /* Remove the client from all channels. This generates new keys to the
      channels as well. */
@@ -3748,7 +3754,9 @@ SILC_SERVER_CMD_FUNC(cmode)
   /* Check that client has rights to change any requested channel modes */
   if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+                                         (chl->mode == 0 ? 
+                                          SILC_STATUS_ERR_NO_CHANNEL_PRIV :
+                                          SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
     goto out;
   }
 
@@ -4173,7 +4181,7 @@ SILC_SERVER_CMD_FUNC(cumode)
      but themselves. */
   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+                                         SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
     goto out;
   }
 
@@ -4638,61 +4646,6 @@ SILC_SERVER_CMD_FUNC(silcoper)
   silc_server_command_free(cmd);
 }
 
-/* Server side command of CONNECT. Connects us to the specified remote
-   server or router. */
-
-SILC_SERVER_CMD_FUNC(connect)
-{
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  unsigned char *tmp, *host;
-  SilcUInt32 tmp_len;
-  SilcUInt32 port = SILC_PORT;
-
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
-    goto out;
-
-  /* Check whether client has the permissions. */
-  if (client->mode == SILC_UMODE_NONE) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
-                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
-    goto out;
-  }
-
-  if (server->server_type == SILC_ROUTER && 
-      client->mode & SILC_UMODE_SERVER_OPERATOR) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
-                                         SILC_STATUS_ERR_NO_ROUTER_PRIV);
-    goto out;
-  }
-
-  /* Get the remote server */
-  host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!host) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-    goto out;
-  }
-
-  /* Get port */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (tmp)
-    SILC_GET32_MSB(port, tmp);
-
-  /* Create the connection. It is done with timeout and is async. */
-  silc_server_create_connection(server, host, port);
-
-  /* Send reply to the sender */
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
-                                       SILC_STATUS_OK);
-
- 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. */
 
@@ -4816,111 +4769,6 @@ SILC_SERVER_CMD_FUNC(ban)
   silc_server_command_free(cmd);
 }
 
-/* Server side command of CLOSE. Closes connection to a specified server. */
-SILC_SERVER_CMD_FUNC(close)
-{
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  SilcServerEntry server_entry;
-  SilcSocketConnection sock;
-  unsigned char *tmp;
-  SilcUInt32 tmp_len;
-  unsigned char *name;
-  SilcUInt32 port = SILC_PORT;
-
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
-    goto out;
-
-  /* Check whether client has the permissions. */
-  if (client->mode == SILC_UMODE_NONE) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
-                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
-    goto out;
-  }
-
-  /* Get the remote server */
-  name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!name) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-    goto out;
-  }
-
-  /* Get port */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (tmp)
-    SILC_GET32_MSB(port, tmp);
-
-  server_entry = silc_idlist_find_server_by_conn(server->local_list,
-                                                name, port, FALSE, NULL);
-  if (!server_entry)
-    server_entry = silc_idlist_find_server_by_conn(server->global_list,
-                                                  name, port, FALSE, NULL);
-  if (!server_entry) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
-                                         SILC_STATUS_ERR_NO_SERVER_ID);
-    goto out;
-  }
-
-  /* Send reply to the sender */
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
-                                       SILC_STATUS_OK);
-
-  /* Close the connection to the server */
-  sock = (SilcSocketConnection)server_entry->connection;
-
-  /* If we shutdown primary router connection manually then don't trigger
-     any reconnect or backup router connections, by setting the router
-     to NULL here. */
-  if (server->router == server_entry) {
-    server->id_entry->router = NULL;
-    server->router = NULL;
-    server->standalone = TRUE;
-  }
-  silc_server_free_sock_user_data(server, sock, NULL);
-  silc_server_close_connection(server, sock);
-  
- out:
-  silc_server_command_free(cmd);
-}
-
-/* Server side command of SHUTDOWN. Shutdowns the server and closes all
-   active connections. */
-SILC_SERVER_CMD_FUNC(shutdown)
-{
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-
-  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
-
-  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
-    goto out;
-
-  /* Check whether client has the permission. */
-  if (client->mode == SILC_UMODE_NONE) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
-                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
-    goto out;
-  }
-
-  /* Send reply to the sender */
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
-                                       SILC_STATUS_OK);
-
-  /* Then, gracefully, or not, bring the server down. */
-  silc_server_stop(server);
-  exit(0);
-
- out:
-  silc_server_command_free(cmd);
-}
 /* Server side command of LEAVE. Removes client from a channel. */
 
 SILC_SERVER_CMD_FUNC(leave)
@@ -4975,8 +4823,8 @@ SILC_SERVER_CMD_FUNC(leave)
                                  server->server_type == SILC_ROUTER ?
                                  TRUE : FALSE, channel, id_entry->id);
 
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
-                                       SILC_STATUS_OK);
+  silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
+                                      SILC_STATUS_OK, 2, tmp, len);
 
   /* Remove client from channel */
   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
@@ -5333,3 +5181,166 @@ SILC_SERVER_CMD_FUNC(getkey)
   silc_free(server_id);
   silc_server_command_free(cmd);
 }
+
+
+/* Private range commands, specific to this implementation */
+
+/* Server side command of CONNECT. Connects us to the specified remote
+   server or router. */
+
+SILC_SERVER_CMD_FUNC(connect)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  unsigned char *tmp, *host;
+  SilcUInt32 tmp_len;
+  SilcUInt32 port = SILC_PORT;
+
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
+
+  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+    goto out;
+
+  /* Check whether client has the permissions. */
+  if (client->mode == SILC_UMODE_NONE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
+                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
+    goto out;
+  }
+
+  if (server->server_type == SILC_ROUTER && 
+      client->mode & SILC_UMODE_SERVER_OPERATOR) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
+                                         SILC_STATUS_ERR_NO_ROUTER_PRIV);
+    goto out;
+  }
+
+  /* Get the remote server */
+  host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!host) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+
+  /* Get port */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (tmp)
+    SILC_GET32_MSB(port, tmp);
+
+  /* Create the connection. It is done with timeout and is async. */
+  silc_server_create_connection(server, host, port);
+
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
+                                       SILC_STATUS_OK);
+
+ out:
+  silc_server_command_free(cmd);
+}
+
+/* Server side command of CLOSE. Closes connection to a specified server. */
+SILC_SERVER_CMD_FUNC(close)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcServerEntry server_entry;
+  SilcSocketConnection sock;
+  unsigned char *tmp;
+  SilcUInt32 tmp_len;
+  unsigned char *name;
+  SilcUInt32 port = SILC_PORT;
+
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
+
+  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+    goto out;
+
+  /* Check whether client has the permissions. */
+  if (client->mode == SILC_UMODE_NONE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
+    goto out;
+  }
+
+  /* Get the remote server */
+  name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!name) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+
+  /* Get port */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (tmp)
+    SILC_GET32_MSB(port, tmp);
+
+  server_entry = silc_idlist_find_server_by_conn(server->local_list,
+                                                name, port, FALSE, NULL);
+  if (!server_entry)
+    server_entry = silc_idlist_find_server_by_conn(server->global_list,
+                                                  name, port, FALSE, NULL);
+  if (!server_entry) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_ID);
+    goto out;
+  }
+
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
+                                       SILC_STATUS_OK);
+
+  /* Close the connection to the server */
+  sock = (SilcSocketConnection)server_entry->connection;
+
+  /* If we shutdown primary router connection manually then don't trigger
+     any reconnect or backup router connections, by setting the router
+     to NULL here. */
+  if (server->router == server_entry) {
+    server->id_entry->router = NULL;
+    server->router = NULL;
+    server->standalone = TRUE;
+  }
+  silc_server_free_sock_user_data(server, sock, NULL);
+  silc_server_close_connection(server, sock);
+  
+ out:
+  silc_server_command_free(cmd);
+}
+
+/* Server side command of SHUTDOWN. Shutdowns the server and closes all
+   active connections. */
+SILC_SERVER_CMD_FUNC(shutdown)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
+
+  if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+    goto out;
+
+  /* Check whether client has the permission. */
+  if (client->mode == SILC_UMODE_NONE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
+                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
+    goto out;
+  }
+
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
+                                       SILC_STATUS_OK);
+
+  /* Then, gracefully, or not, bring the server down. */
+  silc_server_stop(server);
+  exit(0);
+
+ out:
+  silc_server_command_free(cmd);
+}
index 95fbcdd2443e579c303aa711882fe84b31556cfb..0b59e75fdff04721326443b511ad81985996fe45 100644 (file)
@@ -130,24 +130,22 @@ SILC_SERVER_CMD_FUNC(invite);
 SILC_SERVER_CMD_FUNC(quit);
 SILC_SERVER_CMD_FUNC(kill);
 SILC_SERVER_CMD_FUNC(info);
-SILC_SERVER_CMD_FUNC(connect);
 SILC_SERVER_CMD_FUNC(ping);
 SILC_SERVER_CMD_FUNC(oper);
-SILC_SERVER_CMD_FUNC(pass);
-SILC_SERVER_CMD_FUNC(admin);
 SILC_SERVER_CMD_FUNC(join);
 SILC_SERVER_CMD_FUNC(motd);
 SILC_SERVER_CMD_FUNC(umode);
 SILC_SERVER_CMD_FUNC(cmode);
 SILC_SERVER_CMD_FUNC(cumode);
 SILC_SERVER_CMD_FUNC(kick);
-SILC_SERVER_CMD_FUNC(ignore);
 SILC_SERVER_CMD_FUNC(ban);
-SILC_SERVER_CMD_FUNC(close);
-SILC_SERVER_CMD_FUNC(shutdown);
 SILC_SERVER_CMD_FUNC(silcoper);
 SILC_SERVER_CMD_FUNC(leave);
 SILC_SERVER_CMD_FUNC(users);
 SILC_SERVER_CMD_FUNC(getkey);
 
+SILC_SERVER_CMD_FUNC(connect);
+SILC_SERVER_CMD_FUNC(close);
+SILC_SERVER_CMD_FUNC(shutdown);
+
 #endif
index a04e11677f5f0ca9a2dd4a8d3856ea17f535238f..ab8f7d53af5abb6b9b0773020d25001fb2e4526d 100644 (file)
@@ -494,7 +494,7 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
 
 SilcClientEntry
 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
-                             SilcClientID *new_id)
+                             SilcClientID *new_id, const char *nickname)
 {
   SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry client;
@@ -518,12 +518,17 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
 
   /* Remove the old entry and add a new one */
 
-  silc_idcache_del_by_context(id_list->clients, client);
+  if (!silc_idcache_del_by_context(id_list->clients, client))
+    return NULL;
 
   silc_free(client->id);
+  silc_free(client->nickname);
   client->id = new_id;
+  client->nickname = nickname ? strdup(nickname) : NULL;
 
-  silc_idcache_add(id_list->clients, NULL, client->id, client, 0, NULL);
+  if (!silc_idcache_add(id_list->clients, client->nickname, client->id, 
+                       client, 0, NULL))
+    return NULL;
 
   SILC_LOG_DEBUG(("Replaced"));
 
index 74139ceb384af121f365828b477ddce72ed7838a..30fbd3a15e6470bc418e8abb58a14b9e1d7b1bb8 100644 (file)
@@ -597,7 +597,7 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
                              bool registered, SilcIDCacheEntry *ret_entry);
 SilcClientEntry
 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
-                             SilcClientID *new_id);
+                             SilcClientID *new_id, const char *nickname);
 void silc_idlist_client_destructor(SilcIDCache cache,
                                   SilcIDCacheEntry entry);
 SilcChannelEntry
index ab51f0e87c475b143902a251fc9bfa9222ecd6a4..f0c3616da003fd8061cd92cc3000ec7032e41c8a 100644 (file)
@@ -426,6 +426,8 @@ void silc_server_notify(SilcServer server,
        * Distribute the notify to local clients on the channel
        */
       unsigned char *id, *id2;
+      char *nickname;
+      SilcUInt32 nickname_len;
 
       SILC_LOG_DEBUG(("NICK CHANGE notify"));
       
@@ -450,26 +452,24 @@ void silc_server_notify(SilcServer server,
       SILC_LOG_DEBUG(("New Client ID id(%s)", 
                      silc_id_render(client_id2, SILC_ID_CLIENT)));
 
+      /* From protocol version 1.1 we also get the new nickname */
+      nickname = silc_argument_get_arg_type(args, 3, &nickname_len);;
+
       /* Replace the Client ID */
       client = silc_idlist_replace_client_id(server->global_list, client_id,
-                                            client_id2);
+                                            client_id2, nickname);
       if (!client)
        client = silc_idlist_replace_client_id(server->local_list, client_id, 
-                                              client_id2);
+                                              client_id2, nickname);
 
       if (client) {
-       /* The nickname is not valid anymore, set it NULL. This causes that
-          the nickname will be queried if someone wants to know it. */
-       if (client->nickname)
-         silc_free(client->nickname);
-       client->nickname = NULL;
-
        /* Send the NICK_CHANGE notify type to local clients on the channels
           this client is joined to. */
-       silc_server_send_notify_on_channels(server, NULL, client, 
-                                           SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
-                                           id, tmp_len, 
-                                           id2, tmp_len);
+       silc_server_send_notify_on_channels(server, NULL, client,
+                                           SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
+                                           id, tmp_len, id2, tmp_len,
+                                           nickname, nickname ?
+                                           nickname_len : 0);
       }
 
       silc_free(client_id);
@@ -1126,8 +1126,7 @@ void silc_server_notify(SilcServer server,
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO)
       goto out;
     
-    /* Get kicker. In protocol version 1.0 this is not mandatory argument
-       so we check it only if it is provided. */
+    /* From protocol version 1.1 we get the kicker's ID as well. */
     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
     if (tmp) {
       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
@@ -1171,8 +1170,8 @@ void silc_server_notify(SilcServer server,
       /* 
        * Distribute the notify to local clients on channels
        */
-      unsigned char *id;
-      SilcUInt32 id_len;
+      unsigned char *id, *comment;
+      SilcUInt32 id_len, comment_len;
     
       SILC_LOG_DEBUG(("KILLED notify"));
       
@@ -1207,16 +1206,42 @@ void silc_server_notify(SilcServer server,
       }
 
       /* Get comment */
-      tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-      if (tmp_len > 128)
-       tmp = NULL;
+      comment = silc_argument_get_arg_type(args, 2, &comment_len);
+      if (comment_len > 128)
+       comment_len = 127;
+
+      /* From protocol version 1.1 we get the killer's ID as well. */
+      tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+      if (tmp) {
+       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+       if (!client_id)
+         goto out;
+
+       /* If the the client is not in local list we check global list */
+       client2 = silc_idlist_find_client_by_id(server->global_list, 
+                                               client_id, TRUE, NULL);
+       if (!client2) {
+         client2 = silc_idlist_find_client_by_id(server->local_list, 
+                                                 client_id, TRUE, NULL);
+         if (!client2) {
+           silc_free(client_id);
+           goto out;
+         }
+       }
+       silc_free(client_id);
+
+       /* Killer must be router operator */
+       if (!(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+         SILC_LOG_DEBUG(("Killing is not allowed"));
+         goto out;
+       }
+      }
 
       /* Send the notify to local clients on the channels except to the
         client who is killed. */
       silc_server_send_notify_on_channels(server, client, client,
-                                         SILC_NOTIFY_TYPE_KILLED, 
-                                         tmp ? 2 : 1,
-                                         id, id_len, 
+                                         SILC_NOTIFY_TYPE_KILLED, 3,
+                                         id, id_len, comment, comment_len,
                                          tmp, tmp_len);
 
       /* Remove the client from all channels */
@@ -1577,6 +1602,7 @@ void silc_server_channel_message(SilcServer server,
   SilcChannelID *id = NULL;
   void *sender_id = NULL;
   SilcClientEntry sender_entry = NULL;
+  SilcChannelClientEntry chl;
   bool local = TRUE;
 
   SILC_LOG_DEBUG(("Processing channel message"));
@@ -1615,11 +1641,24 @@ void silc_server_channel_message(SilcServer server,
                                                   sender_id, TRUE, NULL);
     }
     if (!sender_entry || !silc_server_client_on_channel(sender_entry, 
-                                                       channel, NULL)) {
+                                                       channel, &chl)) {
       SILC_LOG_DEBUG(("Client not on channel"));
       goto out;
     }
 
+    /* If channel is moderated check that client is allowed to send
+       messages. */
+    if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chl->mode) {
+      SILC_LOG_DEBUG(("Channel is silenced from normal users"));
+      goto out;
+    }
+    if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && 
+       chl->mode & SILC_CHANNEL_UMODE_CHANOP &&
+       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+      SILC_LOG_DEBUG(("Channel is silenced from operators"));
+      goto out;
+    }
+
     /* If the packet is coming from router, but the client entry is local 
        entry to us then some router is rerouting this to us and it is not 
        allowed. When the client is local to us it means that we've routed
index 05b3cd8cff0eb8a334c28384aecf4d9e6c5db414..424a27333fc3cdce4bb4ccfcc143a0b730c6ca80 100644 (file)
@@ -1093,7 +1093,8 @@ void silc_server_send_notify_nick_change(SilcServer server,
                                         SilcSocketConnection sock,
                                         bool broadcast,
                                         SilcClientID *old_id,
-                                        SilcClientID *new_id)
+                                        SilcClientID *new_id,
+                                        const char *nickname)
 {
   SilcBuffer idp1, idp2;
 
@@ -1102,7 +1103,8 @@ void silc_server_send_notify_nick_change(SilcServer server,
 
   silc_server_send_notify(server, sock, broadcast, 
                          SILC_NOTIFY_TYPE_NICK_CHANGE,
-                         2, idp1->data, idp1->len, idp2->data, idp2->len);
+                         3, idp1->data, idp1->len, idp2->data, idp2->len,
+                         nickname, nickname ? strlen(nickname) : 0);
   silc_buffer_free(idp1);
   silc_buffer_free(idp2);
 }
@@ -1284,16 +1286,21 @@ void silc_server_send_notify_killed(SilcServer server,
                                    SilcSocketConnection sock,
                                    bool broadcast,
                                    SilcClientID *client_id,
-                                   char *comment)
+                                   char *comment,
+                                   SilcClientID *killer)
 {
-  SilcBuffer idp;
+  SilcBuffer idp1;
+  SilcBuffer idp2;
 
-  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  idp1 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  idp2 = silc_id_payload_encode((void *)killer, SILC_ID_CLIENT);
   silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id,
                               SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED,
-                              comment ? 2 : 1, idp->data, idp->len,
-                              comment, comment ? strlen(comment) : 0);
-  silc_buffer_free(idp);
+                              3, idp1->data, idp1->len,
+                              comment, comment ? strlen(comment) : 0,
+                              idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
 }
 
 /* Sends UMODE_CHANGE notify type. This tells that `client_id' client's
index 3cd431f96ce4cdcfb6dd354b2d4c2e468ff0e934..b2cbc8aae25cede3dad8c6efa3049c9cb27203ec 100644 (file)
@@ -123,7 +123,8 @@ void silc_server_send_notify_nick_change(SilcServer server,
                                         SilcSocketConnection sock,
                                         bool broadcast,
                                         SilcClientID *old_id,
-                                        SilcClientID *new_id);
+                                        SilcClientID *new_id,
+                                        const char *nickname);
 void silc_server_send_notify_join(SilcServer server,
                                  SilcSocketConnection sock,
                                  bool broadcast,
@@ -171,7 +172,8 @@ void silc_server_send_notify_killed(SilcServer server,
                                    SilcSocketConnection sock,
                                    bool broadcast,
                                    SilcClientID *client_id,
-                                   char *comment);
+                                   char *comment,
+                                   SilcClientID *killer);
 void silc_server_send_notify_umode(SilcServer server,
                                   SilcSocketConnection sock,
                                   bool broadcast,
index 65fafeeae26e53ab27c5f39f2231a9f7e39a4eaa..eb7b3013a01e2f5cdf6c0777ca54fdb4793209e0 100644 (file)
@@ -325,60 +325,36 @@ int silc_server_protocol_ke_set_keys(SilcServer server,
 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
                                     SilcUInt32 len, void *context)
 {
-  SilcSKEStatus status = SILC_SKE_STATUS_OK;
-  char *cp;
-  int maj = 0, min = 0, build = 0, maj2 = 0, min2 = 0, build2 = 0;
+  SilcUInt32 l_protocol_version = 0, r_protocol_version = 0;
 
   SILC_LOG_INFO(("%s (%s) is version %s", ske->sock->hostname,
                 ske->sock->ip, version));
 
-  /* Check for initial version string. Allowed "SILC-x.x-". More 
-     specific protocol version is checked later in session. */
-  if (!strstr(version, "SILC-"))
-    status = SILC_SKE_STATUS_BAD_VERSION;
-
-  /* Check software version */
-
-  cp = version + 9;
-  if (!cp)
-    status = SILC_SKE_STATUS_BAD_VERSION;
-
-  maj = atoi(cp);
-  cp = strchr(cp, '.');
-  if (cp) {
-    min = atoi(cp + 1);
-    cp++;
-  }
-  if (cp) {
-    cp = strchr(cp, '.');
-    if (cp)
-      build = atoi(cp + 1);
+  if (!silc_parse_version_string(version, &r_protocol_version, NULL, NULL,
+                                NULL, NULL)) {
+    SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version", 
+                   ske->sock->hostname, ske->sock->ip, version));
+    return SILC_SKE_STATUS_BAD_VERSION;
   }
 
-  cp = silc_version_string + 9;
-  if (!cp)
-    status = SILC_SKE_STATUS_BAD_VERSION;
-
-  maj2 = atoi(cp);
-  cp = strchr(cp, '.');
-  if (cp) {
-    min2 = atoi(cp + 1);
-    cp++;
-  }
-  if (cp) {
-    cp = strchr(cp, '.');
-    if (cp)
-      build2 = atoi(cp + 1);
+  if (!silc_parse_version_string(silc_version_string, 
+                                &l_protocol_version, NULL, NULL,
+                                NULL, NULL)) {
+    SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version", 
+                   ske->sock->hostname, ske->sock->ip, version));
+    return SILC_SKE_STATUS_BAD_VERSION;
   }
 
-  if (maj != maj2)
-    status = SILC_SKE_STATUS_BAD_VERSION;
-
-  if (status == SILC_SKE_STATUS_BAD_VERSION)
+  /* If remote is too new, don't connect */
+  if (l_protocol_version < r_protocol_version) {
     SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version", 
                    ske->sock->hostname, ske->sock->ip, version));
+    return SILC_SKE_STATUS_BAD_VERSION;
+  }
+
+  ske->sock->version = r_protocol_version;
 
-  return status;
+  return SILC_SKE_STATUS_OK;
 }
 
 /* Callback that is called by the SKE to indicate that it is safe to
index 147346dea24c7ec8e68c1863c3b710aab77029ab..01870b9593dd545d81e6c7f0d18937bc3177c2f8 100644 (file)
@@ -1056,6 +1056,28 @@ bool silc_server_check_cmode_rights(SilcServer server,
     }
   }
   
+  if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
+    if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS))
+      if (is_op && !is_fo)
+       return FALSE;
+  } else {
+    if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
+      if (is_op && !is_fo)
+       return FALSE;
+    }
+  }
+  
+  if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
+    if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS))
+      if (is_op && !is_fo)
+       return FALSE;
+  } else {
+    if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
+      if (is_op && !is_fo)
+       return FALSE;
+    }
+  }
+  
   return TRUE;
 }
 
index 20c7d47fee75ff85f23c5a630e9c59e26246d7a4..d0dcd698c4f9e8f1a50f9ea3ded730ba289bf12c 100644 (file)
@@ -224,7 +224,7 @@ List of all defined commands in SILC follows.
 
    1    SILC_COMMAND_WHOIS
 
-        Max Arguments:  3328
+        Max Arguments:  256
             Arguments:  (1) [<nickname>[@<server>]]  (2) [<count>]
                         (3) [<Client ID>]            (n) [...]
 
@@ -359,7 +359,7 @@ List of all defined commands in SILC follows.
 
    3    SILC_COMMAND_IDENTIFY
 
-        Max Arguments:  3328
+        Max Arguments:  256
             Arguments:  (1) [<nickname>[@<server>]]  (2) [<server name>]
                         (3) [<channel name>]         (4) [<count>]
                         (5) [<ID Payload>]           (n) [...]
@@ -708,34 +708,7 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NO_SERVER_ID
 
 
-   11   SILC_COMMAND_CONNECT
-
-        Max Arguments:  2
-            Arguments:  (1) <remote server/router>  (2) [<port>]
-
-        This command is used by operators to force a server to try to
-        establish a new connection to remote server or router.  The
-        Operator MUST specify the server/router to be connected by
-        setting <remote server> argument.  The port is 32 bit MSB value.
-
-        Reply messages to the command:
-
-        Max Arguments:  1
-            Arguments:  (1) <Status Payload>
-
-        This command replies only with Status Payload.
-
-
-
-        Status messages:
-
-            SILC_STATUS_OK
-            SILC_STATUS_ERR_WILDCARDS
-            SILC_STATUS_ERR_NOT_REGISTERED
-            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS
-            SILC_STATUS_ERR_TOO_MANY_PARAMS
-            SILC_STATUS_ERR_NO_SERVER_PRIV
-            SILC_STATUS_ERR_NO_ROUTER_PRIV
+   11   <deprecated command>
 
 
    12   SILC_COMMAND_PING
@@ -954,14 +927,14 @@ List of all defined commands in SILC follows.
 
         The following client modes are defined:
 
-           0x0000    SILC_UMODE_NONE
+           0x00000000    SILC_UMODE_NONE
 
               No specific mode for client.  This is the initial
               setting when new client is created.  The client is
               normal client now.
 
 
-           0x0001    SILC_UMODE_SERVER_OPERATOR
+           0x00000001    SILC_UMODE_SERVER_OPERATOR
 
               Marks the user as server operator.  Client MUST NOT
               set this mode itself.  Server sets this mode to the
@@ -970,7 +943,7 @@ List of all defined commands in SILC follows.
               MAY unset the mode itself.
 
 
-           0x0002    SILC_UMODE_ROUTER_OPERATOR
+           0x00000002    SILC_UMODE_ROUTER_OPERATOR
 
               Marks the user as router (SILC) operator.  Client
               MUST NOT this mode itself.  Router sets this mode to
@@ -979,7 +952,7 @@ List of all defined commands in SILC follows.
               MAY unset the mode itself.
 
 
-           0x0004    SILC_UMODE_GONE
+           0x00000004    SILC_UMODE_GONE
 
               Marks that the user is not currently present in the
               SILC Network.  Client MAY set and unset this mode.
@@ -1028,14 +1001,14 @@ List of all defined commands in SILC follows.
 
         The following channel modes are defined:
 
-           0x0000    SILC_CMODE_NONE
+           0x00000000    SILC_CMODE_NONE
 
               No specific mode on channel.  This is the default when
               channel is created.  This means that channel is just plain
               normal channel.
 
 
-           0x0001    SILC_CMODE_PRIVATE
+           0x00000001    SILC_CMODE_PRIVATE
 
               Channel is private channel.  Private channels are shown
               in the channel list listed with SILC_COMMAND_LIST command
@@ -1049,7 +1022,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0002    SILC_CMODE_SECRET
+           0x00000002    SILC_CMODE_SECRET
 
               Channel is secret channel.  Secret channels are not shown
               in the list listed with SILC_COMMAND_LIST command.  Secret
@@ -1061,7 +1034,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0004    SILC_CMODE_PRIVKEY
+           0x00000004    SILC_CMODE_PRIVKEY
 
               Channel uses private channel key to protect the traffic
               on the channel.  When this mode is set the client will be
@@ -1093,7 +1066,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0008    SILC_CMODE_INVITE
+           0x00000008    SILC_CMODE_INVITE
 
               Channel is invite only channel.  Client may join to this
               channel only if it is invited to the channel.  Channel
@@ -1103,7 +1076,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0010    SILC_CMODE_TOPIC
+           0x00000010    SILC_CMODE_TOPIC
 
               The topic of the channel may only be set by client that
               is channel founder or channel operator.  Normal clients
@@ -1115,7 +1088,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0020    SILC_CMODE_ULIMIT
+           0x00000020    SILC_CMODE_ULIMIT
 
               User limit has been set to the channel.  New clients
               may not join to the channel when the limit set is
@@ -1127,7 +1100,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0040    SILC_CMODE_PASSPHRASE
+           0x00000040    SILC_CMODE_PASSPHRASE
 
               Passphrase has been set to the channel.  Client may
               join to the channel only if it is able to provide the
@@ -1141,7 +1114,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0080    SILC_CMODE_CIPHER
+           0x00000080    SILC_CMODE_CIPHER
 
               Sets specific cipher to be used to protect channel
               traffic.  The <cipher> argument is the requested cipher.
@@ -1154,7 +1127,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0100    SILC_CMODE_HMAC
+           0x00000100    SILC_CMODE_HMAC
 
               Sets specific hmac to be used to compute the MACs of the
               channel message.  The <hmac> argument is the requested hmac.
@@ -1164,7 +1137,7 @@ List of all defined commands in SILC follows.
               to set/unset this mode.
 
 
-           0x0200    SILC_CMODE_FOUNDER_AUTH
+           0x00000200    SILC_CMODE_FOUNDER_AUTH
 
               Channel founder may set this mode to be able to regain
               channel founder rights even if the client leaves the 
@@ -1192,6 +1165,27 @@ List of all defined commands in SILC follows.
               Typical implementation would use [+|-]f on user interface
               to set/unset this mode.
 
+
+           0x00000400    SILC_CMODE_SILENCE_USERS
+
+              Channel founder may set this mode to silence normal users
+              on the channel.  Users with operator privileges are not
+              affected by this mode.  Messages sent by normal users
+              are dropped by servers when this mode is set.  This mode
+              can be used to moderate the channel.  Only channel founder
+              may set/unset this mode.
+
+
+           0x00000800    SILC_CMODE_SILENCE_OPERS
+
+              Channel founder may set this mode to silence operators
+              on the channel.  When used with SILC_CMODE_SILENCE_USERS
+              mode this can be used to set the channel in state where only
+              the founder of the channel may send messages to the channel.
+              Messages sent by operators are dropped by servers when this
+              mode is set.  Only channel founder may set/unset this mode.
+
+
         To make the mode system work, client MUST keep the channel mode
         mask locally so that the mode setting and unsetting would work
         without problems.  The client receives the initial channel mode
@@ -1221,6 +1215,7 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_BAD_CHANNEL_ID
             SILC_STATUS_ERR_NO_CHANNEL_ID
             SILC_STATUS_ERR_NO_CHANNEL_PRIV
+            SILC_STATUS_ERR_NO_CHANNEL_FOPRIV
             SILC_STATUS_ERR_UNKNOWN_MODE
             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID
             SILC_STATUS_ERR_AUTH_FAILED
@@ -1246,14 +1241,14 @@ List of all defined commands in SILC follows.
 
         The following channel modes are defined:
 
-           0x0000    SILC_CUMODE_NONE
+           0x00000000    SILC_CUMODE_NONE
 
               No specific mode.  This is the normal situation for client.
               Also, this is the mode set when removing all modes from
               the target client.
 
 
-           0x0001    SILC_CUMODE_FOUNDER
+           0x00000001    SILC_CUMODE_FOUNDER
 
               The client is channel founder of the channel.  Usually this
               mode is set only by the server when the channel was created.
@@ -1266,7 +1261,7 @@ List of all defined commands in SILC follows.
               mode was set.  The client MAY remove this mode at any time.
 
 
-           0x0002    SILC_CUMODE_OPERATOR
+           0x00000002    SILC_CUMODE_OPERATOR
 
               Sets channel operator privileges on the channel for a
               client on the channel.  Channel founder and channel operator
@@ -1293,6 +1288,7 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_BAD_CHANNEL_ID
             SILC_STATUS_ERR_NO_CHANNEL_ID
             SILC_STATUS_ERR_NO_CHANNEL_PRIV
+            SILC_STATUS_ERR_NO_CHANNEL_FOPRIV
             SILC_STATUS_ERR_UNKNOWN_MODE
             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID
             SILC_STATUS_ERR_AUTH_FAILED
@@ -1381,53 +1377,10 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NO_CHANNEL_PRIV
 
 
-   21   SILC_COMMAND_CLOSE
-
-        Max Arguments:  2
-            Arguments:  (1) <remote server/router>  (2) [<port>]
-
-        This command is used only by operator to close connection to a
-        remote site.
-
-        Reply messages to the command:
-
-        Max Arguments:  1
-            Arguments:  (1) <Status Payload>
+   21   <deprecated command>
 
-        This command replies only with Status Payload.
 
-        Status messages:
-
-            SILC_STATUS_OK
-            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS
-            SILC_STATUS_ERR_TOO_MANY_PARAMS
-            SILC_STATUS_ERR_NOT_REGISTERED
-            SILC_STATUS_ERR_NO_SUCH_SERVER
-            SILC_STATUS_ERR_NO_SERVER_PRIV
-            SILC_STATUS_ERR_NO_SUCH_SERVER_ID
-
-
-   22   SILC_COMMAND_SHUTDOWN
-
-        Max Arguments:  0
-            Arguments:  None
-
-        This command is used only by operator to shutdown the server.
-        All connections to the server will be closed and the server is
-        shutdown.
-
-        Reply messages to the command:
-
-        Max Arguments:  1
-            Arguments:  (1) <Status Payload>
-
-        This command replies only with Status Payload.
-
-        Status messages:
-
-            SILC_STATUS_OK
-            SILC_STATUS_ERR_NOT_REGISTERED
-            SILC_STATUS_ERR_NO_SERVER_PRIV
+   22   <deprecated command>
 
 
    23   SILC_COMMAND_SILCOPER
@@ -1493,10 +1446,10 @@ List of all defined commands in SILC follows.
 
         Reply messages to the command:
 
-        Max Arguments:  1
-            Arguments:  (1) <Status Payload>
+        Max Arguments:  2
+            Arguments:  (1) <Status Payload>  (2) <Channel ID>
 
-        This command replies only with Status Payload.
+        The <Channel ID> is the ID of left channel.
 
         Status messages:
 
index a8ed3e67d619561c90b101441c552472c7502b48..31b557d768cd9b1271cda40e125e821f5107e0cd 100644 (file)
@@ -1295,12 +1295,13 @@ Also, all ID's sent in arguments are sent inside ID Payload.
       receiving the packet distributes this type to the local clients
       on the channel and broadcast it to the network.
 
-      Max Arguments:  2
+      Max Arguments:  3
           Arguments:  (1) <Old Client ID>  (2) <New Client ID>
+                      (3) <nickname>
 
       The <Old Client ID> is the old ID of the client which changed
       the nickname.  The <New Client ID> is the new ID generated by
-      the change of the nickname.
+      the change of the nickname.  The <nickname> is the new nickname.
 
 
 7     SILC_NOTIFY_TYPE_CMODE_CHANGE
@@ -1415,12 +1416,13 @@ Also, all ID's sent in arguments are sent inside ID Payload.
       or server receiving the packet distributes this type to the local
       clients on the channel and broadcast it to the network.
 
-      Max Arguments:  2
-          Arguments:  (1) <Client ID>  (2) [<comment>]
+      Max Arguments:  3
+          Arguments:  (1) <Client ID>           (2) [<comment>]
+                      (3) <Killer's Client ID>
 
       The <Client ID> is the client which was killed from the network.
       The killer may have set the <comment> to indicate the reason for
-      the killing.
+      the killing.  The <Killer's Client ID> is the killer.
 
 
 14    SILC_NOTIFY_TYPE_UMODE_CHANGE
@@ -1604,11 +1606,26 @@ o Message Flags (2 bytes) - Includes the Message Flags of
           of the signing process and any associated payloads
           of this flag.
 
-  0x0040 - 0x0200 RESERVED
+  0x0040  SILC_MESSAGE_FLAG_REPLY
+
+          This is a generic reply flag to send a reply to
+          previously received request.  A separate document
+          should define any payloads associated to this flag.
+
+  0x0080  SILC_MESSAGE_FLAG_DATA
+
+          This is a generic data flag, indicating that the
+          message includes some data which can be interpreted
+          in a specific way.  Using this flag any kind of data
+          can be delivered inside message payload.  A separate
+          document should define how this flag is interpreted
+          and define any associated payloads.
+
+  0x0100 - 0x0800 RESERVED
 
           Reserved for future flags
 
-  0x0400 - 0x8000 PRIVATE RANGE
+  0x1000 - 0x8000 PRIVATE RANGE
 
           Private range for free use.
 
index e5181fdd95898bc39ec95d2b0a40d189fbe39e29..ae9a85bbe8593521123ab77866a12756d164e124 100644 (file)
@@ -1422,7 +1422,7 @@ software version = <major>[.<minor>[.<build or vendor string>]]
 
 Protocol version MAY provide both major and minor version.  Currently
 implementations MUST set the protocol version and accept the protocol
-version as SILC-1.0-<software version>.  If new protocol version causes
+version as SILC-1.1-<software version>.  If new protocol version causes
 in compatibilities with older version the the <minor> versio number MUST
 be incremented.  The <major> is incremented if new protocol version is
 fully incompatible.
@@ -1434,9 +1434,9 @@ software version MAY be freely set and accepted.
 Thus, the version strings could be, for example:
 
 .in 6
-SILC-1.0-1.2
 SILC-1.1-2.0.2
-SILC-1.0-1.0.VendorXYZ
+SILC-1.0-1.2
+SILC-1.1-1.0.VendorXYZ
 .in 3
 
 
index bf7db76b805f7b67d34b53b053689e70d4b81247..53414eb64ba7584176500f51ed0e8322ab756e0a 100644 (file)
@@ -71,7 +71,7 @@ General {
        # number of the software.  The string can be a regex string to match
        # more widely.  Usually the vendor version checking is not necessary
        # and can be omitted.  These can be overridden with ConnectionParams.
-       #version_protocol = "1.0";
+       #version_protocol = "1.1";
        #version_software = "1.3";
        #version_software_vendor = "SomeVendor";
 
@@ -284,7 +284,7 @@ ConnectionParams {
        # number of the software.  The string can be a regex string to match
        # more widely.  Usually the vendor version checking is not necessary
        # and can be omitted.
-       #version_protocol = "1.0";
+       #version_protocol = "1.1";
        #version_software = "1.3";
        #version_software_vendor = "SomeVendor";
 
index ff2f6d026a92cf69472661ce93e7218a736ab30b..8d781039ae74b1ffe35d9691d3aa9e05eed60ffa 100644 (file)
@@ -52,9 +52,24 @@ void silc_client_send_channel_message(SilcClient client,
   unsigned char *id_string;
   SilcUInt32 iv_len;
   int block_len;
+  SilcChannelUser chu;
 
   SILC_LOG_DEBUG(("Sending packet to channel"));
 
+  chu = silc_client_on_channel(channel, conn->local_entry);
+  if (!chu) {
+    SILC_LOG_ERROR(("Cannot send message to channel we are not joined"));
+    return;
+  }
+
+  /* Check if it is allowed to send messages to this channel by us. */
+  if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS && !chu->mode)
+    return;
+  if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && 
+      chu->mode & SILC_CHANNEL_UMODE_CHANOP &&
+      !(chu->mode & SILC_CHANNEL_UMODE_CHANFO))
+    return;
+
   /* Take the key to be used */
   if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
     if (key) {
@@ -173,6 +188,7 @@ static void silc_client_channel_message_cb(SilcClient client,
   if (clients_count == 1) {
     SilcChannelEntry channel;
     unsigned char *message;
+    SilcUInt32 message_len;
 
     channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
     if (!channel)
@@ -188,13 +204,13 @@ static void silc_client_channel_message_cb(SilcClient client,
       silc_hash_table_add(clients[0]->channels, channel, chu);
     }
 
-    message = silc_channel_message_get_data(res->payload, NULL);
+    message = silc_channel_message_get_data(res->payload, &message_len);
     
     /* Pass the message to application */
     client->internal->ops->channel_message(
                               client, conn, clients[0], channel,
                               silc_channel_message_get_flags(res->payload),
-                              message);
+                              message, message_len);
   }
 
  out:
@@ -219,6 +235,7 @@ void silc_client_channel_message(SilcClient client,
   SilcClientEntry client_entry;
   SilcClientID *client_id = NULL;
   unsigned char *message;
+  SilcUInt32 message_len;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -301,13 +318,13 @@ void silc_client_channel_message(SilcClient client,
     goto out;
   }
 
-  message = silc_channel_message_get_data(payload, NULL);
+  message = silc_channel_message_get_data(payload, &message_len);
 
   /* Pass the message to application */
   client->internal->ops->channel_message(
                                 client, conn, client_entry, channel,
                                 silc_channel_message_get_flags(payload),
-                                message);
+                                message, message_len);
 
  out:
   silc_free(id);
index 5dde20b584565c8434d20947c0c3a51571c4335d..797b464e8deaba7ce547ae69c48c4285238bd04c 100644 (file)
@@ -479,41 +479,71 @@ void silc_client_notify_by_server(SilcClient client,
     if (!client_id)
       goto out;
 
-    /* Find Client entry and if not found resolve it */
-    client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
-    if (!client_entry2) {
-      /* Resolve the entry information */
-      silc_client_notify_by_server_resolve(client, conn, packet, 
-                                          SILC_ID_CLIENT, client_id);
-
-      /* Add the new entry even though we resolved it. This is because we
-        want to replace the old entry with the new entry here right now. */
-      client_entry2 = 
-       silc_client_add_client(client, conn, NULL, NULL, NULL, 
-                              silc_id_dup(client_id, SILC_ID_CLIENT), 
-                              client_entry->mode);
+    /* From protocol version 1.1 we get the new nickname in notify as well,
+       so we don't have to resolve it.  Do it the hard way if server doesn't
+       send it to us. */
+    tmp = silc_argument_get_arg_type(args, 3, NULL);
+    if (tmp) {
+      /* Protocol version 1.1 */
+
+      /* Create new client entry, and save all old information with the
+        new nickname and client ID */
+      client_entry2 = silc_client_add_client(client, conn, NULL, NULL, 
+                                            client_entry->realname,
+                                            silc_id_dup(client_id, 
+                                                        SILC_ID_CLIENT), 0);
+      if (!client_entry2)
+       goto out;
 
-      /* Replace old ID entry with new one on all channels. */
-      silc_client_replace_from_channels(client, conn, client_entry,
-                                       client_entry2);
+      if (client_entry->server)
+       client_entry2->server = strdup(client_entry->server);
+      if (client_entry->username)
+       client_entry2->username = strdup(client_entry->username);
+      if (client_entry->hostname)
+       client_entry2->hostname = strdup(client_entry->hostname);
+      silc_client_update_client(client, conn, client_entry2, tmp, NULL, NULL,
+                               client_entry->mode);
     } else {
+      /* Protocol version 1.0 */
+
+      /* Find client entry and if not found resolve it */
+      client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
+      if (!client_entry2) {
+       /* Resolve the entry information */
+       silc_client_notify_by_server_resolve(client, conn, packet, 
+                                            SILC_ID_CLIENT, client_id);
+
+       /* Add the new entry even though we resolved it. This is because we
+          want to replace the old entry with the new entry here right now. */
+       client_entry2 = 
+         silc_client_add_client(client, conn, NULL, NULL, NULL, 
+                                silc_id_dup(client_id, SILC_ID_CLIENT), 
+                                client_entry->mode);
+
+       /* Replace old ID entry with new one on all channels. */
+       silc_client_replace_from_channels(client, conn, client_entry,
+                                         client_entry2);
+       break;
+      }
+
       if (client_entry2 != conn->local_entry)
        silc_client_nickname_format(client, conn, client_entry2);
+    }
 
-      /* Remove the old from cache */
-      silc_idcache_del_by_context(conn->client_cache, client_entry);
-
-      /* Replace old ID entry with new one on all channels. */
-      silc_client_replace_from_channels(client, conn, client_entry,
-                                       client_entry2);
+    /* Remove the old from cache */
+    silc_idcache_del_by_context(conn->client_cache, client_entry);
+    
+    /* Replace old ID entry with new one on all channels. */
+    silc_client_replace_from_channels(client, conn, client_entry,
+                                     client_entry2);
 
-      /* Notify application */
-      client->internal->ops->notify(client, conn, type, 
-                                   client_entry, client_entry2);
+    /* Notify application */
+    client->internal->ops->notify(client, conn, type, 
+                                 client_entry, client_entry2);
+    
+    /* Free old client entry */
+    silc_client_del_client_entry(client, conn, client_entry);
 
-      /* Free data */
-      silc_client_del_client_entry(client, conn, client_entry);
-    }
     break;
 
   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
@@ -795,9 +825,10 @@ void silc_client_notify_by_server(SilcClient client,
     if (!channel)
       break;
 
-    /* Get the kicker */
+    /* From protocol version 1.1 we get the kicker's client ID as well */
     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
     if (tmp) {
+      silc_free(client_id);
       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
       if (!client_id)
        goto out;
@@ -840,36 +871,60 @@ void silc_client_notify_by_server(SilcClient client,
     break;
 
   case SILC_NOTIFY_TYPE_KILLED:
-    /*
-     * A client (maybe me) was killed from the network.
-     */
+    {
+      /*
+       * A client (maybe me) was killed from the network.
+       */
+      char *comment;
+      SilcUInt32 comment_len;
 
-    SILC_LOG_DEBUG(("Notify: KILLED"));
+      SILC_LOG_DEBUG(("Notify: KILLED"));
 
-    /* Get Client ID */
-    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
-    if (!tmp)
-      goto out;
-
-    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-    if (!client_id)
-      goto out;
+      /* Get Client ID */
+      tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+      if (!tmp)
+       goto out;
 
-    /* Find Client entry */
-    client_entry = silc_client_get_client_by_id(client, conn, client_id);
-    if (!client_entry)
-      goto out;
+      client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+      if (!client_id)
+       goto out;
 
-    /* Get comment */
-    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+      /* Find Client entry */
+      client_entry = silc_client_get_client_by_id(client, conn, client_id);
+      if (!client_entry)
+       goto out;
 
-    /* Notify application. */
-    client->internal->ops->notify(client, conn, type, client_entry, tmp);
+      /* Get comment */
+      comment = silc_argument_get_arg_type(args, 2, &comment_len);
+
+      /* From protocol version 1.1 we get killer's client ID as well */
+      tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+      if (tmp) {
+       silc_free(client_id);
+       client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+       if (!client_id)
+         goto out;
+
+       /* Find killer's client entry and if not found resolve it */
+       client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
+       if (!client_entry2) {
+         silc_client_notify_by_server_resolve(client, conn, packet, 
+                                              SILC_ID_CLIENT, client_id);
+         goto out;
+       } else {
+         if (client_entry2 != conn->local_entry)
+           silc_client_nickname_format(client, conn, client_entry2);
+       }
+      }
 
-    if (client_entry != conn->local_entry)
-      /* Remove the client from all channels and free it */
-      silc_client_del_client(client, conn, client_entry);
+      /* Notify application. */
+      client->internal->ops->notify(client, conn, type, client_entry, 
+                                   comment, client_entry2);
 
+      if (client_entry != conn->local_entry)
+       /* Remove the client from all channels and free it */
+       silc_client_del_client(client, conn, client_entry);
+    }
     break;
     
   case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
index bb17c1a4cd2ca41f594c3ffad34c1459524f7f24..7ecb981b7d899b19d1cde5fe7d751384e3aee872 100644 (file)
@@ -29,7 +29,8 @@ silc_say(SilcClient client, SilcClientConnection conn,
 static void 
 silc_channel_message(SilcClient client, SilcClientConnection conn, 
                     SilcClientEntry sender, SilcChannelEntry channel, 
-                    SilcMessageFlags flags, char *msg)
+                    SilcMessageFlags flags, const unsigned char *message,
+                    SilcUInt32 message_len);
 {
 
 }
@@ -40,7 +41,9 @@ silc_channel_message(SilcClient client, SilcClientConnection conn,
 
 static void 
 silc_private_message(SilcClient client, SilcClientConnection conn, 
-                    SilcClientEntry sender, SilcMessageFlags flags, char *msg)
+                    SilcClientEntry sender, SilcMessageFlags flags, 
+                    const unsigned char *message,
+                    SilcUInt32 message_len);
 {
 
 }
index c229b4509655c111fe43e21c6f0fc45d8922a6d7..a6e09917b0853f1f4e2183fb2c713a10f59e2645 100644 (file)
@@ -148,6 +148,8 @@ void silc_client_private_message(SilcClient client,
   SilcClientID *remote_id = NULL;
   SilcClientEntry remote_client;
   SilcMessageFlags flags;
+  unsigned char *message;
+  SilcUInt32 message_len;
 
   if (packet->src_id_type != SILC_ID_CLIENT)
     goto out;
@@ -187,10 +189,9 @@ void silc_client_private_message(SilcClient client,
   flags = silc_private_message_get_flags(payload);
 
   /* Pass the private message to application */
-  client->internal->ops->private_message(
-                                client, conn, remote_client, flags,
-                                silc_private_message_get_message(payload, 
-                                                                 NULL));
+  message = silc_private_message_get_message(payload, &message_len);
+  client->internal->ops->private_message(client, conn, remote_client, flags,
+                                        message, message_len);
 
   /* See if we are away (gone). If we are away we will reply to the
      sender with the set away message. */
index c0c058d00aa865054db8f0cd17ff918ed946c2ea..7ffc279f4fa165c9b62e24332482fdfb1cd1a968 100644 (file)
@@ -1252,6 +1252,18 @@ SILC_CLIENT_CMD_FUNC(cmode)
       else
        mode &= ~SILC_CHANNEL_MODE_TOPIC;
       break;
+    case 'm':
+      if (add)
+       mode |= SILC_CHANNEL_MODE_SILENCE_USERS;
+      else
+       mode &= ~SILC_CHANNEL_MODE_SILENCE_USERS;
+      break;
+    case 'M':
+      if (add)
+       mode |= SILC_CHANNEL_MODE_SILENCE_OPERS;
+      else
+       mode &= ~SILC_CHANNEL_MODE_SILENCE_OPERS;
+      break;
     case 'l':
       if (add) {
        int ll;
@@ -1785,54 +1797,6 @@ SILC_CLIENT_CMD_FUNC(silcoper)
   silc_client_command_free(cmd);
 }
 
-/* CONNECT command. Connects the server to another server. */
-
-SILC_CLIENT_CMD_FUNC(connect)
-{
-  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-  SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer;
-  unsigned char port[4];
-  SilcUInt32 tmp;
-
-  if (!cmd->conn) {
-    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc < 2) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-       "Usage: /CONNECT <server> [<port>]");
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc == 3) {
-    tmp = atoi(cmd->argv[2]);
-    SILC_PUT32_MSB(tmp, port);
-  }
-
-  if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CONNECT, 0, 2, 
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]),
-                                           2, port, 4);
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CONNECT, 0, 1,
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]));
-  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
-                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
-  silc_buffer_free(buffer);
-
-  /* Notify application */
-  COMMAND;
-
- out:
-  silc_client_command_free(cmd);
-}
-
 /* Command BAN. This is used to manage the ban list of the channel. */
 
 SILC_CLIENT_CMD_FUNC(ban)
@@ -1912,77 +1876,6 @@ SILC_CLIENT_CMD_FUNC(ban)
   silc_client_command_free(cmd);
 }
 
-/* CLOSE command. Close server connection to the remote server */
-SILC_CLIENT_CMD_FUNC(close)
-{
-  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-  SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer;
-  unsigned char port[4];
-  SilcUInt32 tmp;
-
-  if (!cmd->conn) {
-    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc < 2) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
-       "Usage: /CLOSE <server> [<port>]");
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc == 3) {
-    tmp = atoi(cmd->argv[2]);
-    SILC_PUT32_MSB(tmp, port);
-  }
-
-  if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CLOSE, 0, 2, 
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]),
-                                           2, port, 4);
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_CLOSE, 0, 1,
-                                           1, cmd->argv[1], 
-                                           strlen(cmd->argv[1]));
-  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
-                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
-  silc_buffer_free(buffer);
-
-  /* Notify application */
-  COMMAND;
-
- out:
-  silc_client_command_free(cmd);
-}
-/* SHUTDOWN command. Shutdowns the server. */
-
-SILC_CLIENT_CMD_FUNC(shutdown)
-{
-  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-
-  if (!cmd->conn) {
-    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  /* Send the command */
-  silc_client_command_send(cmd->client, cmd->conn, 
-                          SILC_COMMAND_SHUTDOWN, 0, 0);
-
-  /* Notify application */
-  COMMAND;
-
- out:
-  silc_client_command_free(cmd);
-}
-
 /* LEAVE command. Leaves a channel. Client removes itself from a channel. */
 
 SILC_CLIENT_CMD_FUNC(leave)
@@ -2282,6 +2175,129 @@ bool silc_client_command_unregister(SilcClient client,
   return FALSE;
 }
 
+/* Private range commands, specific to this implementation (and compatible
+   with SILC Server). */
+
+/* CONNECT command. Connects the server to another server. */
+
+SILC_CLIENT_CMD_FUNC(connect)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer;
+  unsigned char port[4];
+  SilcUInt32 tmp;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
+       "Usage: /CONNECT <server> [<port>]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc == 3) {
+    tmp = atoi(cmd->argv[2]);
+    SILC_PUT32_MSB(tmp, port);
+  }
+
+  if (cmd->argc == 3)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 2, 
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]),
+                                           2, port, 4);
+  else
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 1,
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]));
+  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
+  silc_buffer_free(buffer);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
+
+
+/* CLOSE command. Close server connection to the remote server */
+SILC_CLIENT_CMD_FUNC(close)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer;
+  unsigned char port[4];
+  SilcUInt32 tmp;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO, 
+       "Usage: /CLOSE <server> [<port>]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc == 3) {
+    tmp = atoi(cmd->argv[2]);
+    SILC_PUT32_MSB(tmp, port);
+  }
+
+  if (cmd->argc == 3)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 2, 
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]),
+                                           2, port, 4);
+  else
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 1,
+                                           1, cmd->argv[1], 
+                                           strlen(cmd->argv[1]));
+  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
+  silc_buffer_free(buffer);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
+/* SHUTDOWN command. Shutdowns the server. */
+
+SILC_CLIENT_CMD_FUNC(shutdown)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  /* Send the command */
+  silc_client_command_send(cmd->client, cmd->conn, 
+                          SILC_COMMAND_PRIV_SHUTDOWN, 0, 0);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
+
 /* Register all default commands provided by the client library for the
    application. */
 
@@ -2300,7 +2316,6 @@ void silc_client_commands_register(SilcClient client)
   SILC_CLIENT_CMD(quit, QUIT, "QUIT", 2);
   SILC_CLIENT_CMD(kill, KILL, "KILL", 3);
   SILC_CLIENT_CMD(info, INFO, "INFO", 2);
-  SILC_CLIENT_CMD(connect, CONNECT, "CONNECT", 3);
   SILC_CLIENT_CMD(ping, PING, "PING", 2);
   SILC_CLIENT_CMD(oper, OPER, "OPER", 3);
   SILC_CLIENT_CMD(join, JOIN, "JOIN", 9);
@@ -2310,12 +2325,14 @@ void silc_client_commands_register(SilcClient client)
   SILC_CLIENT_CMD(cumode, CUMODE, "CUMODE", 5);
   SILC_CLIENT_CMD(kick, KICK, "KICK", 4);
   SILC_CLIENT_CMD(ban, BAN, "BAN", 3);
-  SILC_CLIENT_CMD(close, CLOSE, "CLOSE", 3);
-  SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN", 1);
   SILC_CLIENT_CMD(silcoper, SILCOPER, "SILCOPER", 3);
   SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", 2);
   SILC_CLIENT_CMD(users, USERS, "USERS", 2);
   SILC_CLIENT_CMD(getkey, GETKEY, "GETKEY", 2);
+
+  SILC_CLIENT_CMD(connect, PRIV_CONNECT, "CONNECT", 3);
+  SILC_CLIENT_CMD(close, PRIV_CLOSE, "CLOSE", 3);
+  SILC_CLIENT_CMD(shutdown, PRIV_SHUTDOWN, "SHUTDOWN", 1);
 }
 
 /* Unregister all commands. */
@@ -2332,7 +2349,6 @@ void silc_client_commands_unregister(SilcClient client)
   SILC_CLIENT_CMDU(quit, QUIT, "QUIT");
   SILC_CLIENT_CMDU(kill, KILL, "KILL");
   SILC_CLIENT_CMDU(info, INFO, "INFO");
-  SILC_CLIENT_CMDU(connect, CONNECT, "CONNECT");
   SILC_CLIENT_CMDU(ping, PING, "PING");
   SILC_CLIENT_CMDU(oper, OPER, "OPER");
   SILC_CLIENT_CMDU(join, JOIN, "JOIN");
@@ -2342,10 +2358,12 @@ void silc_client_commands_unregister(SilcClient client)
   SILC_CLIENT_CMDU(cumode, CUMODE, "CUMODE");
   SILC_CLIENT_CMDU(kick, KICK, "KICK");
   SILC_CLIENT_CMDU(ban, BAN, "BAN");
-  SILC_CLIENT_CMDU(close, CLOSE, "CLOSE");
-  SILC_CLIENT_CMDU(shutdown, SHUTDOWN, "SHUTDOWN");
   SILC_CLIENT_CMDU(silcoper, SILCOPER, "SILCOPER");
   SILC_CLIENT_CMDU(leave, LEAVE, "LEAVE");
   SILC_CLIENT_CMDU(users, USERS, "USERS");
   SILC_CLIENT_CMDU(getkey, GETKEY, "GETKEY");
+
+  SILC_CLIENT_CMDU(connect, PRIV_CONNECT, "CONNECT");
+  SILC_CLIENT_CMDU(close, PRIV_CLOSE, "CLOSE");
+  SILC_CLIENT_CMDU(shutdown, PRIV_SHUTDOWN, "SHUTDOWN");
 }
index 9246831c0788ec5c9665738c01a172e72076f73b..289b19178b1de78a61f9cc85862c026fe6c6b2d1 100644 (file)
@@ -1356,26 +1356,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(oper)
   silc_client_command_reply_free(cmd);
 }
 
-SILC_CLIENT_CMD_REPLY_FUNC(connect)
-{
-  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
-  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-
-  if (cmd->status != SILC_STATUS_OK) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(cmd->status));
-    COMMAND_REPLY_ERROR;
-    goto out;
-  }
-
-  /* Notify application */
-  COMMAND_REPLY((ARGS));
-
- out:
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CONNECT);
-  silc_client_command_reply_free(cmd);
-}
-
 SILC_CLIENT_CMD_REPLY_FUNC(ban)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
@@ -1420,30 +1400,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
   silc_client_command_reply_free(cmd);
 }
 
-SILC_CLIENT_CMD_REPLY_FUNC(close)
-{
-  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
-  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-
-  if (cmd->status != SILC_STATUS_OK) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(cmd->status));
-    COMMAND_REPLY_ERROR;
-    goto out;
-  }
-
-  /* Notify application */
-  COMMAND_REPLY((ARGS));
+/* Reply to LEAVE command. */
 
- out:
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE);
-  silc_client_command_reply_free(cmd);
-}
-SILC_CLIENT_CMD_REPLY_FUNC(shutdown)
+SILC_CLIENT_CMD_REPLY_FUNC(leave)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+  SilcChannelID *channel_id;
+  SilcChannelEntry channel = NULL;
+  unsigned char *tmp;
+  SilcUInt32 len;
 
   if (cmd->status != SILC_STATUS_OK) {
     SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
@@ -1452,30 +1418,26 @@ SILC_CLIENT_CMD_REPLY_FUNC(shutdown)
     goto out;
   }
 
-  /* Notify application */
-  COMMAND_REPLY((ARGS));
-
- out:
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SHUTDOWN);
-  silc_client_command_reply_free(cmd);
-}
-/* Reply to LEAVE command. */
+  /* From protocol version 1.1 we get the channel ID of the left channel */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (tmp) {
+    channel_id = silc_id_payload_parse_id(tmp, len, NULL);
+    if (!channel_id)
+      goto out;
 
-SILC_CLIENT_CMD_REPLY_FUNC(leave)
-{
-  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
-  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+    /* Get the channel entry */
+    channel = silc_client_get_channel_by_id(cmd->client, conn, channel_id);
+    if (!channel) {
+      silc_free(channel_id);
+      COMMAND_REPLY_ERROR;
+      goto out;
+    }
 
-  if (cmd->status != SILC_STATUS_OK) {
-    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
-       "%s", silc_client_command_status_message(cmd->status));
-    COMMAND_REPLY_ERROR;
-    goto out;
+    silc_free(channel_id);
   }
 
   /* Notify application */
-  COMMAND_REPLY((ARGS));
+  COMMAND_REPLY((ARGS, channel));
 
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_LEAVE);
@@ -1955,3 +1917,68 @@ SILC_CLIENT_CMD_REPLY_FUNC(info_i)
   silc_free(server_id);
   silc_client_command_reply_free(cmd);
 }
+
+
+/* Private range commands, specific to this implementation (and compatible
+   with SILC Server). */
+
+SILC_CLIENT_CMD_REPLY_FUNC(connect)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+
+  if (cmd->status != SILC_STATUS_OK) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+       "%s", silc_client_command_status_message(cmd->status));
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  /* Notify application */
+  COMMAND_REPLY((ARGS));
+
+ out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_CONNECT);
+  silc_client_command_reply_free(cmd);
+}
+
+SILC_CLIENT_CMD_REPLY_FUNC(close)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+
+  if (cmd->status != SILC_STATUS_OK) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+       "%s", silc_client_command_status_message(cmd->status));
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  /* Notify application */
+  COMMAND_REPLY((ARGS));
+
+ out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_CLOSE);
+  silc_client_command_reply_free(cmd);
+}
+SILC_CLIENT_CMD_REPLY_FUNC(shutdown)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+
+  if (cmd->status != SILC_STATUS_OK) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+       "%s", silc_client_command_status_message(cmd->status));
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  /* Notify application */
+  COMMAND_REPLY((ARGS));
+
+ out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_PRIV_SHUTDOWN);
+  silc_client_command_reply_free(cmd);
+}
+
index 4452df4e00468c4cc05804ab35d970c34d22fa54..5f9f44377f22e609d9cba26112e3a302a35bacbb 100644 (file)
@@ -281,13 +281,16 @@ typedef struct {
      `msg' maybe NULL. */
   void (*channel_message)(SilcClient client, SilcClientConnection conn, 
                          SilcClientEntry sender, SilcChannelEntry channel, 
-                         SilcMessageFlags flags, char *msg);
+                         SilcMessageFlags flags,
+                         const unsigned char *message,
+                         SilcUInt32 message_len);
 
   /* Private message to the client. The `sender' is the sender of the
      message. */
   void (*private_message)(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcMessageFlags flags,
-                         char *msg);
+                         const unsigned char *message,
+                         SilcUInt32 message_len);
 
   /* Notify message to the client. The notify arguments are sent in the
      same order as servers sends them. The arguments are same as received
index 6d97e1a251a7ae483550910a70bc928ba8ac4268..788ef384cbfdbf6216eb17c0faf793e53a7a85f4 100644 (file)
@@ -111,8 +111,10 @@ typedef SilcUInt16 SilcMessageFlags;
 #define SILC_MESSAGE_FLAG_NOTICE      0x0008
 #define SILC_MESSAGE_FLAG_REQUEST     0x0010
 #define SILC_MESSAGE_FLAG_SIGNED      0x0020
-#define SILC_MESSAGE_FLAG_RESERVED    0x0040 /* to 0x0200 */
-#define SILC_MESSAGE_FLAG_PRIVATE     0x0400 /* to 0x8000 */
+#define SILC_MESSAGE_FLAG_REPLY       0x0040
+#define SILC_MESSAGE_FLAG_DATA        0x0080
+#define SILC_MESSAGE_FLAG_RESERVED    0x0100 /* to 0x0800 */
+#define SILC_MESSAGE_FLAG_PRIVATE     0x1000 /* to 0x8000 */
 /***/
 
 /* Prototypes */
index a34f3d68fc87c32d975a4938b65201f9857e98fb..4e84bd5b8c158d372419f72575ac4991b75030df 100644 (file)
@@ -134,7 +134,6 @@ typedef unsigned char SilcCommand;
 #define SILC_COMMAND_QUIT              8
 #define SILC_COMMAND_KILL              9
 #define SILC_COMMAND_INFO              10
-#define SILC_COMMAND_CONNECT           11
 #define SILC_COMMAND_PING              12
 #define SILC_COMMAND_OPER              13
 #define SILC_COMMAND_JOIN              14
@@ -144,13 +143,16 @@ typedef unsigned char SilcCommand;
 #define SILC_COMMAND_CUMODE            18
 #define SILC_COMMAND_KICK              19
 #define SILC_COMMAND_BAN               20
-#define        SILC_COMMAND_CLOSE              21
-#define        SILC_COMMAND_SHUTDOWN           22
 #define SILC_COMMAND_SILCOPER          23
 #define SILC_COMMAND_LEAVE             24
 #define SILC_COMMAND_USERS             25
 #define SILC_COMMAND_GETKEY            26
 
+/* Private range start */
+#define SILC_COMMAND_PRIV_CONNECT       200
+#define SILC_COMMAND_PRIV_CLOSE         201
+#define SILC_COMMAND_PRIV_SHUTDOWN      202
+
 /* Reserved */
 #define SILC_COMMAND_RESERVED           255
 /***/
index 4e365bf75c01d05a37644b4dd0d47986abd31c45..6f47e7f827ecfa0792ce434fef26e4de31e3235b 100644 (file)
@@ -50,6 +50,8 @@
 #define SILC_CHANNEL_MODE_CIPHER       0x0080 /* sets cipher of the channel */
 #define SILC_CHANNEL_MODE_HMAC         0x0100 /* sets hmac of the channel */
 #define SILC_CHANNEL_MODE_FOUNDER_AUTH 0x0200 /* sets founder auth data */
+#define SILC_CHANNEL_MODE_SILENCE_USERS 0x0400 /* sets founder auth data */
+#define SILC_CHANNEL_MODE_SILENCE_OPERS 0x0800 /* sets founder auth data */
 /***/
 
 /****d* silccore/Modes/ChannelUserModes
index 1473fc80d1619f8dfb748d59f294da60f5e9f018..f0c0e7b6a1d429cd2e31f1b940504a64b018ef3c 100644 (file)
@@ -769,6 +769,12 @@ char *silc_client_chmode(SilcUInt32 mode, const char *cipher, const char *hmac)
   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
     strncat(string, "f", 1);
 
+  if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
+    strncat(string, "m", 1);
+
+  if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
+    strncat(string, "M", 1);
+
   if (mode & SILC_CHANNEL_MODE_CIPHER)
     strncat(string, cipher, strlen(cipher));
 
diff --git a/prepare b/prepare
index 71c75d6343baa58f0f573ca2a8ecf06a2dca4e47..f5cfff57183be5e2f33aa19250a525bfc3f2940a 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -142,7 +142,7 @@ file=includes/version_internal.h
 echo "/* Automatically generated by ./prepare */" >$file
 echo "#define SILC_VERSION_STRING \"$version\"" >>$file
 echo "#define SILC_DIST_VERSION_STRING \"$dist_version\"" >>$file
-echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.0-$version\"" >>$file
+echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.1-$version\"" >>$file
 echo "#define SILC_NAME \"SILC $distribution\"" >>$file
 
 # preparing irssi