From: Pekka Riikonen Date: Mon, 19 Mar 2001 17:54:34 +0000 (+0000) Subject: update. X-Git-Tag: 1.2.beta1~2436 X-Git-Url: http://git.silcnet.org/gitweb/?p=runtime.git;a=commitdiff_plain;h=aa5ab390a9c68a75ac4c6a1468fd04946f6270f3 update. --- diff --git a/CHANGES b/CHANGES index 47a58caf..9ee79cc3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,20 @@ +Mon Mar 19 18:43:06 EET 2001 Pekka Riikonen + + * 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 * Added silc_server_get_client_route to resolve the route to diff --git a/README b/README index 559ae953..97e58a37 100644 --- a/README +++ b/README @@ -118,6 +118,8 @@ Following commands has been, at least partly, implemented: Set/unset channel operator. Requires that you are channel operator or channel founder. + /UMODE +|- + /MSG Sends private message to remote client. Support for diff --git a/apps/silc/client_ops.c b/apps/silc/client_ops.c index f2096c66..a37129d7 100644 --- a/apps/silc/client_ops.c +++ b/apps/silc/client_ops.c @@ -114,6 +114,20 @@ void silc_notify(SilcClient client, SilcClientConnection conn, snprintf(message, sizeof(message), "%s (%s) has joined channel %s", client_entry->nickname, client_entry->username, channel_entry->channel_name); + if (client_entry == conn->local_entry) { + SilcChannelUser chu; + + silc_list_start(channel_entry->clients); + while ((chu = silc_list_get(channel_entry->clients)) != SILC_LIST_END) { + if (chu->client == client_entry) { + if (app->screen->bottom_line->mode) + silc_free(app->screen->bottom_line->mode); + app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode); + silc_screen_print_bottom_line(app->screen, 0); + break; + } + } + } break; case SILC_NOTIFY_TYPE_LEAVE: @@ -547,6 +561,56 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn, } break; + case SILC_COMMAND_UMODE: + { + unsigned int mode; + + if (!success) + return; + + mode = va_arg(vp, unsigned int); + + if (!mode && app->screen->bottom_line->umode) { + silc_free(app->screen->bottom_line->umode); + app->screen->bottom_line->umode = NULL; + } + + if (mode & SILC_UMODE_SERVER_OPERATOR) { + if (app->screen->bottom_line->umode) + silc_free(app->screen->bottom_line->umode); + app->screen->bottom_line->umode = strdup("Server Operator");; + } + + if (mode & SILC_UMODE_ROUTER_OPERATOR) { + if (app->screen->bottom_line->umode) + silc_free(app->screen->bottom_line->umode); + app->screen->bottom_line->umode = strdup("SILC Operator");; + } + + silc_screen_print_bottom_line(app->screen, 0); + } + break; + + case SILC_COMMAND_OPER: + if (status == SILC_STATUS_OK) { + conn->local_entry->mode |= SILC_UMODE_SERVER_OPERATOR; + if (app->screen->bottom_line->umode) + silc_free(app->screen->bottom_line->umode); + app->screen->bottom_line->umode = strdup("Server Operator");; + silc_screen_print_bottom_line(app->screen, 0); + } + break; + + case SILC_COMMAND_SILCOPER: + if (status == SILC_STATUS_OK) { + conn->local_entry->mode |= SILC_UMODE_ROUTER_OPERATOR; + if (app->screen->bottom_line->umode) + silc_free(app->screen->bottom_line->umode); + app->screen->bottom_line->umode = strdup("SILC Operator");; + silc_screen_print_bottom_line(app->screen, 0); + } + break; + case SILC_COMMAND_USERS: if (!success) return; @@ -557,8 +621,7 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn, if (chu->client == conn->local_entry) { if (app->screen->bottom_line->mode) silc_free(app->screen->bottom_line->mode); - app->screen->bottom_line->mode = - silc_client_chumode_char(chu->mode); + app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode); silc_screen_print_bottom_line(app->screen, 0); break; } diff --git a/apps/silc/screen.c b/apps/silc/screen.c index dba66925..8fb8a810 100644 --- a/apps/silc/screen.c +++ b/apps/silc/screen.c @@ -215,6 +215,14 @@ void silc_screen_print_bottom_line(SilcScreen screen, int win_index) strncat(buf, ")", 2); } + if (line->umode) { + len = strlen(line->umode); + strncat(buf, " [", 2); + strncat(buf, line->umode, len > SILC_SCREEN_MAX_UMODE_LEN ? + SILC_SCREEN_MAX_UMODE_LEN : len); + strncat(buf, "]", 2); + } + if (line->away) strncat(buf, " (away)", 8); diff --git a/apps/silc/screen.h b/apps/silc/screen.h index ffa89ffd..7f082d5b 100644 --- a/apps/silc/screen.h +++ b/apps/silc/screen.h @@ -27,6 +27,7 @@ typedef struct { char *connection; char *channel; char *channel_mode; + char *umode; int away; } *SilcScreenBottomLine; @@ -77,6 +78,9 @@ typedef SilcScreenObject *SilcScreen; /* Maximum length of connection name that will be shown on the screen */ #define SILC_SCREEN_MAX_CONN_LEN 20 +/* Maximum length of user mode that will be shown on the screen */ +#define SILC_SCREEN_MAX_UMODE_LEN 20 + /* Macros */ /* Macro used to insert typed character into the buffer. The character diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 0cded085..215d0cbd 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -150,6 +150,7 @@ void silc_server_command_process(SilcServer server, { SilcServerCommandContext ctx; SilcServerCommand *cmd; + SilcCommand command; /* Allocate command context. This must be free'd by the command routine receiving it. */ @@ -169,14 +170,16 @@ void silc_server_command_process(SilcServer server, return; } ctx->args = silc_command_get_args(ctx->payload); - + /* Get the command */ + command = silc_command_get(ctx->payload); for (cmd = silc_command_list; cmd->cb; cmd++) - if (cmd->cmd == silc_command_get(ctx->payload)) + if (cmd->cmd == command) break; if (cmd == NULL) { - SILC_LOG_ERROR(("Unknown command, packet dropped")); + silc_server_command_send_status_reply(ctx, command, + SILC_STATUS_ERR_UNKNOWN_COMMAND); silc_server_command_free(ctx); return; } @@ -351,7 +354,10 @@ silc_server_command_send_status_reply(SilcServerCommandContext cmd, SILC_LOG_DEBUG(("Sending command status %d", status)); - buffer = silc_command_reply_payload_encode_va(command, status, 0, 0); + buffer = + silc_command_reply_payload_encode_va(command, status, + silc_command_get_ident(cmd->payload), + 0); silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, buffer->data, buffer->len, FALSE); @@ -373,8 +379,10 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd, SILC_LOG_DEBUG(("Sending command status %d", status)); - buffer = silc_command_reply_payload_encode_va(command, status, 0, 1, - arg_type, arg, arg_len); + buffer = + silc_command_reply_payload_encode_va(command, status, + silc_command_get_ident(cmd->payload), + 1, arg_type, arg, arg_len); silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, buffer->data, buffer->len, FALSE); @@ -1629,6 +1637,7 @@ SILC_SERVER_CMD_FUNC(nick) SilcBuffer packet, nidp, oidp; SilcClientID *new_id; char *nick; + unsigned short ident = silc_command_get_ident(cmd->payload); if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) goto out; @@ -1693,7 +1702,7 @@ SILC_SERVER_CMD_FUNC(nick) /* Send the new Client ID as reply command back to client */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, - SILC_STATUS_OK, 0, 1, + SILC_STATUS_OK, ident, 1, 2, nidp->data, nidp->len); silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, packet->data, packet->len, FALSE); @@ -1724,6 +1733,7 @@ SILC_SERVER_CMD_FUNC(topic) SilcBuffer packet, idp; unsigned char *tmp; unsigned int argc, tmp_len; + unsigned short ident = silc_command_get_ident(cmd->payload); SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2); @@ -1811,13 +1821,13 @@ SILC_SERVER_CMD_FUNC(topic) idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL); if (channel->topic) packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, - SILC_STATUS_OK, 0, 2, + SILC_STATUS_OK, ident, 2, 2, idp->data, idp->len, 3, channel->topic, strlen(channel->topic)); else packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, - SILC_STATUS_OK, 0, 1, + SILC_STATUS_OK, ident, 1, 2, idp->data, idp->len); silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, packet->data, packet->len, FALSE); @@ -2631,8 +2641,70 @@ SILC_SERVER_CMD_FUNC(motd) silc_server_command_free(cmd); } +/* Server side of command UMODE. Client can use this command to set/unset + user mode. Client actually cannot set itself to be as server/router + operator so this can be used only to unset the modes. */ + SILC_SERVER_CMD_FUNC(umode) { + SilcServerCommandContext cmd = (SilcServerCommandContext)context; + SilcServer server = cmd->server; + SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data; + SilcBuffer packet; + unsigned char *tmp_mask; + unsigned int mask; + unsigned short ident = silc_command_get_ident(cmd->payload); + + if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT) + goto out; + + SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2); + + /* Get the client's mode mask */ + tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL); + if (!tmp_mask) { + silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE, + SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); + goto out; + } + SILC_GET32_MSB(mask, tmp_mask); + + /* + * Change the mode + */ + + if (mask & SILC_UMODE_SERVER_OPERATOR) { + /* Cannot operator mode */ + silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE, + SILC_STATUS_ERR_PERM_DENIED); + goto out; + } else { + if (client->mode & SILC_UMODE_SERVER_OPERATOR) + /* Remove the server operator rights */ + client->mode &= ~SILC_UMODE_SERVER_OPERATOR; + } + + if (mask & SILC_UMODE_ROUTER_OPERATOR) { + /* Cannot operator mode */ + silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE, + SILC_STATUS_ERR_PERM_DENIED); + goto out; + } else { + if (client->mode & SILC_UMODE_ROUTER_OPERATOR) + /* Remove the router operator rights */ + client->mode &= ~SILC_UMODE_ROUTER_OPERATOR; + } + + /* Send command reply to sender */ + packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE, + SILC_STATUS_OK, ident, 1, + 2, tmp_mask, 4); + silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, + packet->data, packet->len, FALSE); + silc_buffer_free(packet); + + out: + silc_server_command_free(cmd); } /* Checks that client has rights to add or remove channel modes. If any @@ -2703,6 +2775,7 @@ SILC_SERVER_CMD_FUNC(cmode) SilcBuffer packet, cidp; unsigned char *tmp, *tmp_id, *tmp_mask; unsigned int argc, mode_mask, tmp_len, tmp_len2; + unsigned short ident = silc_command_get_ident(cmd->payload); SILC_LOG_DEBUG(("Start")); @@ -3055,7 +3128,7 @@ SILC_SERVER_CMD_FUNC(cmode) /* Send command reply to sender */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE, - SILC_STATUS_OK, 0, 1, + SILC_STATUS_OK, ident, 1, 2, tmp_mask, 4); silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, packet->data, packet->len, FALSE); @@ -3084,6 +3157,7 @@ SILC_SERVER_CMD_FUNC(cumode) unsigned char *tmp_id, *tmp_ch_id, *tmp_mask; unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len; int notify = FALSE; + unsigned short ident = silc_command_get_ident(cmd->payload); SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3); @@ -3249,7 +3323,7 @@ SILC_SERVER_CMD_FUNC(cumode) /* Send command reply to sender */ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE, - SILC_STATUS_OK, 0, 2, + SILC_STATUS_OK, ident, 2, 2, tmp_mask, 4, 3, tmp_id, tmp_len); silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index ec7ba80c..3129a443 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -2621,8 +2621,8 @@ List of all defined commands in SILC follows. SILC_STATUS_ERR_NO_SUCH_CLIENT_ID SILC_STATUS_ERR_BAD_CLIENT_ID SILC_STATUS_ERR_NOT_YOU + SILC_STATUS_ERR_PERM_DENIED SILC_STATUS_ERR_UNKNOWN_MODE - SILC_STATUS_ERR_NO_RECIPIENT SILC_STATUS_ERR_NO_CLIENT_ID @@ -2830,7 +2830,6 @@ List of all defined commands in SILC follows. all clients on the channel by sending SILC_NOTIFY_TYPE_CMODE_CHANGE notify type. - Reply messages to the command: Max Arguments: 2 @@ -2894,7 +2893,6 @@ List of all defined commands in SILC follows. client on the channel. Channel founder and channel operator may set/unset (promote/demote) this mode. - Reply messages to the command: Max Arguments: 3 @@ -3340,8 +3338,8 @@ List of all defined command status messages following. 31 SILC_STATUS_ERR_PERM_DENIED - "Your host is not among the privileged". The client tried to - register on server that does not allow this host to connect. + "Permission denied". Generic permission denied error status + to indicate disallowed access. 32 SILC_STATUS_ERR_BANNED_FROM_SERVER diff --git a/lib/silcclient/command.c b/lib/silcclient/command.c index f6dca333..7c90c184 100644 --- a/lib/silcclient/command.c +++ b/lib/silcclient/command.c @@ -928,11 +928,91 @@ SILC_CLIENT_CMD_FUNC(motd) silc_client_command_free(cmd); } -/* UMODE. Set user mode in SILC. */ +/* UMODE. Set/unset user mode in SILC. This is used mainly to unset the + modes as client cannot set itself server/router operator privileges. */ SILC_CLIENT_CMD_FUNC(umode) { + SilcClientCommandContext cmd = (SilcClientCommandContext)context; + SilcClientConnection conn = cmd->conn; + SilcBuffer buffer, idp; + unsigned char *cp, modebuf[4]; + unsigned int mode, add, len; + int i; + + if (!cmd->conn) { + SILC_NOT_CONNECTED(cmd->client, cmd->conn); + COMMAND_ERROR; + goto out; + } + + if (cmd->argc < 2) { + cmd->client->ops->say(cmd->client, conn, + "Usage: /UMODE +|-"); + 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 diff --git a/lib/silcclient/command_reply.c b/lib/silcclient/command_reply.c index a2e3e1c4..d0f898a9 100644 --- a/lib/silcclient/command_reply.c +++ b/lib/silcclient/command_reply.c @@ -90,7 +90,7 @@ const SilcCommandStatusMessage silc_command_status_messages[] = { { STAT(NOT_REGISTERED), "You have not registered" }, { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" }, { STAT(TOO_MANY_PARAMS), "Too many parameters" }, - { STAT(PERM_DENIED), "Your host is not among the privileged" }, + { STAT(PERM_DENIED), "Permission denied" }, { STAT(BANNED_FROM_SERVER),"You are banned from this server" }, { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" }, { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" }, @@ -696,10 +696,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill) COMMAND_REPLY((ARGS)); /* Execute any pending command callbacks */ - SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CLOSE); + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_KILL); out: - SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE); + SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_KILL); silc_client_command_reply_free(cmd); } @@ -1059,8 +1059,43 @@ SILC_CLIENT_CMD_REPLY_FUNC(motd) silc_client_command_reply_free(cmd); } +/* Received reply tot he UMODE command. Save the current user mode */ + SILC_CLIENT_CMD_REPLY_FUNC(umode) { + SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context; + SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data; + SilcCommandStatus status; + unsigned char *tmp; + unsigned int mode; + + tmp = silc_argument_get_arg_type(cmd->args, 1, NULL); + SILC_GET16_MSB(status, tmp); + if (status != SILC_STATUS_OK) { + cmd->client->ops->say(cmd->client, conn, + "%s", silc_client_command_status_message(status)); + COMMAND_REPLY_ERROR; + goto out; + } + + tmp = silc_argument_get_arg_type(cmd->args, 2, NULL); + if (!tmp) { + COMMAND_REPLY_ERROR; + goto out; + } + + SILC_GET32_MSB(mode, tmp); + conn->local_entry->mode = mode; + + /* Notify application */ + COMMAND_REPLY((ARGS, mode)); + + /* Execute any pending command callbacks */ + SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_UMODE); + + out: + SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_UMODE); + silc_client_command_reply_free(cmd); } /* Received reply for CMODE command. */ diff --git a/lib/silcclient/idlist.h b/lib/silcclient/idlist.h index 513a52ef..b9f832ad 100644 --- a/lib/silcclient/idlist.h +++ b/lib/silcclient/idlist.h @@ -31,6 +31,7 @@ typedef struct SilcClientEntryStruct { char *server; /* SILC server name */ char *realname; /* Realname (userinfo) */ unsigned int num; + unsigned int mode; /* User mode in SILC */ SilcClientID *id; /* The Client ID */ SilcCipher send_key; /* Private message key for sending */ SilcCipher receive_key; /* Private message key for receiving */