+
+/* Removes a client entry from all channel it has joined. This really is
+ a performance killer (client_entry should have pointers to channel
+ entry list). */
+
+void silc_client_remove_from_channels(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry client_entry)
+{
+ SilcIDCacheEntry id_cache;
+ SilcIDCacheList list;
+ SilcChannelEntry channel;
+ int i;
+
+ if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
+ SILC_ID_CHANNEL, &list))
+ return;
+
+ silc_idcache_list_first(list, &id_cache);
+ channel = (SilcChannelEntry)id_cache->context;
+
+ while (channel) {
+
+ /* Remove client from channel */
+ for (i = 0; i < channel->clients_count; i++) {
+ if (channel->clients[i].client == client_entry) {
+ channel->clients[i].client = NULL;
+ channel->clients_count--;
+ break;
+ }
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+
+ channel = (SilcChannelEntry)id_cache->context;
+ }
+
+ silc_idcache_list_free(list);
+}
+
+/* Replaces `old' client entries from all channels to `new' client entry.
+ This can be called for example when nickname changes and old ID entry
+ is replaced from ID cache with the new one. If the old ID entry is only
+ updated, then this fucntion needs not to be called. */
+
+void silc_client_replace_from_channels(SilcClient client,
+ SilcClientConnection conn,
+ SilcClientEntry old,
+ SilcClientEntry new)
+{
+ SilcIDCacheEntry id_cache;
+ SilcIDCacheList list;
+ SilcChannelEntry channel;
+ int i;
+
+ if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
+ SILC_ID_CHANNEL, &list))
+ return;
+
+ silc_idcache_list_first(list, &id_cache);
+ channel = (SilcChannelEntry)id_cache->context;
+
+ while (channel) {
+
+ /* Remove client from channel */
+ for (i = 0; i < channel->clients_count; i++) {
+ if (channel->clients[i].client == old) {
+ channel->clients[i].client = new;
+ break;
+ }
+ }
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+
+ channel = (SilcChannelEntry)id_cache->context;
+ }
+
+ silc_idcache_list_free(list);
+}
+
+/* Parses mode mask and returns the mode as string. */
+
+char *silc_client_chmode(unsigned int mode)
+{
+ char string[20];
+
+ if (!mode)
+ return NULL;
+
+ memset(string, 0, sizeof(string));
+
+ if (mode & SILC_CHANNEL_MODE_PRIVATE)
+ strncat(string, "p", 1);
+
+ if (mode & SILC_CHANNEL_MODE_SECRET)
+ strncat(string, "s", 1);
+
+ if (mode & SILC_CHANNEL_MODE_PRIVKEY)
+ strncat(string, "k", 1);
+
+ if (mode & SILC_CHANNEL_MODE_INVITE)
+ strncat(string, "i", 1);
+
+ if (mode & SILC_CHANNEL_MODE_TOPIC)
+ strncat(string, "t", 1);
+
+ if (mode & SILC_CHANNEL_MODE_ULIMIT)
+ strncat(string, "l", 1);
+
+ if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
+ strncat(string, "a", 1);
+
+ /* Rest of mode is ignored */
+
+ return strdup(string);
+}
+
+/* Parses channel user mode mask and returns te mode as string */
+
+char *silc_client_chumode(unsigned int mode)
+{
+ char string[4];
+
+ if (!mode)
+ return NULL;
+
+ memset(string, 0, sizeof(string));
+
+ if (mode & SILC_CHANNEL_UMODE_CHANFO)
+ strncat(string, "f", 1);
+
+ if (mode & SILC_CHANNEL_UMODE_CHANOP)
+ strncat(string, "o", 1);
+
+ return strdup(string);
+}
+
+/* Parses channel user mode and returns it as special mode character. */
+
+char *silc_client_chumode_char(unsigned int mode)
+{
+ char string[4];
+
+ if (!mode)
+ return NULL;
+
+ memset(string, 0, sizeof(string));
+
+ if (mode & SILC_CHANNEL_UMODE_CHANFO)
+ strncat(string, "*", 1);
+
+ if (mode & SILC_CHANNEL_UMODE_CHANOP)
+ strncat(string, "@", 1);
+
+ return strdup(string);
+}