+
+/* Empties channel from users. This handles entry locking internally. */
+
+void silc_client_empty_channel(SilcClient client,
+ SilcClientConnection conn,
+ SilcChannelEntry channel)
+{
+ SilcHashTableList htl;
+ SilcChannelUser chu;
+
+ silc_rwlock_wrlock(channel->internal.lock);
+
+ silc_hash_table_list(channel->user_list, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+ silc_hash_table_del(chu->client->channels, chu->channel);
+ silc_hash_table_del(chu->channel->user_list, chu->client);
+ silc_client_unref_client(client, conn, chu->client);
+ silc_client_unref_channel(client, conn, chu->channel);
+ silc_free(chu);
+ }
+
+ silc_rwlock_unlock(channel->internal.lock);
+
+ silc_hash_table_list_reset(&htl);
+}
+
+/* Save public keys to channel public key list. Removes keys that are
+ marked to be removed. Must be called with `channel' locked. */
+
+SilcBool silc_client_channel_save_public_keys(SilcChannelEntry channel,
+ unsigned char *chpk_list,
+ SilcUInt32 chpk_list_len,
+ SilcBool remove_all)
+{
+ SilcArgumentDecodedList a, b;
+ SilcDList chpks;
+ SilcBool found;
+
+ if (remove_all) {
+ /* Remove all channel public keys */
+ if (!channel->channel_pubkeys)
+ return FALSE;
+
+ silc_dlist_start(channel->channel_pubkeys);
+ while ((b = silc_dlist_get(channel->channel_pubkeys)))
+ silc_dlist_del(channel->channel_pubkeys, b);
+
+ silc_dlist_uninit(channel->channel_pubkeys);
+ channel->channel_pubkeys = NULL;
+
+ return TRUE;
+ }
+
+ /* Parse channel public key list and add or remove public keys */
+ chpks = silc_argument_list_parse_decoded(chpk_list, chpk_list_len,
+ SILC_ARGUMENT_PUBLIC_KEY);
+ if (!chpks)
+ return FALSE;
+
+ if (!channel->channel_pubkeys) {
+ channel->channel_pubkeys = silc_dlist_init();
+ if (!channel->channel_pubkeys) {
+ silc_argument_list_free(chpks, SILC_ARGUMENT_PUBLIC_KEY);
+ return FALSE;
+ }
+ }
+
+ silc_dlist_start(chpks);
+ while ((a = silc_dlist_get(chpks))) {
+ found = FALSE;
+ silc_dlist_start(channel->channel_pubkeys);
+ while ((b = silc_dlist_get(channel->channel_pubkeys))) {
+ if (silc_pkcs_public_key_compare(a->argument, b->argument)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if ((a->arg_type == 0x00 || a->arg_type == 0x03) && !found) {
+ silc_dlist_add(channel->channel_pubkeys, a);
+ silc_dlist_del(chpks, a);
+ } else if (a->arg_type == 0x01 && found) {
+ silc_dlist_del(channel->channel_pubkeys, b);
+ }
+ }
+
+ silc_argument_list_free(chpks, SILC_ARGUMENT_PUBLIC_KEY);
+
+ return TRUE;
+}