adding/deleting string entries, but not public key or other.
Server supports both command fully.
+Mon Nov 25 18:21:43 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * The silc_argument_get_[first/next] now return the argument
+ type to caller. Added silc_argument_payload_encode_one.
+
+ Affected files are lib/silccore/silcargument.[ch].
+
+ * Added support for the SILC 1.2 INVITE command and new
+ invite lists to server. Affected files are silcd/command.c,
+ silcd/server_util.[ch] and silcd/packet_[receive/send].[ch].
+
+ * Added support for the SILC 1.2 BAN command and new
+ ban lists to server. Affected files are silcd/command.c,
+ silcd/server_util.[ch] and silcd/packet_[receive/send].[ch].
+
+ * Added support to client sending new INVITE command. Affected
+ file is lib/silcclient/command.c.
+
+ * Added support to client sending new BAN command. Affected
+ file is lib/silcclient/command.c.
+
Sun Nov 24 18:26:42 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* If iv argument to silc_cipher_[encrypt/decrypt] is NULL, use
TODO for Irssi SILC Client 1.0
==============================
- o bugs parsing nicknames with @ in NICK_CHANGE.
+ o Signed message payload handling on UI
- o c0ffee's MIME signal
+ o Support to set arbitrary pulic key in CMODE
- o SILC protocol version 1.2 integration
+ o INVITE/BAN by public key file and Client ID, new INVITE/BAN list handling
+ in command reply.
- o Signed message payload handling
+ o bugs parsing nicknames with @ in NICK_CHANGE
o Testing - See test plan:
http://silcnet.org/docs/silc-client-1.0-test.pdf
TODO for SILC Server 1.0
========================
- o New INVITE and BAN commands and notify types.
-
o Remove client from invite lists in KICKED and KILLED.
o 1.2 backup router support
- o Backup router related issues:
-
- o Add special handling in router and server for "connection
- timed out" error. Be optimistic.
-
- o SILC protocol version 1.2 integration
-
o Testing
SilcChannelEntry channel;
SilcChannelID *channel_id = NULL;
SilcIDListData idata;
- SilcBuffer idp, idp2, packet;
- unsigned char *tmp, *add, *del;
- SilcUInt32 len;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+ SilcArgumentPayload args;
+ SilcHashTableList htl;
+ SilcBuffer packet, list, tmp2;
+ unsigned char *tmp;
+ SilcUInt32 len, type;
+ SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
/* Get destination client ID */
tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
if (tmp) {
- char invite[512];
bool resolve;
dest_id = silc_id_payload_parse_id(tmp, len, NULL);
goto out;
}
- memset(invite, 0, sizeof(invite));
- silc_strncat(invite, sizeof(invite),
- dest->nickname, strlen(dest->nickname));
- silc_strncat(invite, sizeof(invite), "!", 1);
- silc_strncat(invite, sizeof(invite),
- dest->username, strlen(dest->username));
- if (!strchr(dest->username, '@')) {
- silc_strncat(invite, sizeof(invite), "@", 1);
- silc_strncat(invite, sizeof(invite), cmd->sock->hostname,
- strlen(cmd->sock->hostname));
- }
+ /* Add the client to the invite list */
- len = strlen(invite);
+ /* Allocate hash table for invite list if it doesn't exist yet */
if (!channel->invite_list)
- channel->invite_list = silc_calloc(len + 2,
- sizeof(*channel->invite_list));
- else
- channel->invite_list = silc_realloc(channel->invite_list,
- sizeof(*channel->invite_list) *
- (len +
- strlen(channel->invite_list) + 2));
- strncat(channel->invite_list, invite, len);
- strncat(channel->invite_list, ",", 1);
+ channel->invite_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Check if the ID is in the list already */
+ silc_hash_table_list(channel->invite_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new Client ID to invite list */
+ if (tmp) {
+ list = silc_buffer_alloc_size(len);
+ silc_buffer_put(list, tmp, len);
+ silc_hash_table_add(channel->invite_list, (void *)3, list);
+ }
if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
/* Send notify to the client that is invited to the channel */
+ SilcBuffer idp, idp2;
idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
}
}
- /* Add the client to the invite list of the channel */
- add = silc_argument_get_arg_type(cmd->args, 3, &len);
- if (add) {
- if (!channel->invite_list)
- channel->invite_list = silc_calloc(len + 2,
- sizeof(*channel->invite_list));
- else
- channel->invite_list = silc_realloc(channel->invite_list,
- sizeof(*channel->invite_list) *
- (len +
- strlen(channel->invite_list) + 2));
- if (add[len - 1] == ',')
- add[len - 1] = '\0';
-
- strncat(channel->invite_list, add, len);
- strncat(channel->invite_list, ",", 1);
- }
-
- /* Get the invite to be removed and remove it from the list */
- del = silc_argument_get_arg_type(cmd->args, 4, &len);
- if (del && channel->invite_list) {
- char *start, *end, *n;
+ /* Get the invite information */
+ tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
+ if (tmp) {
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(argc, tmp);
+ args = silc_argument_payload_parse(tmp + 2, len - 2, argc);
+ if (!args) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+ 0);
+ goto out;
+ }
- if (!strncmp(channel->invite_list, del,
- strlen(channel->invite_list) - 1)) {
- silc_free(channel->invite_list);
- channel->invite_list = NULL;
- } else {
- start = strstr(channel->invite_list, del);
- if (start && strlen(start) >= len) {
- end = start + len;
- n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
- strncat(n, channel->invite_list, start - channel->invite_list);
- strncat(n, end + 1, ((channel->invite_list +
- strlen(channel->invite_list)) - end) - 1);
- silc_free(channel->invite_list);
- channel->invite_list = n;
+ /* Get the type of action */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp && len == 1) {
+ if (tmp[0] == 0x00) {
+ /* Allocate hash table for invite list if it doesn't exist yet */
+ if (!channel->invite_list)
+ channel->invite_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Check for resource limit */
+ if (silc_hash_table_count(channel->invite_list) > 64) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+ SILC_STATUS_ERR_RESOURCE_LIMIT,
+ 0);
+ goto out;
+ }
}
+
+ /* Now add or delete the information. */
+ silc_server_inviteban_process(server, channel->invite_list,
+ (SilcUInt8)tmp[0], args);
+ }
+ silc_argument_payload_free(args);
+ }
+
+ /* Encode invite list */
+ list = NULL;
+ if (channel->invite_list) {
+ list = silc_buffer_alloc_size(2);
+ silc_buffer_format(list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->invite_list)),
+ SILC_STR_END);
+ silc_hash_table_list(channel->invite_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 1)
+ list = silc_argument_payload_encode_one(list, (char *)tmp2,
+ strlen((char *)tmp2), type);
+ else
+ list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ type);
}
+ silc_hash_table_list_reset(&htl);
}
/* Send notify to the primary router */
- silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
- SILC_BROADCAST(server), channel,
- sender->id, add, del);
+ silc_server_send_notify_invite(
+ server, SILC_PRIMARY_ROUTE(server),
+ SILC_BROADCAST(server), channel, sender->id,
+ silc_argument_get_arg_type(cmd->args, 3, NULL),
+ list);
/* Send command reply */
tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
-
- packet =
- silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
- SILC_STATUS_OK, 0, ident, 2,
- 2, tmp, len,
- 3, channel->invite_list,
- channel->invite_list ?
- strlen(channel->invite_list) : 0);
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
+ SILC_STATUS_OK, 0, ident, 2,
+ 2, tmp, len,
+ 3, list ? list->data : NULL,
+ list ? list->len : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
+ silc_buffer_free(list);
out:
silc_free(dest_id);
unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
SilcClientEntry client;
SilcChannelClientEntry chl;
- SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
+ SilcBuffer reply, chidp, clidp, keyp = NULL;
+ SilcBuffer user_list, mode_list, invite_list, ban_list;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
char check[512], check2[512];
bool founder = FALSE;
/* Check invite list if channel is invite-only channel */
if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
if (!channel->invite_list ||
- (!silc_string_match(channel->invite_list, check) &&
- !silc_string_match(channel->invite_list, check2))) {
+ (!silc_server_inviteban_match(server, channel->invite_list,
+ 3, client->id) &&
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 2, client->data.public_key) &&
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check) &&
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check2))) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_NOT_INVITED, 0);
goto out;
username and/or hostname is in the ban list the access to the
channel is denied. */
if (channel->ban_list) {
- if (silc_string_match(channel->ban_list, check) ||
- silc_string_match(channel->ban_list, check2)) {
+ if (silc_server_inviteban_match(server, channel->invite_list,
+ 3, client->id) ||
+ silc_server_inviteban_match(server, channel->invite_list,
+ 2, client->data.public_key) ||
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check) ||
+ !silc_server_inviteban_match(server, channel->invite_list,
+ 1, check2)) {
silc_server_command_send_status_reply(
cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
if (channel->founder_key)
fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+ /* Encode invite list */
+ invite_list = NULL;
+ if (channel->invite_list) {
+ SilcHashTableList htl;
+
+ invite_list = silc_buffer_alloc_size(2);
+ silc_buffer_format(invite_list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->invite_list)),
+ SILC_STR_END);
+
+ silc_hash_table_list(channel->invite_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
+ if (tmp_len == 1)
+ invite_list = silc_argument_payload_encode_one(invite_list,
+ (char *)reply,
+ strlen((char *)reply),
+ tmp_len);
+ else
+ invite_list = silc_argument_payload_encode_one(invite_list,
+ reply->data,
+ reply->len, tmp_len);
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
+ /* Encode ban list */
+ ban_list = NULL;
+ if (channel->ban_list) {
+ SilcHashTableList htl;
+
+ ban_list = silc_buffer_alloc_size(2);
+ silc_buffer_format(ban_list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->ban_list)),
+ SILC_STR_END);
+
+ silc_hash_table_list(channel->ban_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
+ if (tmp_len == 1)
+ ban_list = silc_argument_payload_encode_one(ban_list,
+ (char *)reply,
+ strlen((char *)reply),
+ tmp_len);
+ else
+ ban_list = silc_argument_payload_encode_one(ban_list,
+ reply->data,
+ reply->len, tmp_len);
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
reply =
silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
SILC_STATUS_OK, 0, ident, 14,
6, tmp2, 4,
7, keyp ? keyp->data : NULL,
keyp ? keyp->len : 0,
- 8, channel->ban_list,
- channel->ban_list ?
- strlen(channel->ban_list) : 0,
- 9, channel->invite_list,
- channel->invite_list ?
- strlen(channel->invite_list) : 0,
+ 8, ban_list ? ban_list->data : NULL,
+ ban_list ? ban_list->len : 0,
+ 9, invite_list ? invite_list->data :
+ NULL,
+ invite_list ? invite_list->len : 0,
10, channel->topic,
channel->topic ?
strlen(channel->topic) : 0,
silc_buffer_free(user_list);
silc_buffer_free(mode_list);
silc_buffer_free(fkey);
+ silc_buffer_free(invite_list);
+ silc_buffer_free(ban_list);
out:
silc_free(passphrase);
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- SilcBuffer packet;
+ SilcBuffer packet, list, tmp2;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcChannelID *channel_id = NULL;
- unsigned char *id, *add, *del;
- SilcUInt32 id_len, tmp_len;
- SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+ unsigned char *id, *tmp;
+ SilcUInt32 id_len, len;
+ SilcArgumentPayload args;
+ SilcHashTableList htl;
+ SilcUInt32 type;
+ SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
goto out;
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;
+ /* Get the ban information */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp) {
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(argc, tmp);
+ args = silc_argument_payload_parse(tmp + 2, len - 2, argc);
+ if (!args) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+ 0);
+ goto out;
+ }
- 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;
+ /* Get the type of action */
+ tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (tmp && len == 1) {
+ if (tmp[0] == 0x00) {
+ /* Allocate hash table for ban list if it doesn't exist yet */
+ if (!channel->ban_list)
+ channel->ban_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Check for resource limit */
+ if (silc_hash_table_count(channel->ban_list) > 64) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+ SILC_STATUS_ERR_RESOURCE_LIMIT,
+ 0);
+ goto out;
+ }
}
+
+ /* Now add or delete the information. */
+ silc_server_inviteban_process(server, channel->ban_list,
+ (SilcUInt8)tmp[0], args);
+ }
+ silc_argument_payload_free(args);
+ }
+
+ /* Encode ban list */
+ list = NULL;
+ if (channel->ban_list) {
+ list = silc_buffer_alloc_size(2);
+ silc_buffer_format(list,
+ SILC_STR_UI_SHORT(silc_hash_table_count(
+ channel->ban_list)),
+ SILC_STR_END);
+ silc_hash_table_list(channel->ban_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 1)
+ list = silc_argument_payload_encode_one(list, (char *)tmp2,
+ strlen((char *)tmp2), type);
+ else
+ list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+ type);
}
+ silc_hash_table_list_reset(&htl);
}
/* Send the BAN notify type to our primary router. */
- if (add || del)
+ if (list)
silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
- SILC_BROADCAST(server), channel, add, del);
+ SILC_BROADCAST(server), channel,
+ silc_argument_get_arg_type(cmd->args, 2, NULL),
+ list);
/* Send the reply back to the client */
packet =
silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
SILC_STATUS_OK, 0, ident, 2,
2, id, id_len,
- 3, channel->ban_list,
- channel->ban_list ?
- strlen(channel->ban_list) -1 : 0);
+ 3, list ? list->data : NULL,
+ list ? list->len : 0);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
+ silc_buffer_free(list);
out:
silc_free(channel_id);
int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
{
if (entry) {
+ SilcHashTableList htl;
+ SilcBuffer tmp;
+ SilcUInt32 type;
+
/* Remove from cache */
if (!silc_idcache_del_by_context(id_list->channels, entry))
return FALSE;
silc_free(entry->channel_name);
silc_free(entry->id);
silc_free(entry->topic);
- silc_free(entry->invite_list);
- silc_free(entry->ban_list);
+
+ if (entry->invite_list) {
+ silc_hash_table_list(entry->invite_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp)) {
+ if (type == 1) {
+ silc_free((char *)tmp);
+ continue;
+ }
+ silc_buffer_free(tmp);
+ }
+ silc_hash_table_list_reset(&htl);
+ silc_hash_table_free(entry->invite_list);
+ }
+
+ if (entry->ban_list) {
+ silc_hash_table_list(entry->ban_list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp)) {
+ if (type == 1) {
+ silc_free((char *)tmp);
+ continue;
+ }
+ silc_buffer_free(tmp);
+ }
+ silc_hash_table_list_reset(&htl);
+ silc_hash_table_free(entry->ban_list);
+ }
+
if (entry->channel_key)
silc_cipher_free(entry->channel_key);
if (entry->key) {
SilcUInt32 user_limit;
unsigned char *passphrase;
- char *invite_list;
- char *ban_list;
+ SilcHashTable invite_list;
+ SilcHashTable ban_list;
/* All users on this channel */
SilcHashTable user_list;
goto out;
}
- /* Get the added invite */
+ /* Get the invite action */
tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
- if (tmp) {
- if (!channel->invite_list)
- channel->invite_list = silc_calloc(tmp_len + 2,
- sizeof(*channel->invite_list));
- else
- channel->invite_list = silc_realloc(channel->invite_list,
- sizeof(*channel->invite_list) *
- (tmp_len +
- strlen(channel->invite_list) +
- 2));
- if (tmp[tmp_len - 1] == ',')
- tmp[tmp_len - 1] = '\0';
-
- strncat(channel->invite_list, tmp, tmp_len);
- strncat(channel->invite_list, ",", 1);
- }
+ if (tmp && tmp_len == 1) {
+ SilcUInt8 action = (SilcUInt8)tmp[0];
+ SilcUInt16 iargc = 0;
+ SilcArgumentPayload iargs;
- /* Get the deleted invite */
- tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
- if (tmp && channel->invite_list) {
- char *start, *end, *n;
-
- if (!strncmp(channel->invite_list, tmp,
- strlen(channel->invite_list) - 1)) {
- silc_free(channel->invite_list);
- channel->invite_list = NULL;
- } else {
- start = strstr(channel->invite_list, tmp);
- if (start && strlen(start) >= tmp_len) {
- end = start + tmp_len;
- n = silc_calloc(strlen(channel->invite_list) - tmp_len, sizeof(*n));
- strncat(n, channel->invite_list, start - channel->invite_list);
- strncat(n, end + 1, ((channel->invite_list +
- strlen(channel->invite_list)) - end) - 1);
- silc_free(channel->invite_list);
- channel->invite_list = n;
- }
- }
+ /* Get invite list */
+ tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(iargc, tmp);
+ iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc);
+ if (!iargs)
+ goto out;
+
+ if (action == 0 && !channel->invite_list)
+ channel->invite_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Proces the invite action */
+ silc_server_inviteban_process(server, channel->invite_list, action,
+ iargs);
+ silc_argument_payload_free(iargs);
}
break;
}
silc_free(channel_id);
- /* Get the new ban and add it to the ban list */
+ /* Get the ban action */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (tmp) {
- 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));
- strncat(channel->ban_list, tmp, tmp_len);
- strncat(channel->ban_list, ",", 1);
- }
+ if (tmp && tmp_len == 1) {
+ SilcUInt8 action = (SilcUInt8)tmp[0];
+ SilcUInt16 iargc = 0;
+ SilcArgumentPayload iargs;
- /* Get the ban to be removed and remove it from the list */
- tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
- if (tmp && channel->ban_list) {
- char *start, *end, *n;
-
- if (!strncmp(channel->ban_list, tmp, strlen(channel->ban_list) - 1)) {
- silc_free(channel->ban_list);
- channel->ban_list = NULL;
- } else {
- start = strstr(channel->ban_list, tmp);
- 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;
- }
- }
+ /* Get ban list */
+ tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Parse the arguments to see they are constructed correctly */
+ SILC_GET16_MSB(iargc, tmp);
+ iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc);
+ if (!iargs)
+ goto out;
+
+ if (action == 0 && !channel->ban_list)
+ channel->ban_list = silc_hash_table_alloc(0, silc_hash_ptr,
+ NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
+ /* Proces the ban action */
+ silc_server_inviteban_process(server, channel->ban_list, action,
+ iargs);
+ silc_argument_payload_free(iargs);
}
break;
SilcSocketConnection sock,
bool broadcast,
SilcChannelEntry channel,
- char *add, char *del)
+ unsigned char *action,
+ SilcBuffer list)
{
SilcBuffer idp;
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_BAN, 3,
idp->data, idp->len,
- add, add ? strlen(add) : 0,
- del, del ? strlen(del) : 0);
+ action ? action : NULL, action ? 1 : 0,
+ list ? list->data : NULL, list ? list->len : 0);
silc_buffer_free(idp);
}
bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
- char *add, char *del)
+ unsigned char *action,
+ SilcBuffer list)
{
SilcBuffer idp, idp2;
idp->data, idp->len,
channel->channel_name, strlen(channel->channel_name),
idp2->data, idp2->len,
- add, add ? strlen(add) : 0,
- del, del ? strlen(del) : 0);
+ action ? action : NULL, action ? 1 : 0,
+ list ? list->data : NULL, list ? list->len : 0);
silc_buffer_free(idp);
silc_buffer_free(idp2);
}
SilcSocketConnection sock,
bool broadcast,
SilcChannelEntry channel,
- char *add, char *del);
+ unsigned char *action,
+ SilcBuffer list);
void silc_server_send_notify_invite(SilcServer server,
SilcSocketConnection sock,
bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
- char *add, char *del);
+ unsigned char *action,
+ SilcBuffer list);
void silc_server_send_notify_watch(SilcServer server,
SilcSocketConnection sock,
SilcClientEntry watcher,
return NULL;
}
+
+/* This function can be used to match the invite and ban lists. */
+
+bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
+ SilcUInt8 type, void *check)
+{
+ unsigned char *tmp = NULL;
+ SilcUInt32 len = 0, t;
+ SilcHashTableList htl;
+ SilcBuffer entry;
+ bool ret = FALSE;
+
+ if (type < 1 || type > 3 || !check)
+ return FALSE;
+
+ if (type == 1) {
+ tmp = strdup((char *)check);
+ if (!tmp)
+ return FALSE;
+ }
+ if (type == 2) {
+ tmp = silc_pkcs_public_key_encode(check, &len);
+ if (!tmp)
+ return FALSE;
+ }
+ if (type == 3) {
+ tmp = silc_id_id2str(check, SILC_ID_CLIENT);
+ if (!tmp)
+ return FALSE;
+ len = silc_id_get_len(check, SILC_ID_CLIENT);
+ }
+
+ /* Compare the list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
+ if (type == t) {
+ if (type == 1) {
+ if (silc_string_match((char *)entry, tmp)) {
+ ret = TRUE;
+ break;
+ }
+ } else if (!memcmp(entry->data, tmp, len)) {
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ silc_free(tmp);
+ return ret;
+}
+
+/* Process invite or ban information */
+
+void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+ SilcUInt8 action, SilcArgumentPayload args)
+{
+ unsigned char *tmp;
+ SilcUInt32 type, len;
+ SilcBuffer tmp2;
+ SilcHashTableList htl;
+
+ SILC_LOG_DEBUG(("Processing invite/ban for %s action",
+ action == 0x00 ? "ADD" : "DEL"));
+
+ /* Add the information to invite list */
+ if (action == 0x00) {
+ /* Traverse all arguments and add to the hash table according to
+ their type. */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Invite string. Get the old invite string from hash table
+ and append this at the end of the existing one. */
+ char *string = NULL;
+ silc_hash_table_find(list, (void *)1,
+ NULL, (void **)&string);
+ silc_hash_table_del(list, (void *)1);
+ if (!string)
+ string = silc_calloc(len + 2, sizeof(*string));
+ else
+ string = silc_realloc(string, sizeof(*string) *
+ (strlen(string) + len + 2));
+ memset(string + strlen(string), 0, len + 2);
+ if (tmp[len - 1] == ',')
+ tmp[len - 1] = '\0';
+ strncat(string, tmp, len);
+ strncat(string, ",", 1);
+
+ /* Add new invite string to invite list */
+ silc_hash_table_add(list, (void *)1, string);
+
+ } else if (type == 2) {
+ /* Public key. Check first if the public key is already on the
+ list and ignore it if it is, otherwise, add it to hash table. */
+
+ /* Check if the public key is in the list already */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new public key to invite list */
+ if (tmp) {
+ tmp2 = silc_buffer_alloc_size(len);
+ silc_buffer_put(tmp2, tmp, len);
+ silc_hash_table_add(list, (void *)2, tmp2);
+ }
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Check if the ID is in the list already */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new Client ID to invite list */
+ if (tmp) {
+ tmp2 = silc_buffer_alloc_size(len);
+ silc_buffer_put(tmp2, tmp, len);
+ silc_hash_table_add(list, (void *)3, tmp2);
+ }
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+
+ /* Delete information to invite list */
+ if (action && list) {
+ /* Now delete the arguments from invite list */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Invite string. Get the old string from hash table and delete
+ the requested string. */
+ char *string = NULL, *start, *end, *n;
+
+ if (silc_hash_table_find(list, (void *)1, NULL, (void **)&string)) {
+ silc_hash_table_del(list, (void *)1);
+
+ if (!strncmp(string, tmp, strlen(string) - 1)) {
+ silc_free(string);
+ string = NULL;
+ } else {
+ start = strstr(string, tmp);
+ if (start && strlen(start) >= len) {
+ end = start + len;
+ n = silc_calloc(strlen(string) - len, sizeof(*n));
+ strncat(n, string, start - string);
+ strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
+ silc_free(string);
+ string = n;
+ }
+ }
+
+ /* Add new invite string to invite list */
+ if (string)
+ silc_hash_table_add(list, (void *)1, string);
+ }
+
+ } else if (type == 2) {
+ /* Public key. */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)2, tmp2);
+ silc_buffer_free(tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)2, tmp2);
+ silc_buffer_free(tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+}
SilcSocketType type,
const char *ip, SilcUInt16 port);
+/* This function can be used to match the invite and ban lists. */
+bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
+ SilcUInt8 type, void *check);
+
+/* Process invite or ban information */
+void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+ SilcUInt8 action, SilcArgumentPayload args);
+
#endif /* SERVER_UTIL_H */
SilcClientConnection conn = cmd->conn;
SilcClientEntry client_entry = NULL;
SilcChannelEntry channel;
- SilcBuffer buffer, clidp, chidp;
- SilcUInt32 type = 0;
+ SilcBuffer buffer, clidp, chidp, args = NULL;
char *nickname = NULL, *name;
char *invite = NULL;
+ unsigned char action[1];
if (!cmd->conn) {
SILC_NOT_CONNECTED(cmd->client, cmd->conn);
invite = cmd->argv[2];
invite++;
if (cmd->argv[2][0] == '+')
- type = 3;
+ action[0] = 0x00;
else
- type = 4;
+ action[0] = 0x01;
}
}
+ if (invite) {
+ args = silc_buffer_alloc_size(2);
+ silc_buffer_format(args,
+ SILC_STR_UI_SHORT(1),
+ SILC_STR_END);
+ args = silc_argument_payload_encode_one(args, invite, strlen(invite), 1);
+ }
+
/* Send the command */
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
if (client_entry) {
clidp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE,
- ++conn->cmd_ident, 3,
+ ++conn->cmd_ident, 4,
1, chidp->data, chidp->len,
2, clidp->data, clidp->len,
- type, invite, invite ?
- strlen(invite) : 0);
+ 3, args ? action : NULL,
+ args ? 1 : 0,
+ 4, args ? args->data : NULL,
+ args ? args->len : 0);
silc_buffer_free(clidp);
} else {
buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE,
- ++conn->cmd_ident, 2,
+ ++conn->cmd_ident, 3,
1, chidp->data, chidp->len,
- type, invite, invite ?
- strlen(invite) : 0);
+ 3, args ? action : NULL,
+ args ? 1 : 0,
+ 4, args ? args->data : NULL,
+ args ? args->len : 0);
}
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(chidp);
+ silc_buffer_free(args),
/* Notify application */
COMMAND(SILC_STATUS_OK);
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
SilcClientConnection conn = cmd->conn;
SilcChannelEntry channel;
- SilcBuffer buffer, chidp;
- int type = 0;
+ SilcBuffer buffer, chidp, args = NULL;
char *name, *ban = NULL;
+ unsigned char action[1];
if (!cmd->conn) {
SILC_NOT_CONNECTED(cmd->client, cmd->conn);
if (cmd->argc == 3) {
if (cmd->argv[2][0] == '+')
- type = 2;
+ action[0] = 0x00;
else
- type = 3;
+ action[0] = 0x01;
ban = cmd->argv[2];
ban++;
}
+ if (ban) {
+ args = silc_buffer_alloc_size(2);
+ silc_buffer_format(args,
+ SILC_STR_UI_SHORT(1),
+ SILC_STR_END);
+ args = silc_argument_payload_encode_one(args, ban, strlen(ban), 1);
+ }
+
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
/* Send the command */
buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN,
- ++conn->cmd_ident, 2,
+ ++conn->cmd_ident, 3,
1, chidp->data, chidp->len,
- type, ban, ban ? strlen(ban) : 0);
+ 2, args ? action : NULL,
+ args ? 1 : 0,
+ 3, args ? args->data : NULL,
+ args ? args->len : 0);
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(chidp);
+ silc_buffer_free(args);
/* Notify application */
COMMAND(SILC_STATUS_OK);