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.
23 #include "buddylist.h"
25 #include "mdns_interface.h"
29 * Creates a new buddy.
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
);
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
);
63 set_bonjour_buddy_value(BonjourBuddy
* buddy
, const char *record_key
, const char *value
, guint32 len
){
66 g_return_if_fail(record_key
!= NULL
);
68 if (purple_strequal(record_key
, "1st"))
70 else if(purple_strequal(record_key
, "email"))
72 else if(purple_strequal(record_key
, "ext"))
74 else if(purple_strequal(record_key
, "jid"))
76 else if(purple_strequal(record_key
, "last"))
78 else if(purple_strequal(record_key
, "msg"))
80 else if(purple_strequal(record_key
, "nick"))
82 else if(purple_strequal(record_key
, "node"))
84 else if(purple_strequal(record_key
, "phsh"))
86 else if(purple_strequal(record_key
, "status"))
88 else if(purple_strequal(record_key
, "vc"))
90 else if(purple_strequal(record_key
, "ver"))
92 else if(purple_strequal(record_key
, "AIM"))
100 *fld
= g_strndup(value
, len
);
104 * Check if all the compulsory buddy data is present.
107 bonjour_buddy_check(BonjourBuddy
*buddy
)
109 if (buddy
->account
== NULL
)
112 if (buddy
->name
== NULL
)
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
124 bonjour_buddy_add_to_purple(BonjourBuddy
*bonjour_buddy
, PurpleBuddy
*buddy
)
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
;
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? */
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 */
150 buddy
= purple_blist_find_buddy(account
, bonjour_buddy
->name
);
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
);
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
);
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
);
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
);
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. */
226 if (data
== NULL
|| len
== 0)
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
);
241 * Deletes a buddy from memory.
244 bonjour_buddy_delete(BonjourBuddy
*buddy
)
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
);
253 g_free(buddy
->status
);
254 g_free(buddy
->email
);
265 bonjour_jabber_close_conversation(buddy
->conversation
);
266 buddy
->conversation
= NULL
;
268 /* Clean up any mdns implementation data */
269 _mdns_delete_buddy(buddy
);