Mercurial > pidgin
annotate src/protocols/jabber/buddy.c @ 8236:a8431dd66cc5
[gaim-migrate @ 8959]
Man, I don't want to explain this one. But I will. For Luke.
BECAUSE I CARE. Yaaaaaaayyyyy Luke.
Anyway, the accounts drop down box in the "Add a Buddy Pounce" dialog...
It only shows only accounts, right? Unfortunately the default account
was the top account in the account editor--whether it is online or offline.
This patch makes the default account be the top ONLINE account.
Oh, and even though the dialog LOOKED right before this change, the
actual value of account was incorrect.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 12 Feb 2004 05:56:16 +0000 |
parents | 8d41a4250bb7 |
children | ba12d8b12ab0 |
rev | line source |
---|---|
7014 | 1 /* |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 #include "internal.h" | |
22 #include "debug.h" | |
7076 | 23 #include "imgstore.h" |
7014 | 24 #include "multi.h" |
25 #include "notify.h" | |
26 #include "request.h" | |
27 #include "util.h" | |
7395 | 28 #include "xmlnode.h" |
7014 | 29 |
30 #include "buddy.h" | |
31 #include "chat.h" | |
32 #include "jabber.h" | |
33 #include "iq.h" | |
34 #include "presence.h" | |
7395 | 35 #include "si.h" |
7014 | 36 |
37 | |
7116 | 38 void jabber_buddy_free(JabberBuddy *jb) |
39 { | |
40 g_return_if_fail(jb != NULL); | |
41 | |
42 if(jb->error_msg) | |
43 g_free(jb->error_msg); | |
44 while(jb->resources) | |
45 jabber_buddy_resource_free(jb->resources->data); | |
46 | |
47 g_free(jb); | |
48 } | |
49 | |
7014 | 50 JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name, |
51 gboolean create) | |
52 { | |
53 JabberBuddy *jb; | |
7445 | 54 const char *realname; |
7014 | 55 |
7445 | 56 if(!(realname = jabber_normalize(js->gc->account, name))) |
7014 | 57 return NULL; |
58 | |
59 jb = g_hash_table_lookup(js->buddies, realname); | |
60 | |
61 if(!jb && create) { | |
62 jb = g_new0(JabberBuddy, 1); | |
63 g_hash_table_insert(js->buddies, g_strdup(realname), jb); | |
64 } | |
65 | |
66 return jb; | |
67 } | |
68 | |
69 | |
70 JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, | |
71 const char *resource) | |
72 { | |
73 JabberBuddyResource *jbr = NULL; | |
74 GList *l; | |
75 | |
76 if(!jb) | |
77 return NULL; | |
78 | |
79 for(l = jb->resources; l; l = l->next) | |
80 { | |
81 if(!jbr && !resource) { | |
82 jbr = l->data; | |
83 } else if(!resource) { | |
84 if(((JabberBuddyResource *)l->data)->priority >= jbr->priority) | |
85 jbr = l->data; | |
86 } else if(((JabberBuddyResource *)l->data)->name) { | |
87 if(!strcmp(((JabberBuddyResource *)l->data)->name, resource)) { | |
88 jbr = l->data; | |
89 break; | |
90 } | |
91 } | |
92 } | |
93 | |
94 return jbr; | |
95 } | |
96 | |
97 void jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, | |
98 int priority, int state, const char *status) | |
99 { | |
100 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); | |
101 | |
102 if(!jbr) { | |
103 jbr = g_new0(JabberBuddyResource, 1); | |
7116 | 104 jbr->jb = jb; |
7014 | 105 jbr->name = g_strdup(resource); |
106 jbr->capabilities = JABBER_CAP_XHTML; | |
107 jb->resources = g_list_append(jb->resources, jbr); | |
108 } | |
109 jbr->priority = priority; | |
110 jbr->state = state; | |
111 if(jbr->status) | |
112 g_free(jbr->status); | |
113 jbr->status = g_strdup(status); | |
114 } | |
115 | |
7116 | 116 void jabber_buddy_resource_free(JabberBuddyResource *jbr) |
117 { | |
118 g_return_if_fail(jbr != NULL); | |
119 | |
120 jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr); | |
121 | |
122 g_free(jbr->name); | |
123 if(jbr->status) | |
124 g_free(jbr->status); | |
125 g_free(jbr); | |
126 } | |
127 | |
7014 | 128 void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource) |
129 { | |
130 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); | |
131 | |
132 if(!jbr) | |
133 return; | |
134 | |
7116 | 135 jabber_buddy_resource_free(jbr); |
7014 | 136 } |
137 | |
138 const char *jabber_buddy_get_status_msg(JabberBuddy *jb) | |
139 { | |
140 JabberBuddyResource *jbr; | |
141 | |
142 if(!jb) | |
143 return NULL; | |
144 | |
145 jbr = jabber_buddy_find_resource(jb, NULL); | |
146 | |
147 if(!jbr) | |
148 return NULL; | |
149 | |
150 return jbr->status; | |
151 } | |
152 | |
153 /******* | |
154 * This is the old vCard stuff taken from the old prpl. vCards, by definition | |
155 * are a temporary thing until jabber can get its act together and come up | |
156 * with a format for user information, hence the namespace of 'vcard-temp' | |
157 * | |
158 * Since I don't feel like putting that much work into something that's | |
159 * _supposed_ to go away, i'm going to just copy the kludgy old code here, | |
160 * and make it purdy when jabber comes up with a standards-track JEP to | |
161 * replace vcard-temp | |
162 * --Nathan | |
163 *******/ | |
164 | |
165 /*---------------------------------------*/ | |
166 /* Jabber "set info" (vCard) support */ | |
167 /*---------------------------------------*/ | |
168 | |
169 /* | |
170 * V-Card format: | |
171 * | |
172 * <vCard prodid='' version='' xmlns=''> | |
173 * <FN></FN> | |
174 * <N> | |
175 * <FAMILY/> | |
176 * <GIVEN/> | |
177 * </N> | |
178 * <NICKNAME/> | |
179 * <URL/> | |
180 * <ADR> | |
181 * <STREET/> | |
182 * <EXTADD/> | |
183 * <LOCALITY/> | |
184 * <REGION/> | |
185 * <PCODE/> | |
186 * <COUNTRY/> | |
187 * </ADR> | |
188 * <TEL/> | |
189 * <EMAIL/> | |
190 * <ORG> | |
191 * <ORGNAME/> | |
192 * <ORGUNIT/> | |
193 * </ORG> | |
194 * <TITLE/> | |
195 * <ROLE/> | |
196 * <DESC/> | |
197 * <BDAY/> | |
198 * </vCard> | |
199 * | |
200 * See also: | |
201 * | |
202 * http://docs.jabber.org/proto/html/vcard-temp.html | |
203 * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd | |
204 */ | |
205 | |
206 /* | |
207 * Cross-reference user-friendly V-Card entry labels to vCard XML tags | |
208 * and attributes. | |
209 * | |
210 * Order is (or should be) unimportant. For example: we have no way of | |
211 * knowing in what order real data will arrive. | |
212 * | |
213 * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag | |
214 * name, XML tag's parent tag "path" (relative to vCard node). | |
215 * | |
216 * List is terminated by a NULL label pointer. | |
217 * | |
218 * Entries with no label text, but with XML tag and parent tag | |
219 * entries, are used by V-Card XML construction routines to | |
220 * "automagically" construct the appropriate XML node tree. | |
221 * | |
222 * Thoughts on future direction/expansion | |
223 * | |
224 * This is a "simple" vCard. | |
225 * | |
226 * It is possible for nodes other than the "vCard" node to have | |
227 * attributes. Should that prove necessary/desirable, add an | |
228 * "attributes" pointer to the vcard_template struct, create the | |
229 * necessary tag_attr structs, and add 'em to the vcard_dflt_data | |
230 * array. | |
231 * | |
232 * The above changes will (obviously) require changes to the vCard | |
233 * construction routines. | |
234 */ | |
235 | |
236 struct vcard_template { | |
237 char *label; /* label text pointer */ | |
238 char *text; /* entry text pointer */ | |
239 int visible; /* should entry field be "visible?" */ | |
240 int editable; /* should entry field be editable? */ | |
241 char *tag; /* tag text */ | |
242 char *ptag; /* parent tag "path" text */ | |
243 char *url; /* vCard display format if URL */ | |
244 } vcard_template_data[] = { | |
245 {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, | |
246 {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, | |
247 {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, | |
248 {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, | |
249 {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, | |
250 {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, | |
251 {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, | |
252 {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, | |
253 {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, | |
254 {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, | |
255 {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, | |
256 {N_("Telephone"), NULL, TRUE, TRUE, "TELEPHONE", NULL, NULL}, | |
257 {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, | |
258 {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, | |
259 {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, | |
260 {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, | |
261 {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, | |
262 {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, | |
263 {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, | |
264 {"", NULL, TRUE, TRUE, "N", NULL, NULL}, | |
265 {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, | |
266 {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, | |
267 {NULL, NULL, 0, 0, NULL, NULL, NULL} | |
268 }; | |
269 | |
270 /* | |
271 * The "vCard" tag's attibute list... | |
272 */ | |
273 struct tag_attr { | |
274 char *attr; | |
275 char *value; | |
276 } vcard_tag_attr_list[] = { | |
277 {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, | |
278 {"version", "2.0", }, | |
279 {"xmlns", "vcard-temp", }, | |
280 {NULL, NULL}, | |
281 }; | |
282 | |
283 | |
284 /* | |
285 * Insert a tag node into an xmlnode tree, recursively inserting parent tag | |
286 * nodes as necessary | |
287 * | |
288 * Returns pointer to inserted node | |
289 * | |
290 * Note to hackers: this code is designed to be re-entrant (it's recursive--it | |
291 * calls itself), so don't put any "static"s in here! | |
292 */ | |
293 static xmlnode *insert_tag_to_parent_tag(xmlnode *start, const char *parent_tag, const char *new_tag) | |
294 { | |
295 xmlnode *x = NULL; | |
296 | |
297 /* | |
298 * If the parent tag wasn't specified, see if we can get it | |
299 * from the vCard template struct. | |
300 */ | |
301 if(parent_tag == NULL) { | |
302 struct vcard_template *vc_tp = vcard_template_data; | |
303 | |
304 while(vc_tp->label != NULL) { | |
305 if(strcmp(vc_tp->tag, new_tag) == 0) { | |
306 parent_tag = vc_tp->ptag; | |
307 break; | |
308 } | |
309 ++vc_tp; | |
310 } | |
311 } | |
312 | |
313 /* | |
314 * If we have a parent tag... | |
315 */ | |
316 if(parent_tag != NULL ) { | |
317 /* | |
318 * Try to get the parent node for a tag | |
319 */ | |
320 if((x = xmlnode_get_child(start, parent_tag)) == NULL) { | |
321 /* | |
322 * Descend? | |
323 */ | |
324 char *grand_parent = g_strdup(parent_tag); | |
325 char *parent; | |
326 | |
327 if((parent = strrchr(grand_parent, '/')) != NULL) { | |
328 *(parent++) = '\0'; | |
329 x = insert_tag_to_parent_tag(start, grand_parent, parent); | |
330 } else { | |
331 x = xmlnode_new_child(start, grand_parent); | |
332 } | |
333 g_free(grand_parent); | |
334 } else { | |
335 /* | |
336 * We found *something* to be the parent node. | |
337 * Note: may be the "root" node! | |
338 */ | |
339 xmlnode *y; | |
340 if((y = xmlnode_get_child(x, new_tag)) != NULL) { | |
341 return(y); | |
342 } | |
343 } | |
344 } | |
345 | |
346 /* | |
347 * insert the new tag into its parent node | |
348 */ | |
349 return(xmlnode_new_child((x == NULL? start : x), new_tag)); | |
350 } | |
351 | |
352 /* | |
353 * Send vCard info to Jabber server | |
354 */ | |
355 void jabber_set_info(GaimConnection *gc, const char *info) | |
356 { | |
357 JabberIq *iq; | |
358 JabberStream *js = gc->proto_data; | |
359 xmlnode *vc_node; | |
360 | |
361 | |
362 /* | |
363 * Send only if there's actually any *information* to send | |
364 */ | |
365 vc_node = xmlnode_from_str(info, -1); | |
366 | |
367 if(vc_node) { | |
368 if (vc_node->name && | |
369 !g_ascii_strncasecmp(vc_node->name, "vcard", 5)) { | |
370 iq = jabber_iq_new(js, JABBER_IQ_SET); | |
371 xmlnode_insert_child(iq->node, vc_node); | |
372 jabber_iq_send(iq); | |
373 } else { | |
374 xmlnode_free(vc_node); | |
375 } | |
376 } | |
377 } | |
378 | |
379 /* | |
380 * This is the callback from the "ok clicked" for "set vCard" | |
381 * | |
382 * Formats GSList data into XML-encoded string and returns a pointer | |
383 * to said string. | |
384 * | |
385 * g_free()'ing the returned string space is the responsibility of | |
386 * the caller. | |
387 */ | |
388 static void | |
389 jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) | |
390 { | |
391 GaimAccount *account; | |
392 xmlnode *vc_node; | |
393 GaimRequestField *field; | |
394 const char *text; | |
395 char *p; | |
396 const struct vcard_template *vc_tp; | |
397 struct tag_attr *tag_attr; | |
398 | |
399 vc_node = xmlnode_new("vCard"); | |
400 | |
401 for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) | |
402 xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value); | |
403 | |
404 for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) { | |
405 if (*vc_tp->label == '\0') | |
406 continue; | |
407 | |
408 field = gaim_request_fields_get_field(fields, vc_tp->tag); | |
409 text = gaim_request_field_string_get_value(field); | |
410 | |
411 gaim_debug(GAIM_DEBUG_INFO, "jabber", | |
412 "Setting %s to '%s'\n", vc_tp->tag, text); | |
413 | |
414 if (text != NULL && *text != '\0') { | |
415 xmlnode *xp; | |
416 | |
417 if ((xp = insert_tag_to_parent_tag(vc_node, | |
418 NULL, vc_tp->tag)) != NULL) { | |
419 | |
420 xmlnode_insert_data(xp, text, -1); | |
421 } | |
422 } | |
423 } | |
424 | |
7642 | 425 p = xmlnode_to_str(vc_node, NULL); |
7014 | 426 xmlnode_free(vc_node); |
427 | |
428 account = gaim_connection_get_account(gc); | |
429 | |
430 if (account != NULL) { | |
431 gaim_account_set_user_info(account, p); | |
432 | |
433 if (gc != NULL) | |
434 serv_set_info(gc, p); | |
435 } | |
436 | |
437 g_free(p); | |
438 } | |
439 | |
440 /* | |
441 * This gets executed by the proto action | |
442 * | |
443 * Creates a new GaimRequestFields struct, gets the XML-formatted user_info | |
444 * string (if any) into GSLists for the (multi-entry) edit dialog and | |
445 * calls the set_vcard dialog. | |
446 */ | |
447 void jabber_setup_set_info(GaimConnection *gc) | |
448 { | |
449 GaimRequestFields *fields; | |
450 GaimRequestFieldGroup *group; | |
451 GaimRequestField *field; | |
452 const struct vcard_template *vc_tp; | |
453 char *user_info; | |
454 char *cdata; | |
455 xmlnode *x_vc_data = NULL; | |
456 | |
457 fields = gaim_request_fields_new(); | |
458 group = gaim_request_field_group_new(NULL); | |
459 gaim_request_fields_add_group(fields, group); | |
460 | |
461 /* | |
462 * Get existing, XML-formatted, user info | |
463 */ | |
464 if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) | |
465 x_vc_data = xmlnode_from_str(user_info, -1); | |
466 else | |
467 user_info = g_strdup(""); | |
468 | |
469 /* | |
470 * Set up GSLists for edit with labels from "template," data from user info | |
471 */ | |
472 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
473 xmlnode *data_node; | |
474 if((vc_tp->label)[0] == '\0') | |
475 continue; | |
476 if(vc_tp->ptag == NULL) { | |
477 data_node = xmlnode_get_child(x_vc_data, vc_tp->tag); | |
478 } else { | |
479 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
480 data_node = xmlnode_get_child(x_vc_data, tag); | |
481 g_free(tag); | |
482 } | |
483 if(data_node) | |
484 cdata = xmlnode_get_data(data_node); | |
485 else | |
486 cdata = NULL; | |
487 | |
488 if(strcmp(vc_tp->tag, "DESC") == 0) { | |
489 field = gaim_request_field_string_new(vc_tp->tag, | |
490 _(vc_tp->label), cdata, | |
491 TRUE); | |
492 } else { | |
493 field = gaim_request_field_string_new(vc_tp->tag, | |
494 _(vc_tp->label), cdata, | |
495 FALSE); | |
496 } | |
497 | |
498 gaim_request_field_group_add_field(group, field); | |
499 } | |
500 | |
501 if(x_vc_data != NULL) | |
502 xmlnode_free(x_vc_data); | |
503 | |
504 g_free(user_info); | |
505 | |
506 gaim_request_fields(gc, _("Edit Jabber vCard"), | |
507 _("Edit Jabber vCard"), | |
508 _("All items below are optional. Enter only the " | |
509 "information with which you feel comfortable."), | |
510 fields, | |
511 _("Save"), G_CALLBACK(jabber_format_info), | |
512 _("Cancel"), NULL, | |
513 gc); | |
514 } | |
515 | |
516 /*---------------------------------------*/ | |
517 /* End Jabber "set info" (vCard) support */ | |
518 /*---------------------------------------*/ | |
519 | |
520 /****** | |
521 * end of that ancient crap that needs to die | |
522 ******/ | |
523 | |
524 | |
7395 | 525 static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data) |
7014 | 526 { |
527 GList *resources; | |
528 const char *from = xmlnode_get_attrib(packet, "from"); | |
529 JabberBuddy *jb; | |
530 JabberBuddyResource *jbr; | |
531 GString *info_text; | |
7306 | 532 char *resource_name; |
7955 | 533 char *bare_jid; |
7014 | 534 char *title; |
8213 | 535 char *text; |
7014 | 536 xmlnode *vcard; |
7955 | 537 GaimBuddy *b; |
7014 | 538 |
539 if(!from) | |
540 return; | |
541 | |
7116 | 542 /* XXX: make this handle handle errors */ |
543 | |
7014 | 544 resource_name = jabber_get_resource(from); |
7955 | 545 bare_jid = jabber_get_bare_jid(from); |
546 | |
547 b = gaim_find_buddy(js->gc->account, bare_jid); | |
7014 | 548 |
549 jb = jabber_buddy_find(js, from, TRUE); | |
550 info_text = g_string_new(""); | |
551 | |
8213 | 552 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", _("Jabber ID"), |
7014 | 553 from); |
554 | |
555 if(resource_name) { | |
556 jbr = jabber_buddy_find_resource(jb, resource_name); | |
557 if(jbr) { | |
7145 | 558 char *purdy = NULL; |
559 if(jbr->status) | |
560 purdy = gaim_strdup_withhtml(jbr->status); | |
8213 | 561 g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/>", |
7014 | 562 _("Status"), jabber_get_state_string(jbr->state), |
563 purdy ? ": " : "", | |
564 purdy ? purdy : ""); | |
7145 | 565 if(purdy) |
566 g_free(purdy); | |
7014 | 567 } else { |
8213 | 568 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 569 _("Status"), _("Unknown")); |
570 } | |
571 } else { | |
572 for(resources = jb->resources; resources; resources = resources->next) { | |
7145 | 573 char *purdy = NULL; |
7014 | 574 jbr = resources->data; |
7145 | 575 if(jbr->status) |
576 purdy = gaim_strdup_withhtml(jbr->status); | |
8213 | 577 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 578 _("Resource"), jbr->name); |
8213 | 579 g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/><br/>", |
7014 | 580 _("Status"), jabber_get_state_string(jbr->state), |
581 purdy ? ": " : "", | |
582 purdy ? purdy : ""); | |
7145 | 583 if(purdy) |
584 g_free(purdy); | |
7014 | 585 } |
586 } | |
587 | |
7306 | 588 g_free(resource_name); |
7955 | 589 g_free(bare_jid); |
7306 | 590 |
7014 | 591 if((vcard = xmlnode_get_child(packet, "vCard"))) { |
592 xmlnode *child; | |
593 for(child = vcard->child; child; child = child->next) | |
594 { | |
595 xmlnode *child2; | |
596 | |
8135 | 597 if(child->type != XMLNODE_TYPE_TAG) |
7014 | 598 continue; |
599 | |
600 text = xmlnode_get_data(child); | |
601 if(text && !strcmp(child->name, "FN")) { | |
8213 | 602 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 603 _("Full Name"), text); |
604 } else if(!strcmp(child->name, "N")) { | |
605 for(child2 = child->child; child2; child2 = child2->next) | |
606 { | |
607 char *text2; | |
608 | |
8135 | 609 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 610 continue; |
611 | |
612 text2 = xmlnode_get_data(child2); | |
613 if(text2 && !strcmp(child2->name, "FAMILY")) { | |
614 g_string_append_printf(info_text, | |
8213 | 615 "<b>%s:</b> %s<br/>", |
7014 | 616 _("Family Name"), text2); |
617 } else if(text2 && !strcmp(child2->name, "GIVEN")) { | |
618 g_string_append_printf(info_text, | |
8213 | 619 "<b>%s:</b> %s<br/>", |
7014 | 620 _("Given Name"), text2); |
621 } else if(text2 && !strcmp(child2->name, "MIDDLE")) { | |
622 g_string_append_printf(info_text, | |
8213 | 623 "<b>%s:</b> %s<br/>", |
7014 | 624 _("Middle Name"), text2); |
625 } | |
626 g_free(text2); | |
627 } | |
628 } else if(text && !strcmp(child->name, "NICKNAME")) { | |
629 serv_got_alias(js->gc, from, text); | |
7955 | 630 if(b) { |
631 gaim_blist_node_set_string((GaimBlistNode*)b, "servernick", text); | |
632 gaim_blist_save(); | |
633 } | |
8213 | 634 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 635 _("Nickname"), text); |
636 } else if(text && !strcmp(child->name, "BDAY")) { | |
8213 | 637 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 638 _("Birthday"), text); |
639 } else if(!strcmp(child->name, "ADR")) { | |
640 /* show which address it is */ | |
641 if(child->child) | |
8213 | 642 g_string_append_printf(info_text, "<b>%s:</b><br/>", |
7014 | 643 _("Address")); |
644 for(child2 = child->child; child2; child2 = child2->next) | |
645 { | |
646 char *text2; | |
647 | |
8135 | 648 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 649 continue; |
650 | |
651 text2 = xmlnode_get_data(child2); | |
652 if(text2 && !strcmp(child2->name, "POBOX")) { | |
653 g_string_append_printf(info_text, | |
8213 | 654 " <b>%s:</b> %s<br/>", |
7014 | 655 _("P.O. Box"), text2); |
656 } else if(text2 && !strcmp(child2->name, "EXTADR")) { | |
657 g_string_append_printf(info_text, | |
8213 | 658 " <b>%s:</b> %s<br/>", |
7014 | 659 _("Extended Address"), text2); |
660 } else if(text2 && !strcmp(child2->name, "STREET")) { | |
661 g_string_append_printf(info_text, | |
8213 | 662 " <b>%s:</b> %s<br/>", |
7014 | 663 _("Street Address"), text2); |
664 } else if(text2 && !strcmp(child2->name, "LOCALITY")) { | |
665 g_string_append_printf(info_text, | |
8213 | 666 " <b>%s:</b> %s<br/>", |
7014 | 667 _("Locality"), text2); |
668 } else if(text2 && !strcmp(child2->name, "REGION")) { | |
669 g_string_append_printf(info_text, | |
8213 | 670 " <b>%s:</b> %s<br/>", |
7014 | 671 _("Region"), text2); |
672 } else if(text2 && !strcmp(child2->name, "PCODE")) { | |
673 g_string_append_printf(info_text, | |
8213 | 674 " <b>%s:</b> %s<br/>", |
7014 | 675 _("Postal Code"), text2); |
676 } else if(text2 && (!strcmp(child2->name, "CTRY") | |
677 || !strcmp(child2->name, "COUNTRY"))) { | |
678 g_string_append_printf(info_text, | |
8213 | 679 " <b>%s:</b> %s<br/>", |
7014 | 680 _("Country"), text2); |
681 } | |
682 g_free(text2); | |
683 } | |
684 } else if(!strcmp(child->name, "TEL")) { | |
685 char *number; | |
686 if((child2 = xmlnode_get_child(child, "NUMBER"))) { | |
687 /* show what kind of number it is */ | |
688 number = xmlnode_get_data(child2); | |
689 if(number) { | |
690 g_string_append_printf(info_text, | |
8213 | 691 "<b>%s:</b> %s<br/>", _("Telephone"), number); |
7014 | 692 g_free(number); |
693 } | |
694 } else if((number = xmlnode_get_data(child))) { | |
695 /* lots of clients (including gaim) do this, but it's | |
696 * out of spec */ | |
697 g_string_append_printf(info_text, | |
8213 | 698 "<b>%s:</b> %s<br/>", _("Telephone"), number); |
7014 | 699 g_free(number); |
700 } | |
701 } else if(!strcmp(child->name, "EMAIL")) { | |
702 char *userid; | |
703 if((child2 = xmlnode_get_child(child, "USERID"))) { | |
704 /* show what kind of email it is */ | |
705 userid = xmlnode_get_data(child2); | |
706 if(userid) { | |
707 g_string_append_printf(info_text, | |
8213 | 708 "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>", |
7014 | 709 _("Email"), userid, userid); |
710 g_free(userid); | |
711 } | |
712 } else if((userid = xmlnode_get_data(child))) { | |
713 /* lots of clients (including gaim) do this, but it's | |
714 * out of spec */ | |
715 g_string_append_printf(info_text, | |
8213 | 716 "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>", |
7014 | 717 _("Email"), userid, userid); |
718 g_free(userid); | |
719 } | |
720 } else if(!strcmp(child->name, "ORG")) { | |
721 for(child2 = child->child; child2; child2 = child2->next) | |
722 { | |
723 char *text2; | |
724 | |
8135 | 725 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 726 continue; |
727 | |
728 text2 = xmlnode_get_data(child2); | |
729 if(text2 && !strcmp(child2->name, "ORGNAME")) { | |
730 g_string_append_printf(info_text, | |
8213 | 731 "<b>%s:</b> %s<br/>", |
7014 | 732 _("Organization Name"), text2); |
733 } else if(text2 && !strcmp(child2->name, "ORGUNIT")) { | |
734 g_string_append_printf(info_text, | |
8213 | 735 "<b>%s:</b> %s<br/>", |
7014 | 736 _("Organization Unit"), text2); |
737 } | |
738 g_free(text2); | |
739 } | |
740 } else if(text && !strcmp(child->name, "TITLE")) { | |
8213 | 741 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 742 _("Title"), text); |
743 } else if(text && !strcmp(child->name, "ROLE")) { | |
8213 | 744 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 745 _("Role"), text); |
746 } else if(text && !strcmp(child->name, "DESC")) { | |
8213 | 747 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
748 _("Description"), text); | |
7076 | 749 } else if(!strcmp(child->name, "PHOTO") || |
750 !strcmp(child->name, "LOGO")) { | |
751 if((child2 = xmlnode_get_child(child, "BINVAL"))) { | |
752 char *data, *text2; | |
753 int size, imgid; | |
754 if((text2 = xmlnode_get_data(child2))) { | |
7106
db6bd3e794d8
[gaim-migrate @ 7671]
Christian Hammond <chipx86@chipx86.com>
parents:
7076
diff
changeset
|
755 gaim_base64_decode(text2, &data, &size); |
7076 | 756 |
757 imgid = gaim_imgstore_add(data, size, "logo.png"); | |
758 g_string_append_printf(info_text, | |
7116 | 759 "<b>%s:</b> <img id='%d'><br/>", |
7076 | 760 strcmp(child->name, "PHOTO") == 0 ? |
761 _("Photo") : _("Logo"), | |
762 imgid); | |
763 | |
764 g_free(data); | |
765 g_free(text2); | |
766 } | |
767 } | |
7014 | 768 } |
769 g_free(text); | |
770 } | |
771 } | |
772 | |
773 title = g_strdup_printf("User info for %s", from); | |
774 | |
8213 | 775 text = gaim_strdup_withhtml(info_text->str); |
776 | |
7014 | 777 gaim_notify_formatted(NULL, title, _("Jabber Profile"), |
8213 | 778 NULL, text, NULL, NULL); |
7014 | 779 |
780 g_free(title); | |
781 g_string_free(info_text, TRUE); | |
8213 | 782 g_free(text); |
7014 | 783 } |
784 | |
785 void jabber_buddy_get_info(GaimConnection *gc, const char *who) | |
786 { | |
787 JabberStream *js = gc->proto_data; | |
788 JabberIq *iq; | |
789 xmlnode *vcard; | |
790 | |
791 iq = jabber_iq_new(js, JABBER_IQ_GET); | |
792 | |
793 xmlnode_set_attrib(iq->node, "to", who); | |
794 vcard = xmlnode_new_child(iq->node, "vCard"); | |
795 xmlnode_set_attrib(vcard, "xmlns", "vcard-temp"); | |
796 | |
7395 | 797 jabber_iq_set_callback(iq, jabber_vcard_parse, NULL); |
7014 | 798 |
799 jabber_iq_send(iq); | |
800 } | |
801 | |
802 void jabber_buddy_get_info_chat(GaimConnection *gc, int id, | |
803 const char *resource) | |
804 { | |
805 JabberStream *js = gc->proto_data; | |
806 JabberChat *chat = jabber_chat_find_by_id(js, id); | |
807 char *full_jid; | |
808 | |
809 if(!chat) | |
810 return; | |
811 | |
812 full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, resource); | |
813 jabber_buddy_get_info(gc, full_jid); | |
814 g_free(full_jid); | |
815 } | |
816 | |
7395 | 817 |
7757 | 818 #if 0 |
7395 | 819 static void jabber_buddy_ask_send_file(GaimConnection *gc, const char *name) |
820 { | |
821 JabberStream *js = gc->proto_data; | |
822 GaimXfer *xfer; | |
823 JabberSIXfer *jsx; | |
824 | |
825 xfer = gaim_xfer_new(gaim_connection_get_account(gc), GAIM_XFER_SEND, name); | |
826 | |
827 xfer->data = jsx = g_new0(JabberSIXfer, 1); | |
828 jsx->js = js; | |
829 | |
830 gaim_xfer_set_init_fnc(xfer, jabber_si_xfer_init); | |
831 gaim_xfer_set_start_fnc(xfer, jabber_si_xfer_start); | |
832 gaim_xfer_set_end_fnc(xfer, jabber_si_xfer_end); | |
833 gaim_xfer_set_cancel_send_fnc(xfer, jabber_si_xfer_cancel_send); | |
834 gaim_xfer_set_cancel_recv_fnc(xfer, jabber_si_xfer_cancel_recv); | |
835 gaim_xfer_set_ack_fnc(xfer, jabber_si_xfer_ack); | |
836 | |
837 js->file_transfers = g_list_append(js->file_transfers, xfer); | |
838 | |
839 gaim_xfer_request(xfer); | |
840 } | |
7757 | 841 #endif |
7395 | 842 |
7014 | 843 static void jabber_buddy_set_invisibility(JabberStream *js, const char *who, |
844 gboolean invisible) | |
845 { | |
846 JabberBuddy *jb = jabber_buddy_find(js, who, TRUE); | |
847 xmlnode *presence; | |
848 | |
849 presence = jabber_presence_create(js->gc->away_state, js->gc->away); | |
850 xmlnode_set_attrib(presence, "to", who); | |
851 if(invisible) { | |
852 xmlnode_set_attrib(presence, "type", "invisible"); | |
853 jb->invisible |= JABBER_INVIS_BUDDY; | |
854 } else { | |
855 jb->invisible &= ~JABBER_INVIS_BUDDY; | |
856 } | |
857 | |
858 jabber_send(js, presence); | |
859 xmlnode_free(presence); | |
860 } | |
861 | |
862 static void jabber_buddy_make_invisible(GaimConnection *gc, const char *name) | |
863 { | |
864 JabberStream *js = gc->proto_data; | |
865 jabber_buddy_set_invisibility(js, name, TRUE); | |
866 } | |
867 | |
868 static void jabber_buddy_make_visible(GaimConnection *gc, const char *name) | |
869 { | |
870 JabberStream *js = gc->proto_data; | |
871 jabber_buddy_set_invisibility(js, name, FALSE); | |
872 } | |
873 | |
874 static void jabber_buddy_cancel_presence_notification(GaimConnection *gc, | |
875 const char *name) | |
876 { | |
877 JabberStream *js = gc->proto_data; | |
878 | |
879 /* I wonder if we should prompt the user before doing this */ | |
880 jabber_presence_subscription_set(js, name, "unsubscribed"); | |
881 } | |
882 | |
883 static void jabber_buddy_rerequest_auth(GaimConnection *gc, const char *name) | |
884 { | |
885 JabberStream *js = gc->proto_data; | |
886 | |
887 jabber_presence_subscription_set(js, name, "subscribe"); | |
888 } | |
889 | |
7250 | 890 static void jabber_buddy_unsubscribe(GaimConnection *gc, const char *name) |
891 { | |
892 JabberStream *js = gc->proto_data; | |
893 | |
894 jabber_presence_subscription_set(js, name, "unsubscribe"); | |
895 } | |
896 | |
7014 | 897 GList *jabber_buddy_menu(GaimConnection *gc, const char *name) |
898 { | |
899 GList *m = NULL; | |
900 struct proto_buddy_menu *pbm; | |
901 JabberStream *js = gc->proto_data; | |
902 JabberBuddy *jb = jabber_buddy_find(js, name, TRUE); | |
7395 | 903 |
904 if(!jb) | |
905 return m; | |
906 | |
7425 | 907 /* XXX: should check capability once we know we want to send |
908 pbm = g_new0(struct proto_buddy_menu, 1); | |
909 pbm->label = _("Send File"); | |
910 pbm->callback = jabber_buddy_ask_send_file; | |
911 pbm->gc = gc; | |
912 m = g_list_append(m, pbm); | |
7395 | 913 |
7425 | 914 */ |
7014 | 915 |
8185 | 916 /* XXX: fix the NOT ME below */ |
917 | |
918 if(js->protocol_version == JABBER_PROTO_0_9 /* && NOT ME */) { | |
8166 | 919 pbm = g_new0(struct proto_buddy_menu, 1); |
920 if(jb->invisible & JABBER_INVIS_BUDDY) { | |
921 pbm->label = _("Un-hide From"); | |
922 pbm->callback = jabber_buddy_make_visible; | |
923 } else { | |
924 pbm->label = _("Temporarily Hide From"); | |
925 pbm->callback = jabber_buddy_make_invisible; | |
926 } | |
927 pbm->gc = gc; | |
928 m = g_list_append(m, pbm); | |
7014 | 929 } |
930 | |
8185 | 931 if(jb->subscription & JABBER_SUB_FROM /* && NOT ME */) { |
7014 | 932 pbm = g_new0(struct proto_buddy_menu, 1); |
933 pbm->label = _("Cancel Presence Notification"); | |
934 pbm->callback = jabber_buddy_cancel_presence_notification; | |
935 pbm->gc = gc; | |
936 m = g_list_append(m, pbm); | |
937 } | |
938 | |
939 if(!(jb->subscription & JABBER_SUB_TO)) { | |
940 pbm = g_new0(struct proto_buddy_menu, 1); | |
7250 | 941 pbm->label = _("(Re-)Request authorization"); |
7014 | 942 pbm->callback = jabber_buddy_rerequest_auth; |
943 pbm->gc = gc; | |
944 m = g_list_append(m, pbm); | |
8185 | 945 } else /* if(NOT ME) */{ |
7250 | 946 pbm = g_new0(struct proto_buddy_menu, 1); |
947 pbm->label = _("Unsubscribe"); | |
948 pbm->callback = jabber_buddy_unsubscribe; | |
949 pbm->gc = gc; | |
950 m = g_list_append(m, pbm); | |
7014 | 951 } |
952 | |
953 return m; | |
954 } |