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

📄 buddy.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  silcpurple_buddy.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"/***************************** Key Agreement *********************************/static voidsilcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data);static voidsilcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,			 			 gboolean force_local);typedef struct {	char *nick;	PurpleConnection *gc;} *SilcPurpleResolve;static voidsilcpurple_buddy_keyagr_resolved(SilcClient client,			       SilcClientConnection conn,			       SilcClientEntry *clients,			       SilcUInt32 clients_count,			       void *context){	PurpleConnection *gc = client->application;	SilcPurpleResolve r = context;	char tmp[256];	if (!clients) {		g_snprintf(tmp, sizeof(tmp),			   _("User %s is not present in the network"), r->nick);		purple_notify_error(gc, _("Key Agreement"),				  _("Cannot perform the key agreement"), tmp);		silc_free(r->nick);		silc_free(r);		return;	}	silcpurple_buddy_keyagr_do(gc, r->nick, FALSE);	silc_free(r->nick);	silc_free(r);}typedef struct {	gboolean responder;} *SilcPurpleKeyAgr;static voidsilcpurple_buddy_keyagr_cb(SilcClient client,			 SilcClientConnection conn,			 SilcClientEntry client_entry,			 SilcKeyAgreementStatus status,			 SilcSKEKeyMaterial *key,			 void *context){	PurpleConnection *gc = client->application;	SilcPurple sg = gc->proto_data;	SilcPurpleKeyAgr a = context;	if (!sg->conn)		return;	switch (status) {	case SILC_KEY_AGREEMENT_OK:		{			PurpleConversation *convo;			char tmp[128];			/* Set the private key for this client */			silc_client_del_private_message_key(client, conn, client_entry);			silc_client_add_private_message_key_ske(client, conn, client_entry,								NULL, NULL, key, a->responder);			silc_ske_free_key_material(key);						/* Open IM window */			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,									client_entry->nickname, sg->account);			if (convo) {				/* we don't have windows in the core anymore...but we may want to				 * provide some method for asking the UI to show the window				purple_conv_window_show(purple_conversation_get_window(convo));				 */			} else {				convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account,							      client_entry->nickname);			}			g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname);			purple_conversation_set_title(convo, tmp);		}		break;	case SILC_KEY_AGREEMENT_ERROR:		purple_notify_error(gc, _("Key Agreement"),				  _("Error occurred during key agreement"), NULL);		break;	case SILC_KEY_AGREEMENT_FAILURE:		purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL);		break;	case SILC_KEY_AGREEMENT_TIMEOUT:		purple_notify_error(gc, _("Key Agreement"),				  _("Timeout during key agreement"), NULL);		break;	case SILC_KEY_AGREEMENT_ABORTED:		purple_notify_error(gc, _("Key Agreement"),				  _("Key agreement was aborted"), NULL);		break;	case SILC_KEY_AGREEMENT_ALREADY_STARTED:		purple_notify_error(gc, _("Key Agreement"),				  _("Key agreement is already started"), NULL);		break;	case SILC_KEY_AGREEMENT_SELF_DENIED:		purple_notify_error(gc, _("Key Agreement"),				  _("Key agreement cannot be started with yourself"),				  NULL);		break;	default:		break;	}	silc_free(a);}static voidsilcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,			 gboolean force_local){	SilcPurple sg = gc->proto_data;	SilcClientEntry *clients;	SilcUInt32 clients_count;	char *local_ip = NULL, *remote_ip = NULL;	gboolean local = TRUE;	char *nickname;	SilcPurpleKeyAgr a;	if (!sg->conn || !name)		return;	if (!silc_parse_userfqdn(name, &nickname, NULL))		return;	/* Find client entry */	clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name,						&clients_count);	if (!clients) {		/* Resolve unknown user */		SilcPurpleResolve r = silc_calloc(1, sizeof(*r));		if (!r)			return;		r->nick = g_strdup(name);		r->gc = gc;		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,					silcpurple_buddy_keyagr_resolved, r);		silc_free(nickname);		return;	}	/* Resolve the local IP from the outgoing socket connection.  We resolve	   it to check whether we have a private range IP address or public IP	   address.  If we have public then we will assume that we are not behind	   NAT and will provide automatically the point of connection to the	   agreement.  If we have private range address we assume that we are	   behind NAT and we let the responder provide the point of connection.	   The algorithm also checks the remote IP address of server connection.	   If it is private range address and we have private range address we	   assume that we are chatting in LAN and will provide the point of	   connection.	   Naturally this algorithm does not always get things right. */	if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) {		/* Check if the IP is private */		if (!force_local && silcpurple_ip_is_private(local_ip)) {			local = FALSE;			/* Local IP is private, resolve the remote server IP to see whether			   we are talking to Internet or just on LAN. */			if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL,							&remote_ip))				if (silcpurple_ip_is_private(remote_ip))					/* We assume we are in LAN.  Let's provide					   the connection point. */					local = TRUE;		}	}	if (force_local)		local = TRUE;	if (local && !local_ip)		local_ip = silc_net_localip();	a = silc_calloc(1, sizeof(*a));	if (!a)		return;	a->responder = local;	/* Send the key agreement request */	silc_client_send_key_agreement(sg->client, sg->conn, clients[0],				       local ? local_ip : NULL, NULL, 0, 60,				       silcpurple_buddy_keyagr_cb, a);	silc_free(local_ip);	silc_free(remote_ip);	silc_free(clients);}typedef struct {	SilcClient client;	SilcClientConnection conn;	SilcClientID client_id;	char *hostname;	SilcUInt16 port;} *SilcPurpleKeyAgrAsk;static voidsilcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id){	SilcPurpleKeyAgr ai;	SilcClientEntry client_entry;	if (id != 1)		goto out;	/* Get the client entry. */	client_entry = silc_client_get_client_by_id(a->client, a->conn,						    &a->client_id);	if (!client_entry) {		purple_notify_error(a->client->application, _("Key Agreement"),				  _("The remote user is not present in the network any more"),				  NULL);		goto out;	}	/* If the hostname was provided by the requestor perform the key agreement	   now.  Otherwise, we will send him a request to connect to us. */	if (a->hostname) {		ai = silc_calloc(1, sizeof(*ai));		if (!ai)			goto out;		ai->responder = FALSE;		silc_client_perform_key_agreement(a->client, a->conn, client_entry,						  a->hostname, a->port,						  silcpurple_buddy_keyagr_cb, ai);	} else {		/* Send request.  Force us as the point of connection since requestor		   did not provide the point of connection. */		silcpurple_buddy_keyagr_do(a->client->application,					 client_entry->nickname, TRUE);	} out:	silc_free(a->hostname);	silc_free(a);}void silcpurple_buddy_keyagr_request(SilcClient client,				   SilcClientConnection conn,				   SilcClientEntry client_entry,				   const char *hostname, SilcUInt16 port){	char tmp[128], tmp2[128];	SilcPurpleKeyAgrAsk a;	PurpleConnection *gc = client->application;	g_snprintf(tmp, sizeof(tmp),		   _("Key agreement request received from %s. Would you like to "		     "perform the key agreement?"), client_entry->nickname);	if (hostname)		g_snprintf(tmp2, sizeof(tmp2),			   _("The remote user is waiting key agreement on:\n"			     "Remote host: %s\nRemote port: %d"), hostname, port);	a = silc_calloc(1, sizeof(*a));	if (!a)		return;	a->client = client;	a->conn = conn;	a->client_id = *client_entry->id;	if (hostname)		a->hostname = strdup(hostname);	a->port = port;	purple_request_action(client->application, _("Key Agreement Request"), tmp,			    hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname,				NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),			    _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));}static voidsilcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data){	PurpleBuddy *buddy;	buddy = (PurpleBuddy *)node;	silcpurple_buddy_keyagr_do(buddy->account->gc, buddy->name, FALSE);}/**************************** Static IM Key **********************************/static voidsilcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data){	PurpleBuddy *b;	PurpleConnection *gc;        SilcPurple sg;	char *nickname;	SilcClientEntry *clients;	SilcUInt32 clients_count;	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));	b = (PurpleBuddy *) node;	gc = purple_account_get_connection(b->account);	sg = gc->proto_data;	if (!silc_parse_userfqdn(b->name, &nickname, NULL))		return;	/* Find client entry */	clients = silc_client_get_clients_local(sg->client, sg->conn,						nickname, b->name,						&clients_count);	if (!clients) {		silc_free(nickname);		return;	}	clients[0]->prv_resp = FALSE;	silc_client_del_private_message_key(sg->client, sg->conn,					    clients[0]);	silc_free(clients);	silc_free(nickname);}typedef struct {	SilcClient client;	SilcClientConnection conn;	SilcClientID client_id;} *SilcPurplePrivkey;static voidsilcpurple_buddy_privkey(PurpleConnection *gc, const char *name);static voidsilcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase){	SilcClientEntry client_entry;        if (!passphrase || !(*passphrase)) {                silc_free(p);                return;        }	/* Get the client entry. */	client_entry = silc_client_get_client_by_id(p->client, p->conn,						    &p->client_id);	if (!client_entry) {		purple_notify_error(p->client->application, _("IM With Password"),				  _("The remote user is not present in the network any more"),				  NULL);		silc_free(p);		return;	}	/* Set the private message key */	silc_client_del_private_message_key(p->client, p->conn,					    client_entry);	silc_client_add_private_message_key(p->client, p->conn,					    client_entry, NULL, NULL,					    (unsigned char *)passphrase,					    strlen(passphrase), FALSE,					    client_entry->prv_resp);	if (!client_entry->prv_resp)		silc_client_send_private_message_key_request(p->client,							     p->conn,							     client_entry);        silc_free(p);}static voidsilcpurple_buddy_privkey_resolved(SilcClient client,				SilcClientConnection conn,				SilcClientEntry *clients,				SilcUInt32 clients_count,				void *context){	char tmp[256];	if (!clients) {		g_snprintf(tmp, sizeof(tmp),			   _("User %s is not present in the network"),			   (const char *)context);		purple_notify_error(client->application, _("IM With Password"),				  _("Cannot set IM key"), tmp);		g_free(context);		return;	}	silcpurple_buddy_privkey(client->application, context);	silc_free(context);}static void

⌨️ 快捷键说明

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