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

📄 presence.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * purple - Jabber Protocol Plugin * * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> * * 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; either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include "internal.h"#include "account.h"#include "cipher.h"#include "conversation.h"#include "debug.h"#include "notify.h"#include "request.h"#include "server.h"#include "status.h"#include "util.h"#include "xmlnode.h"#include "buddy.h"#include "chat.h"#include "presence.h"#include "iq.h"#include "jutil.h"static void chats_send_presence_foreach(gpointer key, gpointer val,		gpointer user_data){	JabberChat *chat = val;	xmlnode *presence = user_data;	char *chat_full_jid;	if(!chat->conv)		return;	chat_full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server,			chat->handle);	xmlnode_set_attrib(presence, "to", chat_full_jid);	jabber_send(chat->js, presence);	g_free(chat_full_jid);}void jabber_presence_fake_to_self(JabberStream *js, const PurpleStatus *gstatus) {	char *my_base_jid;	if(!js->user)		return;	my_base_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);	if(purple_find_buddy(js->gc->account, my_base_jid)) {		JabberBuddy *jb;		JabberBuddyResource *jbr;		if((jb = jabber_buddy_find(js, my_base_jid, TRUE))) {			JabberBuddyState state;			char *msg;			int priority;			purple_status_to_jabber(gstatus, &state, &msg, &priority);			if (state == JABBER_BUDDY_STATE_UNAVAILABLE || state == JABBER_BUDDY_STATE_UNKNOWN) {				jabber_buddy_remove_resource(jb, js->user->resource);			} else {				jabber_buddy_track_resource(jb, js->user->resource, priority, state, msg);			}			if((jbr = jabber_buddy_find_resource(jb, NULL))) {				purple_prpl_got_user_status(js->gc->account, my_base_jid, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL);			} else {				purple_prpl_got_user_status(js->gc->account, my_base_jid, "offline", msg ? "message" : NULL, msg, NULL);			}			g_free(msg);		}	}	g_free(my_base_jid);}void jabber_presence_send(PurpleAccount *account, PurpleStatus *status){	PurpleConnection *gc = NULL;	JabberStream *js = NULL;	gboolean disconnected;	int primitive;	xmlnode *presence, *x, *photo;	char *stripped = NULL;	JabberBuddyState state;	int priority;	if(!purple_status_is_active(status))		return;	disconnected = purple_account_is_disconnected(account);	if(disconnected)		return;	primitive = purple_status_type_get_primitive(purple_status_get_type(status));	gc = purple_account_get_connection(account);	js = gc->proto_data;	purple_status_to_jabber(status, &state, &stripped, &priority);	presence = jabber_presence_create(state, stripped, priority);	g_free(stripped);	if(js->avatar_hash) {		x = xmlnode_new_child(presence, "x");		xmlnode_set_namespace(x, "vcard-temp:x:update");		photo = xmlnode_new_child(x, "photo");		xmlnode_insert_data(photo, js->avatar_hash, -1);	}	jabber_send(js, presence);	g_hash_table_foreach(js->chats, chats_send_presence_foreach, presence);	xmlnode_free(presence);	jabber_presence_fake_to_self(js, status);}xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority){	xmlnode *show, *status, *presence, *pri, *c;	const char *show_string = NULL;	presence = xmlnode_new("presence");	if(state == JABBER_BUDDY_STATE_UNAVAILABLE)		xmlnode_set_attrib(presence, "type", "unavailable");	else if(state != JABBER_BUDDY_STATE_ONLINE &&			state != JABBER_BUDDY_STATE_UNKNOWN &&			state != JABBER_BUDDY_STATE_ERROR)		show_string = jabber_buddy_state_get_show(state);	if(show_string) {		show = xmlnode_new_child(presence, "show");		xmlnode_insert_data(show, show_string, -1);	}	if(msg) {		status = xmlnode_new_child(presence, "status");		xmlnode_insert_data(status, msg, -1);	}	if(priority) {		char *pstr = g_strdup_printf("%d", priority);		pri = xmlnode_new_child(presence, "priority");		xmlnode_insert_data(pri, pstr, -1);		g_free(pstr);	}	/* JEP-0115 */	c = xmlnode_new_child(presence, "c");	xmlnode_set_namespace(c, "http://jabber.org/protocol/caps");	xmlnode_set_attrib(c, "node", CAPS0115_NODE);	xmlnode_set_attrib(c, "ver", VERSION);	return presence;}struct _jabber_add_permit {	PurpleConnection *gc;	JabberStream *js;	char *who;};static void authorize_add_cb(struct _jabber_add_permit *jap){	jabber_presence_subscription_set(jap->gc->proto_data, jap->who,			"subscribed");	g_free(jap->who);	g_free(jap);}static void deny_add_cb(struct _jabber_add_permit *jap){	jabber_presence_subscription_set(jap->gc->proto_data, jap->who,			"unsubscribed");	g_free(jap->who);	g_free(jap);}static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah){	JabberBuddy *jb = NULL;	xmlnode *vcard, *photo, *binval;	char *text;	guchar *data;	gsize size;	const char *from = xmlnode_get_attrib(packet, "from");	if(!from)		return;	jb = jabber_buddy_find(js, from, TRUE);	js->pending_avatar_requests = g_slist_remove(js->pending_avatar_requests, jb);	if((vcard = xmlnode_get_child(packet, "vCard")) ||			(vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) {		if((photo = xmlnode_get_child(vcard, "PHOTO")) &&				(( (binval = xmlnode_get_child(photo, "BINVAL")) &&				(text = xmlnode_get_data(binval))) ||				(text = xmlnode_get_data(photo)))) {			unsigned char hashval[20];			char hash[41], *p;			int i;			data = purple_base64_decode(text, &size);			purple_cipher_digest_region("sha1", data, size,					sizeof(hashval), hashval, NULL);			p = hash;			for(i=0; i<20; i++, p+=2)				snprintf(p, 3, "%02x", hashval[i]);			purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash);			g_free(text);		}	}}void jabber_presence_parse(JabberStream *js, xmlnode *packet){	const char *from = xmlnode_get_attrib(packet, "from");	const char *type = xmlnode_get_attrib(packet, "type");	const char *real_jid = NULL;	const char *affiliation = NULL;	const char *role = NULL;	char *status = NULL;	int priority = 0;	JabberID *jid;	JabberChat *chat;	JabberBuddy *jb;	JabberBuddyResource *jbr = NULL, *found_jbr = NULL;	PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE;	gboolean delayed = FALSE;	PurpleBuddy *b = NULL;	char *buddy_name;	JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN;	xmlnode *y;	gboolean muc = FALSE;	char *avatar_hash = NULL;	if(!(jb = jabber_buddy_find(js, from, TRUE)))		return;	if(!(jid = jabber_id_new(from)))		return;	if(jb->error_msg) {		g_free(jb->error_msg);		jb->error_msg = NULL;	}	if(type && !strcmp(type, "error")) {		char *msg = jabber_parse_error(js, packet);		state = JABBER_BUDDY_STATE_ERROR;		jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence"));	} else if(type && !strcmp(type, "subscribe")) {		struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1);		gboolean onlist = FALSE;		PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(js->gc), from);		JabberBuddy *jb = NULL;		if (buddy) {			jb = jabber_buddy_find(js, from, TRUE);			if ((jb->subscription & JABBER_SUB_TO))				onlist = TRUE;		}		jap->gc = js->gc;		jap->who = g_strdup(from);		jap->js = js;		purple_account_request_authorization(purple_connection_get_account(js->gc), from, NULL, NULL, NULL, onlist,				G_CALLBACK(authorize_add_cb), G_CALLBACK(deny_add_cb), jap);		jabber_id_free(jid);		return;	} else if(type && !strcmp(type, "subscribed")) {		/* we've been allowed to see their presence, but we don't care */		jabber_id_free(jid);		return;	} else if(type && !strcmp(type, "unsubscribe")) {		/* XXX I'm not sure this is the right way to handle this, it		 * might be better to add "unsubscribe" to the presence status		 * if lower down, but I'm not sure. */

⌨️ 快捷键说明

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