Mercurial > pidgin
annotate src/protocols/jabber/buddy.c @ 13691:87b027bb1f15
[gaim-migrate @ 16094]
SF Patch #1462332 from cbanal
"When updating an avatar and the accounts vcard / info
is empty. The resulting vCard xml that is sent does not
contain the proper attributes.
This causes the vCard update to be ignored by the
jabber server."
I'm not 100% positive about this, but it seems right.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Tue, 25 Apr 2006 17:19:45 +0000 |
parents | d12bbe6da705 |
children | 2cf94cdb2e99 |
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" | |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
22 #include "cipher.h" |
7014 | 23 #include "debug.h" |
7076 | 24 #include "imgstore.h" |
9713 | 25 #include "prpl.h" |
7014 | 26 #include "notify.h" |
27 #include "request.h" | |
28 #include "util.h" | |
7395 | 29 #include "xmlnode.h" |
7014 | 30 |
31 #include "buddy.h" | |
32 #include "chat.h" | |
33 #include "jabber.h" | |
34 #include "iq.h" | |
35 #include "presence.h" | |
11675 | 36 #include "xdata.h" |
7014 | 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 | |
9954 | 97 JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, |
98 int priority, JabberBuddyState state, const char *status) | |
7014 | 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); | |
9954 | 114 |
115 return jbr; | |
7014 | 116 } |
117 | |
7116 | 118 void jabber_buddy_resource_free(JabberBuddyResource *jbr) |
119 { | |
120 g_return_if_fail(jbr != NULL); | |
121 | |
122 jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr); | |
123 | |
124 g_free(jbr->name); | |
125 if(jbr->status) | |
126 g_free(jbr->status); | |
8400 | 127 if(jbr->thread_id) |
128 g_free(jbr->thread_id); | |
7116 | 129 g_free(jbr); |
130 } | |
131 | |
7014 | 132 void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource) |
133 { | |
134 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); | |
135 | |
136 if(!jbr) | |
137 return; | |
138 | |
7116 | 139 jabber_buddy_resource_free(jbr); |
7014 | 140 } |
141 | |
142 const char *jabber_buddy_get_status_msg(JabberBuddy *jb) | |
143 { | |
144 JabberBuddyResource *jbr; | |
145 | |
146 if(!jb) | |
147 return NULL; | |
148 | |
149 jbr = jabber_buddy_find_resource(jb, NULL); | |
150 | |
151 if(!jbr) | |
152 return NULL; | |
153 | |
154 return jbr->status; | |
155 } | |
156 | |
157 /******* | |
158 * This is the old vCard stuff taken from the old prpl. vCards, by definition | |
159 * are a temporary thing until jabber can get its act together and come up | |
160 * with a format for user information, hence the namespace of 'vcard-temp' | |
161 * | |
162 * Since I don't feel like putting that much work into something that's | |
163 * _supposed_ to go away, i'm going to just copy the kludgy old code here, | |
164 * and make it purdy when jabber comes up with a standards-track JEP to | |
165 * replace vcard-temp | |
166 * --Nathan | |
167 *******/ | |
168 | |
169 /*---------------------------------------*/ | |
170 /* Jabber "set info" (vCard) support */ | |
171 /*---------------------------------------*/ | |
172 | |
173 /* | |
174 * V-Card format: | |
175 * | |
176 * <vCard prodid='' version='' xmlns=''> | |
177 * <FN></FN> | |
178 * <N> | |
179 * <FAMILY/> | |
180 * <GIVEN/> | |
181 * </N> | |
182 * <NICKNAME/> | |
183 * <URL/> | |
184 * <ADR> | |
185 * <STREET/> | |
186 * <EXTADD/> | |
187 * <LOCALITY/> | |
188 * <REGION/> | |
189 * <PCODE/> | |
190 * <COUNTRY/> | |
191 * </ADR> | |
192 * <TEL/> | |
193 * <EMAIL/> | |
194 * <ORG> | |
195 * <ORGNAME/> | |
196 * <ORGUNIT/> | |
197 * </ORG> | |
198 * <TITLE/> | |
199 * <ROLE/> | |
200 * <DESC/> | |
201 * <BDAY/> | |
202 * </vCard> | |
203 * | |
204 * See also: | |
205 * | |
206 * http://docs.jabber.org/proto/html/vcard-temp.html | |
207 * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd | |
208 */ | |
209 | |
210 /* | |
211 * Cross-reference user-friendly V-Card entry labels to vCard XML tags | |
212 * and attributes. | |
213 * | |
214 * Order is (or should be) unimportant. For example: we have no way of | |
215 * knowing in what order real data will arrive. | |
216 * | |
217 * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag | |
218 * name, XML tag's parent tag "path" (relative to vCard node). | |
219 * | |
220 * List is terminated by a NULL label pointer. | |
221 * | |
222 * Entries with no label text, but with XML tag and parent tag | |
223 * entries, are used by V-Card XML construction routines to | |
224 * "automagically" construct the appropriate XML node tree. | |
225 * | |
226 * Thoughts on future direction/expansion | |
227 * | |
228 * This is a "simple" vCard. | |
229 * | |
230 * It is possible for nodes other than the "vCard" node to have | |
231 * attributes. Should that prove necessary/desirable, add an | |
232 * "attributes" pointer to the vcard_template struct, create the | |
233 * necessary tag_attr structs, and add 'em to the vcard_dflt_data | |
234 * array. | |
235 * | |
236 * The above changes will (obviously) require changes to the vCard | |
237 * construction routines. | |
238 */ | |
239 | |
240 struct vcard_template { | |
241 char *label; /* label text pointer */ | |
242 char *text; /* entry text pointer */ | |
243 int visible; /* should entry field be "visible?" */ | |
244 int editable; /* should entry field be editable? */ | |
245 char *tag; /* tag text */ | |
246 char *ptag; /* parent tag "path" text */ | |
247 char *url; /* vCard display format if URL */ | |
248 } vcard_template_data[] = { | |
249 {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, | |
250 {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, | |
251 {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, | |
252 {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, | |
253 {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, | |
254 {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, | |
255 {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, | |
256 {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, | |
257 {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, | |
258 {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, | |
13331 | 259 {N_("Country"), NULL, TRUE, TRUE, "CTRY", "ADR", NULL}, |
11361 | 260 {N_("Telephone"), NULL, TRUE, TRUE, "NUMBER", "TEL", NULL}, |
13545
cfc2f7fcb3dd
[gaim-migrate @ 15922]
Richard Laager <rlaager@wiktel.com>
parents:
13344
diff
changeset
|
261 {N_("E-Mail"), NULL, TRUE, TRUE, "USERID", "EMAIL", "<A HREF=\"mailto:%s\">%s</A>"}, |
7014 | 262 {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, |
263 {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, | |
264 {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, | |
265 {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, | |
266 {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, | |
267 {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, | |
268 {"", NULL, TRUE, TRUE, "N", NULL, NULL}, | |
269 {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, | |
270 {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, | |
271 {NULL, NULL, 0, 0, NULL, NULL, NULL} | |
272 }; | |
273 | |
274 /* | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8401
diff
changeset
|
275 * The "vCard" tag's attribute list... |
7014 | 276 */ |
277 struct tag_attr { | |
278 char *attr; | |
279 char *value; | |
280 } vcard_tag_attr_list[] = { | |
281 {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, | |
282 {"version", "2.0", }, | |
283 {"xmlns", "vcard-temp", }, | |
284 {NULL, NULL}, | |
285 }; | |
286 | |
287 | |
288 /* | |
289 * Insert a tag node into an xmlnode tree, recursively inserting parent tag | |
290 * nodes as necessary | |
291 * | |
292 * Returns pointer to inserted node | |
293 * | |
294 * Note to hackers: this code is designed to be re-entrant (it's recursive--it | |
295 * calls itself), so don't put any "static"s in here! | |
296 */ | |
297 static xmlnode *insert_tag_to_parent_tag(xmlnode *start, const char *parent_tag, const char *new_tag) | |
298 { | |
299 xmlnode *x = NULL; | |
300 | |
301 /* | |
302 * If the parent tag wasn't specified, see if we can get it | |
303 * from the vCard template struct. | |
304 */ | |
305 if(parent_tag == NULL) { | |
306 struct vcard_template *vc_tp = vcard_template_data; | |
307 | |
308 while(vc_tp->label != NULL) { | |
309 if(strcmp(vc_tp->tag, new_tag) == 0) { | |
310 parent_tag = vc_tp->ptag; | |
311 break; | |
312 } | |
313 ++vc_tp; | |
314 } | |
315 } | |
316 | |
317 /* | |
318 * If we have a parent tag... | |
319 */ | |
320 if(parent_tag != NULL ) { | |
321 /* | |
322 * Try to get the parent node for a tag | |
323 */ | |
324 if((x = xmlnode_get_child(start, parent_tag)) == NULL) { | |
325 /* | |
326 * Descend? | |
327 */ | |
328 char *grand_parent = g_strdup(parent_tag); | |
329 char *parent; | |
330 | |
331 if((parent = strrchr(grand_parent, '/')) != NULL) { | |
332 *(parent++) = '\0'; | |
333 x = insert_tag_to_parent_tag(start, grand_parent, parent); | |
334 } else { | |
335 x = xmlnode_new_child(start, grand_parent); | |
336 } | |
337 g_free(grand_parent); | |
338 } else { | |
339 /* | |
340 * We found *something* to be the parent node. | |
341 * Note: may be the "root" node! | |
342 */ | |
343 xmlnode *y; | |
344 if((y = xmlnode_get_child(x, new_tag)) != NULL) { | |
345 return(y); | |
346 } | |
347 } | |
348 } | |
349 | |
350 /* | |
351 * insert the new tag into its parent node | |
352 */ | |
353 return(xmlnode_new_child((x == NULL? start : x), new_tag)); | |
354 } | |
355 | |
356 /* | |
357 * Send vCard info to Jabber server | |
358 */ | |
359 void jabber_set_info(GaimConnection *gc, const char *info) | |
360 { | |
361 JabberIq *iq; | |
362 JabberStream *js = gc->proto_data; | |
363 xmlnode *vc_node; | |
11303
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11183
diff
changeset
|
364 char *avatar_file = NULL; |
13691
87b027bb1f15
[gaim-migrate @ 16094]
Richard Laager <rlaager@wiktel.com>
parents:
13640
diff
changeset
|
365 struct tag_attr *tag_attr; |
7014 | 366 |
10189 | 367 if(js->avatar_hash) |
368 g_free(js->avatar_hash); | |
369 js->avatar_hash = NULL; | |
7014 | 370 |
371 /* | |
372 * Send only if there's actually any *information* to send | |
373 */ | |
11388 | 374 vc_node = info ? xmlnode_from_str(info, -1) : NULL; |
11318 | 375 avatar_file = gaim_buddy_icons_get_full_path(gaim_account_get_buddy_icon(gc->account)); |
10189 | 376 |
377 if(!vc_node && avatar_file) { | |
378 vc_node = xmlnode_new("vCard"); | |
13691
87b027bb1f15
[gaim-migrate @ 16094]
Richard Laager <rlaager@wiktel.com>
parents:
13640
diff
changeset
|
379 for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) |
87b027bb1f15
[gaim-migrate @ 16094]
Richard Laager <rlaager@wiktel.com>
parents:
13640
diff
changeset
|
380 xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value); |
10189 | 381 } |
7014 | 382 |
383 if(vc_node) { | |
384 if (vc_node->name && | |
10189 | 385 !g_ascii_strncasecmp(vc_node->name, "vCard", 5)) { |
386 GError *error = NULL; | |
11509 | 387 gchar *avatar_data_tmp; |
388 guchar *avatar_data; | |
10189 | 389 gsize avatar_len; |
390 | |
11509 | 391 if(avatar_file && g_file_get_contents(avatar_file, &avatar_data_tmp, &avatar_len, &error)) { |
10941 | 392 xmlnode *photo, *binval; |
11127 | 393 gchar *enc; |
10189 | 394 int i; |
395 unsigned char hashval[20]; | |
396 char *p, hash[41]; | |
397 | |
11521 | 398 avatar_data = (guchar *) avatar_data_tmp; |
10189 | 399 photo = xmlnode_new_child(vc_node, "PHOTO"); |
10941 | 400 binval = xmlnode_new_child(photo, "BINVAL"); |
10189 | 401 enc = gaim_base64_encode(avatar_data, avatar_len); |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
402 |
11183 | 403 gaim_cipher_digest_region("sha1", (guchar *)avatar_data, |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
404 avatar_len, sizeof(hashval), |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
405 hashval, NULL); |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
406 |
10189 | 407 p = hash; |
408 for(i=0; i<20; i++, p+=2) | |
409 snprintf(p, 3, "%02x", hashval[i]); | |
410 js->avatar_hash = g_strdup(hash); | |
411 | |
10941 | 412 xmlnode_insert_data(binval, enc, -1); |
10189 | 413 g_free(enc); |
414 g_free(avatar_data); | |
10504 | 415 } else if (error != NULL) { |
10189 | 416 g_error_free(error); |
417 } | |
11303
10066662176a
[gaim-migrate @ 13503]
Richard Laager <rlaager@wiktel.com>
parents:
11183
diff
changeset
|
418 g_free(avatar_file); |
10189 | 419 |
7014 | 420 iq = jabber_iq_new(js, JABBER_IQ_SET); |
421 xmlnode_insert_child(iq->node, vc_node); | |
422 jabber_iq_send(iq); | |
423 } else { | |
424 xmlnode_free(vc_node); | |
425 } | |
426 } | |
427 } | |
428 | |
10189 | 429 void jabber_set_buddy_icon(GaimConnection *gc, const char *iconfile) |
430 { | |
431 GaimPresence *gpresence; | |
432 GaimStatus *status; | |
433 | |
434 jabber_set_info(gc, gaim_account_get_user_info(gc->account)); | |
435 | |
436 gpresence = gaim_account_get_presence(gc->account); | |
437 status = gaim_presence_get_active_status(gpresence); | |
10216 | 438 jabber_presence_send(gc->account, status); |
10189 | 439 } |
440 | |
7014 | 441 /* |
442 * This is the callback from the "ok clicked" for "set vCard" | |
443 * | |
444 * Formats GSList data into XML-encoded string and returns a pointer | |
445 * to said string. | |
446 * | |
447 * g_free()'ing the returned string space is the responsibility of | |
448 * the caller. | |
449 */ | |
450 static void | |
451 jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) | |
452 { | |
453 GaimAccount *account; | |
454 xmlnode *vc_node; | |
455 GaimRequestField *field; | |
456 const char *text; | |
457 char *p; | |
458 const struct vcard_template *vc_tp; | |
459 struct tag_attr *tag_attr; | |
460 | |
461 vc_node = xmlnode_new("vCard"); | |
462 | |
463 for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) | |
464 xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value); | |
465 | |
466 for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) { | |
467 if (*vc_tp->label == '\0') | |
468 continue; | |
469 | |
470 field = gaim_request_fields_get_field(fields, vc_tp->tag); | |
471 text = gaim_request_field_string_get_value(field); | |
472 | |
473 | |
474 if (text != NULL && *text != '\0') { | |
475 xmlnode *xp; | |
476 | |
9339 | 477 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
478 "Setting %s to '%s'\n", vc_tp->tag, text); | |
479 | |
7014 | 480 if ((xp = insert_tag_to_parent_tag(vc_node, |
481 NULL, vc_tp->tag)) != NULL) { | |
482 | |
483 xmlnode_insert_data(xp, text, -1); | |
484 } | |
485 } | |
486 } | |
487 | |
7642 | 488 p = xmlnode_to_str(vc_node, NULL); |
7014 | 489 xmlnode_free(vc_node); |
490 | |
491 account = gaim_connection_get_account(gc); | |
492 | |
493 if (account != NULL) { | |
494 gaim_account_set_user_info(account, p); | |
495 | |
496 if (gc != NULL) | |
497 serv_set_info(gc, p); | |
498 } | |
499 | |
500 g_free(p); | |
501 } | |
502 | |
503 /* | |
504 * This gets executed by the proto action | |
505 * | |
506 * Creates a new GaimRequestFields struct, gets the XML-formatted user_info | |
507 * string (if any) into GSLists for the (multi-entry) edit dialog and | |
508 * calls the set_vcard dialog. | |
509 */ | |
9015 | 510 void jabber_setup_set_info(GaimPluginAction *action) |
7014 | 511 { |
9015 | 512 GaimConnection *gc = (GaimConnection *) action->context; |
7014 | 513 GaimRequestFields *fields; |
514 GaimRequestFieldGroup *group; | |
515 GaimRequestField *field; | |
516 const struct vcard_template *vc_tp; | |
517 char *user_info; | |
518 char *cdata; | |
519 xmlnode *x_vc_data = NULL; | |
520 | |
521 fields = gaim_request_fields_new(); | |
522 group = gaim_request_field_group_new(NULL); | |
523 gaim_request_fields_add_group(fields, group); | |
524 | |
525 /* | |
526 * Get existing, XML-formatted, user info | |
527 */ | |
528 if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) | |
529 x_vc_data = xmlnode_from_str(user_info, -1); | |
530 else | |
531 user_info = g_strdup(""); | |
532 | |
533 /* | |
534 * Set up GSLists for edit with labels from "template," data from user info | |
535 */ | |
536 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
537 xmlnode *data_node; | |
538 if((vc_tp->label)[0] == '\0') | |
539 continue; | |
540 if(vc_tp->ptag == NULL) { | |
541 data_node = xmlnode_get_child(x_vc_data, vc_tp->tag); | |
542 } else { | |
543 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
544 data_node = xmlnode_get_child(x_vc_data, tag); | |
545 g_free(tag); | |
546 } | |
547 if(data_node) | |
548 cdata = xmlnode_get_data(data_node); | |
549 else | |
550 cdata = NULL; | |
551 | |
552 if(strcmp(vc_tp->tag, "DESC") == 0) { | |
553 field = gaim_request_field_string_new(vc_tp->tag, | |
554 _(vc_tp->label), cdata, | |
555 TRUE); | |
556 } else { | |
557 field = gaim_request_field_string_new(vc_tp->tag, | |
558 _(vc_tp->label), cdata, | |
559 FALSE); | |
560 } | |
561 | |
562 gaim_request_field_group_add_field(group, field); | |
563 } | |
564 | |
565 if(x_vc_data != NULL) | |
566 xmlnode_free(x_vc_data); | |
567 | |
568 g_free(user_info); | |
569 | |
570 gaim_request_fields(gc, _("Edit Jabber vCard"), | |
571 _("Edit Jabber vCard"), | |
572 _("All items below are optional. Enter only the " | |
573 "information with which you feel comfortable."), | |
574 fields, | |
575 _("Save"), G_CALLBACK(jabber_format_info), | |
576 _("Cancel"), NULL, | |
577 gc); | |
578 } | |
579 | |
580 /*---------------------------------------*/ | |
581 /* End Jabber "set info" (vCard) support */ | |
582 /*---------------------------------------*/ | |
583 | |
584 /****** | |
585 * end of that ancient crap that needs to die | |
586 ******/ | |
587 | |
588 | |
7395 | 589 static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data) |
7014 | 590 { |
591 GList *resources; | |
592 const char *from = xmlnode_get_attrib(packet, "from"); | |
593 JabberBuddy *jb; | |
594 JabberBuddyResource *jbr; | |
595 GString *info_text; | |
7306 | 596 char *resource_name; |
7955 | 597 char *bare_jid; |
8213 | 598 char *text; |
7014 | 599 xmlnode *vcard; |
7955 | 600 GaimBuddy *b; |
10189 | 601 GSList *imgids = NULL; |
7014 | 602 |
603 if(!from) | |
604 return; | |
605 | |
11361 | 606 if(!(jb = jabber_buddy_find(js, from, TRUE))) |
607 return; | |
608 | |
10490 | 609 /* XXX: handle the error case */ |
610 | |
7014 | 611 resource_name = jabber_get_resource(from); |
7955 | 612 bare_jid = jabber_get_bare_jid(from); |
613 | |
614 b = gaim_find_buddy(js->gc->account, bare_jid); | |
7014 | 615 |
11361 | 616 |
7014 | 617 info_text = g_string_new(""); |
618 | |
619 if(resource_name) { | |
620 jbr = jabber_buddy_find_resource(jb, resource_name); | |
621 if(jbr) { | |
7145 | 622 char *purdy = NULL; |
623 if(jbr->status) | |
624 purdy = gaim_strdup_withhtml(jbr->status); | |
8213 | 625 g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/>", |
9954 | 626 _("Status"), jabber_buddy_state_get_name(jbr->state), |
7014 | 627 purdy ? ": " : "", |
628 purdy ? purdy : ""); | |
7145 | 629 if(purdy) |
630 g_free(purdy); | |
7014 | 631 } else { |
8213 | 632 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 633 _("Status"), _("Unknown")); |
634 } | |
635 } else { | |
636 for(resources = jb->resources; resources; resources = resources->next) { | |
7145 | 637 char *purdy = NULL; |
7014 | 638 jbr = resources->data; |
7145 | 639 if(jbr->status) |
640 purdy = gaim_strdup_withhtml(jbr->status); | |
8213 | 641 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 642 _("Resource"), jbr->name); |
8213 | 643 g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/><br/>", |
9954 | 644 _("Status"), jabber_buddy_state_get_name(jbr->state), |
7014 | 645 purdy ? ": " : "", |
646 purdy ? purdy : ""); | |
7145 | 647 if(purdy) |
648 g_free(purdy); | |
7014 | 649 } |
650 } | |
651 | |
7306 | 652 g_free(resource_name); |
653 | |
10189 | 654 if((vcard = xmlnode_get_child(packet, "vCard")) || |
655 (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) { | |
7014 | 656 xmlnode *child; |
657 for(child = vcard->child; child; child = child->next) | |
658 { | |
659 xmlnode *child2; | |
660 | |
8135 | 661 if(child->type != XMLNODE_TYPE_TAG) |
7014 | 662 continue; |
663 | |
664 text = xmlnode_get_data(child); | |
665 if(text && !strcmp(child->name, "FN")) { | |
8213 | 666 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 667 _("Full Name"), text); |
668 } else if(!strcmp(child->name, "N")) { | |
669 for(child2 = child->child; child2; child2 = child2->next) | |
670 { | |
671 char *text2; | |
672 | |
8135 | 673 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 674 continue; |
675 | |
676 text2 = xmlnode_get_data(child2); | |
677 if(text2 && !strcmp(child2->name, "FAMILY")) { | |
678 g_string_append_printf(info_text, | |
8213 | 679 "<b>%s:</b> %s<br/>", |
7014 | 680 _("Family Name"), text2); |
681 } else if(text2 && !strcmp(child2->name, "GIVEN")) { | |
682 g_string_append_printf(info_text, | |
8213 | 683 "<b>%s:</b> %s<br/>", |
7014 | 684 _("Given Name"), text2); |
685 } else if(text2 && !strcmp(child2->name, "MIDDLE")) { | |
686 g_string_append_printf(info_text, | |
8213 | 687 "<b>%s:</b> %s<br/>", |
7014 | 688 _("Middle Name"), text2); |
689 } | |
690 g_free(text2); | |
691 } | |
692 } else if(text && !strcmp(child->name, "NICKNAME")) { | |
693 serv_got_alias(js->gc, from, text); | |
7955 | 694 if(b) { |
695 gaim_blist_node_set_string((GaimBlistNode*)b, "servernick", text); | |
696 } | |
8213 | 697 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 698 _("Nickname"), text); |
699 } else if(text && !strcmp(child->name, "BDAY")) { | |
8213 | 700 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 701 _("Birthday"), text); |
702 } else if(!strcmp(child->name, "ADR")) { | |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
703 gboolean address_line_added = FALSE; |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
704 |
7014 | 705 for(child2 = child->child; child2; child2 = child2->next) |
706 { | |
707 char *text2; | |
708 | |
8135 | 709 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 710 continue; |
711 | |
712 text2 = xmlnode_get_data(child2); | |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
713 if (text2 == NULL) |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
714 continue; |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
715 |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
716 /* We do this here so that it's not added if all the child |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
717 * elements are empty. */ |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
718 if (!address_line_added) |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
719 { |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
720 g_string_append_printf(info_text, "<b>%s:</b><br/>", |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
721 _("Address")); |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
722 address_line_added = TRUE; |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
723 } |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
724 |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
725 if(!strcmp(child2->name, "POBOX")) { |
7014 | 726 g_string_append_printf(info_text, |
8213 | 727 " <b>%s:</b> %s<br/>", |
7014 | 728 _("P.O. Box"), text2); |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
729 } else if(!strcmp(child2->name, "EXTADR")) { |
7014 | 730 g_string_append_printf(info_text, |
8213 | 731 " <b>%s:</b> %s<br/>", |
7014 | 732 _("Extended Address"), text2); |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
733 } else if(!strcmp(child2->name, "STREET")) { |
7014 | 734 g_string_append_printf(info_text, |
8213 | 735 " <b>%s:</b> %s<br/>", |
7014 | 736 _("Street Address"), text2); |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
737 } else if(!strcmp(child2->name, "LOCALITY")) { |
7014 | 738 g_string_append_printf(info_text, |
8213 | 739 " <b>%s:</b> %s<br/>", |
7014 | 740 _("Locality"), text2); |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
741 } else if(!strcmp(child2->name, "REGION")) { |
7014 | 742 g_string_append_printf(info_text, |
8213 | 743 " <b>%s:</b> %s<br/>", |
7014 | 744 _("Region"), text2); |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
745 } else if(!strcmp(child2->name, "PCODE")) { |
7014 | 746 g_string_append_printf(info_text, |
8213 | 747 " <b>%s:</b> %s<br/>", |
7014 | 748 _("Postal Code"), text2); |
12933
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
749 } else if(!strcmp(child2->name, "CTRY") |
75ac13ab161f
[gaim-migrate @ 15286]
Richard Laager <rlaager@wiktel.com>
parents:
12919
diff
changeset
|
750 || !strcmp(child2->name, "COUNTRY")) { |
7014 | 751 g_string_append_printf(info_text, |
8213 | 752 " <b>%s:</b> %s<br/>", |
7014 | 753 _("Country"), text2); |
754 } | |
755 g_free(text2); | |
756 } | |
757 } else if(!strcmp(child->name, "TEL")) { | |
758 char *number; | |
759 if((child2 = xmlnode_get_child(child, "NUMBER"))) { | |
760 /* show what kind of number it is */ | |
761 number = xmlnode_get_data(child2); | |
762 if(number) { | |
763 g_string_append_printf(info_text, | |
8213 | 764 "<b>%s:</b> %s<br/>", _("Telephone"), number); |
7014 | 765 g_free(number); |
766 } | |
767 } else if((number = xmlnode_get_data(child))) { | |
768 /* lots of clients (including gaim) do this, but it's | |
769 * out of spec */ | |
770 g_string_append_printf(info_text, | |
8213 | 771 "<b>%s:</b> %s<br/>", _("Telephone"), number); |
7014 | 772 g_free(number); |
773 } | |
774 } else if(!strcmp(child->name, "EMAIL")) { | |
775 char *userid; | |
776 if((child2 = xmlnode_get_child(child, "USERID"))) { | |
777 /* show what kind of email it is */ | |
778 userid = xmlnode_get_data(child2); | |
779 if(userid) { | |
780 g_string_append_printf(info_text, | |
8213 | 781 "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>", |
13545
cfc2f7fcb3dd
[gaim-migrate @ 15922]
Richard Laager <rlaager@wiktel.com>
parents:
13344
diff
changeset
|
782 _("E-Mail"), userid, userid); |
7014 | 783 g_free(userid); |
784 } | |
785 } else if((userid = xmlnode_get_data(child))) { | |
786 /* lots of clients (including gaim) do this, but it's | |
787 * out of spec */ | |
788 g_string_append_printf(info_text, | |
8213 | 789 "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>", |
13545
cfc2f7fcb3dd
[gaim-migrate @ 15922]
Richard Laager <rlaager@wiktel.com>
parents:
13344
diff
changeset
|
790 _("E-Mail"), userid, userid); |
7014 | 791 g_free(userid); |
792 } | |
793 } else if(!strcmp(child->name, "ORG")) { | |
794 for(child2 = child->child; child2; child2 = child2->next) | |
795 { | |
796 char *text2; | |
797 | |
8135 | 798 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 799 continue; |
800 | |
801 text2 = xmlnode_get_data(child2); | |
802 if(text2 && !strcmp(child2->name, "ORGNAME")) { | |
803 g_string_append_printf(info_text, | |
8213 | 804 "<b>%s:</b> %s<br/>", |
7014 | 805 _("Organization Name"), text2); |
806 } else if(text2 && !strcmp(child2->name, "ORGUNIT")) { | |
807 g_string_append_printf(info_text, | |
8213 | 808 "<b>%s:</b> %s<br/>", |
7014 | 809 _("Organization Unit"), text2); |
810 } | |
811 g_free(text2); | |
812 } | |
813 } else if(text && !strcmp(child->name, "TITLE")) { | |
8213 | 814 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 815 _("Title"), text); |
816 } else if(text && !strcmp(child->name, "ROLE")) { | |
8213 | 817 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 818 _("Role"), text); |
819 } else if(text && !strcmp(child->name, "DESC")) { | |
8213 | 820 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
821 _("Description"), text); | |
7076 | 822 } else if(!strcmp(child->name, "PHOTO") || |
823 !strcmp(child->name, "LOGO")) { | |
10941 | 824 char *bintext = NULL; |
825 xmlnode *binval; | |
11361 | 826 |
827 if( ((binval = xmlnode_get_child(child, "BINVAL")) && | |
828 (bintext = xmlnode_get_data(binval))) || | |
829 (bintext = xmlnode_get_data(child))) { | |
11127 | 830 gsize size; |
11137 | 831 guchar *data; |
11127 | 832 int i; |
10941 | 833 unsigned char hashval[20]; |
11127 | 834 char *p, hash[41]; |
10941 | 835 gboolean photo = (strcmp(child->name, "PHOTO") == 0); |
10189 | 836 |
11361 | 837 data = gaim_base64_decode(bintext, &size); |
7076 | 838 |
10941 | 839 imgids = g_slist_prepend(imgids, GINT_TO_POINTER(gaim_imgstore_add(data, size, "logo.png"))); |
840 g_string_append_printf(info_text, | |
841 "<b>%s:</b> <img id='%d'><br/>", | |
842 photo ? _("Photo") : _("Logo"), | |
843 GPOINTER_TO_INT(imgids->data)); | |
7076 | 844 |
10941 | 845 gaim_buddy_icons_set_for_user(js->gc->account, bare_jid, |
846 data, size); | |
10189 | 847 |
11183 | 848 gaim_cipher_digest_region("sha1", (guchar *)data, size, |
10941 | 849 sizeof(hashval), hashval, NULL); |
850 p = hash; | |
851 for(i=0; i<20; i++, p+=2) | |
852 snprintf(p, 3, "%02x", hashval[i]); | |
853 gaim_blist_node_set_string((GaimBlistNode*)b, "avatar_hash", hash); | |
10189 | 854 |
10941 | 855 g_free(data); |
856 g_free(bintext); | |
857 } | |
7014 | 858 } |
859 g_free(text); | |
860 } | |
861 } | |
862 | |
8213 | 863 text = gaim_strdup_withhtml(info_text->str); |
864 | |
11533
c9b815aeddc1
[gaim-migrate @ 13782]
Richard Laager <rlaager@wiktel.com>
parents:
11532
diff
changeset
|
865 gaim_notify_userinfo(js->gc, from, text, NULL, NULL); |
7014 | 866 |
10189 | 867 while(imgids) { |
868 gaim_imgstore_unref(GPOINTER_TO_INT(imgids->data)); | |
869 imgids = g_slist_delete_link(imgids, imgids); | |
870 } | |
7014 | 871 g_string_free(info_text, TRUE); |
8213 | 872 g_free(text); |
10189 | 873 g_free(bare_jid); |
7014 | 874 } |
875 | |
10189 | 876 static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *full_jid) |
7014 | 877 { |
878 JabberIq *iq; | |
879 xmlnode *vcard; | |
880 | |
881 iq = jabber_iq_new(js, JABBER_IQ_GET); | |
882 | |
10189 | 883 xmlnode_set_attrib(iq->node, "to", full_jid); |
7014 | 884 vcard = xmlnode_new_child(iq->node, "vCard"); |
885 xmlnode_set_attrib(vcard, "xmlns", "vcard-temp"); | |
886 | |
7395 | 887 jabber_iq_set_callback(iq, jabber_vcard_parse, NULL); |
7014 | 888 |
889 jabber_iq_send(iq); | |
890 } | |
891 | |
10189 | 892 void jabber_buddy_get_info(GaimConnection *gc, const char *who) |
893 { | |
894 JabberStream *js = gc->proto_data; | |
895 char *bare_jid = jabber_get_bare_jid(who); | |
896 | |
897 if(bare_jid) { | |
898 jabber_buddy_get_info_for_jid(js, bare_jid); | |
899 g_free(bare_jid); | |
900 } | |
901 } | |
902 | |
7014 | 903 void jabber_buddy_get_info_chat(GaimConnection *gc, int id, |
904 const char *resource) | |
905 { | |
906 JabberStream *js = gc->proto_data; | |
907 JabberChat *chat = jabber_chat_find_by_id(js, id); | |
908 char *full_jid; | |
909 | |
910 if(!chat) | |
911 return; | |
912 | |
913 full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, resource); | |
10189 | 914 jabber_buddy_get_info_for_jid(js, full_jid); |
7014 | 915 g_free(full_jid); |
916 } | |
917 | |
7395 | 918 |
7014 | 919 static void jabber_buddy_set_invisibility(JabberStream *js, const char *who, |
920 gboolean invisible) | |
921 { | |
9944 | 922 GaimPresence *gpresence; |
923 GaimAccount *account; | |
924 GaimStatus *status; | |
7014 | 925 JabberBuddy *jb = jabber_buddy_find(js, who, TRUE); |
926 xmlnode *presence; | |
9954 | 927 JabberBuddyState state; |
928 const char *msg; | |
929 int priority; | |
7014 | 930 |
9944 | 931 account = gaim_connection_get_account(js->gc); |
932 gpresence = gaim_account_get_presence(account); | |
933 status = gaim_presence_get_active_status(gpresence); | |
934 | |
9954 | 935 gaim_status_to_jabber(status, &state, &msg, &priority); |
936 presence = jabber_presence_create(state, msg, priority); | |
937 | |
7014 | 938 xmlnode_set_attrib(presence, "to", who); |
939 if(invisible) { | |
940 xmlnode_set_attrib(presence, "type", "invisible"); | |
941 jb->invisible |= JABBER_INVIS_BUDDY; | |
942 } else { | |
943 jb->invisible &= ~JABBER_INVIS_BUDDY; | |
944 } | |
945 | |
946 jabber_send(js, presence); | |
947 xmlnode_free(presence); | |
948 } | |
949 | |
9030 | 950 static void jabber_buddy_make_invisible(GaimBlistNode *node, gpointer data) |
7014 | 951 { |
9030 | 952 GaimBuddy *buddy; |
953 GaimConnection *gc; | |
954 JabberStream *js; | |
955 | |
956 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
957 | |
958 buddy = (GaimBuddy *) node; | |
959 gc = gaim_account_get_connection(buddy->account); | |
960 js = gc->proto_data; | |
961 | |
962 jabber_buddy_set_invisibility(js, buddy->name, TRUE); | |
7014 | 963 } |
964 | |
9030 | 965 static void jabber_buddy_make_visible(GaimBlistNode *node, gpointer data) |
7014 | 966 { |
9030 | 967 GaimBuddy *buddy; |
968 GaimConnection *gc; | |
969 JabberStream *js; | |
7014 | 970 |
9030 | 971 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
7014 | 972 |
9030 | 973 buddy = (GaimBuddy *) node; |
974 gc = gaim_account_get_connection(buddy->account); | |
975 js = gc->proto_data; | |
976 | |
977 jabber_buddy_set_invisibility(js, buddy->name, FALSE); | |
7014 | 978 } |
979 | |
9030 | 980 static void jabber_buddy_cancel_presence_notification(GaimBlistNode *node, |
981 gpointer data) | |
7014 | 982 { |
9030 | 983 GaimBuddy *buddy; |
984 GaimConnection *gc; | |
985 JabberStream *js; | |
986 | |
987 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
7014 | 988 |
9030 | 989 buddy = (GaimBuddy *) node; |
990 gc = gaim_account_get_connection(buddy->account); | |
991 js = gc->proto_data; | |
992 | |
993 /* I wonder if we should prompt the user before doing this */ | |
994 jabber_presence_subscription_set(js, buddy->name, "unsubscribed"); | |
7014 | 995 } |
996 | |
9030 | 997 static void jabber_buddy_rerequest_auth(GaimBlistNode *node, gpointer data) |
7250 | 998 { |
9030 | 999 GaimBuddy *buddy; |
1000 GaimConnection *gc; | |
1001 JabberStream *js; | |
1002 | |
1003 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
7250 | 1004 |
9030 | 1005 buddy = (GaimBuddy *) node; |
1006 gc = gaim_account_get_connection(buddy->account); | |
1007 js = gc->proto_data; | |
1008 | |
1009 jabber_presence_subscription_set(js, buddy->name, "subscribe"); | |
7250 | 1010 } |
1011 | |
9030 | 1012 |
1013 static void jabber_buddy_unsubscribe(GaimBlistNode *node, gpointer data) | |
7014 | 1014 { |
9030 | 1015 GaimBuddy *buddy; |
1016 GaimConnection *gc; | |
1017 JabberStream *js; | |
1018 | |
1019 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
1020 | |
1021 buddy = (GaimBuddy *) node; | |
1022 gc = gaim_account_get_connection(buddy->account); | |
1023 js = gc->proto_data; | |
1024 | |
1025 jabber_presence_subscription_set(js, buddy->name, "unsubscribe"); | |
1026 } | |
1027 | |
1028 | |
12323
fc464a0abccc
[gaim-migrate @ 14627]
Richard Laager <rlaager@wiktel.com>
parents:
12284
diff
changeset
|
1029 static GList *jabber_buddy_menu(GaimBuddy *buddy) |
9030 | 1030 { |
1031 GaimConnection *gc = gaim_account_get_connection(buddy->account); | |
1032 JabberStream *js = gc->proto_data; | |
1033 JabberBuddy *jb = jabber_buddy_find(js, buddy->name, TRUE); | |
1034 | |
7014 | 1035 GList *m = NULL; |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1036 GaimMenuAction *act; |
7395 | 1037 |
1038 if(!jb) | |
1039 return m; | |
1040 | |
8185 | 1041 /* XXX: fix the NOT ME below */ |
1042 | |
1043 if(js->protocol_version == JABBER_PROTO_0_9 /* && NOT ME */) { | |
8166 | 1044 if(jb->invisible & JABBER_INVIS_BUDDY) { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1045 act = gaim_menu_action_new(_("Un-hide From"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1046 GAIM_CALLBACK(jabber_buddy_make_visible), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1047 NULL, NULL); |
8166 | 1048 } else { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1049 act = gaim_menu_action_new(_("Temporarily Hide From"), |
13019
8504ce176d38
[gaim-migrate @ 15372]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12933
diff
changeset
|
1050 GAIM_CALLBACK(jabber_buddy_make_invisible), |
8504ce176d38
[gaim-migrate @ 15372]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12933
diff
changeset
|
1051 NULL, NULL); |
8166 | 1052 } |
9030 | 1053 m = g_list_append(m, act); |
7014 | 1054 } |
1055 | |
8185 | 1056 if(jb->subscription & JABBER_SUB_FROM /* && NOT ME */) { |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1057 act = gaim_menu_action_new(_("Cancel Presence Notification"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1058 GAIM_CALLBACK(jabber_buddy_cancel_presence_notification), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1059 NULL, NULL); |
9030 | 1060 m = g_list_append(m, act); |
7014 | 1061 } |
1062 | |
1063 if(!(jb->subscription & JABBER_SUB_TO)) { | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1064 act = gaim_menu_action_new(_("(Re-)Request authorization"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1065 GAIM_CALLBACK(jabber_buddy_rerequest_auth), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1066 NULL, NULL); |
9030 | 1067 m = g_list_append(m, act); |
1068 | |
8185 | 1069 } else /* if(NOT ME) */{ |
9030 | 1070 |
1071 /* shouldn't this just happen automatically when the buddy is | |
1072 removed? */ | |
12919
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1073 act = gaim_menu_action_new(_("Unsubscribe"), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1074 GAIM_CALLBACK(jabber_buddy_unsubscribe), |
248b8b39c671
[gaim-migrate @ 15272]
Etan Reisner <pidgin@unreliablesource.net>
parents:
12683
diff
changeset
|
1075 NULL, NULL); |
9030 | 1076 m = g_list_append(m, act); |
7014 | 1077 } |
1078 | |
1079 return m; | |
1080 } | |
9030 | 1081 |
1082 GList * | |
1083 jabber_blist_node_menu(GaimBlistNode *node) | |
1084 { | |
1085 if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1086 return jabber_buddy_menu((GaimBuddy *) node); | |
1087 } else { | |
1088 return NULL; | |
1089 } | |
1090 } | |
1091 | |
1092 | |
9954 | 1093 const char * |
1094 jabber_buddy_state_get_name(JabberBuddyState state) | |
1095 { | |
1096 switch(state) { | |
1097 case JABBER_BUDDY_STATE_UNKNOWN: | |
1098 return _("Unknown"); | |
1099 case JABBER_BUDDY_STATE_ERROR: | |
1100 return _("Error"); | |
1101 case JABBER_BUDDY_STATE_UNAVAILABLE: | |
1102 return _("Offline"); | |
1103 case JABBER_BUDDY_STATE_ONLINE: | |
12467
1b57012eec7b
[gaim-migrate @ 14777]
Richard Laager <rlaager@wiktel.com>
parents:
12323
diff
changeset
|
1104 return _("Available"); |
9954 | 1105 case JABBER_BUDDY_STATE_CHAT: |
1106 return _("Chatty"); | |
1107 case JABBER_BUDDY_STATE_AWAY: | |
1108 return _("Away"); | |
1109 case JABBER_BUDDY_STATE_XA: | |
1110 return _("Extended Away"); | |
1111 case JABBER_BUDDY_STATE_DND: | |
1112 return _("Do Not Disturb"); | |
1113 } | |
1114 | |
1115 return _("Unknown"); | |
1116 } | |
1117 | |
1118 JabberBuddyState jabber_buddy_status_id_get_state(const char *id) { | |
1119 if(!id) | |
1120 return JABBER_BUDDY_STATE_UNKNOWN; | |
11540 | 1121 if(!strcmp(id, "available")) |
9954 | 1122 return JABBER_BUDDY_STATE_ONLINE; |
12683 | 1123 if(!strcmp(id, "freeforchat")) |
1124 return JABBER_BUDDY_STATE_CHAT; | |
1125 if(!strcmp(id, "away")) | |
1126 return JABBER_BUDDY_STATE_AWAY; | |
1127 if(!strcmp(id, "extended_away")) | |
1128 return JABBER_BUDDY_STATE_XA; | |
1129 if(!strcmp(id, "dnd")) | |
1130 return JABBER_BUDDY_STATE_DND; | |
1131 if(!strcmp(id, "offline")) | |
1132 return JABBER_BUDDY_STATE_UNAVAILABLE; | |
1133 if(!strcmp(id, "error")) | |
1134 return JABBER_BUDDY_STATE_ERROR; | |
1135 | |
1136 return JABBER_BUDDY_STATE_UNKNOWN; | |
1137 } | |
1138 | |
1139 JabberBuddyState jabber_buddy_show_get_state(const char *id) { | |
1140 if(!id) | |
1141 return JABBER_BUDDY_STATE_UNKNOWN; | |
1142 if(!strcmp(id, "available")) | |
1143 return JABBER_BUDDY_STATE_ONLINE; | |
9954 | 1144 if(!strcmp(id, "chat")) |
1145 return JABBER_BUDDY_STATE_CHAT; | |
1146 if(!strcmp(id, "away")) | |
1147 return JABBER_BUDDY_STATE_AWAY; | |
1148 if(!strcmp(id, "xa")) | |
1149 return JABBER_BUDDY_STATE_XA; | |
1150 if(!strcmp(id, "dnd")) | |
1151 return JABBER_BUDDY_STATE_DND; | |
1152 if(!strcmp(id, "offline")) | |
1153 return JABBER_BUDDY_STATE_UNAVAILABLE; | |
1154 if(!strcmp(id, "error")) | |
1155 return JABBER_BUDDY_STATE_ERROR; | |
1156 | |
1157 return JABBER_BUDDY_STATE_UNKNOWN; | |
1158 } | |
1159 | |
12683 | 1160 const char *jabber_buddy_state_get_show(JabberBuddyState state) { |
9954 | 1161 switch(state) { |
1162 case JABBER_BUDDY_STATE_CHAT: | |
1163 return "chat"; | |
1164 case JABBER_BUDDY_STATE_AWAY: | |
1165 return "away"; | |
1166 case JABBER_BUDDY_STATE_XA: | |
1167 return "xa"; | |
1168 case JABBER_BUDDY_STATE_DND: | |
1169 return "dnd"; | |
1170 case JABBER_BUDDY_STATE_ONLINE: | |
11540 | 1171 return "available"; |
9954 | 1172 case JABBER_BUDDY_STATE_UNKNOWN: |
1173 case JABBER_BUDDY_STATE_ERROR: | |
1174 return NULL; | |
1175 case JABBER_BUDDY_STATE_UNAVAILABLE: | |
1176 return "offline"; | |
1177 } | |
1178 return NULL; | |
1179 } | |
11675 | 1180 |
12683 | 1181 const char *jabber_buddy_state_get_status_id(JabberBuddyState state) { |
1182 switch(state) { | |
1183 case JABBER_BUDDY_STATE_CHAT: | |
1184 return "freeforchat"; | |
1185 case JABBER_BUDDY_STATE_AWAY: | |
1186 return "away"; | |
1187 case JABBER_BUDDY_STATE_XA: | |
1188 return "extended_away"; | |
1189 case JABBER_BUDDY_STATE_DND: | |
1190 return "dnd"; | |
1191 case JABBER_BUDDY_STATE_ONLINE: | |
1192 return "available"; | |
1193 case JABBER_BUDDY_STATE_UNKNOWN: | |
1194 case JABBER_BUDDY_STATE_ERROR: | |
1195 return NULL; | |
1196 case JABBER_BUDDY_STATE_UNAVAILABLE: | |
1197 return "offline"; | |
1198 } | |
1199 return NULL; | |
1200 } | |
1201 | |
13640 | 1202 static void user_search_result_add_buddy_cb(GaimConnection *gc, GList *row, void *user_data) |
11675 | 1203 { |
1204 /* XXX find out the jid */ | |
1205 gaim_blist_request_add_buddy(gaim_connection_get_account(gc), | |
1206 g_list_nth_data(row, 0), NULL, NULL); | |
1207 } | |
1208 | |
1209 static void user_search_result_cb(JabberStream *js, xmlnode *packet, gpointer data) | |
1210 { | |
1211 GaimNotifySearchResults *results; | |
1212 GaimNotifySearchColumn *column; | |
1213 xmlnode *x, *query, *item, *field; | |
1214 | |
1215 /* XXX error checking? */ | |
1216 if(!(query = xmlnode_get_child(packet, "query"))) | |
1217 return; | |
1218 | |
1219 results = gaim_notify_searchresults_new(); | |
1220 if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) { | |
1221 xmlnode *reported; | |
1222 gaim_debug_info("jabber", "new-skool\n"); | |
1223 if((reported = xmlnode_get_child(x, "reported"))) { | |
1224 xmlnode *field = xmlnode_get_child(reported, "field"); | |
1225 while(field) { | |
1226 /* XXX keep track of this order, use it below */ | |
1227 const char *var = xmlnode_get_attrib(field, "var"); | |
1228 const char *label = xmlnode_get_attrib(field, "label"); | |
1229 if(var) { | |
1230 column = gaim_notify_searchresults_column_new(label ? label : var); | |
1231 gaim_notify_searchresults_column_add(results, column); | |
1232 } | |
1233 field = xmlnode_get_next_twin(field); | |
1234 } | |
1235 } | |
1236 item = xmlnode_get_child(x, "item"); | |
1237 while(item) { | |
1238 GList *row = NULL; | |
1239 field = xmlnode_get_child(item, "field"); | |
1240 while(field) { | |
13344 | 1241 xmlnode *valuenode = xmlnode_get_child(field, "value"); |
11675 | 1242 if(valuenode) { |
1243 char *value = xmlnode_get_data(valuenode); | |
1244 row = g_list_append(row, value); | |
1245 } | |
1246 field = xmlnode_get_next_twin(field); | |
1247 } | |
1248 gaim_notify_searchresults_row_add(results, row); | |
1249 | |
1250 item = xmlnode_get_next_twin(item); | |
1251 } | |
1252 } else { | |
1253 /* old skool */ | |
1254 gaim_debug_info("jabber", "old-skool\n"); | |
1255 | |
13571
02a8424191ea
[gaim-migrate @ 15950]
Richard Laager <rlaager@wiktel.com>
parents:
13545
diff
changeset
|
1256 column = gaim_notify_searchresults_column_new(_("JID")); |
11675 | 1257 gaim_notify_searchresults_column_add(results, column); |
13571
02a8424191ea
[gaim-migrate @ 15950]
Richard Laager <rlaager@wiktel.com>
parents:
13545
diff
changeset
|
1258 column = gaim_notify_searchresults_column_new(_("First Name")); |
11675 | 1259 gaim_notify_searchresults_column_add(results, column); |
13571
02a8424191ea
[gaim-migrate @ 15950]
Richard Laager <rlaager@wiktel.com>
parents:
13545
diff
changeset
|
1260 column = gaim_notify_searchresults_column_new(_("Last Name")); |
11675 | 1261 gaim_notify_searchresults_column_add(results, column); |
13571
02a8424191ea
[gaim-migrate @ 15950]
Richard Laager <rlaager@wiktel.com>
parents:
13545
diff
changeset
|
1262 column = gaim_notify_searchresults_column_new(_("Nickname")); |
11675 | 1263 gaim_notify_searchresults_column_add(results, column); |
13571
02a8424191ea
[gaim-migrate @ 15950]
Richard Laager <rlaager@wiktel.com>
parents:
13545
diff
changeset
|
1264 column = gaim_notify_searchresults_column_new(_("E-Mail")); |
11675 | 1265 gaim_notify_searchresults_column_add(results, column); |
1266 | |
1267 for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { | |
1268 const char *jid; | |
1269 xmlnode *node; | |
1270 GList *row = NULL; | |
1271 | |
1272 if(!(jid = xmlnode_get_attrib(item, "jid"))) | |
1273 continue; | |
1274 | |
1275 row = g_list_append(row, g_strdup(jid)); | |
1276 node = xmlnode_get_child(item, "first"); | |
1277 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); | |
1278 node = xmlnode_get_child(item, "last"); | |
1279 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); | |
1280 node = xmlnode_get_child(item, "nick"); | |
1281 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); | |
1282 node = xmlnode_get_child(item, "email"); | |
1283 row = g_list_append(row, node ? xmlnode_get_data(node) : NULL); | |
1284 gaim_debug_info("jabber", "row=%d\n", row); | |
1285 gaim_notify_searchresults_row_add(results, row); | |
1286 } | |
1287 } | |
1288 | |
12624
851b0bd7eb52
[gaim-migrate @ 14960]
Christopher O'Brien <siege@pidgin.im>
parents:
12467
diff
changeset
|
1289 gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_ADD, |
11675 | 1290 user_search_result_add_buddy_cb); |
1291 | |
1292 gaim_notify_searchresults(js->gc, NULL, NULL, _("The following are the results of your search"), results, NULL, NULL); | |
1293 } | |
1294 | |
1295 static void user_search_x_data_cb(JabberStream *js, xmlnode *result, gpointer data) | |
1296 { | |
1297 xmlnode *query; | |
1298 JabberIq *iq; | |
13344 | 1299 char *dir_server = data; |
11675 | 1300 |
1301 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:search"); | |
1302 query = xmlnode_get_child(iq->node, "query"); | |
1303 | |
1304 xmlnode_insert_child(query, result); | |
1305 | |
1306 jabber_iq_set_callback(iq, user_search_result_cb, NULL); | |
13344 | 1307 xmlnode_set_attrib(iq->node, "to", dir_server); |
11675 | 1308 jabber_iq_send(iq); |
13344 | 1309 g_free(dir_server); |
11675 | 1310 } |
1311 | |
1312 struct user_search_info { | |
1313 JabberStream *js; | |
1314 char *directory_server; | |
1315 }; | |
1316 | |
1317 static void user_search_cancel_cb(struct user_search_info *usi, GaimRequestFields *fields) | |
1318 { | |
1319 g_free(usi->directory_server); | |
1320 g_free(usi); | |
1321 } | |
1322 | |
1323 static void user_search_cb(struct user_search_info *usi, GaimRequestFields *fields) | |
1324 { | |
1325 JabberStream *js = usi->js; | |
1326 JabberIq *iq; | |
1327 xmlnode *query; | |
1328 GList *groups, *flds; | |
1329 | |
1330 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:search"); | |
1331 query = xmlnode_get_child(iq->node, "query"); | |
1332 | |
1333 for(groups = gaim_request_fields_get_groups(fields); groups; groups = groups->next) { | |
1334 for(flds = gaim_request_field_group_get_fields(groups->data); | |
1335 flds; flds = flds->next) { | |
1336 GaimRequestField *field = flds->data; | |
1337 const char *id = gaim_request_field_get_id(field); | |
1338 const char *value = gaim_request_field_string_get_value(field); | |
1339 | |
1340 if(value && (!strcmp(id, "first") || !strcmp(id, "last") || !strcmp(id, "nick") || !strcmp(id, "email"))) { | |
1341 xmlnode *y = xmlnode_new_child(query, id); | |
1342 xmlnode_insert_data(y, value, -1); | |
1343 } | |
1344 } | |
1345 } | |
1346 | |
1347 jabber_iq_set_callback(iq, user_search_result_cb, NULL); | |
1348 xmlnode_set_attrib(iq->node, "to", usi->directory_server); | |
1349 jabber_iq_send(iq); | |
1350 | |
1351 g_free(usi->directory_server); | |
1352 g_free(usi); | |
1353 } | |
1354 | |
13616
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1355 #if 0 |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1356 /* This is for gettext only -- it will see this even though there's an #if 0. */ |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1357 |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1358 /* |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1359 * An incomplete list of server generated original language search |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1360 * comments for Jabber User Directories |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1361 * |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1362 * See discussion thread "Search comment for Jabber is not translatable" |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1363 * in gaim-i18n@lists.sourceforge.net (March 2006) |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1364 */ |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1365 static const char * jabber_user_dir_comments [] = { |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1366 /* current comment from Jabber User Directory users.jabber.org */ |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1367 N_("Find a contact by entering the search criteria in the given fields. " |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1368 "Note: Each field supports wild card searches (%)"), |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1369 NULL |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1370 }; |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1371 #endif |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1372 |
11675 | 1373 static void user_search_fields_result_cb(JabberStream *js, xmlnode *packet, gpointer data) |
1374 { | |
1375 xmlnode *query, *x; | |
13344 | 1376 const char *from, *type; |
11675 | 1377 |
12284
ecd471d1eeec
[gaim-migrate @ 14588]
Etan Reisner <pidgin@unreliablesource.net>
parents:
11675
diff
changeset
|
1378 if(!(from = xmlnode_get_attrib(packet, "from"))) |
11675 | 1379 return; |
1380 | |
13344 | 1381 if(!(type = xmlnode_get_attrib(packet, "type")) || !strcmp(type, "error")) { |
13633
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1382 char *msg = jabber_parse_error(js, packet); |
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1383 |
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1384 if(!msg) |
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1385 msg = g_strdup(_("Unknown error")); |
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1386 |
13617
513d0e06f35f
[gaim-migrate @ 16003]
Richard Laager <rlaager@wiktel.com>
parents:
13616
diff
changeset
|
1387 gaim_notify_error(js->gc, _("Directory Query Failed"), |
13633
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1388 _("Could not query the directory server."), msg); |
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1389 g_free(msg); |
c86c6f0505ea
[gaim-migrate @ 16031]
Richard Laager <rlaager@wiktel.com>
parents:
13618
diff
changeset
|
1390 |
13344 | 1391 return; |
1392 } | |
1393 | |
11675 | 1394 |
1395 if(!(query = xmlnode_get_child(packet, "query"))) | |
1396 return; | |
1397 | |
13329 | 1398 if((x = xmlnode_get_child_with_namespace(query, "x", "jabber:x:data"))) { |
13344 | 1399 jabber_x_data_request(js, x, user_search_x_data_cb, g_strdup(from)); |
11675 | 1400 return; |
1401 } else { | |
1402 struct user_search_info *usi; | |
1403 xmlnode *instnode; | |
13616
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1404 char *instructions = NULL; |
11675 | 1405 GaimRequestFields *fields; |
1406 GaimRequestFieldGroup *group; | |
1407 GaimRequestField *field; | |
1408 | |
1409 /* old skool */ | |
1410 fields = gaim_request_fields_new(); | |
1411 group = gaim_request_field_group_new(NULL); | |
1412 gaim_request_fields_add_group(fields, group); | |
1413 | |
1414 if((instnode = xmlnode_get_child(query, "instructions"))) | |
13573
0b2e4a5a8e79
[gaim-migrate @ 15952]
Richard Laager <rlaager@wiktel.com>
parents:
13571
diff
changeset
|
1415 { |
0b2e4a5a8e79
[gaim-migrate @ 15952]
Richard Laager <rlaager@wiktel.com>
parents:
13571
diff
changeset
|
1416 char *tmp = xmlnode_get_data(instnode); |
13616
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1417 |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1418 if(tmp) |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1419 { |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1420 /* Try to translate the message (see static message |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1421 list in jabber_user_dir_comments[]) */ |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1422 instructions = g_strdup_printf(_("Server Instructions: %s"), _(tmp)); |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1423 g_free(tmp); |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1424 } |
13573
0b2e4a5a8e79
[gaim-migrate @ 15952]
Richard Laager <rlaager@wiktel.com>
parents:
13571
diff
changeset
|
1425 } |
13616
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1426 |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1427 if(!instructions) |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1428 { |
11675 | 1429 instructions = g_strdup(_("Fill in one or more fields to search " |
13616
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1430 "for any matching Jabber users.")); |
ee7f92a706ac
[gaim-migrate @ 16002]
Richard Laager <rlaager@wiktel.com>
parents:
13573
diff
changeset
|
1431 } |
11675 | 1432 |
1433 if(xmlnode_get_child(query, "first")) { | |
1434 field = gaim_request_field_string_new("first", _("First Name"), | |
1435 NULL, FALSE); | |
1436 gaim_request_field_group_add_field(group, field); | |
1437 } | |
1438 if(xmlnode_get_child(query, "last")) { | |
1439 field = gaim_request_field_string_new("last", _("Last Name"), | |
1440 NULL, FALSE); | |
1441 gaim_request_field_group_add_field(group, field); | |
1442 } | |
1443 if(xmlnode_get_child(query, "nick")) { | |
1444 field = gaim_request_field_string_new("nick", _("Nickname"), | |
1445 NULL, FALSE); | |
1446 gaim_request_field_group_add_field(group, field); | |
1447 } | |
1448 if(xmlnode_get_child(query, "email")) { | |
1449 field = gaim_request_field_string_new("email", _("E-Mail Address"), | |
1450 NULL, FALSE); | |
1451 gaim_request_field_group_add_field(group, field); | |
1452 } | |
1453 | |
1454 usi = g_new0(struct user_search_info, 1); | |
1455 usi->js = js; | |
1456 usi->directory_server = g_strdup(from); | |
1457 | |
1458 gaim_request_fields(js->gc, _("Search for Jabber users"), | |
1459 _("Search for Jabber users"), instructions, fields, | |
1460 _("Search"), G_CALLBACK(user_search_cb), | |
1461 _("Cancel"), G_CALLBACK(user_search_cancel_cb), usi); | |
1462 | |
1463 g_free(instructions); | |
1464 } | |
1465 } | |
1466 | |
1467 static void jabber_user_search_ok(JabberStream *js, const char *directory) | |
1468 { | |
1469 JabberIq *iq; | |
1470 | |
1471 /* XXX: should probably better validate the directory we're given */ | |
1472 if(!directory || !*directory) { | |
1473 gaim_notify_error(js->gc, _("Invalid Directory"), _("Invalid Directory"), NULL); | |
1474 return; | |
1475 } | |
1476 | |
1477 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search"); | |
1478 xmlnode_set_attrib(iq->node, "to", directory); | |
1479 | |
1480 jabber_iq_set_callback(iq, user_search_fields_result_cb, NULL); | |
1481 | |
1482 jabber_iq_send(iq); | |
1483 } | |
1484 | |
1485 void jabber_user_search_begin(GaimPluginAction *action) | |
1486 { | |
1487 GaimConnection *gc = (GaimConnection *) action->context; | |
1488 JabberStream *js = gc->proto_data; | |
1489 | |
1490 gaim_request_input(gc, _("Enter a User Directory"), _("Enter a User Directory"), | |
1491 _("Select a user directory to search"), | |
1492 js->user_directories ? js->user_directories->data : "users.jabber.org", | |
1493 FALSE, FALSE, NULL, | |
1494 _("Search Directory"), GAIM_CALLBACK(jabber_user_search_ok), | |
1495 _("Cancel"), NULL, js); | |
1496 } |