Mercurial > pidgin
annotate src/protocols/jabber/buddy.c @ 10684:72a5babfa8b4
[gaim-migrate @ 12231]
the cipher api that grim has been working on for ages is finally done!! big
congrats and thanks to him!!
lots of modified files in this commit. it builds here.
moved the md5 files to src/protocols/oscar so that it continues to depend
on nothing in gaim. everything else uses the new centralized cipher api.
I'm not sure if src/md5.* needs to be removed or not, so I left it there.
someone let me know or do it directly.
someone check if these need to be added to potfiles.in
and let there be much rejoicing!
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Fri, 11 Mar 2005 13:05:31 +0000 |
parents | 54ac161a876e |
children | b256ce6b85b8 |
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" | |
36 | |
7116 | 37 void jabber_buddy_free(JabberBuddy *jb) |
38 { | |
39 g_return_if_fail(jb != NULL); | |
40 | |
41 if(jb->error_msg) | |
42 g_free(jb->error_msg); | |
43 while(jb->resources) | |
44 jabber_buddy_resource_free(jb->resources->data); | |
45 | |
46 g_free(jb); | |
47 } | |
48 | |
7014 | 49 JabberBuddy *jabber_buddy_find(JabberStream *js, const char *name, |
50 gboolean create) | |
51 { | |
52 JabberBuddy *jb; | |
7445 | 53 const char *realname; |
7014 | 54 |
7445 | 55 if(!(realname = jabber_normalize(js->gc->account, name))) |
7014 | 56 return NULL; |
57 | |
58 jb = g_hash_table_lookup(js->buddies, realname); | |
59 | |
60 if(!jb && create) { | |
61 jb = g_new0(JabberBuddy, 1); | |
62 g_hash_table_insert(js->buddies, g_strdup(realname), jb); | |
63 } | |
64 | |
65 return jb; | |
66 } | |
67 | |
68 | |
69 JabberBuddyResource *jabber_buddy_find_resource(JabberBuddy *jb, | |
70 const char *resource) | |
71 { | |
72 JabberBuddyResource *jbr = NULL; | |
73 GList *l; | |
74 | |
75 if(!jb) | |
76 return NULL; | |
77 | |
78 for(l = jb->resources; l; l = l->next) | |
79 { | |
80 if(!jbr && !resource) { | |
81 jbr = l->data; | |
82 } else if(!resource) { | |
83 if(((JabberBuddyResource *)l->data)->priority >= jbr->priority) | |
84 jbr = l->data; | |
85 } else if(((JabberBuddyResource *)l->data)->name) { | |
86 if(!strcmp(((JabberBuddyResource *)l->data)->name, resource)) { | |
87 jbr = l->data; | |
88 break; | |
89 } | |
90 } | |
91 } | |
92 | |
93 return jbr; | |
94 } | |
95 | |
9954 | 96 JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource, |
97 int priority, JabberBuddyState state, const char *status) | |
7014 | 98 { |
99 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); | |
100 | |
101 if(!jbr) { | |
102 jbr = g_new0(JabberBuddyResource, 1); | |
7116 | 103 jbr->jb = jb; |
7014 | 104 jbr->name = g_strdup(resource); |
105 jbr->capabilities = JABBER_CAP_XHTML; | |
106 jb->resources = g_list_append(jb->resources, jbr); | |
107 } | |
108 jbr->priority = priority; | |
109 jbr->state = state; | |
110 if(jbr->status) | |
111 g_free(jbr->status); | |
112 jbr->status = g_strdup(status); | |
9954 | 113 |
114 return jbr; | |
7014 | 115 } |
116 | |
7116 | 117 void jabber_buddy_resource_free(JabberBuddyResource *jbr) |
118 { | |
119 g_return_if_fail(jbr != NULL); | |
120 | |
121 jbr->jb->resources = g_list_remove(jbr->jb->resources, jbr); | |
122 | |
123 g_free(jbr->name); | |
124 if(jbr->status) | |
125 g_free(jbr->status); | |
8400 | 126 if(jbr->thread_id) |
127 g_free(jbr->thread_id); | |
7116 | 128 g_free(jbr); |
129 } | |
130 | |
7014 | 131 void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource) |
132 { | |
133 JabberBuddyResource *jbr = jabber_buddy_find_resource(jb, resource); | |
134 | |
135 if(!jbr) | |
136 return; | |
137 | |
7116 | 138 jabber_buddy_resource_free(jbr); |
7014 | 139 } |
140 | |
141 const char *jabber_buddy_get_status_msg(JabberBuddy *jb) | |
142 { | |
143 JabberBuddyResource *jbr; | |
144 | |
145 if(!jb) | |
146 return NULL; | |
147 | |
148 jbr = jabber_buddy_find_resource(jb, NULL); | |
149 | |
150 if(!jbr) | |
151 return NULL; | |
152 | |
153 return jbr->status; | |
154 } | |
155 | |
156 /******* | |
157 * This is the old vCard stuff taken from the old prpl. vCards, by definition | |
158 * are a temporary thing until jabber can get its act together and come up | |
159 * with a format for user information, hence the namespace of 'vcard-temp' | |
160 * | |
161 * Since I don't feel like putting that much work into something that's | |
162 * _supposed_ to go away, i'm going to just copy the kludgy old code here, | |
163 * and make it purdy when jabber comes up with a standards-track JEP to | |
164 * replace vcard-temp | |
165 * --Nathan | |
166 *******/ | |
167 | |
168 /*---------------------------------------*/ | |
169 /* Jabber "set info" (vCard) support */ | |
170 /*---------------------------------------*/ | |
171 | |
172 /* | |
173 * V-Card format: | |
174 * | |
175 * <vCard prodid='' version='' xmlns=''> | |
176 * <FN></FN> | |
177 * <N> | |
178 * <FAMILY/> | |
179 * <GIVEN/> | |
180 * </N> | |
181 * <NICKNAME/> | |
182 * <URL/> | |
183 * <ADR> | |
184 * <STREET/> | |
185 * <EXTADD/> | |
186 * <LOCALITY/> | |
187 * <REGION/> | |
188 * <PCODE/> | |
189 * <COUNTRY/> | |
190 * </ADR> | |
191 * <TEL/> | |
192 * <EMAIL/> | |
193 * <ORG> | |
194 * <ORGNAME/> | |
195 * <ORGUNIT/> | |
196 * </ORG> | |
197 * <TITLE/> | |
198 * <ROLE/> | |
199 * <DESC/> | |
200 * <BDAY/> | |
201 * </vCard> | |
202 * | |
203 * See also: | |
204 * | |
205 * http://docs.jabber.org/proto/html/vcard-temp.html | |
206 * http://www.vcard-xml.org/dtd/vCard-XML-v2-20010520.dtd | |
207 */ | |
208 | |
209 /* | |
210 * Cross-reference user-friendly V-Card entry labels to vCard XML tags | |
211 * and attributes. | |
212 * | |
213 * Order is (or should be) unimportant. For example: we have no way of | |
214 * knowing in what order real data will arrive. | |
215 * | |
216 * Format: Label, Pre-set text, "visible" flag, "editable" flag, XML tag | |
217 * name, XML tag's parent tag "path" (relative to vCard node). | |
218 * | |
219 * List is terminated by a NULL label pointer. | |
220 * | |
221 * Entries with no label text, but with XML tag and parent tag | |
222 * entries, are used by V-Card XML construction routines to | |
223 * "automagically" construct the appropriate XML node tree. | |
224 * | |
225 * Thoughts on future direction/expansion | |
226 * | |
227 * This is a "simple" vCard. | |
228 * | |
229 * It is possible for nodes other than the "vCard" node to have | |
230 * attributes. Should that prove necessary/desirable, add an | |
231 * "attributes" pointer to the vcard_template struct, create the | |
232 * necessary tag_attr structs, and add 'em to the vcard_dflt_data | |
233 * array. | |
234 * | |
235 * The above changes will (obviously) require changes to the vCard | |
236 * construction routines. | |
237 */ | |
238 | |
239 struct vcard_template { | |
240 char *label; /* label text pointer */ | |
241 char *text; /* entry text pointer */ | |
242 int visible; /* should entry field be "visible?" */ | |
243 int editable; /* should entry field be editable? */ | |
244 char *tag; /* tag text */ | |
245 char *ptag; /* parent tag "path" text */ | |
246 char *url; /* vCard display format if URL */ | |
247 } vcard_template_data[] = { | |
248 {N_("Full Name"), NULL, TRUE, TRUE, "FN", NULL, NULL}, | |
249 {N_("Family Name"), NULL, TRUE, TRUE, "FAMILY", "N", NULL}, | |
250 {N_("Given Name"), NULL, TRUE, TRUE, "GIVEN", "N", NULL}, | |
251 {N_("Nickname"), NULL, TRUE, TRUE, "NICKNAME", NULL, NULL}, | |
252 {N_("URL"), NULL, TRUE, TRUE, "URL", NULL, "<A HREF=\"%s\">%s</A>"}, | |
253 {N_("Street Address"), NULL, TRUE, TRUE, "STREET", "ADR", NULL}, | |
254 {N_("Extended Address"), NULL, TRUE, TRUE, "EXTADD", "ADR", NULL}, | |
255 {N_("Locality"), NULL, TRUE, TRUE, "LOCALITY", "ADR", NULL}, | |
256 {N_("Region"), NULL, TRUE, TRUE, "REGION", "ADR", NULL}, | |
257 {N_("Postal Code"), NULL, TRUE, TRUE, "PCODE", "ADR", NULL}, | |
258 {N_("Country"), NULL, TRUE, TRUE, "COUNTRY", "ADR", NULL}, | |
10215 | 259 {N_("Telephone"), NULL, TRUE, TRUE, "TEL", NULL, NULL}, |
7014 | 260 {N_("Email"), NULL, TRUE, TRUE, "EMAIL", NULL, "<A HREF=\"mailto:%s\">%s</A>"}, |
261 {N_("Organization Name"), NULL, TRUE, TRUE, "ORGNAME", "ORG", NULL}, | |
262 {N_("Organization Unit"), NULL, TRUE, TRUE, "ORGUNIT", "ORG", NULL}, | |
263 {N_("Title"), NULL, TRUE, TRUE, "TITLE", NULL, NULL}, | |
264 {N_("Role"), NULL, TRUE, TRUE, "ROLE", NULL, NULL}, | |
265 {N_("Birthday"), NULL, TRUE, TRUE, "BDAY", NULL, NULL}, | |
266 {N_("Description"), NULL, TRUE, TRUE, "DESC", NULL, NULL}, | |
267 {"", NULL, TRUE, TRUE, "N", NULL, NULL}, | |
268 {"", NULL, TRUE, TRUE, "ADR", NULL, NULL}, | |
269 {"", NULL, TRUE, TRUE, "ORG", NULL, NULL}, | |
270 {NULL, NULL, 0, 0, NULL, NULL, NULL} | |
271 }; | |
272 | |
273 /* | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
8401
diff
changeset
|
274 * The "vCard" tag's attribute list... |
7014 | 275 */ |
276 struct tag_attr { | |
277 char *attr; | |
278 char *value; | |
279 } vcard_tag_attr_list[] = { | |
280 {"prodid", "-//HandGen//NONSGML vGen v1.0//EN"}, | |
281 {"version", "2.0", }, | |
282 {"xmlns", "vcard-temp", }, | |
283 {NULL, NULL}, | |
284 }; | |
285 | |
286 | |
287 /* | |
288 * Insert a tag node into an xmlnode tree, recursively inserting parent tag | |
289 * nodes as necessary | |
290 * | |
291 * Returns pointer to inserted node | |
292 * | |
293 * Note to hackers: this code is designed to be re-entrant (it's recursive--it | |
294 * calls itself), so don't put any "static"s in here! | |
295 */ | |
296 static xmlnode *insert_tag_to_parent_tag(xmlnode *start, const char *parent_tag, const char *new_tag) | |
297 { | |
298 xmlnode *x = NULL; | |
299 | |
300 /* | |
301 * If the parent tag wasn't specified, see if we can get it | |
302 * from the vCard template struct. | |
303 */ | |
304 if(parent_tag == NULL) { | |
305 struct vcard_template *vc_tp = vcard_template_data; | |
306 | |
307 while(vc_tp->label != NULL) { | |
308 if(strcmp(vc_tp->tag, new_tag) == 0) { | |
309 parent_tag = vc_tp->ptag; | |
310 break; | |
311 } | |
312 ++vc_tp; | |
313 } | |
314 } | |
315 | |
316 /* | |
317 * If we have a parent tag... | |
318 */ | |
319 if(parent_tag != NULL ) { | |
320 /* | |
321 * Try to get the parent node for a tag | |
322 */ | |
323 if((x = xmlnode_get_child(start, parent_tag)) == NULL) { | |
324 /* | |
325 * Descend? | |
326 */ | |
327 char *grand_parent = g_strdup(parent_tag); | |
328 char *parent; | |
329 | |
330 if((parent = strrchr(grand_parent, '/')) != NULL) { | |
331 *(parent++) = '\0'; | |
332 x = insert_tag_to_parent_tag(start, grand_parent, parent); | |
333 } else { | |
334 x = xmlnode_new_child(start, grand_parent); | |
335 } | |
336 g_free(grand_parent); | |
337 } else { | |
338 /* | |
339 * We found *something* to be the parent node. | |
340 * Note: may be the "root" node! | |
341 */ | |
342 xmlnode *y; | |
343 if((y = xmlnode_get_child(x, new_tag)) != NULL) { | |
344 return(y); | |
345 } | |
346 } | |
347 } | |
348 | |
349 /* | |
350 * insert the new tag into its parent node | |
351 */ | |
352 return(xmlnode_new_child((x == NULL? start : x), new_tag)); | |
353 } | |
354 | |
355 /* | |
356 * Send vCard info to Jabber server | |
357 */ | |
358 void jabber_set_info(GaimConnection *gc, const char *info) | |
359 { | |
360 JabberIq *iq; | |
361 JabberStream *js = gc->proto_data; | |
362 xmlnode *vc_node; | |
10189 | 363 const char *avatar_file = NULL; |
7014 | 364 |
10189 | 365 if(js->avatar_hash) |
366 g_free(js->avatar_hash); | |
367 js->avatar_hash = NULL; | |
7014 | 368 |
369 /* | |
370 * Send only if there's actually any *information* to send | |
371 */ | |
372 vc_node = xmlnode_from_str(info, -1); | |
10189 | 373 avatar_file = gaim_account_get_buddy_icon(gc->account); |
374 | |
375 if(!vc_node && avatar_file) { | |
376 vc_node = xmlnode_new("vCard"); | |
377 } | |
7014 | 378 |
379 if(vc_node) { | |
380 if (vc_node->name && | |
10189 | 381 !g_ascii_strncasecmp(vc_node->name, "vCard", 5)) { |
382 GError *error = NULL; | |
10441 | 383 unsigned char *avatar_data; |
10189 | 384 gsize avatar_len; |
385 | |
10442 | 386 if(avatar_file && g_file_get_contents(avatar_file, (gchar **)&avatar_data, &avatar_len, &error)) { |
10189 | 387 xmlnode *photo; |
10441 | 388 unsigned char *enc; |
10189 | 389 int i; |
390 unsigned char hashval[20]; | |
391 char *p, hash[41]; | |
392 | |
393 photo = xmlnode_new_child(vc_node, "PHOTO"); | |
394 enc = gaim_base64_encode(avatar_data, avatar_len); | |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
395 |
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
396 gaim_cipher_digest_region("sha1", (guint8 *)avatar_data, |
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
397 avatar_len, hashval, NULL); |
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
398 |
10189 | 399 p = hash; |
400 for(i=0; i<20; i++, p+=2) | |
401 snprintf(p, 3, "%02x", hashval[i]); | |
402 js->avatar_hash = g_strdup(hash); | |
403 | |
404 xmlnode_insert_data(photo, enc, -1); | |
405 g_free(enc); | |
406 g_free(avatar_data); | |
10504 | 407 } else if (error != NULL) { |
10189 | 408 g_error_free(error); |
409 } | |
410 | |
7014 | 411 iq = jabber_iq_new(js, JABBER_IQ_SET); |
412 xmlnode_insert_child(iq->node, vc_node); | |
413 jabber_iq_send(iq); | |
414 } else { | |
415 xmlnode_free(vc_node); | |
416 } | |
417 } | |
418 } | |
419 | |
10189 | 420 void jabber_set_buddy_icon(GaimConnection *gc, const char *iconfile) |
421 { | |
422 GaimPresence *gpresence; | |
423 GaimStatus *status; | |
424 | |
425 jabber_set_info(gc, gaim_account_get_user_info(gc->account)); | |
426 | |
427 gpresence = gaim_account_get_presence(gc->account); | |
428 status = gaim_presence_get_active_status(gpresence); | |
10216 | 429 jabber_presence_send(gc->account, status); |
10189 | 430 } |
431 | |
7014 | 432 /* |
433 * This is the callback from the "ok clicked" for "set vCard" | |
434 * | |
435 * Formats GSList data into XML-encoded string and returns a pointer | |
436 * to said string. | |
437 * | |
438 * g_free()'ing the returned string space is the responsibility of | |
439 * the caller. | |
440 */ | |
441 static void | |
442 jabber_format_info(GaimConnection *gc, GaimRequestFields *fields) | |
443 { | |
444 GaimAccount *account; | |
445 xmlnode *vc_node; | |
446 GaimRequestField *field; | |
447 const char *text; | |
448 char *p; | |
449 const struct vcard_template *vc_tp; | |
450 struct tag_attr *tag_attr; | |
451 | |
452 vc_node = xmlnode_new("vCard"); | |
453 | |
454 for(tag_attr = vcard_tag_attr_list; tag_attr->attr != NULL; ++tag_attr) | |
455 xmlnode_set_attrib(vc_node, tag_attr->attr, tag_attr->value); | |
456 | |
457 for (vc_tp = vcard_template_data; vc_tp->label != NULL; vc_tp++) { | |
458 if (*vc_tp->label == '\0') | |
459 continue; | |
460 | |
461 field = gaim_request_fields_get_field(fields, vc_tp->tag); | |
462 text = gaim_request_field_string_get_value(field); | |
463 | |
464 | |
465 if (text != NULL && *text != '\0') { | |
466 xmlnode *xp; | |
467 | |
9339 | 468 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
469 "Setting %s to '%s'\n", vc_tp->tag, text); | |
470 | |
7014 | 471 if ((xp = insert_tag_to_parent_tag(vc_node, |
472 NULL, vc_tp->tag)) != NULL) { | |
473 | |
474 xmlnode_insert_data(xp, text, -1); | |
475 } | |
476 } | |
477 } | |
478 | |
7642 | 479 p = xmlnode_to_str(vc_node, NULL); |
7014 | 480 xmlnode_free(vc_node); |
481 | |
482 account = gaim_connection_get_account(gc); | |
483 | |
484 if (account != NULL) { | |
485 gaim_account_set_user_info(account, p); | |
486 | |
487 if (gc != NULL) | |
488 serv_set_info(gc, p); | |
489 } | |
490 | |
491 g_free(p); | |
492 } | |
493 | |
494 /* | |
495 * This gets executed by the proto action | |
496 * | |
497 * Creates a new GaimRequestFields struct, gets the XML-formatted user_info | |
498 * string (if any) into GSLists for the (multi-entry) edit dialog and | |
499 * calls the set_vcard dialog. | |
500 */ | |
9015 | 501 void jabber_setup_set_info(GaimPluginAction *action) |
7014 | 502 { |
9015 | 503 GaimConnection *gc = (GaimConnection *) action->context; |
7014 | 504 GaimRequestFields *fields; |
505 GaimRequestFieldGroup *group; | |
506 GaimRequestField *field; | |
507 const struct vcard_template *vc_tp; | |
508 char *user_info; | |
509 char *cdata; | |
510 xmlnode *x_vc_data = NULL; | |
511 | |
512 fields = gaim_request_fields_new(); | |
513 group = gaim_request_field_group_new(NULL); | |
514 gaim_request_fields_add_group(fields, group); | |
515 | |
516 /* | |
517 * Get existing, XML-formatted, user info | |
518 */ | |
519 if((user_info = g_strdup(gaim_account_get_user_info(gc->account))) != NULL) | |
520 x_vc_data = xmlnode_from_str(user_info, -1); | |
521 else | |
522 user_info = g_strdup(""); | |
523 | |
524 /* | |
525 * Set up GSLists for edit with labels from "template," data from user info | |
526 */ | |
527 for(vc_tp = vcard_template_data; vc_tp->label != NULL; ++vc_tp) { | |
528 xmlnode *data_node; | |
529 if((vc_tp->label)[0] == '\0') | |
530 continue; | |
531 if(vc_tp->ptag == NULL) { | |
532 data_node = xmlnode_get_child(x_vc_data, vc_tp->tag); | |
533 } else { | |
534 gchar *tag = g_strdup_printf("%s/%s", vc_tp->ptag, vc_tp->tag); | |
535 data_node = xmlnode_get_child(x_vc_data, tag); | |
536 g_free(tag); | |
537 } | |
538 if(data_node) | |
539 cdata = xmlnode_get_data(data_node); | |
540 else | |
541 cdata = NULL; | |
542 | |
543 if(strcmp(vc_tp->tag, "DESC") == 0) { | |
544 field = gaim_request_field_string_new(vc_tp->tag, | |
545 _(vc_tp->label), cdata, | |
546 TRUE); | |
547 } else { | |
548 field = gaim_request_field_string_new(vc_tp->tag, | |
549 _(vc_tp->label), cdata, | |
550 FALSE); | |
551 } | |
552 | |
553 gaim_request_field_group_add_field(group, field); | |
554 } | |
555 | |
556 if(x_vc_data != NULL) | |
557 xmlnode_free(x_vc_data); | |
558 | |
559 g_free(user_info); | |
560 | |
561 gaim_request_fields(gc, _("Edit Jabber vCard"), | |
562 _("Edit Jabber vCard"), | |
563 _("All items below are optional. Enter only the " | |
564 "information with which you feel comfortable."), | |
565 fields, | |
566 _("Save"), G_CALLBACK(jabber_format_info), | |
567 _("Cancel"), NULL, | |
568 gc); | |
569 } | |
570 | |
571 /*---------------------------------------*/ | |
572 /* End Jabber "set info" (vCard) support */ | |
573 /*---------------------------------------*/ | |
574 | |
575 /****** | |
576 * end of that ancient crap that needs to die | |
577 ******/ | |
578 | |
579 | |
7395 | 580 static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data) |
7014 | 581 { |
582 GList *resources; | |
583 const char *from = xmlnode_get_attrib(packet, "from"); | |
584 JabberBuddy *jb; | |
585 JabberBuddyResource *jbr; | |
586 GString *info_text; | |
7306 | 587 char *resource_name; |
7955 | 588 char *bare_jid; |
7014 | 589 char *title; |
8213 | 590 char *text; |
7014 | 591 xmlnode *vcard; |
7955 | 592 GaimBuddy *b; |
10189 | 593 GSList *imgids = NULL; |
7014 | 594 |
595 if(!from) | |
596 return; | |
597 | |
10490 | 598 /* XXX: handle the error case */ |
599 | |
7014 | 600 resource_name = jabber_get_resource(from); |
7955 | 601 bare_jid = jabber_get_bare_jid(from); |
602 | |
603 b = gaim_find_buddy(js->gc->account, bare_jid); | |
7014 | 604 |
605 jb = jabber_buddy_find(js, from, TRUE); | |
606 info_text = g_string_new(""); | |
607 | |
8213 | 608 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", _("Jabber ID"), |
7014 | 609 from); |
610 | |
611 if(resource_name) { | |
612 jbr = jabber_buddy_find_resource(jb, resource_name); | |
613 if(jbr) { | |
7145 | 614 char *purdy = NULL; |
615 if(jbr->status) | |
616 purdy = gaim_strdup_withhtml(jbr->status); | |
8213 | 617 g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/>", |
9954 | 618 _("Status"), jabber_buddy_state_get_name(jbr->state), |
7014 | 619 purdy ? ": " : "", |
620 purdy ? purdy : ""); | |
7145 | 621 if(purdy) |
622 g_free(purdy); | |
7014 | 623 } else { |
8213 | 624 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 625 _("Status"), _("Unknown")); |
626 } | |
627 } else { | |
628 for(resources = jb->resources; resources; resources = resources->next) { | |
7145 | 629 char *purdy = NULL; |
7014 | 630 jbr = resources->data; |
7145 | 631 if(jbr->status) |
632 purdy = gaim_strdup_withhtml(jbr->status); | |
8213 | 633 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 634 _("Resource"), jbr->name); |
8213 | 635 g_string_append_printf(info_text, "<b>%s:</b> %s%s%s<br/><br/>", |
9954 | 636 _("Status"), jabber_buddy_state_get_name(jbr->state), |
7014 | 637 purdy ? ": " : "", |
638 purdy ? purdy : ""); | |
7145 | 639 if(purdy) |
640 g_free(purdy); | |
7014 | 641 } |
642 } | |
643 | |
7306 | 644 g_free(resource_name); |
645 | |
10189 | 646 if((vcard = xmlnode_get_child(packet, "vCard")) || |
647 (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) { | |
7014 | 648 xmlnode *child; |
649 for(child = vcard->child; child; child = child->next) | |
650 { | |
651 xmlnode *child2; | |
652 | |
8135 | 653 if(child->type != XMLNODE_TYPE_TAG) |
7014 | 654 continue; |
655 | |
656 text = xmlnode_get_data(child); | |
657 if(text && !strcmp(child->name, "FN")) { | |
8213 | 658 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 659 _("Full Name"), text); |
660 } else if(!strcmp(child->name, "N")) { | |
661 for(child2 = child->child; child2; child2 = child2->next) | |
662 { | |
663 char *text2; | |
664 | |
8135 | 665 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 666 continue; |
667 | |
668 text2 = xmlnode_get_data(child2); | |
669 if(text2 && !strcmp(child2->name, "FAMILY")) { | |
670 g_string_append_printf(info_text, | |
8213 | 671 "<b>%s:</b> %s<br/>", |
7014 | 672 _("Family Name"), text2); |
673 } else if(text2 && !strcmp(child2->name, "GIVEN")) { | |
674 g_string_append_printf(info_text, | |
8213 | 675 "<b>%s:</b> %s<br/>", |
7014 | 676 _("Given Name"), text2); |
677 } else if(text2 && !strcmp(child2->name, "MIDDLE")) { | |
678 g_string_append_printf(info_text, | |
8213 | 679 "<b>%s:</b> %s<br/>", |
7014 | 680 _("Middle Name"), text2); |
681 } | |
682 g_free(text2); | |
683 } | |
684 } else if(text && !strcmp(child->name, "NICKNAME")) { | |
685 serv_got_alias(js->gc, from, text); | |
7955 | 686 if(b) { |
687 gaim_blist_node_set_string((GaimBlistNode*)b, "servernick", text); | |
688 } | |
8213 | 689 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 690 _("Nickname"), text); |
691 } else if(text && !strcmp(child->name, "BDAY")) { | |
8213 | 692 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 693 _("Birthday"), text); |
694 } else if(!strcmp(child->name, "ADR")) { | |
695 /* show which address it is */ | |
696 if(child->child) | |
8213 | 697 g_string_append_printf(info_text, "<b>%s:</b><br/>", |
7014 | 698 _("Address")); |
699 for(child2 = child->child; child2; child2 = child2->next) | |
700 { | |
701 char *text2; | |
702 | |
8135 | 703 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 704 continue; |
705 | |
706 text2 = xmlnode_get_data(child2); | |
707 if(text2 && !strcmp(child2->name, "POBOX")) { | |
708 g_string_append_printf(info_text, | |
8213 | 709 " <b>%s:</b> %s<br/>", |
7014 | 710 _("P.O. Box"), text2); |
711 } else if(text2 && !strcmp(child2->name, "EXTADR")) { | |
712 g_string_append_printf(info_text, | |
8213 | 713 " <b>%s:</b> %s<br/>", |
7014 | 714 _("Extended Address"), text2); |
715 } else if(text2 && !strcmp(child2->name, "STREET")) { | |
716 g_string_append_printf(info_text, | |
8213 | 717 " <b>%s:</b> %s<br/>", |
7014 | 718 _("Street Address"), text2); |
719 } else if(text2 && !strcmp(child2->name, "LOCALITY")) { | |
720 g_string_append_printf(info_text, | |
8213 | 721 " <b>%s:</b> %s<br/>", |
7014 | 722 _("Locality"), text2); |
723 } else if(text2 && !strcmp(child2->name, "REGION")) { | |
724 g_string_append_printf(info_text, | |
8213 | 725 " <b>%s:</b> %s<br/>", |
7014 | 726 _("Region"), text2); |
727 } else if(text2 && !strcmp(child2->name, "PCODE")) { | |
728 g_string_append_printf(info_text, | |
8213 | 729 " <b>%s:</b> %s<br/>", |
7014 | 730 _("Postal Code"), text2); |
731 } else if(text2 && (!strcmp(child2->name, "CTRY") | |
732 || !strcmp(child2->name, "COUNTRY"))) { | |
733 g_string_append_printf(info_text, | |
8213 | 734 " <b>%s:</b> %s<br/>", |
7014 | 735 _("Country"), text2); |
736 } | |
737 g_free(text2); | |
738 } | |
739 } else if(!strcmp(child->name, "TEL")) { | |
740 char *number; | |
741 if((child2 = xmlnode_get_child(child, "NUMBER"))) { | |
742 /* show what kind of number it is */ | |
743 number = xmlnode_get_data(child2); | |
744 if(number) { | |
745 g_string_append_printf(info_text, | |
8213 | 746 "<b>%s:</b> %s<br/>", _("Telephone"), number); |
7014 | 747 g_free(number); |
748 } | |
749 } else if((number = xmlnode_get_data(child))) { | |
750 /* lots of clients (including gaim) do this, but it's | |
751 * out of spec */ | |
752 g_string_append_printf(info_text, | |
8213 | 753 "<b>%s:</b> %s<br/>", _("Telephone"), number); |
7014 | 754 g_free(number); |
755 } | |
756 } else if(!strcmp(child->name, "EMAIL")) { | |
757 char *userid; | |
758 if((child2 = xmlnode_get_child(child, "USERID"))) { | |
759 /* show what kind of email it is */ | |
760 userid = xmlnode_get_data(child2); | |
761 if(userid) { | |
762 g_string_append_printf(info_text, | |
8213 | 763 "<b>%s:</b> <a href='mailto:%s'>%s</a><br/>", |
7014 | 764 _("Email"), userid, userid); |
765 g_free(userid); | |
766 } | |
767 } else if((userid = 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> <a href='mailto:%s'>%s</a><br/>", |
7014 | 772 _("Email"), userid, userid); |
773 g_free(userid); | |
774 } | |
775 } else if(!strcmp(child->name, "ORG")) { | |
776 for(child2 = child->child; child2; child2 = child2->next) | |
777 { | |
778 char *text2; | |
779 | |
8135 | 780 if(child2->type != XMLNODE_TYPE_TAG) |
7014 | 781 continue; |
782 | |
783 text2 = xmlnode_get_data(child2); | |
784 if(text2 && !strcmp(child2->name, "ORGNAME")) { | |
785 g_string_append_printf(info_text, | |
8213 | 786 "<b>%s:</b> %s<br/>", |
7014 | 787 _("Organization Name"), text2); |
788 } else if(text2 && !strcmp(child2->name, "ORGUNIT")) { | |
789 g_string_append_printf(info_text, | |
8213 | 790 "<b>%s:</b> %s<br/>", |
7014 | 791 _("Organization Unit"), text2); |
792 } | |
793 g_free(text2); | |
794 } | |
795 } else if(text && !strcmp(child->name, "TITLE")) { | |
8213 | 796 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 797 _("Title"), text); |
798 } else if(text && !strcmp(child->name, "ROLE")) { | |
8213 | 799 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
7014 | 800 _("Role"), text); |
801 } else if(text && !strcmp(child->name, "DESC")) { | |
8213 | 802 g_string_append_printf(info_text, "<b>%s:</b> %s<br/>", |
803 _("Description"), text); | |
7076 | 804 } else if(!strcmp(child->name, "PHOTO") || |
805 !strcmp(child->name, "LOGO")) { | |
10189 | 806 int size, i; |
807 unsigned char hashval[20]; | |
808 char *data, *p, hash[41]; | |
809 gboolean photo = (strcmp(child->name, "PHOTO") == 0); | |
810 | |
811 gaim_base64_decode(text, &data, &size); | |
7076 | 812 |
10189 | 813 imgids = g_slist_prepend(imgids, GINT_TO_POINTER(gaim_imgstore_add(data, size, "logo.png"))); |
814 g_string_append_printf(info_text, | |
815 "<b>%s:</b> <img id='%d'><br/>", | |
816 photo ? _("Photo") : _("Logo"), | |
817 GPOINTER_TO_INT(imgids->data)); | |
7076 | 818 |
10189 | 819 gaim_buddy_icons_set_for_user(js->gc->account, bare_jid, |
820 data, size); | |
821 | |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
822 gaim_cipher_digest_region("sha1", (guint8 *)data, size, |
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10662
diff
changeset
|
823 hashval, NULL); |
10189 | 824 p = hash; |
825 for(i=0; i<20; i++, p+=2) | |
826 snprintf(p, 3, "%02x", hashval[i]); | |
827 gaim_blist_node_set_string((GaimBlistNode*)b, "avatar_hash", hash); | |
828 | |
829 g_free(data); | |
7014 | 830 } |
831 g_free(text); | |
832 } | |
833 } | |
834 | |
835 title = g_strdup_printf("User info for %s", from); | |
836 | |
8213 | 837 text = gaim_strdup_withhtml(info_text->str); |
838 | |
9797 | 839 gaim_notify_userinfo(js->gc, from, title, _("Jabber Profile"), |
8213 | 840 NULL, text, NULL, NULL); |
7014 | 841 |
10189 | 842 while(imgids) { |
843 gaim_imgstore_unref(GPOINTER_TO_INT(imgids->data)); | |
844 imgids = g_slist_delete_link(imgids, imgids); | |
845 } | |
7014 | 846 g_free(title); |
847 g_string_free(info_text, TRUE); | |
8213 | 848 g_free(text); |
10189 | 849 g_free(bare_jid); |
7014 | 850 } |
851 | |
10189 | 852 static void jabber_buddy_get_info_for_jid(JabberStream *js, const char *full_jid) |
7014 | 853 { |
854 JabberIq *iq; | |
855 xmlnode *vcard; | |
856 | |
857 iq = jabber_iq_new(js, JABBER_IQ_GET); | |
858 | |
10189 | 859 xmlnode_set_attrib(iq->node, "to", full_jid); |
7014 | 860 vcard = xmlnode_new_child(iq->node, "vCard"); |
861 xmlnode_set_attrib(vcard, "xmlns", "vcard-temp"); | |
862 | |
7395 | 863 jabber_iq_set_callback(iq, jabber_vcard_parse, NULL); |
7014 | 864 |
865 jabber_iq_send(iq); | |
866 } | |
867 | |
10189 | 868 void jabber_buddy_get_info(GaimConnection *gc, const char *who) |
869 { | |
870 JabberStream *js = gc->proto_data; | |
871 char *bare_jid = jabber_get_bare_jid(who); | |
872 | |
873 if(bare_jid) { | |
874 jabber_buddy_get_info_for_jid(js, bare_jid); | |
875 g_free(bare_jid); | |
876 } | |
877 } | |
878 | |
7014 | 879 void jabber_buddy_get_info_chat(GaimConnection *gc, int id, |
880 const char *resource) | |
881 { | |
882 JabberStream *js = gc->proto_data; | |
883 JabberChat *chat = jabber_chat_find_by_id(js, id); | |
884 char *full_jid; | |
885 | |
886 if(!chat) | |
887 return; | |
888 | |
889 full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, resource); | |
10189 | 890 jabber_buddy_get_info_for_jid(js, full_jid); |
7014 | 891 g_free(full_jid); |
892 } | |
893 | |
7395 | 894 |
7014 | 895 static void jabber_buddy_set_invisibility(JabberStream *js, const char *who, |
896 gboolean invisible) | |
897 { | |
9944 | 898 GaimPresence *gpresence; |
899 GaimAccount *account; | |
900 GaimStatus *status; | |
7014 | 901 JabberBuddy *jb = jabber_buddy_find(js, who, TRUE); |
902 xmlnode *presence; | |
9954 | 903 JabberBuddyState state; |
904 const char *msg; | |
905 int priority; | |
7014 | 906 |
9944 | 907 account = gaim_connection_get_account(js->gc); |
908 gpresence = gaim_account_get_presence(account); | |
909 status = gaim_presence_get_active_status(gpresence); | |
910 | |
9954 | 911 gaim_status_to_jabber(status, &state, &msg, &priority); |
912 presence = jabber_presence_create(state, msg, priority); | |
913 | |
7014 | 914 xmlnode_set_attrib(presence, "to", who); |
915 if(invisible) { | |
916 xmlnode_set_attrib(presence, "type", "invisible"); | |
917 jb->invisible |= JABBER_INVIS_BUDDY; | |
918 } else { | |
919 jb->invisible &= ~JABBER_INVIS_BUDDY; | |
920 } | |
921 | |
922 jabber_send(js, presence); | |
923 xmlnode_free(presence); | |
924 } | |
925 | |
9030 | 926 static void jabber_buddy_make_invisible(GaimBlistNode *node, gpointer data) |
7014 | 927 { |
9030 | 928 GaimBuddy *buddy; |
929 GaimConnection *gc; | |
930 JabberStream *js; | |
931 | |
932 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
933 | |
934 buddy = (GaimBuddy *) node; | |
935 gc = gaim_account_get_connection(buddy->account); | |
936 js = gc->proto_data; | |
937 | |
938 jabber_buddy_set_invisibility(js, buddy->name, TRUE); | |
7014 | 939 } |
940 | |
9030 | 941 static void jabber_buddy_make_visible(GaimBlistNode *node, gpointer data) |
7014 | 942 { |
9030 | 943 GaimBuddy *buddy; |
944 GaimConnection *gc; | |
945 JabberStream *js; | |
7014 | 946 |
9030 | 947 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); |
7014 | 948 |
9030 | 949 buddy = (GaimBuddy *) node; |
950 gc = gaim_account_get_connection(buddy->account); | |
951 js = gc->proto_data; | |
952 | |
953 jabber_buddy_set_invisibility(js, buddy->name, FALSE); | |
7014 | 954 } |
955 | |
9030 | 956 static void jabber_buddy_cancel_presence_notification(GaimBlistNode *node, |
957 gpointer data) | |
7014 | 958 { |
9030 | 959 GaimBuddy *buddy; |
960 GaimConnection *gc; | |
961 JabberStream *js; | |
962 | |
963 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
7014 | 964 |
9030 | 965 buddy = (GaimBuddy *) node; |
966 gc = gaim_account_get_connection(buddy->account); | |
967 js = gc->proto_data; | |
968 | |
969 /* I wonder if we should prompt the user before doing this */ | |
970 jabber_presence_subscription_set(js, buddy->name, "unsubscribed"); | |
7014 | 971 } |
972 | |
9030 | 973 static void jabber_buddy_rerequest_auth(GaimBlistNode *node, gpointer data) |
7250 | 974 { |
9030 | 975 GaimBuddy *buddy; |
976 GaimConnection *gc; | |
977 JabberStream *js; | |
978 | |
979 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
7250 | 980 |
9030 | 981 buddy = (GaimBuddy *) node; |
982 gc = gaim_account_get_connection(buddy->account); | |
983 js = gc->proto_data; | |
984 | |
985 jabber_presence_subscription_set(js, buddy->name, "subscribe"); | |
7250 | 986 } |
987 | |
9030 | 988 |
989 static void jabber_buddy_unsubscribe(GaimBlistNode *node, gpointer data) | |
7014 | 990 { |
9030 | 991 GaimBuddy *buddy; |
992 GaimConnection *gc; | |
993 JabberStream *js; | |
994 | |
995 g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); | |
996 | |
997 buddy = (GaimBuddy *) node; | |
998 gc = gaim_account_get_connection(buddy->account); | |
999 js = gc->proto_data; | |
1000 | |
1001 jabber_presence_subscription_set(js, buddy->name, "unsubscribe"); | |
1002 } | |
1003 | |
1004 | |
1005 GList *jabber_buddy_menu(GaimBuddy *buddy) | |
1006 { | |
1007 GaimConnection *gc = gaim_account_get_connection(buddy->account); | |
1008 JabberStream *js = gc->proto_data; | |
1009 JabberBuddy *jb = jabber_buddy_find(js, buddy->name, TRUE); | |
1010 | |
7014 | 1011 GList *m = NULL; |
9030 | 1012 GaimBlistNodeAction *act; |
7395 | 1013 |
1014 if(!jb) | |
1015 return m; | |
1016 | |
8185 | 1017 /* XXX: fix the NOT ME below */ |
1018 | |
1019 if(js->protocol_version == JABBER_PROTO_0_9 /* && NOT ME */) { | |
8166 | 1020 if(jb->invisible & JABBER_INVIS_BUDDY) { |
9030 | 1021 act = gaim_blist_node_action_new(_("Un-hide From"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10504
diff
changeset
|
1022 jabber_buddy_make_visible, NULL, NULL); |
8166 | 1023 } else { |
9030 | 1024 act = gaim_blist_node_action_new(_("Temporarily Hide From"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10504
diff
changeset
|
1025 jabber_buddy_make_invisible, NULL, NULL); |
8166 | 1026 } |
9030 | 1027 m = g_list_append(m, act); |
7014 | 1028 } |
1029 | |
8185 | 1030 if(jb->subscription & JABBER_SUB_FROM /* && NOT ME */) { |
9030 | 1031 act = gaim_blist_node_action_new(_("Cancel Presence Notification"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10504
diff
changeset
|
1032 jabber_buddy_cancel_presence_notification, NULL, NULL); |
9030 | 1033 m = g_list_append(m, act); |
7014 | 1034 } |
1035 | |
1036 if(!(jb->subscription & JABBER_SUB_TO)) { | |
9030 | 1037 act = gaim_blist_node_action_new(_("(Re-)Request authorization"), |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10504
diff
changeset
|
1038 jabber_buddy_rerequest_auth, NULL, NULL); |
9030 | 1039 m = g_list_append(m, act); |
1040 | |
8185 | 1041 } else /* if(NOT ME) */{ |
9030 | 1042 |
1043 /* shouldn't this just happen automatically when the buddy is | |
1044 removed? */ | |
1045 act = gaim_blist_node_action_new(_("Unsubscribe"), | |
10662
54ac161a876e
[gaim-migrate @ 12199]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10504
diff
changeset
|
1046 jabber_buddy_unsubscribe, NULL, NULL); |
9030 | 1047 m = g_list_append(m, act); |
7014 | 1048 } |
1049 | |
1050 return m; | |
1051 } | |
9030 | 1052 |
1053 GList * | |
1054 jabber_blist_node_menu(GaimBlistNode *node) | |
1055 { | |
1056 if(GAIM_BLIST_NODE_IS_BUDDY(node)) { | |
1057 return jabber_buddy_menu((GaimBuddy *) node); | |
1058 } else { | |
1059 return NULL; | |
1060 } | |
1061 } | |
1062 | |
1063 | |
9954 | 1064 const char * |
1065 jabber_buddy_state_get_name(JabberBuddyState state) | |
1066 { | |
1067 switch(state) { | |
1068 case JABBER_BUDDY_STATE_UNKNOWN: | |
1069 return _("Unknown"); | |
1070 case JABBER_BUDDY_STATE_ERROR: | |
1071 return _("Error"); | |
1072 case JABBER_BUDDY_STATE_UNAVAILABLE: | |
1073 return _("Offline"); | |
1074 case JABBER_BUDDY_STATE_ONLINE: | |
1075 return _("Online"); | |
1076 case JABBER_BUDDY_STATE_CHAT: | |
1077 return _("Chatty"); | |
1078 case JABBER_BUDDY_STATE_AWAY: | |
1079 return _("Away"); | |
1080 case JABBER_BUDDY_STATE_XA: | |
1081 return _("Extended Away"); | |
1082 case JABBER_BUDDY_STATE_DND: | |
1083 return _("Do Not Disturb"); | |
1084 } | |
1085 | |
1086 return _("Unknown"); | |
1087 } | |
1088 | |
1089 JabberBuddyState jabber_buddy_status_id_get_state(const char *id) { | |
1090 if(!id) | |
1091 return JABBER_BUDDY_STATE_UNKNOWN; | |
1092 if(!strcmp(id, "online")) | |
1093 return JABBER_BUDDY_STATE_ONLINE; | |
1094 if(!strcmp(id, "chat")) | |
1095 return JABBER_BUDDY_STATE_CHAT; | |
1096 if(!strcmp(id, "away")) | |
1097 return JABBER_BUDDY_STATE_AWAY; | |
1098 if(!strcmp(id, "xa")) | |
1099 return JABBER_BUDDY_STATE_XA; | |
1100 if(!strcmp(id, "dnd")) | |
1101 return JABBER_BUDDY_STATE_DND; | |
1102 if(!strcmp(id, "offline")) | |
1103 return JABBER_BUDDY_STATE_UNAVAILABLE; | |
1104 if(!strcmp(id, "error")) | |
1105 return JABBER_BUDDY_STATE_ERROR; | |
1106 | |
1107 return JABBER_BUDDY_STATE_UNKNOWN; | |
1108 } | |
1109 | |
1110 const char *jabber_buddy_state_get_status_id(JabberBuddyState state) { | |
1111 switch(state) { | |
1112 case JABBER_BUDDY_STATE_CHAT: | |
1113 return "chat"; | |
1114 case JABBER_BUDDY_STATE_AWAY: | |
1115 return "away"; | |
1116 case JABBER_BUDDY_STATE_XA: | |
1117 return "xa"; | |
1118 case JABBER_BUDDY_STATE_DND: | |
1119 return "dnd"; | |
1120 case JABBER_BUDDY_STATE_ONLINE: | |
1121 return "online"; | |
1122 case JABBER_BUDDY_STATE_UNKNOWN: | |
1123 case JABBER_BUDDY_STATE_ERROR: | |
1124 return NULL; | |
1125 case JABBER_BUDDY_STATE_UNAVAILABLE: | |
1126 return "offline"; | |
1127 } | |
1128 return NULL; | |
1129 } |