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); }
void silc_client_remove_from_channels(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry) { SilcHashTableList htl; SilcChannelUser chu; if (!silc_hash_table_count(client_entry->channels)) return; SILC_LOG_DEBUG(("Remove client from all joined channels")); silc_rwlock_wrlock(client_entry->internal.lock); silc_hash_table_list(client_entry->channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { silc_rwlock_wrlock(chu->channel->internal.lock); silc_hash_table_del(chu->client->channels, chu->channel); silc_hash_table_del(chu->channel->user_list, chu->client); /* If channel became empty, delete it */ if (!silc_hash_table_count(chu->channel->user_list)) silc_client_del_channel(client, conn, chu->channel); silc_rwlock_unlock(chu->channel->internal.lock); silc_client_unref_client(client, conn, chu->client); silc_client_unref_channel(client, conn, chu->channel); silc_free(chu); } silc_rwlock_unlock(client_entry->internal.lock); silc_hash_table_list_reset(&htl); }
static void silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components) { SilcPurple sg = gc->proto_data; const char *chname; char tmp[256], *tmp2; GString *s; SilcChannelEntry channel; SilcHashTableList htl; SilcChannelUser chu; if (!components) return; chname = g_hash_table_lookup(components, "channel"); if (!chname) return; channel = silc_client_get_channel(sg->client, sg->conn, (char *)chname); if (!channel) { silc_client_get_channel_resolve(sg->client, sg->conn, (char *)chname, silcpurple_chat_getinfo_res, components); return; } s = g_string_new(""); tmp2 = g_markup_escape_text(channel->channel_name, -1); g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2); g_free(tmp2); if (channel->user_list && silc_hash_table_count(channel->user_list)) g_string_append_printf(s, _("<br><b>User Count:</b> %d"), (int)silc_hash_table_count(channel->user_list)); silc_hash_table_list(channel->user_list, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { tmp2 = g_markup_escape_text(chu->client->nickname, -1); g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"), tmp2); g_free(tmp2); break; } } silc_hash_table_list_reset(&htl); if (channel->cipher) g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"), channel->cipher); if (channel->hmac) /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"), channel->hmac); if (channel->topic) { tmp2 = g_markup_escape_text(channel->topic, -1); g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2); g_free(tmp2); } if (channel->mode) { g_string_append_printf(s, _("<br><b>Channel Modes:</b> ")); silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); g_string_append(s, tmp); } if (channel->founder_key) { char *fingerprint, *babbleprint; unsigned char *pk; SilcUInt32 pk_len; pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len); if (pk) { fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint); g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint); silc_free(fingerprint); silc_free(babbleprint); silc_free(pk); } } purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, s->str, NULL, NULL); g_string_free(s, TRUE); }
unsigned char *silc_mime_encode(SilcMime mime, SilcUInt32 *encoded_len) { SilcMime part; SilcHashTableList htl; SilcBufferStruct buf; SilcBuffer buffer; char *field, *value, tmp[1024], tmp2[4]; unsigned char *ret; int i; SILC_LOG_DEBUG(("Encoding MIME message")); if (!mime) return NULL; memset(&buf, 0, sizeof(buf)); /* Encode the headers. Order doesn't matter */ i = 0; silc_hash_table_list(mime->fields, &htl); while (silc_hash_table_get(&htl, (void *)&field, (void *)&value)) { memset(tmp, 0, sizeof(tmp)); SILC_LOG_DEBUG(("Header %s: %s", field, value)); silc_snprintf(tmp, sizeof(tmp) - 1, "%s: %s\r\n", field, value); silc_buffer_strformat(&buf, tmp, SILC_STRFMT_END); i++; } silc_hash_table_list_reset(&htl); if (i) silc_buffer_strformat(&buf, "\r\n", SILC_STRFMT_END); /* Assemble the whole buffer */ buffer = silc_buffer_alloc_size(mime->data_len + silc_buffer_len(&buf)); if (!buffer) return NULL; /* Add headers */ if (silc_buffer_len(&buf)) { silc_buffer_put(buffer, buf.head, silc_buffer_len(&buf)); silc_buffer_pull(buffer, silc_buffer_len(&buf)); silc_buffer_purge(&buf); } /* Add data */ if (mime->data) { SILC_LOG_DEBUG(("Data len %d", mime->data_len)); silc_buffer_put(buffer, mime->data, mime->data_len); } /* Add multiparts */ if (mime->multiparts) { SILC_LOG_DEBUG(("Encoding multiparts")); silc_dlist_start(mime->multiparts); i = 0; while ((part = silc_dlist_get(mime->multiparts)) != SILC_LIST_END) { unsigned char *pd; SilcUInt32 pd_len; /* Recursive encoding */ pd = silc_mime_encode(part, &pd_len); if (!pd) return NULL; memset(tmp, 0, sizeof(tmp)); memset(tmp2, 0, sizeof(tmp2)); /* If fields are not present, add extra CRLF */ if (!silc_hash_table_count(part->fields)) silc_snprintf(tmp2, sizeof(tmp2) - 1, "\r\n"); silc_snprintf(tmp, sizeof(tmp) - 1, "%s--%s\r\n%s", i != 0 ? "\r\n" : "", mime->boundary, tmp2); i = 1; buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) + pd_len + strlen(tmp)); if (!buffer) return NULL; silc_buffer_put_tail(buffer, tmp, strlen(tmp)); silc_buffer_pull_tail(buffer, strlen(tmp)); silc_buffer_put_tail(buffer, pd, pd_len); silc_buffer_pull_tail(buffer, pd_len); silc_free(pd); } memset(tmp, 0, sizeof(tmp)); silc_snprintf(tmp, sizeof(tmp) - 1, "\r\n--%s--\r\n", mime->boundary); buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) + strlen(tmp)); if (!buffer) return NULL; silc_buffer_put_tail(buffer, tmp, strlen(tmp)); silc_buffer_pull_tail(buffer, strlen(tmp)); } ret = silc_buffer_steal(buffer, encoded_len); silc_buffer_free(buffer); return ret; }
static void refresh_nicklist_resolved(SilcClient client, SilcClientConnection conn, SilcClientEntry *clients, SilcUInt32 clients_count, void *context) { SilcJoinResolve *r = context; SilcChannelEntry channel_entry = r->channel; SilcHashTableList htl; SilcChannelUser chu; struct presence *presence; struct channel_presence *chpres; struct i_silc_presence *silc_presence; struct i_silc_gateway_connection *silc_gwconn; struct i_silc_channel_connection *silc_chconn; int usercount = 0; char *userhost; silc_gwconn = (struct i_silc_gateway_connection *) i_silc_gateway_connection_lookup_conn(conn); i_assert(silc_gwconn != NULL); silc_chconn = i_silc_channel_connection_lookup_entry(silc_gwconn, channel_entry); i_assert(silc_chconn != NULL); if( !clients && r->retry < 1 ) { r->retry++; silc_client_get_clients_by_channel(client, conn, channel_entry, refresh_nicklist_resolved, context); return; } silc_hash_table_list(channel_entry->user_list, &htl); while( silc_hash_table_get(&htl, NULL, (void *)&chu) ) { if( !chu->client->nickname ) continue; usercount++; /* Do not init myself, as I'm already inited */ if( chu->client == silc_gwconn->conn->local_entry ) continue; userhost = i_silc_userhost(chu->client); presence = presence_lookup(&silc_gwconn->gwconn, chu->client->nickname); if( presence == NULL ) { presence = presence_init(&silc_gwconn->gwconn, chu->client->nickname); presence_set_address(presence, userhost); presence_set_real_name(presence, chu->client->realname); chpres = channel_connection_presence_init( &silc_chconn->chconn, presence); channel_connection_add_presence(&silc_chconn->chconn, chpres); presence_unref(presence); silc_presence = (struct i_silc_presence *)presence; silc_presence->client_entry = chu->client; } else { chpres = channel_connection_presence_init( &silc_chconn->chconn, presence); channel_connection_add_presence(&silc_chconn->chconn, chpres); } free(userhost); } silc_hash_table_list_reset(&htl); channel_connection_initial_presences_added(&silc_chconn->chconn); }
void silc_command_reply(SilcClient client, SilcClientConnection conn, SilcCommand command, SilcStatus status, SilcStatus error, va_list ap) { // "infrastructure" struct t_gui_buffer *channelbuffer, *serverbuffer; SilcConnectionContext ctx = conn->context; //SilcPluginChannelList channel; struct SilcChannelContext *chanCtx; // possible args char *str, *topic, *cipher, *hmac; SilcChannelEntry channel_entry; SilcUInt32 mode, userlimit; SilcHashTableList *userlist; SilcPublicKey key; SilcDList pubkeys; size_t strsize; // needed for the nicklist SilcClientEntry user_client; SilcChannelUser user; struct t_gui_nick *nick = NULL; switch (command) { case SILC_COMMAND_JOIN: str = va_arg(ap, char *); channel_entry = va_arg(ap, SilcChannelEntry); mode = va_arg(ap, SilcUInt32); userlist = va_arg(ap, SilcHashTableList *); topic = va_arg(ap, char *); cipher = va_arg(ap, char *); hmac = va_arg(ap, char *); key = va_arg(ap, SilcPublicKey); pubkeys = va_arg(ap, SilcDList); userlimit = va_arg(ap, SilcUInt32); chanCtx = malloc(sizeof(struct SilcChannelContext)); chanCtx->channel_name = str; chanCtx->channel_entry = channel_entry; chanCtx->connection = conn; strsize = strlen(channel_entry->channel_name) + strlen(channel_entry->server) + 1; str = malloc(strsize+1); snprintf(str, strsize, "%s.%s", channel_entry->channel_name, channel_entry->server); // create a regular chat buffer and set some senible values channelbuffer = weechat_buffer_new(str, &silc_plugin_channel_input, chanCtx, NULL, NULL); weechat_buffer_set(channelbuffer, "name", str); weechat_buffer_set(channelbuffer, "short_name", channel_entry->channel_name); weechat_buffer_set(channelbuffer, "title", topic); weechat_buffer_set(channelbuffer, "hotlist", WEECHAT_HOTLIST_LOW); weechat_buffer_set(channelbuffer, "nicklist", "1"); chanCtx->channel_buffer = channelbuffer; channel_entry->context = channelbuffer; serverbuffer = ctx->server_buffer; add_channel(channel_entry->channel_name, find_server_for_buffer(serverbuffer), channel_entry, NULL, channelbuffer); // fill the nicklist with users currently on the channel while (silc_hash_table_get(userlist, (void **)&user_client, (void **)&user)) { nick = silc_nicklist_add(user); } break; default: weechat_log_printf("unhandled command reply for %d", command); break; } }