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

📄 buddy.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  silcpurple_buddy.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"/***************************** 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,				 SilcStatus status,				 SilcDList clients,				 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);}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;	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);			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;	}}static voidsilcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,			   gboolean force_local){	SilcPurple sg = gc->proto_data;	SilcDList clients;	SilcClientEntry client_entry;	SilcClientConnectionParams params;	char *local_ip = NULL, *remote_ip = NULL;	gboolean local = TRUE;	SilcSocket sock;	if (!sg->conn || !name)		return;	/* Find client entry */	clients = silc_client_get_clients_local(sg->client, sg->conn, name,						FALSE);	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, name, NULL,					silcpurple_buddy_keyagr_resolved, r);		return;	}	silc_socket_stream_get_info(silc_packet_stream_get_stream(sg->conn->stream),				    &sock, NULL, NULL, NULL);	/* 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(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(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();	silc_dlist_start(clients);	client_entry = silc_dlist_get(clients);	memset(&params, 0, sizeof(params));	params.timeout_secs = 60;	if (local)	  /* Provide connection point */	  params.local_ip = local_ip;	/* Send the key agreement request */	silc_client_send_key_agreement(sg->client, sg->conn, client_entry,				       &params, sg->public_key,				       sg->private_key,				       silcpurple_buddy_keyagr_cb, NULL);	silc_free(local_ip);	silc_free(remote_ip);	silc_client_list_free(sg->client, sg->conn, 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){	SilcClientEntry client_entry;	SilcClientConnectionParams params;	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) {		memset(&params, 0, sizeof(params));		params.timeout_secs = 60;		silc_client_perform_key_agreement(a->client, a->conn,						  client_entry, &params,						  a->conn->public_key,						  a->conn->private_key,						  a->hostname, a->port,						  silcpurple_buddy_keyagr_cb, NULL);	} 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,				     SilcUInt16 protocol){	char tmp[128], tmp2[128];	SilcPurpleKeyAgrAsk a;	PurpleConnection *gc = client->application;	/* For now Pidgin don't support UDP key agreement */	if (protocol == 1)	  return;	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;	SilcDList clients;	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));	b = (PurpleBuddy *) node;	gc = purple_account_get_connection(b->account);	sg = gc->proto_data;	/* Find client entry */	clients = silc_client_get_clients_local(sg->client, sg->conn,						b->name, FALSE);	if (!clients)		return;	silc_dlist_start(clients);	silc_client_del_private_message_key(sg->client, sg->conn,					    silc_dlist_get(clients));	silc_client_list_free(sg->client, sg->conn, clients);}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));        silc_free(p);}static voidsilcpurple_buddy_privkey_resolved(SilcClient client,				  SilcClientConnection conn,				  SilcStatus status,				  SilcDList clients,				  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 voidsilcpurple_buddy_privkey(PurpleConnection *gc, const char *name){	SilcPurple sg = gc->proto_data;	SilcPurplePrivkey p;	SilcDList clients;	SilcClientEntry client_entry;	if (!name)		return;

⌨️ 快捷键说明

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