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

📄 chat.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  silcpurple_chat.c  Author: Pekka Riikonen <priikone@silcnet.org>  Copyright (C) 2004 - 2007 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 "silc.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,			    SilcStatus status,			    SilcDList channels,			    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->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);		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;	SilcDList 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)) {		silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);		silc_dlist_uninit(sgc->pubkeys);		silc_free(sgc);		purple_notify_error(client->application,				    _("Add Channel Public Key"),				    _("Could not load public key"), NULL);		return;	}	pk = silc_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,						 silc_buffer_len(pk), 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,				 silcpurple_command_reply, NULL, 3,				 1, chidp->data, silc_buffer_len(chidp),				 2, mode, sizeof(mode),				 9, chpks->data, silc_buffer_len(chpks));	silc_buffer_free(chpks);	silc_buffer_free(chidp);	if (sgc->pubkeys) {	  silc_dlist_start(sgc->pubkeys);	  while ((public_key = silc_dlist_get(sgc->pubkeys)))		silc_pkcs_public_key_free(public_key);	  silc_dlist_uninit(sgc->pubkeys);	}	silc_free(sgc);}static voidsilcpurple_chat_chpk_cancel(void *user_data, const char *name){	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;	SilcPublicKey public_key;	silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);	if (sgc->pubkeys) {	  silc_dlist_start(sgc->pubkeys);	  while ((public_key = silc_dlist_get(sgc->pubkeys)))		silc_pkcs_public_key_free(public_key);	  silc_dlist_uninit(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_public_key_payload_encode(public_key);			chpks = silc_argument_payload_encode_one(chpks, pk->data,								 silc_buffer_len(pk), 0x01);			silc_buffer_free(pk);			c++;		}	}	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,				 silcpurple_command_reply, NULL, 3,				 1, chidp->data, silc_buffer_len(chidp),				 2, mode, sizeof(mode),				 9, chpks->data, silc_buffer_len(chpks));	silc_buffer_free(chpks);	silc_buffer_free(chidp);	if (sgc->pubkeys) {	  silc_dlist_start(sgc->pubkeys);	  while ((public_key = silc_dlist_get(sgc->pubkeys)))		silc_pkcs_public_key_free(public_key);	  silc_dlist_uninit(sgc->pubkeys);	}	silc_free(sgc);}static voidsilcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields){	SilcPurple sg = sgc->sg;	PurpleRequestField *f;	SilcPublicKey public_key;	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");	}	if (sgc->pubkeys) {	  silc_dlist_start(sgc->pubkeys);	  while ((public_key = silc_dlist_get(sgc->pubkeys)))		silc_pkcs_public_key_free(public_key);	  silc_dlist_uninit(sgc->pubkeys);	}	silc_free(sgc);}void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,				 SilcDList channel_pubkeys){	SilcPublicKey public_key;	SilcSILCPublicKey silc_pubkey;	unsigned char *pk;	SilcUInt32 pk_len;	char *fingerprint, *babbleprint;	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 || !silc_dlist_count(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);		if (channel_pubkeys)		  silc_dlist_uninit(channel_pubkeys);		return;	}	sgc->pubkeys = 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_dlist_start(channel_pubkeys);	while ((public_key = silc_dlist_get(channel_pubkeys))) {		pk = silc_pkcs_public_key_encode(public_key, &pk_len);		fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);		babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);		silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);		ident = &silc_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, public_key);		silc_free(fingerprint);		silc_free(babbleprint);	}	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),

⌨️ 快捷键说明

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