+Tue Apr 9 17:15:42 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added new user modes ANONYMOUS for special anonymous servers
+ that may set the mode for client, and BLOCK_PRIVMSG which
+ client may set to block incoming private messages unless the
+ Private Message Key flag is set (using private keys to protect
+ private messages). Updated protocol specs and code in client
+ and server and core library. Protocol TODO #23. Affected
+ files are lib/silccore/silcmode.h, silcd/server.[ch],
+ irssi/src/silc/core/client_ops.c, silcd/packet_receive.c,
+ irssi/docs/help/in/umode.in, lib/silcclient/command.c.
+
+ * Added new channel user mode BLOCK_MESSAGES which the client
+ may set to itself to tell server not send channel messages.
+ Other packets such as channel key packets are still sent.
+ Protocol TODO #23. Updated the protocol specs, client and
+ server. Affected files are lib/silccore/silcmode.h,
+ irssi/docs/help/in/cumode.in, lib/silcclient/command.c,
+ lib/silcutil/silcutil.c, silcd/command.c, and
+ silcd/packet_send.c.
+
Mon Apr 8 23:57:32 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
* Redefined the Status Payload to include now two 8 bit fields,
22. Session detachment/resume?
- 23. Message blocking via user modes (which could be expanded via
- services, but basic blocking would be a feature)?
-
o Inviting and banning by public key should be made possible. To be
included in protocol version 1.2.
Set/unset channel operator. Requires that
you are channel operator or channel founder.
+ b <nickname>[@<server>]
+
+ Set/unset channel message blocking. Client
+ may set this mode only to itself. When set
+ the server will not send channel message to
+ to the client. This mode can be used to block
+ unwanted messages if desired.
+
+
See also: CMODE, UMODE
p Set/unset to await paging
h Set/unset to be hyper active
t Set/unset to be actually robot
+ P Set/unset to block incoming private messages.
+ If set then only private message secured with
+ private message keys are delivered. Other
+ private messages server automatically discards.
+ This can be used to block unwanted private
+ messages.
See also: CMODE, CUMODE, AWAY
strcat(buf, " hyper active");
if (mode & SILC_UMODE_ROBOT)
strcat(buf, " robot");
+ if (mode & SILC_UMODE_ANONYMOUS)
+ strcat(buf, " anonymous");
+ if (mode & SILC_UMODE_BLOCK_PRIVMSG)
+ strcat(buf, " blocks private messages");
printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
SILCTXT_WHOIS_MODES, buf);
strcat(stat, "H");
else if (e->mode & SILC_UMODE_ROBOT)
strcat(stat, "R");
+ else if (e->mode & SILC_UMODE_ANONYMOUS)
+ strcat(stat, "?");
else
strcat(stat, "A");
if (mode)
}
/* Get route to the client */
- dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
+ dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
+ &idata, NULL);
if (!dest_sock) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
goto out;
}
+ /* Anonymous mode cannot be set by client */
+ if (mask & SILC_UMODE_ANONYMOUS) {
+ if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+ SILC_STATUS_ERR_PERM_DENIED);
+ goto out;
+ }
+ } else {
+ if (client->mode & SILC_UMODE_ANONYMOUS) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+ SILC_STATUS_ERR_PERM_DENIED);
+ goto out;
+ }
+ }
+
/* Change the mode */
client->mode = mask;
}
if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
+ if (target_client != client) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+ SILC_STATUS_ERR_NOT_YOU);
+ goto out;
+ }
+
if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
/* The client tries to claim the founder rights. */
unsigned char *tmp_auth;
SilcUInt32 tmp_auth_len, auth_len;
void *auth;
- if (target_client != client) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
- SILC_STATUS_ERR_NOT_YOU);
- goto out;
- }
-
if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
!channel->founder_key || !idata->public_key ||
!silc_pkcs_public_key_compare(channel->founder_key,
}
}
+ if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
+ if (target_client != client) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+ SILC_STATUS_ERR_NOT_YOU);
+ goto out;
+ }
+
+ if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
+ chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
+ notify = TRUE;
+ }
+ } else {
+ if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
+ if (target_client != client) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+ SILC_STATUS_ERR_NOT_YOU);
+ goto out;
+ }
+
+ chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
+ notify = TRUE;
+ }
+ }
+
+
idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
SilcSocketConnection dest_sock;
dest_sock = silc_server_get_client_route(server, NULL, 0,
- client_id, NULL);
+ client_id, NULL, NULL);
if (!dest_sock)
goto out;
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
username = silc_argument_get_arg_type(cmd->args, 4, &len);
realname = silc_argument_get_arg_type(cmd->args, 5, &len);
- if (!id_data || !nickname || !username || !realname) {
- SILC_LOG_ERROR(("Incomplete WHOIS info: %s %s %s",
- nickname ? nickname : "",
- username ? username : "",
- realname ? realname : ""));
+ if (!id_data || !nickname || !username || !realname)
return FALSE;
- }
tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
if (tmp)
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, NULL, &idata);
+ packet->dst_id_len, NULL,
+ &idata, NULL);
if (dst_sock)
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
{
SilcSocketConnection dst_sock;
SilcIDListData idata;
+ SilcClientEntry client;
SILC_LOG_DEBUG(("Start"));
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, NULL, &idata);
+ packet->dst_id_len, NULL,
+ &idata, &client);
if (!dst_sock) {
/* Send IDENTIFY command reply with error status to indicate that
such destination ID does not exist or is invalid */
return;
}
+ /* Check whether destination client wishes to receive private messages */
+ if (client && !(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY) &&
+ client->mode & SILC_UMODE_BLOCK_PRIVMSG) {
+ SILC_LOG_DEBUG(("Client blocks private messages, discarding packet"));
+ return;
+ }
+
/* Send the private message */
silc_server_send_private_message(server, dst_sock, idata->send_key,
idata->hmac_send, idata->psn_send++,
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, NULL, &idata);
+ packet->dst_id_len, NULL,
+ &idata, NULL);
if (!dst_sock)
return;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, NULL, &idata);
+ packet->dst_id_len, NULL,
+ &idata, NULL);
if (!dst_sock)
return;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, NULL, &idata);
+ packet->dst_id_len, NULL,
+ &idata, NULL);
if (!dst_sock)
return;
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
client = chl->client;
- if (!client || client == sender_entry)
+ if (!client || client == sender_entry ||
+ chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
continue;
/* If the client has set router it means that it is not locally
could not be found to the client. If the `client_id' is specified then
it is used and the `id_data' is ignored. */
-SilcSocketConnection silc_server_get_client_route(SilcServer server,
- unsigned char *id_data,
- SilcUInt32 id_len,
- SilcClientID *client_id,
- SilcIDListData *idata)
+SilcSocketConnection
+silc_server_get_client_route(SilcServer server,
+ unsigned char *id_data,
+ SilcUInt32 id_len,
+ SilcClientID *client_id,
+ SilcIDListData *idata,
+ SilcClientEntry *client_entry)
{
SilcClientID *id;
SilcClientEntry client;
id = silc_id_dup(client_id, SILC_ID_CLIENT);
}
+ if (client_entry)
+ *client_entry = NULL;
+
/* If the destination belongs to our server we don't have to route
the packet anywhere but to send it to the local destination. */
client = silc_idlist_find_client_by_id(server->local_list, id, TRUE, NULL);
/* Seems that client really is directly connected to us */
if (idata)
*idata = (SilcIDListData)client;
+ if (client_entry)
+ *client_entry = client;
return client->connection;
}
SilcBuffer user_list,
SilcBuffer mode_list,
SilcUInt32 user_count);
-SilcSocketConnection silc_server_get_client_route(SilcServer server,
- unsigned char *id_data,
- SilcUInt32 id_len,
- SilcClientID *client_id,
- SilcIDListData *idata);
+SilcSocketConnection
+silc_server_get_client_route(SilcServer server,
+ unsigned char *id_data,
+ SilcUInt32 id_len,
+ SilcClientID *client_id,
+ SilcIDListData *idata,
+ SilcClientEntry *client_entry);
SilcBuffer silc_server_get_client_channel_list(SilcServer server,
SilcClientEntry client);
SilcClientEntry silc_server_get_client_resolve(SilcServer server,
0x00000002 SILC_UMODE_ROUTER_OPERATOR
Marks the user as router (SILC) operator. Client
- MUST NOT this mode itself. Router sets this mode to
- the client when client attains the router operator
+ MUST NOT set this mode itself. Router sets this mode
+ to the client when client attains the router operator
privileges by SILC_COMMAND_SILCOPER command. Client
MAY unset the mode itself.
Client MAY set and unset this mode.
+ 0x00000100 SILC_UMODE_ANONYMOUS
+
+ Marks that the client is anonymous client. Server
+ that specificly is designed for anonymous services
+ can set and unset this mode. Client MUST NOT set or
+ unset this mode itself. A client with this mode set
+ would have the username and the hostname information
+ scrambled by the server which set this mode.
+
+
+ 0x00000200 SILC_UMODE_BLOCK_PRIVMSG
+
+ Marks that the client wishes to block private
+ messages sent to the client, unless the Private
+ Message Key flag is set in the SILC packet header.
+ If this mode is set server MUST NOT deliver private
+ messages to the client without the Private Message
+ Key flag being set.
+
+ A separate service could provide additional filtering
+ features for accepting private messages from certain
+ sender. However, this document does not specify such
+ service.
+
+ The client MAY set and unset this mode.
+
+
Reply messages to the command:
Max Arguments: 2
Sets channel operator privileges on the channel for a
client on the channel. Channel founder and channel operator
- MAY set/unset this mode.
+ MAY set/unset this mode. The client MAY remove this mode
+ at any time.
+
+
+ 0x00000004 SILC_CUMODE_BLOCK_MESSAGES
+
+ Marks that the client wishes not to receive any channel
+ messages sent for the channel. Client MAY set and unset
+ this mode to itself. Client MUST NOT set it to anyone else.
+ When this mode is set server MUST NOT deliver channel
+ messages to this client. Other packets such as channel
+ key packets are still sent to the client.
+
+ A separate service could provide additional filtering
+ features for accepting channel messages from certain
+ sender. However, this document does not specify such
+ service.
+
Reply messages to the command:
else
mode &= ~SILC_UMODE_ROBOT;
break;
+ case 'P':
+ if (add)
+ mode |= SILC_UMODE_BLOCK_PRIVMSG;
+ else
+ mode &= ~SILC_UMODE_BLOCK_PRIVMSG;
+ break;
default:
COMMAND_ERROR;
goto out;
if (add) {
mode |= SILC_CHANNEL_UMODE_CHANFO;
mode |= SILC_CHANNEL_UMODE_CHANOP;
+ mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
} else {
mode = SILC_CHANNEL_UMODE_NONE;
}
else
mode &= ~SILC_CHANNEL_UMODE_CHANOP;
break;
+ case 'b':
+ if (add)
+ mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
+ else
+ mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
+ break;
default:
COMMAND_ERROR;
goto out;
*
* DESCRIPTION
*
- * All user modes on channel
+ * All user modes on channel. These indicate the user's status on the
+ * channel. Some of the modes can be set by channel founder and channel
+ * operator. Some modes may be set by users themself.
*
* SOURCE
*/
-#define SILC_CHANNEL_UMODE_NONE 0x0000 /* Normal user */
-#define SILC_CHANNEL_UMODE_CHANFO 0x0001 /* channel founder */
-#define SILC_CHANNEL_UMODE_CHANOP 0x0002 /* channel operator */
+#define SILC_CHANNEL_UMODE_NONE 0x00000000 /* Normal user */
+#define SILC_CHANNEL_UMODE_CHANFO 0x00000001 /* channel founder */
+#define SILC_CHANNEL_UMODE_CHANOP 0x00000002 /* channel operator */
+#define SILC_CHANNEL_UMODE_BLOCK_MESSAGES 0x00000004 /* messages blocked */
/***/
/****d* silccore/Modes/SilcUserMode
*
* SOURCE
*/
-#define SILC_UMODE_NONE 0x00000000 /* Normal SILC user */
-#define SILC_UMODE_SERVER_OPERATOR 0x00000001 /* Server operator */
-#define SILC_UMODE_ROUTER_OPERATOR 0x00000002 /* Router (SILC) operator */
-#define SILC_UMODE_GONE 0x00000004 /* Client is gone */
-#define SILC_UMODE_INDISPOSED 0x00000008 /* Client is indisposed */
-#define SILC_UMODE_BUSY 0x00000010 /* Client is busy */
-#define SILC_UMODE_PAGE 0x00000020 /* Client requests paging */
-#define SILC_UMODE_HYPER 0x00000040 /* Client is hyper active */
-#define SILC_UMODE_ROBOT 0x00000080 /* Client is a robot */
+#define SILC_UMODE_NONE 0x00000000 /* Normal SILC user */
+#define SILC_UMODE_SERVER_OPERATOR 0x00000001 /* Server operator */
+#define SILC_UMODE_ROUTER_OPERATOR 0x00000002 /* Router (SILC) operator */
+#define SILC_UMODE_GONE 0x00000004 /* Client is gone */
+#define SILC_UMODE_INDISPOSED 0x00000008 /* Client is indisposed */
+#define SILC_UMODE_BUSY 0x00000010 /* Client is busy */
+#define SILC_UMODE_PAGE 0x00000020 /* Client requests paging */
+#define SILC_UMODE_HYPER 0x00000040 /* Client is hyper active */
+#define SILC_UMODE_ROBOT 0x00000080 /* Client is a robot */
+#define SILC_UMODE_ANONYMOUS 0x00000100 /* Client is anonymous */
+#define SILC_UMODE_BLOCK_PRIVMSG 0x00000200 /* Client blocks privmsgs */
/***/
#endif
if (mode & SILC_CHANNEL_UMODE_CHANOP)
strncat(string, "o", 1);
+ if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
+ strncat(string, "b", 1);
+
return strdup(string);
}