1 /*
2  * Copyright (C) 2007,2008,2009 Colin DIDIER
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  */
17 
18 #include "module.h"
19 #include "queries.h"
20 #include "signals.h"
21 
22 #include "xmpp-servers.h"
23 #include "xmpp-commands.h"
24 #include "tools.h"
25 #include "disco.h"
26 
27 #define XMLNS_VCARD "vcard-temp"
28 
29 static void
request_vcard(XMPP_SERVER_REC * server,const char * dest)30 request_vcard(XMPP_SERVER_REC *server, const char *dest)
31 {
32 	LmMessage *lmsg;
33 	LmMessageNode *node;
34 	char *recoded;
35 
36 	recoded = xmpp_recode_out(dest);
37 	lmsg = lm_message_new_with_sub_type(recoded,
38 	    LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_GET);
39 	g_free(recoded);
40 	node = lm_message_node_add_child(lmsg->node, "vCard", NULL);
41 	lm_message_node_set_attribute(node, XMLNS, XMLNS_VCARD);
42 	signal_emit("xmpp send iq", 2, server, lmsg);
43 	lm_message_unref(lmsg);
44 }
45 
46 /* SYNTAX: VCARD [<jid>|<name>]
47  * SYNTAX: WHOIS [<jid>|<name>] */
48 static void
cmd_vcard(const char * data,XMPP_SERVER_REC * server,WI_ITEM_REC * item)49 cmd_vcard(const char *data, XMPP_SERVER_REC *server, WI_ITEM_REC *item)
50 {
51 	char *cmd_dest, *dest;
52 	void *free_arg;
53 
54 	CMD_XMPP_SERVER(server);
55 	if (!cmd_get_params(data, &free_arg, 1, &cmd_dest))
56 		return;
57 	dest = xmpp_get_dest(cmd_dest, server, item);
58 	request_vcard(server, dest);
59 	g_free(dest);
60 	cmd_params_free(free_arg);
61 }
62 
63 static void
vcard_handle(XMPP_SERVER_REC * server,const char * jid,LmMessageNode * node)64 vcard_handle(XMPP_SERVER_REC *server, const char *jid, LmMessageNode *node)
65 {
66 	LmMessageNode *child, *subchild;
67 	GHashTable *ht;
68 	const char *adressing;
69 	char *value;
70 
71 	ht = g_hash_table_new_full(g_str_hash, g_str_equal,
72 	    NULL, g_free);
73 	child = node->children;
74 	while (child != NULL) {
75 		/* ignore avatar */
76 		if (g_ascii_strcasecmp(child->name, "PHOTO") == 0)
77 			goto next;
78 		if (child->value != NULL) {
79 			value = xmpp_recode_in(child->value);
80 			g_strstrip(value);
81 			g_hash_table_insert(ht, child->name, value);
82 			goto next;
83 		}
84 		/* find the adressing type indicator */
85 		subchild = child->children;
86 		adressing = NULL;
87 		while (subchild != NULL && adressing == NULL) {
88 			if (subchild->value == NULL && (
89 			    g_ascii_strcasecmp(subchild->name , "HOME") == 0 ||
90 			    g_ascii_strcasecmp(subchild->name , "WORK") == 0))
91 				adressing = subchild->name;
92 			subchild = subchild->next;
93 		}
94 		subchild = child->children;
95 		while (subchild != NULL) {
96 			if (subchild->value != NULL) {
97 				value = xmpp_recode_in(subchild->value);
98 				/* TODO sub... */
99 				g_free(value);
100 			}
101 			subchild = subchild->next;
102 		}
103 
104 next:
105 		child = child->next;
106 	}
107 	signal_emit("xmpp vcard", 3, server, jid, ht);
108 	g_hash_table_destroy(ht);
109 }
110 
111 static void
sig_recv_iq(XMPP_SERVER_REC * server,LmMessage * lmsg,const int type,const char * id,const char * from,const char * to)112 sig_recv_iq(XMPP_SERVER_REC *server, LmMessage *lmsg, const int type,
113     const char *id, const char *from, const char *to)
114 {
115 	LmMessageNode *node;
116 
117 	if (type != LM_MESSAGE_SUB_TYPE_RESULT)
118 		return;
119 	node = lm_find_node(lmsg->node, "vCard", XMLNS, XMLNS_VCARD);
120 	if (node != NULL)
121 		vcard_handle(server, from, node);
122 }
123 
124 void
vcard_init(void)125 vcard_init(void)
126 {
127 	disco_add_feature(XMLNS_VCARD);
128 	command_bind_xmpp("vcard", NULL, (SIGNAL_FUNC)cmd_vcard);
129 	command_bind_xmpp("whois", NULL, (SIGNAL_FUNC)cmd_vcard);
130 	signal_add("xmpp recv iq", sig_recv_iq);
131 }
132 
133 void
vcard_deinit(void)134 vcard_deinit(void)
135 {
136 	command_unbind("vcard", (SIGNAL_FUNC)cmd_vcard);
137 	command_unbind("whois", (SIGNAL_FUNC)cmd_vcard);
138 	signal_remove("xmpp recv iq", sig_recv_iq);
139 }
140