+Mon Mar 19 18:43:06 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Fixed the mode printing on the user interface on joining.
+ Affected file silc/client_ops.c.
+
+ * Implemented the UMODE command and user modes in general to the
+ client library and to the user interface.
+
+ * Implemented the UMODE command to the server.
+
+ * The server now sends UNKNOWN_COMMAND error status if client sends
+ unknown command. Affected file silcd/command.c.
+
+ * All server commands now handle the command identifier the right
+ way when sending the command reply to the client. The client can
+ use to identify the command replies with the identifier.
+
Mon Mar 19 16:13:07 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Added silc_server_get_client_route to resolve the route to
Set/unset channel operator. Requires that
you are channel operator or channel founder.
+ /UMODE +|-<modes>
+
/MSG <nickname> <message>
Sends private message to remote client. Support for
snprintf(message, sizeof(message), "%s (%s) has joined channel %s",
client_entry->nickname, client_entry->username,
channel_entry->channel_name);
+ if (client_entry == conn->local_entry) {
+ SilcChannelUser chu;
+
+ silc_list_start(channel_entry->clients);
+ while ((chu = silc_list_get(channel_entry->clients)) != SILC_LIST_END) {
+ if (chu->client == client_entry) {
+ if (app->screen->bottom_line->mode)
+ silc_free(app->screen->bottom_line->mode);
+ app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode);
+ silc_screen_print_bottom_line(app->screen, 0);
+ break;
+ }
+ }
+ }
break;
case SILC_NOTIFY_TYPE_LEAVE:
}
break;
+ case SILC_COMMAND_UMODE:
+ {
+ unsigned int mode;
+
+ if (!success)
+ return;
+
+ mode = va_arg(vp, unsigned int);
+
+ if (!mode && app->screen->bottom_line->umode) {
+ silc_free(app->screen->bottom_line->umode);
+ app->screen->bottom_line->umode = NULL;
+ }
+
+ if (mode & SILC_UMODE_SERVER_OPERATOR) {
+ if (app->screen->bottom_line->umode)
+ silc_free(app->screen->bottom_line->umode);
+ app->screen->bottom_line->umode = strdup("Server Operator");;
+ }
+
+ if (mode & SILC_UMODE_ROUTER_OPERATOR) {
+ if (app->screen->bottom_line->umode)
+ silc_free(app->screen->bottom_line->umode);
+ app->screen->bottom_line->umode = strdup("SILC Operator");;
+ }
+
+ silc_screen_print_bottom_line(app->screen, 0);
+ }
+ break;
+
+ case SILC_COMMAND_OPER:
+ if (status == SILC_STATUS_OK) {
+ conn->local_entry->mode |= SILC_UMODE_SERVER_OPERATOR;
+ if (app->screen->bottom_line->umode)
+ silc_free(app->screen->bottom_line->umode);
+ app->screen->bottom_line->umode = strdup("Server Operator");;
+ silc_screen_print_bottom_line(app->screen, 0);
+ }
+ break;
+
+ case SILC_COMMAND_SILCOPER:
+ if (status == SILC_STATUS_OK) {
+ conn->local_entry->mode |= SILC_UMODE_ROUTER_OPERATOR;
+ if (app->screen->bottom_line->umode)
+ silc_free(app->screen->bottom_line->umode);
+ app->screen->bottom_line->umode = strdup("SILC Operator");;
+ silc_screen_print_bottom_line(app->screen, 0);
+ }
+ break;
+
case SILC_COMMAND_USERS:
if (!success)
return;
if (chu->client == conn->local_entry) {
if (app->screen->bottom_line->mode)
silc_free(app->screen->bottom_line->mode);
- app->screen->bottom_line->mode =
- silc_client_chumode_char(chu->mode);
+ app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode);
silc_screen_print_bottom_line(app->screen, 0);
break;
}
strncat(buf, ")", 2);
}
+ if (line->umode) {
+ len = strlen(line->umode);
+ strncat(buf, " [", 2);
+ strncat(buf, line->umode, len > SILC_SCREEN_MAX_UMODE_LEN ?
+ SILC_SCREEN_MAX_UMODE_LEN : len);
+ strncat(buf, "]", 2);
+ }
+
if (line->away)
strncat(buf, " (away)", 8);
char *connection;
char *channel;
char *channel_mode;
+ char *umode;
int away;
} *SilcScreenBottomLine;
/* Maximum length of connection name that will be shown on the screen */
#define SILC_SCREEN_MAX_CONN_LEN 20
+/* Maximum length of user mode that will be shown on the screen */
+#define SILC_SCREEN_MAX_UMODE_LEN 20
+
/* Macros */
/* Macro used to insert typed character into the buffer. The character
{
SilcServerCommandContext ctx;
SilcServerCommand *cmd;
+ SilcCommand command;
/* Allocate command context. This must be free'd by the
command routine receiving it. */
return;
}
ctx->args = silc_command_get_args(ctx->payload);
-
+
/* Get the command */
+ command = silc_command_get(ctx->payload);
for (cmd = silc_command_list; cmd->cb; cmd++)
- if (cmd->cmd == silc_command_get(ctx->payload))
+ if (cmd->cmd == command)
break;
if (cmd == NULL) {
- SILC_LOG_ERROR(("Unknown command, packet dropped"));
+ silc_server_command_send_status_reply(ctx, command,
+ SILC_STATUS_ERR_UNKNOWN_COMMAND);
silc_server_command_free(ctx);
return;
}
SILC_LOG_DEBUG(("Sending command status %d", status));
- buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
+ buffer =
+ silc_command_reply_payload_encode_va(command, status,
+ silc_command_get_ident(cmd->payload),
+ 0);
silc_server_packet_send(cmd->server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
buffer->data, buffer->len, FALSE);
SILC_LOG_DEBUG(("Sending command status %d", status));
- buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
- arg_type, arg, arg_len);
+ buffer =
+ silc_command_reply_payload_encode_va(command, status,
+ silc_command_get_ident(cmd->payload),
+ 1, arg_type, arg, arg_len);
silc_server_packet_send(cmd->server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
buffer->data, buffer->len, FALSE);
SilcBuffer packet, nidp, oidp;
SilcClientID *new_id;
char *nick;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
goto out;
/* Send the new Client ID as reply command back to client */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
- SILC_STATUS_OK, 0, 1,
+ SILC_STATUS_OK, ident, 1,
2, nidp->data, nidp->len);
silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
0, packet->data, packet->len, FALSE);
SilcBuffer packet, idp;
unsigned char *tmp;
unsigned int argc, tmp_len;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
if (channel->topic)
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
- SILC_STATUS_OK, 0, 2,
+ SILC_STATUS_OK, ident, 2,
2, idp->data, idp->len,
3, channel->topic,
strlen(channel->topic));
else
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
- SILC_STATUS_OK, 0, 1,
+ SILC_STATUS_OK, ident, 1,
2, idp->data, idp->len);
silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
0, packet->data, packet->len, FALSE);
silc_server_command_free(cmd);
}
+/* Server side of command UMODE. Client can use this command to set/unset
+ user mode. Client actually cannot set itself to be as server/router
+ operator so this can be used only to unset the modes. */
+
SILC_SERVER_CMD_FUNC(umode)
{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ SilcServer server = cmd->server;
+ SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+ SilcBuffer packet;
+ unsigned char *tmp_mask;
+ unsigned int mask;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
+
+ if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+ goto out;
+
+ SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
+
+ /* Get the client's mode mask */
+ tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
+ if (!tmp_mask) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+ SILC_GET32_MSB(mask, tmp_mask);
+
+ /*
+ * Change the mode
+ */
+
+ if (mask & SILC_UMODE_SERVER_OPERATOR) {
+ /* Cannot operator mode */
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+ SILC_STATUS_ERR_PERM_DENIED);
+ goto out;
+ } else {
+ if (client->mode & SILC_UMODE_SERVER_OPERATOR)
+ /* Remove the server operator rights */
+ client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
+ }
+
+ if (mask & SILC_UMODE_ROUTER_OPERATOR) {
+ /* Cannot operator mode */
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+ SILC_STATUS_ERR_PERM_DENIED);
+ goto out;
+ } else {
+ if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
+ /* Remove the router operator rights */
+ client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
+ }
+
+ /* Send command reply to sender */
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
+ SILC_STATUS_OK, ident, 1,
+ 2, tmp_mask, 4);
+ silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
+ packet->data, packet->len, FALSE);
+ silc_buffer_free(packet);
+
+ out:
+ silc_server_command_free(cmd);
}
/* Checks that client has rights to add or remove channel modes. If any
SilcBuffer packet, cidp;
unsigned char *tmp, *tmp_id, *tmp_mask;
unsigned int argc, mode_mask, tmp_len, tmp_len2;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
SILC_LOG_DEBUG(("Start"));
/* Send command reply to sender */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
- SILC_STATUS_OK, 0, 1,
+ SILC_STATUS_OK, ident, 1,
2, tmp_mask, 4);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
int notify = FALSE;
+ unsigned short ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
/* Send command reply to sender */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
- SILC_STATUS_OK, 0, 2,
+ SILC_STATUS_OK, ident, 2,
2, tmp_mask, 4,
3, tmp_id, tmp_len);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
SILC_STATUS_ERR_NO_SUCH_CLIENT_ID
SILC_STATUS_ERR_BAD_CLIENT_ID
SILC_STATUS_ERR_NOT_YOU
+ SILC_STATUS_ERR_PERM_DENIED
SILC_STATUS_ERR_UNKNOWN_MODE
- SILC_STATUS_ERR_NO_RECIPIENT
SILC_STATUS_ERR_NO_CLIENT_ID
all clients on the channel by sending SILC_NOTIFY_TYPE_CMODE_CHANGE
notify type.
-
Reply messages to the command:
Max Arguments: 2
client on the channel. Channel founder and channel operator
may set/unset (promote/demote) this mode.
-
Reply messages to the command:
Max Arguments: 3
31 SILC_STATUS_ERR_PERM_DENIED
- "Your host is not among the privileged". The client tried to
- register on server that does not allow this host to connect.
+ "Permission denied". Generic permission denied error status
+ to indicate disallowed access.
32 SILC_STATUS_ERR_BANNED_FROM_SERVER
silc_client_command_free(cmd);
}
-/* UMODE. Set user mode in SILC. */
+/* UMODE. Set/unset user mode in SILC. This is used mainly to unset the
+ modes as client cannot set itself server/router operator privileges. */
SILC_CLIENT_CMD_FUNC(umode)
{
+ SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+ SilcClientConnection conn = cmd->conn;
+ SilcBuffer buffer, idp;
+ unsigned char *cp, modebuf[4];
+ unsigned int mode, add, len;
+ int i;
+
+ if (!cmd->conn) {
+ SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+ COMMAND_ERROR;
+ goto out;
+ }
+
+ if (cmd->argc < 2) {
+ cmd->client->ops->say(cmd->client, conn,
+ "Usage: /UMODE +|-<modes>");
+ COMMAND_ERROR;
+ goto out;
+ }
+
+ mode = conn->local_entry->mode;
+
+ /* Are we adding or removing mode */
+ if (cmd->argv[1][0] == '-')
+ add = FALSE;
+ else
+ add = TRUE;
+
+ /* Parse mode */
+ cp = cmd->argv[1] + 1;
+ len = strlen(cp);
+ for (i = 0; i < len; i++) {
+ switch(cp[i]) {
+ case 'a':
+ if (add) {
+ mode = 0;
+ mode |= SILC_UMODE_SERVER_OPERATOR;
+ mode |= SILC_UMODE_ROUTER_OPERATOR;
+ } else {
+ mode = SILC_UMODE_NONE;
+ }
+ break;
+ case 's':
+ if (add)
+ mode |= SILC_UMODE_SERVER_OPERATOR;
+ else
+ mode &= ~SILC_UMODE_SERVER_OPERATOR;
+ break;
+ case 'r':
+ if (add)
+ mode |= SILC_UMODE_ROUTER_OPERATOR;
+ else
+ mode &= ~SILC_UMODE_ROUTER_OPERATOR;
+ break;
+ default:
+ COMMAND_ERROR;
+ goto out;
+ break;
+ }
+ }
+ idp = silc_id_payload_encode(conn->local_id, SILC_ID_CLIENT);
+ SILC_PUT32_MSB(mode, modebuf);
+
+ /* Send the command packet. We support sending only one mode at once
+ that requires an argument. */
+ buffer =
+ silc_command_payload_encode_va(SILC_COMMAND_UMODE, ++conn->cmd_ident, 2,
+ 1, idp->data, idp->len,
+ 2, modebuf, sizeof(modebuf));
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ 0, NULL, NULL, buffer->data, buffer->len, TRUE);
+ silc_buffer_free(buffer);
+ silc_buffer_free(idp);
+
+ /* Notify application */
+ COMMAND;
+
+ out:
+ silc_client_command_free(cmd);
}
/* CMODE command. Sets channel mode. Modes that does not require any arguments
{ STAT(NOT_REGISTERED), "You have not registered" },
{ STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" },
{ STAT(TOO_MANY_PARAMS), "Too many parameters" },
- { STAT(PERM_DENIED), "Your host is not among the privileged" },
+ { STAT(PERM_DENIED), "Permission denied" },
{ STAT(BANNED_FROM_SERVER),"You are banned from this server" },
{ STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" },
{ STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" },
COMMAND_REPLY((ARGS));
/* Execute any pending command callbacks */
- SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE);
+ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL);
out:
- SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE);
+ SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KILL);
silc_client_command_reply_free(cmd);
}
silc_client_command_reply_free(cmd);
}
+/* Received reply tot he UMODE command. Save the current user mode */
+
SILC_CLIENT_CMD_REPLY_FUNC(umode)
{
+ SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+ SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+ SilcCommandStatus status;
+ unsigned char *tmp;
+ unsigned int mode;
+
+ tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
+ SILC_GET16_MSB(status, tmp);
+ if (status != SILC_STATUS_OK) {
+ cmd->client->ops->say(cmd->client, conn,
+ "%s", silc_client_command_status_message(status));
+ COMMAND_REPLY_ERROR;
+ goto out;
+ }
+
+ tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+ if (!tmp) {
+ COMMAND_REPLY_ERROR;
+ goto out;
+ }
+
+ SILC_GET32_MSB(mode, tmp);
+ conn->local_entry->mode = mode;
+
+ /* Notify application */
+ COMMAND_REPLY((ARGS, mode));
+
+ /* Execute any pending command callbacks */
+ SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE);
+
+ out:
+ SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_UMODE);
+ silc_client_command_reply_free(cmd);
}
/* Received reply for CMODE command. */
char *server; /* SILC server name */
char *realname; /* Realname (userinfo) */
unsigned int num;
+ unsigned int mode; /* User mode in SILC */
SilcClientID *id; /* The Client ID */
SilcCipher send_key; /* Private message key for sending */
SilcCipher receive_key; /* Private message key for receiving */