mark PurpleImageClass as private
[pidgin-git.git] / libpurple / protocols / bonjour / buddy.c
blob1de00fc7524d857e9acc6a4b82440aa5a675e893
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
17 #include <glib.h>
18 #include <stdlib.h>
20 #include "internal.h"
21 #include "buddy.h"
22 #include "account.h"
23 #include "buddylist.h"
24 #include "bonjour.h"
25 #include "mdns_interface.h"
26 #include "debug.h"
28 /**
29 * Creates a new buddy.
31 BonjourBuddy *
32 bonjour_buddy_new(const gchar *name, PurpleAccount* account)
34 BonjourBuddy *buddy = g_new0(BonjourBuddy, 1);
36 buddy->account = account;
37 buddy->name = g_strdup(name);
39 _mdns_init_buddy(buddy);
41 return buddy;
44 void
45 clear_bonjour_buddy_values(BonjourBuddy *buddy)
47 g_clear_pointer(&buddy->first, g_free);
48 g_clear_pointer(&buddy->email, g_free);
49 g_clear_pointer(&buddy->ext, g_free);
50 g_clear_pointer(&buddy->jid, g_free);
51 g_clear_pointer(&buddy->last, g_free);
52 g_clear_pointer(&buddy->msg, g_free);
53 g_clear_pointer(&buddy->nick, g_free);
54 g_clear_pointer(&buddy->node, g_free);
55 g_clear_pointer(&buddy->phsh, g_free);
56 g_clear_pointer(&buddy->status, g_free);
57 g_clear_pointer(&buddy->vc, g_free);
58 g_clear_pointer(&buddy->ver, g_free);
59 g_clear_pointer(&buddy->AIM, g_free);
62 void
63 set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, guint32 len){
64 gchar **fld = NULL;
66 g_return_if_fail(record_key != NULL);
68 if (purple_strequal(record_key, "1st"))
69 fld = &buddy->first;
70 else if(purple_strequal(record_key, "email"))
71 fld = &buddy->email;
72 else if(purple_strequal(record_key, "ext"))
73 fld = &buddy->ext;
74 else if(purple_strequal(record_key, "jid"))
75 fld = &buddy->jid;
76 else if(purple_strequal(record_key, "last"))
77 fld = &buddy->last;
78 else if(purple_strequal(record_key, "msg"))
79 fld = &buddy->msg;
80 else if(purple_strequal(record_key, "nick"))
81 fld = &buddy->nick;
82 else if(purple_strequal(record_key, "node"))
83 fld = &buddy->node;
84 else if(purple_strequal(record_key, "phsh"))
85 fld = &buddy->phsh;
86 else if(purple_strequal(record_key, "status"))
87 fld = &buddy->status;
88 else if(purple_strequal(record_key, "vc"))
89 fld = &buddy->vc;
90 else if(purple_strequal(record_key, "ver"))
91 fld = &buddy->ver;
92 else if(purple_strequal(record_key, "AIM"))
93 fld = &buddy->AIM;
95 if(fld == NULL)
96 return;
98 g_free(*fld);
99 *fld = NULL;
100 *fld = g_strndup(value, len);
104 * Check if all the compulsory buddy data is present.
106 gboolean
107 bonjour_buddy_check(BonjourBuddy *buddy)
109 if (buddy->account == NULL)
110 return FALSE;
112 if (buddy->name == NULL)
113 return FALSE;
115 return TRUE;
119 * If the buddy does not yet exist, then create it and add it to
120 * our buddy list. In either case we set the correct status for
121 * the buddy.
123 void
124 bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy)
126 PurpleGroup *group;
127 PurpleAccount *account = bonjour_buddy->account;
128 const char *status_id, *old_hash, *new_hash, *name;
130 /* Translate between the Bonjour status and the Purple status */
131 if (bonjour_buddy->status != NULL && g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
132 status_id = BONJOUR_STATUS_ID_AWAY;
133 else
134 status_id = BONJOUR_STATUS_ID_AVAILABLE;
137 * TODO: Figure out the idle time by getting the "away"
138 * field from the DNS SD.
141 /* Make sure the Bonjour group exists in our buddy list */
142 group = purple_blist_find_group(BONJOUR_GROUP_NAME); /* Use the buddy's domain, instead? */
143 if (group == NULL) {
144 group = purple_group_new(BONJOUR_GROUP_NAME);
145 purple_blist_add_group(group, NULL);
148 /* Make sure the buddy exists in our buddy list */
149 if (buddy == NULL)
150 buddy = purple_blist_find_buddy(account, bonjour_buddy->name);
152 if (buddy == NULL) {
153 buddy = purple_buddy_new(account, bonjour_buddy->name, NULL);
154 purple_blist_node_set_transient(PURPLE_BLIST_NODE(buddy), TRUE);
155 purple_blist_add_buddy(buddy, NULL, group, NULL);
158 name = purple_buddy_get_name(buddy);
159 purple_buddy_set_protocol_data(buddy, bonjour_buddy);
161 /* Create the alias for the buddy using the first and the last name */
162 if (bonjour_buddy->nick && *bonjour_buddy->nick)
163 purple_serv_got_alias(purple_account_get_connection(account), name, bonjour_buddy->nick);
164 else {
165 gchar *alias = NULL;
166 const char *first, *last;
167 first = bonjour_buddy->first;
168 last = bonjour_buddy->last;
169 if ((first && *first) || (last && *last))
170 alias = g_strdup_printf("%s%s%s",
171 (first && *first ? first : ""),
172 (first && *first && last && *last ? " " : ""),
173 (last && *last ? last : ""));
174 purple_serv_got_alias(purple_account_get_connection(account), name, alias);
175 g_free(alias);
178 /* Set the user's status */
179 if (bonjour_buddy->msg != NULL)
180 purple_protocol_got_user_status(account, name, status_id,
181 "message", bonjour_buddy->msg, NULL);
182 else
183 purple_protocol_got_user_status(account, name, status_id, NULL);
185 purple_protocol_got_user_idle(account, name, FALSE, 0);
187 /* TODO: Because we don't save Bonjour buddies in blist.xml,
188 * we will always have to look up the buddy icon at login time.
189 * I think we should figure out a way to do something about this. */
191 /* Deal with the buddy icon */
192 old_hash = purple_buddy_icons_get_checksum_for_user(buddy);
193 new_hash = (bonjour_buddy->phsh && *(bonjour_buddy->phsh)) ? bonjour_buddy->phsh : NULL;
194 if (new_hash && !purple_strequal(old_hash, new_hash)) {
195 /* Look up the new icon data */
196 /* TODO: Make sure the hash assigned to the retrieved buddy icon is the same
197 * as what we looked up. */
198 bonjour_dns_sd_retrieve_buddy_icon(bonjour_buddy);
199 } else if (!new_hash)
200 purple_buddy_icons_set_for_user(account, name, NULL, 0, NULL);
204 * The buddy has signed off Bonjour.
205 * If the buddy is being saved, mark as offline, otherwise delete
207 void bonjour_buddy_signed_off(PurpleBuddy *pb) {
208 if (purple_blist_node_is_transient(PURPLE_BLIST_NODE(pb))) {
209 purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL);
210 purple_blist_remove_buddy(pb);
211 } else {
212 purple_protocol_got_user_status(purple_buddy_get_account(pb),
213 purple_buddy_get_name(pb), "offline", NULL);
214 bonjour_buddy_delete(purple_buddy_get_protocol_data(pb));
215 purple_buddy_set_protocol_data(pb, NULL);
220 * We got the buddy icon data; deal with it
222 void bonjour_buddy_got_buddy_icon(BonjourBuddy *buddy, gconstpointer data, gsize len) {
223 /* Recalculate the hash instead of using the current phsh to make sure it is accurate for the icon. */
224 gchar *hash;
226 if (data == NULL || len == 0)
227 return;
229 hash = g_compute_checksum_for_data(G_CHECKSUM_SHA1, data, len);
231 purple_debug_info("bonjour", "Got buddy icon for %s icon hash='%s' phsh='%s'.\n", buddy->name,
232 hash, buddy->phsh ? buddy->phsh : "(null)");
234 purple_buddy_icons_set_for_user(buddy->account, buddy->name,
235 g_memdup(data, len), len, hash);
237 g_free(hash);
241 * Deletes a buddy from memory.
243 void
244 bonjour_buddy_delete(BonjourBuddy *buddy)
246 g_free(buddy->name);
247 while (buddy->ips != NULL) {
248 g_free(buddy->ips->data);
249 buddy->ips = g_slist_delete_link(buddy->ips, buddy->ips);
251 g_free(buddy->first);
252 g_free(buddy->phsh);
253 g_free(buddy->status);
254 g_free(buddy->email);
255 g_free(buddy->last);
256 g_free(buddy->jid);
257 g_free(buddy->AIM);
258 g_free(buddy->vc);
259 g_free(buddy->msg);
260 g_free(buddy->ext);
261 g_free(buddy->nick);
262 g_free(buddy->node);
263 g_free(buddy->ver);
265 bonjour_jabber_close_conversation(buddy->conversation);
266 buddy->conversation = NULL;
268 /* Clean up any mdns implementation data */
269 _mdns_delete_buddy(buddy);
271 g_free(buddy);