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

📄 buddy.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 "cipher.h"#include "debug.h"#include "imgstore.h"#include "prpl.h"#include "notify.h"#include "request.h"#include "util.h"#include "xmlnode.h"#include "buddy.h"#include "chat.h"#include "jabber.h"#include "iq.h"#include "presence.h"#include "xdata.h"typedef struct {	long idle_seconds;} JabberBuddyInfoResource;typedef struct {	JabberStream *js;	JabberBuddy *jb;	char *jid;	GSList *ids;	GHashTable *resources;	int timeout_handle;	char *vcard_text;	GSList *vcard_imgids;} JabberBuddyInfo;void jabber_buddy_free(JabberBuddy *jb){	g_return_if_fail(jb != NULL);	if(jb->error_msg)		g_free(jb->error_msg);	while(jb->resources)		jabber_buddy_resource_free(jb->resources->data);	g_free(jb);}JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name,		gboolean create){	JabberBuddy *jb;	const char *realname;	if (js->buddies == NULL)		return NULL;	if(!(realname = jabber_normalize(js->gc->account, name)))		return NULL;	jb = g_hash_table_lookup(js->buddies, realname);	if(!jb && create) {		jb = g_new0(JabberBuddy, 1);		g_hash_table_insert(js->buddies, g_strdup(realname), jb);	}	return jb;}JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb,		const char *resource){	JabberBuddyResource *jbr = NULL;	GList *l;	if(!jb)		return NULL;	for(l = jb->resources; l; l = l->next)	{		if(!jbr && !resource) {			jbr = l->data;		} else if(!resource) {			if(((JabberBuddyResource *)l->data)->priority >= jbr->priority)				jbr = l->data;		} else if(((JabberBuddyResource *)l->data)->name) {			if(!strcmp(((JabberBuddyResource *)l->data)->name, resource)) {				jbr = l->data;				break;			}		}	}	return jbr;}JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource,		int priority, JabberBuddyState state, const char *status){	JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource);	if(!jbr) {		jbr = g_new0(JabberBuddyResource, 1);		jbr->jb = jb;		jbr->name = g_strdup(resource);		jbr->capabilities = JABBER_CAP_XHTML;		jb->resources = g_list_append(jb->resources, jbr);	}	jbr->priority = priority;	jbr->state = state;	if(jbr->status)		g_free(jbr->status);        if (status)		jbr->status = g_markup_escape_text(status, -1);	else		jbr->status = NULL;	return jbr;}void jabber_buddy_resource_free(JabberBuddyResource *jbr){	g_return_if_fail(jbr != NULL);	jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr);	g_free(jbr->name);	g_free(jbr->status);	g_free(jbr->thread_id);	g_free(jbr->client.name);	g_free(jbr->client.version);	g_free(jbr->client.os);	g_free(jbr);}void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource){	JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource);	if(!jbr)		return;	jabber_buddy_resource_free(jbr);}const char *jabber_buddy_get_status_msg(JabberBuddy *jb){	JabberBuddyResource *jbr;	if(!jb)		return NULL;	jbr = jabber_buddy_find_resource(jb, NULL);	if(!jbr)		return NULL;	return jbr->status;}/******* * This is the old vCard stuff taken from the old prpl.  vCards, by definition * are a temporary thing until jabber can get its act together and come up * with a format for user information, hence the namespace of 'vcard-temp' * * Since I don't feel like putting that much work into something that's * _supposed_ to go away, i'm going to just copy the kludgy old code here, * and make it purdy when jabber comes up with a standards-track JEP to * replace vcard-temp *                                 --Nathan *******//*---------------------------------------*//* Jabber "set info" (vCard) support     *//*---------------------------------------*//* * V-Card format: * *  <vCard prodid='' version='' xmlns=''> *    <FN></FN> *    <N> *	<FAMILY/> *	<GIVEN/> *    </N> *    <NICKNAME/> *    <URL/> *    <ADR> *	<STREET/> *	<EXTADD/> *	<LOCALITY/> *	<REGION/> *	<PCODE/> *	<COUNTRY/> *    </ADR> *    <TEL/> *    <EMAIL/> *    <ORG> *	<ORGNAME/> *	<ORGUNIT/> *    </ORG> *    <TITLE/> *    <ROLE/> *    <DESC/> *    <BDAY/> *  </vCard> * * See also: * *	http://docs.jabber.org/proto/html/vcard-temp.html *	http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd *//* * Cross-reference user-friendly V-Card entry labels to vCard XML tags * and attributes. * * Order is (or should be) unimportant.  For example: we have no way of * knowing in what order real data will arrive. * * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag *         name, XML tag's parent tag "path" (relative to vCard node). * *         List is terminated by a NULL label pointer. * *	   Entries with no label text, but with XML tag and parent tag *	   entries, are used by V-Card XML construction routines to *	   "automagically" construct the appropriate XML node tree. * * Thoughts on future direction/expansion * *	This is a "simple" vCard. * *	It is possible for nodes other than the "vCard" node to have *      attributes.  Should that prove necessary/desirable, add an *      "attributes" pointer to the vcard_template struct, create the *      necessary tag_attr structs, and add 'em to the vcard_dflt_data *      array. * *	The above changes will (obviously) require changes to the vCard *      construction routines. */struct vcard_template {	char *label;			/* label text pointer */	char *text;			/* entry text pointer */	int  visible;			/* should entry field be "visible?" */	int  editable;			/* should entry field be editable? */	char *tag;			/* tag text */	char *ptag;			/* parent tag "path" text */	char *url;			/* vCard display format if URL */} vcard_template_data[] = {	{N_("Full Name"),          NULL, TRUE, TRUE, "FN",        NULL,  NULL},	{N_("Family Name"),        NULL, TRUE, TRUE, "FAMILY",    "N",   NULL},	{N_("Given Name"),         NULL, TRUE, TRUE, "GIVEN",     "N",   NULL},	{N_("Nickname"),           NULL, TRUE, TRUE, "NICKNAME",  NULL,  NULL},	{N_("URL"),                NULL, TRUE, TRUE, "URL",       NULL,  "<A HREF=\"%s\">%s</A>"},	{N_("Street Address"),     NULL, TRUE, TRUE, "STREET",    "ADR", NULL},	{N_("Extended Address"),   NULL, TRUE, TRUE, "EXTADD",    "ADR", NULL},	{N_("Locality"),           NULL, TRUE, TRUE, "LOCALITY",  "ADR", NULL},	{N_("Region"),             NULL, TRUE, TRUE, "REGION",    "ADR", NULL},	{N_("Postal Code"),        NULL, TRUE, TRUE, "PCODE",     "ADR", NULL},	{N_("Country"),            NULL, TRUE, TRUE, "CTRY",      "ADR", NULL},	{N_("Telephone"),          NULL, TRUE, TRUE, "NUMBER",    "TEL",  NULL},	{N_("E-Mail"),             NULL, TRUE, TRUE, "USERID",    "EMAIL",  "<A HREF=\"mailto:%s\">%s</A>"},	{N_("Organization Name"),  NULL, TRUE, TRUE, "ORGNAME",   "ORG", NULL},	{N_("Organization Unit"),  NULL, TRUE, TRUE, "ORGUNIT",   "ORG", NULL},	{N_("Title"),              NULL, TRUE, TRUE, "TITLE",     NULL,  NULL},	{N_("Role"),               NULL, TRUE, TRUE, "ROLE",      NULL,  NULL},	{N_("Birthday"),           NULL, TRUE, TRUE, "BDAY",      NULL,  NULL},	{N_("Description"),        NULL, TRUE, TRUE, "DESC",      NULL,  NULL},	{"", NULL, TRUE, TRUE, "N",     NULL, NULL},	{"", NULL, TRUE, TRUE, "ADR",   NULL, NULL},	{"", NULL, TRUE, TRUE, "ORG",   NULL, NULL},	{NULL, NULL, 0, 0, NULL, NULL, NULL}};/* * The "vCard" tag's attribute list... */struct tag_attr {	char *attr;	char *value;} vcard_tag_attr_list[] = {	{"prodid",   "-//HandGen//NONSGML vGen v1.0//EN"},	{"version",  "2.0",                             },	{"xmlns",    "vcard-temp",                      },	{NULL, NULL},};/* * Insert a tag node into an xmlnode tree, recursively inserting parent tag * nodes as necessary * * Returns pointer to inserted node * * Note to hackers: this code is designed to be re-entrant (it's recursive--it * calls itself), so don't put any "static"s in here! */static xmlnode *insert_tag_to_parent_tag(xmlnode *start, const char *parent_tag, const char *new_tag){	xmlnode *x = NULL;	/*	 * If the parent tag wasn't specified, see if we can get it	 * from the vCard template struct.	 */	if(parent_tag == NULL) {		struct vcard_template *vc_tp = vcard_template_data;		while(vc_tp->label != NULL) {			if(strcmp(vc_tp->tag, new_tag) == 0) {				parent_tag = vc_tp->ptag;				break;			}			++vc_tp;		}	}	/*	 * If we have a parent tag...	 */	if(parent_tag != NULL ) {		/*		 * Try to get the parent node for a tag		 */		if((x = xmlnode_get_child(start, parent_tag)) == NULL) {			/*			 * Descend?			 */			char *grand_parent = g_strdup(parent_tag);			char *parent;			if((parent = strrchr(grand_parent, '/')) != NULL) {				*(parent++) = '\0';				x = insert_tag_to_parent_tag(start, grand_parent, parent);			} else {				x = xmlnode_new_child(start, grand_parent);			}			g_free(grand_parent);		} else {			/*			 * We found *something* to be the parent node.			 * Note: may be the "root" node!			 */			xmlnode *y;			if((y = xmlnode_get_child(x, new_tag)) != NULL) {				return(y);			}		}	}	/*	 * insert the new tag into its parent node	 */	return(xmlnode_new_child((x == NULL? start : x), new_tag));}/* * Send vCard info to Jabber server */void jabber_set_info(PurpleConnection *gc, const char *info){	JabberIq *iq;	JabberStream *js = gc->proto_data;	xmlnode *vc_node;	struct tag_attr *tag_attr;	g_free(js->avatar_hash);	js->avatar_hash = NULL;	/*	 * Send only if there's actually any *information* to send	 */	vc_node = info ? xmlnode_from_str(info, -1) : NULL;	if(!vc_node) {		vc_node = xmlnode_new("vCard");		for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr)			xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value);	}	if (vc_node->name &&			!g_ascii_strncasecmp(vc_node->name, "vCard", 5)) {		PurpleStoredImage *img;		if ((img = purple_buddy_icons_find_account_icon(gc->account))) {			gconstpointer avatar_data;			gsize avatar_len;			xmlnode *photo, *binval;			gchar *enc;			int i;			unsigned char hashval[20];			char *p, hash[41];			avatar_data = purple_imgstore_get_data(img);			avatar_len = purple_imgstore_get_size(img);			photo = xmlnode_new_child(vc_node, "PHOTO");			binval = xmlnode_new_child(photo, "BINVAL");			enc = purple_base64_encode(avatar_data, avatar_len);			purple_cipher_digest_region("sha1", avatar_data,									  avatar_len, sizeof(hashval),									  hashval, NULL);			purple_imgstore_unref(img);			p = hash;			for(i=0; i<20; i++, p+=2)				snprintf(p, 3, "%02x", hashval[i]);			js->avatar_hash = g_strdup(hash);			xmlnode_insert_data(binval, enc, -1);			g_free(enc);		}		iq = jabber_iq_new(js, JABBER_IQ_SET);		xmlnode_insert_child(iq->node, vc_node);		jabber_iq_send(iq);	} else {		xmlnode_free(vc_node);	}}void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img){	PurplePresence *gpresence;	PurpleStatus *status;	jabber_set_info(gc, purple_account_get_user_info(gc->account));	gpresence = purple_account_get_presence(gc->account);	status = purple_presence_get_active_status(gpresence);	jabber_presence_send(gc->account, status);}/* * This is the callback from the "ok clicked" for "set vCard" *

⌨️ 快捷键说明

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