📄 chat.c
字号:
/************************** Channel Private Groups **************************//* Private groups are "virtual" channels. They are groups inside a channel. This is implemented by using channel private keys. By knowing a channel private key user becomes part of that group and is able to talk on that group. Other users, on the same channel, won't be able to see the messages of that group. It is possible to have multiple groups inside a channel - and thus having multiple private keys on the channel. */typedef struct { SilcPurple sg; PurpleChat *c; const char *channel;} *SilcPurpleCharPrv;static voidsilcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields){ SilcPurple sg = p->sg; char tmp[512]; PurpleRequestField *f; const char *name, *passphrase, *alias; GHashTable *comp; PurpleGroup *g; PurpleChat *cn; f = purple_request_fields_get_field(fields, "name"); name = purple_request_field_string_get_value(f); if (!name) { silc_free(p); return; } f = purple_request_fields_get_field(fields, "passphrase"); passphrase = purple_request_field_string_get_value(f); f = purple_request_fields_get_field(fields, "alias"); alias = purple_request_field_string_get_value(f); /* Add private group to buddy list */ g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name); comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp)); g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase)); cn = purple_chat_new(sg->account, alias, comp); g = (PurpleGroup *)p->c->node.parent; purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c); /* Associate to a real channel */ purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel); /* Join the group */ silcpurple_chat_join(sg->gc, comp); silc_free(p);}static voidsilcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields){ silc_free(p);}static voidsilcpurple_chat_prv(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; SilcPurpleCharPrv p; PurpleRequestFields *fields; PurpleRequestFieldGroup *g; PurpleRequestField *f; char tmp[512]; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; p = silc_calloc(1, sizeof(*p)); if (!p) return; p->sg = sg; p->channel = g_hash_table_lookup(chat->components, "channel"); p->c = purple_blist_find_chat(sg->account, p->channel); fields = purple_request_fields_new(); g = purple_request_field_group_new(NULL); f = purple_request_field_string_new("name", _("Group Name"), NULL, FALSE); purple_request_field_group_add_field(g, f); f = purple_request_field_string_new("passphrase", _("Passphrase"), NULL, FALSE); purple_request_field_string_set_masked(f, TRUE); purple_request_field_group_add_field(g, f); f = purple_request_field_string_new("alias", _("Alias"), NULL, FALSE); purple_request_field_group_add_field(g, f); purple_request_fields_add_group(fields, g); g_snprintf(tmp, sizeof(tmp), _("Please enter the %s channel private group name and passphrase."), p->channel); purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, _("Add"), G_CALLBACK(silcpurple_chat_prv_add), _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), purple_connection_get_account(gc), NULL, NULL, p);}/****************************** Channel Modes ********************************/static voidsilcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "-f", NULL);}static voidsilcpurple_chat_permanent(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; const char *channel; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; if (!sg->conn) return; /* XXX we should have ability to define which founder key to use. Now we use the user's own public key (default key). */ /* Call CMODE */ channel = g_hash_table_lookup(chat->components, "channel"); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel, "+f", NULL);}typedef struct { SilcPurple sg; const char *channel;} *SilcPurpleChatInput;static voidsilcpurple_chat_ulimit_cb(SilcPurpleChatInput s, const char *limit){ SilcChannelEntry channel; int ulimit = 0; channel = silc_client_get_channel(s->sg->client, s->sg->conn, (char *)s->channel); if (!channel) return; if (limit) ulimit = atoi(limit); if (!limit || !(*limit) || *limit == '0') { if (limit && ulimit == channel->user_limit) { silc_free(s); return; } silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", s->channel, "-l", NULL); silc_free(s); return; } if (ulimit == channel->user_limit) { silc_free(s); return; } /* Call CMODE */ silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", s->channel, "+l", limit, NULL); silc_free(s);}static voidsilcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; SilcPurpleChatInput s; SilcChannelEntry channel; const char *ch; char tmp[32]; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; if (!sg->conn) return; ch = g_strdup(g_hash_table_lookup(chat->components, "channel")); channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch); if (!channel) return; s = silc_calloc(1, sizeof(*s)); if (!s) return; s->channel = ch; s->sg = sg; g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); purple_request_input(gc, _("User Limit"), NULL, _("Set user limit on channel. Set to zero to reset user limit."), tmp, FALSE, FALSE, NULL, _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb), _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb), purple_connection_get_account(gc), NULL, NULL, s);}static voidsilcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "-t", NULL);}static voidsilcpurple_chat_settopic(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "+t", NULL);}static voidsilcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "-p", NULL);}static voidsilcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "+p", NULL);}static voidsilcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "-s", NULL);}static voidsilcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data){ PurpleChat *chat; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); chat = (PurpleChat *) node; gc = purple_account_get_connection(chat->account); sg = gc->proto_data; silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(chat->components, "channel"), "+s", NULL);}typedef struct { SilcPurple sg; SilcChannelEntry channel;} *SilcPurpleChatWb;static voidsilcpurple_chat_wb(PurpleBlistNode *node, gpointer data){ SilcPurpleChatWb wb = data; silcpurple_wb_init_ch(wb->sg, wb->channel); silc_free(wb);}GList *silcpurple_chat_menu(PurpleChat *chat){ GHashTable *components = chat->components; PurpleConnection *gc = purple_account_get_connection(chat->account); SilcPurple sg = gc->proto_data; SilcClientConnection conn = sg->conn; const char *chname = NULL; SilcChannelEntry channel = NULL; SilcChannelUser chu = NULL; SilcUInt32 mode = 0; GList *m = NULL; PurpleMenuAction *act; if (components) chname = g_hash_table_lookup(components, "channel"); if (chname) channel = silc_client_get_channel(sg->client, sg->conn, (char *)chname); if (channel) { chu = silc_client_on_channel(channel, conn->local_entry); if (chu) mode = chu->mode; } if (strstr(chname, "[Private Group]")) return NULL; act = purple_menu_action_new(_("Get Info"), PURPLE_CALLBACK(silcpurple_chat_getinfo_menu), NULL, NULL); m = g_list_append(m, act);#if 0 /* XXX For now these are not implemented. We need better listview dialog from Purple for these. */ if (mode & SILC_CHANNEL_UMODE_CHANOP) { act = purple_menu_action_new(_("Invite List"), PURPLE_CALLBACK(silcpurple_chat_invitelist), NULL, NULL); m = g_list_append(m, act); act = purple_menu_action_new(_("Ban List"), PURPLE_CALLBACK(silcpurple_chat_banlist), NULL, NULL); m = g_list_append(m, act); }#endif if (chu) { act = purple_menu_action_new(_("Add Private Group"), PURPLE_CALLBACK(silcpurple_chat_prv), NULL, NULL); m = g_list_append(m, act); } if (mode & SILC_CHANNEL_UMODE_CHANFO) { act = purple_menu_action_new(_("Channel Authentication"), PURPLE_CALLBACK(silcpurple_chat_chauth), NULL, NULL); m = g_list_append(m, act); if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { act = purple_menu_action_new(_("Reset Permanent"), PURPLE_CALLBACK(silcpurple_chat_permanent_reset), NULL, NULL); m = g_list_append(m, act); } else { act = purple_menu_action_new(_("Set Permanent"), PURPLE_CALLBACK(silcpurple_chat_permanent), NULL, NULL); m = g_list_append(m, act); } } if (mode & SILC_CHANNEL_UMODE_CHANOP) { act = purple_menu_action_new(_("Set User Limit"), PURPLE_CALLBACK(silcpurple_chat_ulimit), NULL, NULL); m = g_list_append(m, act); if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { act = purple_menu_action_new(_("Reset Topic Restriction"), PURPLE_CALLBACK(silcpurple_chat_resettopic), NULL, NULL); m = g_list_append(m, act); } else { act = purple_menu_action_new(_("Set Topic Restriction"), PURPLE_CALLBACK(silcpurple_chat_settopic), NULL, NULL); m = g_list_append(m, act); } if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { act = purple_menu_action_new(_("Reset Private Channel"), PURPLE_CALLBACK(silcpurple_chat_resetprivate), NULL, NULL); m = g_list_append(m, act); } else { act = purple_menu_action_new(_("Set Private Channel"), PURPLE_CALLBACK(silcpurple_chat_setprivate), NULL, NULL); m = g_list_append(m, act); } if (channel->mode & SILC_CHANNEL_MODE_SECRET) { act = purple_menu_action_new(_("Reset Secret Channel"), PURPLE_CALLBACK(silcpurple_chat_resetsecret), NULL, NULL); m = g_list_append(m, act); } else { act = purple_menu_action_new(_("Set Secret Channel"), PURPLE_CALLBACK(silcpurple_chat_setsecret), NULL, NULL); m = g_list_append(m, act); } } if (channel) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -