-
-/* Server side of command BAN. This is used to manage the ban list of the
- channel. To add clients and remove clients from the ban list. */
-
-SILC_SERVER_CMD_FUNC(ban)
-{
- SilcServerCommandContext cmd = (SilcServerCommandContext)context;
- SilcServer server = cmd->server;
- SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- SilcBuffer packet;
- SilcChannelEntry channel;
- SilcChannelClientEntry chl;
- SilcChannelID *channel_id = NULL;
- unsigned char *id, *add, *del;
- unsigned int id_len, tmp_len;
- unsigned short ident = silc_command_get_ident(cmd->payload);
-
- if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
- goto out;
-
- SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
-
- /* Get Channel ID */
- id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
- if (id) {
- channel_id = silc_id_payload_parse_id(id, id_len);
- if (!channel_id) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
- SILC_STATUS_ERR_NO_CHANNEL_ID);
- goto out;
- }
- }
-
- /* Get channel entry. The server must know about the channel since the
- client is expected to be on the channel. */
- channel = silc_idlist_find_channel_by_id(server->local_list,
- channel_id, NULL);
- if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
- channel_id, NULL);
- if (!channel) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
- SILC_STATUS_ERR_NO_SUCH_CHANNEL);
- goto out;
- }
- }
-
- /* Check whether this client is on the channel */
- if (!silc_server_client_on_channel(client, channel)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
- SILC_STATUS_ERR_NOT_ON_CHANNEL);
- goto out;
- }
-
- /* Get entry to the channel user list */
- silc_list_start(channel->user_list);
- while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
- if (chl->client == client)
- break;
-
- /* The client must be at least channel operator. */
- if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
- silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
- SILC_STATUS_ERR_NO_CHANNEL_PRIV);
- goto out;
- }
-
- /* Get the new ban and add it to the ban list */
- add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (add) {
- if (!channel->ban_list)
- channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
- else
- channel->ban_list = silc_realloc(channel->ban_list,
- sizeof(*channel->ban_list) *
- (tmp_len +
- strlen(channel->ban_list) + 2));
- if (add[tmp_len - 1] == ',')
- add[tmp_len - 1] = '\0';
-
- strncat(channel->ban_list, add, tmp_len);
- strncat(channel->ban_list, ",", 1);
- }
-
- /* Get the ban to be removed and remove it from the list */
- del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
- if (del && channel->ban_list) {
- char *start, *end, *n;
-
- if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
- silc_free(channel->ban_list);
- channel->ban_list = NULL;
- } else {
- start = strstr(channel->ban_list, del);
- if (start && strlen(start) >= tmp_len) {
- end = start + tmp_len;
- n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
- strncat(n, channel->ban_list, start - channel->ban_list);
- strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
- end) - 1);
- silc_free(channel->ban_list);
- channel->ban_list = n;
- }
- }
- }
-
- /* Send the BAN notify type to our primary router. */
- if (!server->standalone && (add || del))
- silc_server_send_notify_ban(server, server->router->connection,
- server->server_type == SILC_ROUTER ?
- TRUE : FALSE, channel, add, del);
-
- /* Send the reply back to the client */
- if (channel->ban_list)
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
- SILC_STATUS_OK, ident, 2,
- 2, id, id_len,
- 3, channel->ban_list,
- strlen(channel->ban_list) - 1);
- else
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
- SILC_STATUS_OK, ident, 1,
- 2, id, id_len);
-
- silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
- packet->data, packet->len, FALSE);
-
- silc_buffer_free(packet);
-
- out:
- if (channel_id)
- silc_free(channel_id);
- silc_server_command_free(cmd);
-}