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

📄 silc.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  silcpurple.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 "version.h"#include "wb.h"extern SilcClientOperations ops;static PurplePlugin *silc_plugin = NULL;/* Error log message callback */static SilcBool silcpurple_log_error(SilcLogType type, char *message,				     void *context){	silc_say(NULL, NULL, SILC_CLIENT_MESSAGE_ERROR, message);	return TRUE;}static const char *silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b){	return (const char *)"silc";}static GList *silcpurple_away_states(PurpleAccount *account){	PurpleStatusType *type;	GList *types = NULL;	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, FALSE, TRUE, FALSE);	types = g_list_append(types, type);	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), FALSE, TRUE, FALSE);	types = g_list_append(types, type);	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, FALSE, TRUE, FALSE);	types = g_list_append(types, type);	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), FALSE, TRUE, FALSE);	types = g_list_append(types, type);	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), FALSE, TRUE, FALSE);	types = g_list_append(types, type);	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), FALSE, TRUE, FALSE);	types = g_list_append(types, type);	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, FALSE, TRUE, FALSE);	types = g_list_append(types, type);	return types;}static voidsilcpurple_set_status(PurpleAccount *account, PurpleStatus *status){	PurpleConnection *gc = purple_account_get_connection(account);	SilcPurple sg = NULL;	SilcUInt32 mode;	SilcBuffer idp;	unsigned char mb[4];	const char *state;	if (gc != NULL)		sg = gc->proto_data;	if (status == NULL)		return;	state = purple_status_get_id(status);	if (state == NULL)		return;	if ((sg == NULL) || (sg->conn == NULL))		return;	mode = sg->conn->local_entry->mode;	mode &= ~(SILC_UMODE_GONE |		  SILC_UMODE_HYPER |		  SILC_UMODE_BUSY |		  SILC_UMODE_INDISPOSED |		  SILC_UMODE_PAGE);	if (!strcmp(state, "hyper"))		mode |= SILC_UMODE_HYPER;	else if (!strcmp(state, "away"))		mode |= SILC_UMODE_GONE;	else if (!strcmp(state, "busy"))		mode |= SILC_UMODE_BUSY;	else if (!strcmp(state, "indisposed"))		mode |= SILC_UMODE_INDISPOSED;	else if (!strcmp(state, "page"))		mode |= SILC_UMODE_PAGE;	/* Send UMODE */	idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT);	SILC_PUT32_MSB(mode, mb);	silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE,				 silcpurple_command_reply, NULL, 2,				 1, idp->data, silc_buffer_len(idp),				 2, mb, sizeof(mb));	silc_buffer_free(idp);}/*************************** Connection Routines *****************************/static voidsilcpurple_keepalive(PurpleConnection *gc){	SilcPurple sg = gc->proto_data;	silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0,			 NULL, 0);}static gbooleansilcpurple_scheduler(gpointer *context){	SilcClient client = (SilcClient)context;	silc_client_run_one(client);	return TRUE;}static voidsilcpurple_connect_cb(SilcClient client, SilcClientConnection conn,		      SilcClientConnectionStatus status, SilcStatus error,		      const char *message, void *context){	PurpleConnection *gc = context;	SilcPurple sg;	SilcUInt32 mask;	char tz[16];	PurpleStoredImage *img;#ifdef HAVE_SYS_UTSNAME_H	struct utsname u;#endif	sg = gc->proto_data;	switch (status) {	case SILC_CLIENT_CONN_SUCCESS:	case SILC_CLIENT_CONN_SUCCESS_RESUME:		sg->conn = conn;		/* Connection created successfully */		purple_connection_set_state(gc, PURPLE_CONNECTED);		/* Send the server our buddy list */		silcpurple_send_buddylist(gc);		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));		/* Send any UMODEs configured for account */		if (purple_account_get_bool(sg->account, "block-ims", FALSE)) {			silc_client_command_call(sg->client, sg->conn, NULL,						 "UMODE", "+P", NULL);		}		/* Set default attributes */		mask = SILC_ATTRIBUTE_MOOD_NORMAL;		silc_client_attribute_add(client, conn,					  SILC_ATTRIBUTE_STATUS_MOOD,					  SILC_32_TO_PTR(mask),					  sizeof(SilcUInt32));		mask = SILC_ATTRIBUTE_CONTACT_CHAT;		silc_client_attribute_add(client, conn,					  SILC_ATTRIBUTE_PREFERRED_CONTACT,					  SILC_32_TO_PTR(mask),					  sizeof(SilcUInt32));#ifdef HAVE_SYS_UTSNAME_H		if (!uname(&u)) {			SilcAttributeObjDevice dev;			memset(&dev, 0, sizeof(dev));			dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;			dev.version = u.release;			dev.model = u.sysname;			silc_client_attribute_add(client, conn,						  SILC_ATTRIBUTE_DEVICE_INFO,						  (void *)&dev, sizeof(dev));		}#endif		silc_timezone(tz, sizeof(tz));		silc_client_attribute_add(client, conn,					  SILC_ATTRIBUTE_TIMEZONE,					  (void *)tz, strlen(tz));		/* Set our buddy icon */		img = purple_buddy_icons_find_account_icon(sg->account);		silcpurple_buddy_set_icon(gc, img);		purple_imgstore_unref(img);		return;		break;	case SILC_CLIENT_CONN_DISCONNECTED:		/* Disconnected */		if (sg->resuming && !sg->detaching)		  g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));		/* Close the connection */		if (!sg->detaching)		  purple_connection_error(gc, _("Disconnected by server"));		else		  /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */		  purple_account_disconnect(purple_connection_get_account(gc));		break;	case SILC_CLIENT_CONN_ERROR:		purple_connection_error(gc, _("Error during connecting to SILC Server"));		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));		break;	case SILC_CLIENT_CONN_ERROR_KE:		purple_connection_error(gc, _("Key Exchange failed"));		break;	case SILC_CLIENT_CONN_ERROR_AUTH:		purple_connection_error(gc, _("Authentication failed"));		break;	case SILC_CLIENT_CONN_ERROR_RESUME:		purple_connection_error(gc,				      _("Resuming detached session failed. "					"Press Reconnect to create new connection."));		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));		break;	case SILC_CLIENT_CONN_ERROR_TIMEOUT:		purple_connection_error(gc, _("Connection Timeout"));		break;	}	/* Error */	sg->conn = NULL;}static voidsilcpurple_stream_created(SilcSocketStreamStatus status, SilcStream stream,			  void *context){	PurpleConnection *gc = context;	SilcPurple sg;	SilcClient client;	SilcClientConnectionParams params;	const char *dfile;	sg = gc->proto_data;	if (status != SILC_SOCKET_OK) {		purple_connection_error(gc, _("Connection failed"));		silc_pkcs_public_key_free(sg->public_key);		silc_pkcs_private_key_free(sg->private_key);		silc_free(sg);		gc->proto_data = NULL;		return;	}	client = sg->client;	/* Progress */	if (params.detach_data) {		purple_connection_update_progress(gc, _("Resuming session"), 2, 5);		sg->resuming = TRUE;	} else {		purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5);	}	/* Get session detachment data, if available */	memset(&params, 0, sizeof(params));	dfile = silcpurple_session_file(purple_account_get_username(sg->account));	params.detach_data = (unsigned char *)silc_file_readfile(dfile, &params.detach_data_len);	if (params.detach_data)		params.detach_data[params.detach_data_len] = 0;	params.ignore_requested_attributes = FALSE;	params.pfs = purple_account_get_bool(sg->account, "pfs", FALSE);	/* Perform SILC Key Exchange. */	silc_client_key_exchange(sg->client, &params, sg->public_key,				 sg->private_key, stream, SILC_CONN_SERVER,				 silcpurple_connect_cb, gc);	silc_free(params.detach_data);}static voidsilcpurple_login_connected(gpointer data, gint source, const gchar *error_message){	PurpleConnection *gc = data;	SilcPurple sg;	g_return_if_fail(gc != NULL);	sg = gc->proto_data;	if (source < 0) {		purple_connection_error(gc, _("Connection failed"));		silc_pkcs_public_key_free(sg->public_key);		silc_pkcs_private_key_free(sg->private_key);		silc_free(sg);		gc->proto_data = NULL;		return;	}	/* Wrap socket to TCP stream */	silc_socket_tcp_stream_create(source, TRUE, FALSE,				      sg->client->schedule,				      silcpurple_stream_created, gc);}static void silcpurple_running(SilcClient client, void *context){	PurpleAccount *account = context;	PurpleConnection *gc = account->gc;	SilcPurple sg;	char pkd[256], prd[256];	sg = silc_calloc(1, sizeof(*sg));	if (!sg)		return;	memset(sg, 0, sizeof(*sg));	sg->client = client;	sg->gc = gc;	sg->account = account;	sg->scheduler = SILC_PTR_TO_32(gc->proto_data);	gc->proto_data = sg;	/* Progress */	purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);	/* Load SILC key pair */	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),				(char *)purple_account_get_string(account, "private-key", prd),				(gc->password == NULL) ? "" : gc->password,				&sg->public_key, &sg->private_key)) {		g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair"));		purple_connection_error(gc, pkd);		gc->proto_data = NULL;		silc_free(sg);		return;	}	/* Connect to the SILC server */	if (purple_proxy_connect(gc, account,				 purple_account_get_string(account, "server",							   "silc.silcnet.org"),				 purple_account_get_int(account, "port", 706),				 silcpurple_login_connected, gc) == NULL)	{		purple_connection_error(gc, _("Unable to create connection"));		gc->proto_data = NULL;		silc_free(sg);		return;	}}static voidsilcpurple_login(PurpleAccount *account){	SilcClient client;	PurpleConnection *gc;	SilcClientParams params;	const char *cipher, *hmac;	char *username, *hostname, *realname, **up;	guint scheduler;	int i;	gc = account->gc;	if (!gc)		return;	gc->proto_data = NULL;	memset(&params, 0, sizeof(params));	strcat(params.nickname_format, "%n#a");	/* Allocate SILC client */	client = silc_client_alloc(&ops, &params, gc, NULL);	if (!client) {		purple_connection_error(gc, _("Out of memory"));		return;	}

⌨️ 快捷键说明

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