⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chat.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  silcpurple_chat.c  Author: Pekka Riikonen <priikone@silcnet.org>  Copyright (C) 2004 Pekka Riikonen  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; version 2 of the License.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.*/#include "silcincludes.h"#include "silcclient.h"#include "silcpurple.h"#include "wb.h"/***************************** Channel Routines ******************************/GList *silcpurple_chat_info(PurpleConnection *gc){	GList *ci = NULL;	struct proto_chat_entry *pce;	pce = g_new0(struct proto_chat_entry, 1);	pce->label = _("_Channel:");	pce->identifier = "channel";	pce->required = TRUE;	ci = g_list_append(ci, pce);	pce = g_new0(struct proto_chat_entry, 1);	pce->label = _("_Passphrase:");	pce->identifier = "passphrase";	pce->secret = TRUE;	ci = g_list_append(ci, pce);	return ci;}GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name){	GHashTable *defaults;	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);	if (chat_name != NULL)		g_hash_table_insert(defaults, "channel", g_strdup(chat_name));	return defaults;}static voidsilcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components);static voidsilcpurple_chat_getinfo_res(SilcClient client,			  SilcClientConnection conn,			  SilcChannelEntry *channels,			  SilcUInt32 channels_count,			  void *context){	GHashTable *components = context;	PurpleConnection *gc = client->application;	const char *chname;	char tmp[256];	chname = g_hash_table_lookup(components, "channel");	if (!chname)		return;	if (!channels) {		g_snprintf(tmp, sizeof(tmp),			   _("Channel %s does not exist in the network"), chname);		purple_notify_error(gc, _("Channel Information"),				  _("Cannot get channel information"), tmp);		return;	}	silcpurple_chat_getinfo(gc, components);}static voidsilcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components){	SilcPurple sg = gc->proto_data;	const char *chname;	char *buf, 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->channel_key)		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),				       silc_cipher_get_name(channel->channel_key));	if (channel->hmac)		/* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),				       silc_hmac_get_name(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);		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);	}	buf = g_string_free(s, FALSE);	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL);	g_free(buf);}static voidsilcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data){	PurpleChat *chat = (PurpleChat *)node;	silcpurple_chat_getinfo(chat->account->gc, chat->components);}#if 0   /* XXX For now these are not implemented.  We need better	   listview dialog from Purple for these. *//************************** Channel Invite List ******************************/static voidsilcpurple_chat_invitelist(PurpleBlistNode *node, gpointer data);{}/**************************** Channel Ban List *******************************/static voidsilcpurple_chat_banlist(PurpleBlistNode *node, gpointer data);{}#endif/************************* Channel Authentication ****************************/typedef struct {	SilcPurple sg;	SilcChannelEntry channel;	PurpleChat *c;	SilcBuffer pubkeys;} *SilcPurpleChauth;static voidsilcpurple_chat_chpk_add(void *user_data, const char *name){	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;	SilcPurple sg = sgc->sg;	SilcClient client = sg->client;	SilcClientConnection conn = sg->conn;	SilcPublicKey public_key;	SilcBuffer chpks, pk, chidp;	unsigned char mode[4];	SilcUInt32 m;	/* Load the public key */	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {		silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);		silc_buffer_free(sgc->pubkeys);		silc_free(sgc);		purple_notify_error(client->application,				  _("Add Channel Public Key"),				  _("Could not load public key"), NULL);		return;	}	pk = silc_pkcs_public_key_payload_encode(public_key);	chpks = silc_buffer_alloc_size(2);	SILC_PUT16_MSB(1, chpks->head);	chpks = silc_argument_payload_encode_one(chpks, pk->data,						 pk->len, 0x00);	silc_buffer_free(pk);	m = sgc->channel->mode;	m |= SILC_CHANNEL_MODE_CHANNEL_AUTH;	/* Send CMODE */	SILC_PUT32_MSB(m, mode);	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,				 ++conn->cmd_ident, 3,				 1, chidp->data, chidp->len,				 2, mode, sizeof(mode),				 9, chpks->data, chpks->len);	silc_buffer_free(chpks);	silc_buffer_free(chidp);	silc_buffer_free(sgc->pubkeys);	silc_free(sgc);}static voidsilcpurple_chat_chpk_cancel(void *user_data, const char *name){	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;	silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);	silc_buffer_free(sgc->pubkeys);	silc_free(sgc);}static voidsilcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields){	SilcPurple sg = sgc->sg;	SilcClient client = sg->client;	SilcClientConnection conn = sg->conn;	PurpleRequestField *f;	const GList *list;	SilcPublicKey public_key;	SilcBuffer chpks, pk, chidp;	SilcUInt16 c = 0, ct;	unsigned char mode[4];	SilcUInt32 m;	f = purple_request_fields_get_field(fields, "list");	if (!purple_request_field_list_get_selected(f)) {		/* Add new public key */		purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE,				  G_CALLBACK(silcpurple_chat_chpk_add),				  G_CALLBACK(silcpurple_chat_chpk_cancel),				  purple_connection_get_account(sg->gc), NULL, NULL, sgc);		return;	}	list = purple_request_field_list_get_items(f);	chpks = silc_buffer_alloc_size(2);	for (ct = 0; list; list = list->next, ct++) {		public_key = purple_request_field_list_get_data(f, list->data);		if (purple_request_field_list_is_selected(f, list->data)) {			/* Delete this public key */			pk = silc_pkcs_public_key_payload_encode(public_key);			chpks = silc_argument_payload_encode_one(chpks, pk->data,								 pk->len, 0x01);			silc_buffer_free(pk);			c++;		}		silc_pkcs_public_key_free(public_key);	}	if (!c) {		silc_buffer_free(chpks);		return;	}	SILC_PUT16_MSB(c, chpks->head);	m = sgc->channel->mode;	if (ct == c)		m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH;	/* Send CMODE */	SILC_PUT32_MSB(m, mode);	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,				 ++conn->cmd_ident, 3,				 1, chidp->data, chidp->len,				 2, mode, sizeof(mode),				 9, chpks->data, chpks->len);	silc_buffer_free(chpks);	silc_buffer_free(chidp);	silc_buffer_free(sgc->pubkeys);	silc_free(sgc);}static voidsilcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields){	SilcPurple sg = sgc->sg;	PurpleRequestField *f;	const char *curpass, *val;	int set;	f = purple_request_fields_get_field(fields, "passphrase");	val = purple_request_field_string_get_value(f);	curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");	if (!val && curpass)		set = 0;	else if (val && !curpass)		set = 1;	else if (val && curpass && strcmp(val, curpass))		set = 1;	else		set = -1;	if (set == 1) {		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",					 sgc->channel->channel_name, "+a", val, NULL);		purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val);	} else if (set == 0) {		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",					 sgc->channel->channel_name, "-a", NULL);		purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase");	}	silc_buffer_free(sgc->pubkeys);	silc_free(sgc);}void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,			       SilcBuffer channel_pubkeys){	SilcUInt16 argc;	SilcArgumentPayload chpks;	unsigned char *pk;	SilcUInt32 pk_len, type;	char *fingerprint, *babbleprint;	SilcPublicKey pubkey;	SilcPublicKeyIdentifier ident;	char tmp2[1024], t[512];	PurpleRequestFields *fields;	PurpleRequestFieldGroup *g;	PurpleRequestField *f;	SilcPurpleChauth sgc;	const char *curpass = NULL;	sgc = silc_calloc(1, sizeof(*sgc));	if (!sgc)		return;	sgc->sg = sg;	sgc->channel = channel;	fields = purple_request_fields_new();	if (sgc->c)	  curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");	g = purple_request_field_group_new(NULL);	f = purple_request_field_string_new("passphrase", _("Channel Passphrase"),					  curpass, FALSE);	purple_request_field_string_set_masked(f, TRUE);	purple_request_field_group_add_field(g, f);	purple_request_fields_add_group(fields, g);	g = purple_request_field_group_new(NULL);	f = purple_request_field_label_new("l1", _("Channel Public Keys List"));	purple_request_field_group_add_field(g, f);	purple_request_fields_add_group(fields, g);	g_snprintf(t, sizeof(t),		   _("Channel authentication is used to secure the channel from "		     "unauthorized access. The authentication may be based on "		     "passphrase and digital signatures. If passphrase is set, it "		     "is required to be able to join. If channel public keys are set "		     "then only users whose public keys are listed are able to join."));	if (!channel_pubkeys) {		f = purple_request_field_list_new("list", NULL);		purple_request_field_group_add_field(g, f);		purple_request_fields(sg->gc, _("Channel Authentication"),				    _("Channel Authentication"), t, fields,				    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),				    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),					purple_connection_get_account(sg->gc), NULL, NULL, sgc);		return;	}	sgc->pubkeys = silc_buffer_copy(channel_pubkeys);	g = purple_request_field_group_new(NULL);	f = purple_request_field_list_new("list", NULL);	purple_request_field_group_add_field(g, f);	purple_request_fields_add_group(fields, g);	SILC_GET16_MSB(argc, channel_pubkeys->data);	chpks = silc_argument_payload_parse(channel_pubkeys->data + 2,					    channel_pubkeys->len - 2, argc);	if (!chpks)		return;	pk = silc_argument_get_first_arg(chpks, &type, &pk_len);	while (pk) {		fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);		babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);		silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey);		ident = silc_pkcs_decode_identifier(pubkey->identifier);		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",			   ident->realname ? ident->realname : ident->username ?			   ident->username : "", fingerprint, babbleprint);		purple_request_field_list_add(f, tmp2, pubkey);		silc_free(fingerprint);		silc_free(babbleprint);		silc_pkcs_free_identifier(ident);		pk = silc_argument_get_next_arg(chpks, &type, &pk_len);	}	purple_request_field_list_set_multi_select(f, FALSE);	purple_request_fields(sg->gc, _("Channel Authentication"),			    _("Channel Authentication"), t, fields,			    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),			    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),				purple_connection_get_account(sg->gc), NULL, NULL, sgc);	silc_argument_payload_free(chpks);}static voidsilcpurple_chat_chauth(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"),				 "+C", NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -