buddy: fix typo in process_get_info_response()
[siplcs.git] / src / core / sipe-buddy.c
blob2331815bacc74e12acc3a69820c3fcc1e379de63
1 /**
2 * @file sipe-buddy.c
4 * pidgin-sipe
6 * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include <string.h>
28 #include <time.h>
30 #include <glib.h>
32 #include "sipe-common.h"
33 #include "http-conn.h" /* sipe-cal.h requires this */
34 #include "sipmsg.h"
35 #include "sip-csta.h"
36 #include "sip-soap.h"
37 #include "sip-transport.h"
38 #include "sipe-backend.h"
39 #include "sipe-buddy.h"
40 #include "sipe-cal.h"
41 #include "sipe-core.h"
42 #include "sipe-core-private.h"
43 #include "sipe-group.h"
44 #include "sipe-nls.h"
45 #include "sipe-ocs2007.h"
46 #include "sipe-schedule.h"
47 #include "sipe-subscriptions.h"
48 #include "sipe-utils.h"
49 #include "sipe-xml.h"
50 #include "sipe.h"
52 static void buddy_free(struct sipe_buddy *buddy)
54 #ifndef _WIN32
56 * We are calling g_hash_table_foreach_steal(). That means that no
57 * key/value deallocation functions are called. Therefore the glib
58 * hash code does not touch the key (buddy->name) or value (buddy)
59 * of the to-be-deleted hash node at all. It follows that we
61 * - MUST free the memory for the key ourselves and
62 * - ARE allowed to do it in this function
64 * Conclusion: glib must be broken on the Windows platform if sipe
65 * crashes with SIGTRAP when closing. You'll have to live
66 * with the memory leak until this is fixed.
68 g_free(buddy->name);
69 #endif
70 g_free(buddy->activity);
71 g_free(buddy->meeting_subject);
72 g_free(buddy->meeting_location);
73 g_free(buddy->note);
75 g_free(buddy->cal_start_time);
76 g_free(buddy->cal_free_busy_base64);
77 g_free(buddy->cal_free_busy);
78 g_free(buddy->last_non_cal_activity);
80 sipe_cal_free_working_hours(buddy->cal_working_hours);
82 g_free(buddy->device_name);
83 g_slist_free(buddy->groups);
84 g_free(buddy);
87 static gboolean buddy_free_cb(SIPE_UNUSED_PARAMETER gpointer key,
88 gpointer buddy,
89 SIPE_UNUSED_PARAMETER gpointer user_data)
91 buddy_free(buddy);
92 /* We must return TRUE as the key/value have already been deleted */
93 return(TRUE);
96 void sipe_buddy_free_all(struct sipe_core_private *sipe_private)
98 g_hash_table_foreach_steal(sipe_private->buddies,
99 buddy_free_cb,
100 NULL);
103 gchar *sipe_core_buddy_status(struct sipe_core_public *sipe_public,
104 const gchar *name,
105 const sipe_activity activity,
106 const gchar *status_text)
108 struct sipe_buddy *sbuddy;
109 const char *activity_str;
111 if (!sipe_public) return NULL; /* happens on pidgin exit */
113 sbuddy = g_hash_table_lookup(SIPE_CORE_PRIVATE->buddies, name);
114 if (!sbuddy) return NULL;
116 activity_str = sbuddy->activity ? sbuddy->activity :
117 (activity == SIPE_ACTIVITY_BUSY) || (activity == SIPE_ACTIVITY_BRB) ?
118 status_text : NULL;
120 if (activity_str && sbuddy->note) {
121 return g_strdup_printf("%s - <i>%s</i>", activity_str, sbuddy->note);
122 } else if (activity_str) {
123 return g_strdup(activity_str);
124 } else if (sbuddy->note) {
125 return g_strdup_printf("<i>%s</i>", sbuddy->note);
126 } else {
127 return NULL;
131 gchar *sipe_buddy_get_alias(struct sipe_core_private *sipe_private,
132 const gchar *with)
134 sipe_backend_buddy pbuddy;
135 gchar *alias = NULL;
136 if ((pbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, with, NULL))) {
137 alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, pbuddy);
139 return alias;
142 void sipe_core_buddy_group(struct sipe_core_public *sipe_public,
143 const gchar *who,
144 const gchar *old_group_name,
145 const gchar *new_group_name)
147 struct sipe_buddy * buddy = g_hash_table_lookup(SIPE_CORE_PRIVATE->buddies, who);
148 struct sipe_group * old_group = NULL;
149 struct sipe_group * new_group;
151 SIPE_DEBUG_INFO("sipe_core_buddy_group: who:%s old_group_name:%s new_group_name:%s",
152 who ? who : "", old_group_name ? old_group_name : "", new_group_name ? new_group_name : "");
154 if(!buddy) { // buddy not in roaming list
155 return;
158 if (old_group_name) {
159 old_group = sipe_group_find_by_name(SIPE_CORE_PRIVATE, old_group_name);
161 new_group = sipe_group_find_by_name(SIPE_CORE_PRIVATE, new_group_name);
163 if (old_group) {
164 buddy->groups = g_slist_remove(buddy->groups, old_group);
165 SIPE_DEBUG_INFO("sipe_core_buddy_group: buddy %s removed from old group %s", who, old_group_name);
168 if (!new_group) {
169 sipe_group_create(SIPE_CORE_PRIVATE, new_group_name, who);
170 } else {
171 buddy->groups = slist_insert_unique_sorted(buddy->groups, new_group, (GCompareFunc)sipe_group_compare);
172 sipe_core_group_set_user(sipe_public, who);
176 void sipe_core_buddy_add(struct sipe_core_public *sipe_public,
177 const gchar *name,
178 const gchar *group_name)
180 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
182 if (!g_hash_table_lookup(sipe_private->buddies, name)) {
183 struct sipe_buddy *b = g_new0(struct sipe_buddy, 1);
185 SIPE_DEBUG_INFO("sipe_core_buddy_add: %s", name);
187 b->name = g_strdup(name);
188 b->just_added = TRUE;
189 g_hash_table_insert(sipe_private->buddies, b->name, b);
191 /* @TODO should go to callback */
192 sipe_subscribe_presence_single(sipe_private, b->name);
194 } else {
195 SIPE_DEBUG_INFO("sipe_core_buddy_add: buddy %s already in internal list",
196 name);
199 sipe_core_buddy_group(SIPE_CORE_PUBLIC,
200 name,
201 NULL,
202 group_name);
206 * Unassociates buddy from group first.
207 * Then see if no groups left, removes buddy completely.
208 * Otherwise updates buddy groups on server.
210 void sipe_core_buddy_remove(struct sipe_core_public *sipe_public,
211 const gchar *name,
212 const gchar *group_name)
214 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
215 struct sipe_buddy *b = g_hash_table_lookup(sipe_private->buddies,
216 name);
218 if (!b) return;
220 if (group_name) {
221 struct sipe_group *g = sipe_group_find_by_name(sipe_private,
222 group_name);
223 if (g) {
224 b->groups = g_slist_remove(b->groups, g);
225 SIPE_DEBUG_INFO("sipe_core_buddy_remove: buddy %s removed from group %s",
226 name, g->name);
230 if (g_slist_length(b->groups) < 1) {
231 gchar *action_name = sipe_utils_presence_key(name);
232 sipe_schedule_cancel(sipe_private, action_name);
233 g_free(action_name);
235 g_hash_table_remove(sipe_private->buddies, name);
237 if (b->name) {
238 gchar *request = g_strdup_printf("<m:URI>%s</m:URI>",
239 b->name);
240 sip_soap_request(sipe_private,
241 "deleteContact",
242 request);
243 g_free(request);
246 buddy_free(b);
247 } else {
248 /* updates groups on server */
249 sipe_core_group_set_user(SIPE_CORE_PUBLIC, b->name);
254 void sipe_core_buddy_got_status(struct sipe_core_public *sipe_public,
255 const gchar* uri,
256 const gchar *status_id)
258 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
259 struct sipe_buddy *sbuddy = g_hash_table_lookup(sipe_private->buddies,
260 uri);
262 if (!sbuddy) return;
264 /* Check if on 2005 system contact's calendar,
265 * then set/preserve it.
267 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
268 sipe_backend_buddy_set_status(sipe_public, uri, status_id);
269 } else {
270 sipe_apply_calendar_status(sipe_private, sbuddy, status_id);
274 GSList *sipe_core_buddy_info(struct sipe_core_public *sipe_public,
275 const gchar *name,
276 const gchar *status_name,
277 gboolean is_online)
279 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
280 gchar *note = NULL;
281 gboolean is_oof_note = FALSE;
282 const gchar *activity = NULL;
283 gchar *calendar = NULL;
284 const gchar *meeting_subject = NULL;
285 const gchar *meeting_location = NULL;
286 gchar *access_text = NULL;
287 GSList *info = NULL;
289 #define SIPE_ADD_BUDDY_INFO_COMMON(l, t) \
291 struct sipe_buddy_info *sbi = g_malloc(sizeof(struct sipe_buddy_info)); \
292 sbi->label = (l); \
293 sbi->text = (t); \
294 info = g_slist_append(info, sbi); \
296 #define SIPE_ADD_BUDDY_INFO(l, t) SIPE_ADD_BUDDY_INFO_COMMON((l), g_markup_escape_text((t), -1))
297 #define SIPE_ADD_BUDDY_INFO_NOESCAPE(l, t) SIPE_ADD_BUDDY_INFO_COMMON((l), (t))
299 if (sipe_public) { //happens on pidgin exit
300 struct sipe_buddy *sbuddy = g_hash_table_lookup(sipe_private->buddies, name);
301 if (sbuddy) {
302 note = sbuddy->note;
303 is_oof_note = sbuddy->is_oof_note;
304 activity = sbuddy->activity;
305 calendar = sipe_cal_get_description(sbuddy);
306 meeting_subject = sbuddy->meeting_subject;
307 meeting_location = sbuddy->meeting_location;
309 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
310 gboolean is_group_access = FALSE;
311 const int container_id = sipe_ocs2007_find_access_level(sipe_private, "user", sipe_get_no_sip_uri(name), &is_group_access);
312 const char *access_level = sipe_ocs2007_access_level_name(container_id);
313 access_text = is_group_access ?
314 g_strdup(access_level) :
315 g_strdup_printf(SIPE_OCS2007_INDENT_MARKED_FMT,
316 access_level);
320 if (is_online)
322 const gchar *status_str = activity ? activity : status_name;
324 SIPE_ADD_BUDDY_INFO(_("Status"), status_str);
326 if (is_online && !is_empty(calendar))
328 SIPE_ADD_BUDDY_INFO(_("Calendar"), calendar);
330 g_free(calendar);
331 if (!is_empty(meeting_location))
333 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting location: '%s'", name, meeting_location);
334 SIPE_ADD_BUDDY_INFO(_("Meeting in"), meeting_location);
336 if (!is_empty(meeting_subject))
338 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting subject: '%s'", name, meeting_subject);
339 SIPE_ADD_BUDDY_INFO(_("Meeting about"), meeting_subject);
341 if (note)
343 SIPE_DEBUG_INFO("sipe_tooltip_text: %s note: '%s'", name, note);
344 SIPE_ADD_BUDDY_INFO_NOESCAPE(is_oof_note ? _("Out of office note") : _("Note"),
345 g_strdup_printf("<i>%s</i>", note));
347 if (access_text) {
348 SIPE_ADD_BUDDY_INFO(_("Access level"), access_text);
349 g_free(access_text);
352 return(info);
355 void sipe_buddy_update_property(struct sipe_core_private *sipe_private,
356 const char *uri,
357 sipe_buddy_info_fields propkey,
358 char *property_value)
360 GSList *buddies, *entry;
362 if (property_value)
363 property_value = g_strstrip(property_value);
365 entry = buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC, uri, NULL); /* all buddies in different groups */
366 while (entry) {
367 gchar *prop_str;
368 gchar *server_alias;
369 gchar *alias;
370 sipe_backend_buddy p_buddy = entry->data;
372 /* for Display Name */
373 if (propkey == SIPE_BUDDY_INFO_DISPLAY_NAME) {
374 alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, p_buddy);
375 if (property_value && sipe_is_bad_alias(uri, alias)) {
376 SIPE_DEBUG_INFO("Replacing alias for %s with %s", uri, property_value);
377 sipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
379 g_free(alias);
381 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC, p_buddy);
382 if (!is_empty(property_value) &&
383 (!sipe_strequal(property_value, server_alias) || is_empty(server_alias)) )
385 SIPE_DEBUG_INFO("Replacing service alias for %s with %s", uri, property_value);
386 sipe_backend_buddy_set_server_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
388 g_free(server_alias);
390 /* for other properties */
391 else {
392 if (!is_empty(property_value)) {
393 prop_str = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC, p_buddy, propkey);
394 if (!prop_str || !sipe_strcase_equal(prop_str, property_value)) {
395 sipe_backend_buddy_set_string(SIPE_CORE_PUBLIC, p_buddy, propkey, property_value);
397 g_free(prop_str);
401 entry = entry->next;
403 g_slist_free(buddies);
406 static gboolean process_search_contact_response(struct sipe_core_private *sipe_private,
407 struct sipmsg *msg,
408 SIPE_UNUSED_PARAMETER struct transaction *trans)
410 struct sipe_backend_search_results *results;
411 sipe_xml *searchResults;
412 const sipe_xml *mrow;
413 guint match_count = 0;
414 gboolean more = FALSE;
415 gchar *secondary;
417 /* valid response? */
418 if (msg->response != 200) {
419 SIPE_DEBUG_ERROR("process_search_contact_response: request failed (%d)",
420 msg->response);
421 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
422 _("Contact search failed"),
423 NULL);
424 return(FALSE);
427 SIPE_DEBUG_INFO("process_search_contact_response: body:\n%s", msg->body ? msg->body : "");
429 /* valid XML? */
430 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
431 if (!searchResults) {
432 SIPE_DEBUG_INFO_NOFORMAT("process_search_contact_response: no parseable searchResults");
433 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
434 _("Contact search failed"),
435 NULL);
436 return(FALSE);
439 /* any matches? */
440 mrow = sipe_xml_child(searchResults, "Body/Array/row");
441 if (!mrow) {
442 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: no matches");
443 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
444 _("No contacts found"),
445 NULL);
447 sipe_xml_free(searchResults);
448 return(FALSE);
451 /* OK, we found something - show the results to the user */
452 results = sipe_backend_search_results_start(SIPE_CORE_PUBLIC);
453 if (!results) {
454 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: Unable to display the search results.");
455 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
456 _("Unable to display the search results"),
457 NULL);
459 sipe_xml_free(searchResults);
460 return FALSE;
463 for (/* initialized above */ ; mrow; mrow = sipe_xml_twin(mrow)) {
464 gchar **uri_parts = g_strsplit(sipe_xml_attribute(mrow, "uri"), ":", 2);
465 sipe_backend_search_results_add(SIPE_CORE_PUBLIC,
466 results,
467 uri_parts[1],
468 sipe_xml_attribute(mrow, "displayName"),
469 sipe_xml_attribute(mrow, "company"),
470 sipe_xml_attribute(mrow, "country"),
471 sipe_xml_attribute(mrow, "email"));
472 g_strfreev(uri_parts);
473 match_count++;
476 if ((mrow = sipe_xml_child(searchResults, "Body/directorySearch/moreAvailable")) != NULL) {
477 char *data = sipe_xml_data(mrow);
478 more = (g_strcasecmp(data, "true") == 0);
479 g_free(data);
482 secondary = g_strdup_printf(
483 dngettext(PACKAGE_NAME,
484 "Found %d contact%s:",
485 "Found %d contacts%s:", match_count),
486 match_count, more ? _(" (more matched your query)") : "");
488 sipe_backend_search_results_finalize(SIPE_CORE_PUBLIC,
489 results,
490 secondary);
491 g_free(secondary);
492 sipe_xml_free(searchResults);
494 return(TRUE);
497 #define SIPE_SOAP_SEARCH_ROW "<m:row m:attrib=\"%s\" m:value=\"%s\"/>"
499 void sipe_core_buddy_search(struct sipe_core_public *sipe_public,
500 const gchar *given_name,
501 const gchar *surname,
502 const gchar *company,
503 const gchar *country)
505 gchar **attrs = g_new(gchar *, 5);
506 guint i = 0;
508 if (!attrs) return;
510 #define ADD_QUERY_ROW(a, v) \
511 if (v) attrs[i++] = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW, a, v)
513 ADD_QUERY_ROW("givenName", given_name);
514 ADD_QUERY_ROW("sn", surname);
515 ADD_QUERY_ROW("company", company);
516 ADD_QUERY_ROW("c", country);
518 if (i) {
519 gchar *query;
521 attrs[i] = NULL;
522 query = g_strjoinv(NULL, attrs);
523 SIPE_DEBUG_INFO("sipe_core_buddy_search: rows:\n%s",
524 query ? query : "");
525 sip_soap_directory_search(SIPE_CORE_PRIVATE,
526 100,
527 query,
528 process_search_contact_response,
529 NULL);
530 g_free(query);
533 g_strfreev(attrs);
536 static gboolean process_options_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,
537 struct sipmsg *msg,
538 SIPE_UNUSED_PARAMETER struct transaction *trans)
540 if (msg->response != 200) {
541 SIPE_DEBUG_INFO("process_options_response: OPTIONS response is %d",
542 msg->response);
543 return(FALSE);
544 } else {
545 SIPE_DEBUG_INFO("process_options_response: body:\n%s",
546 msg->body ? msg->body : "");
547 return(TRUE);
551 /* Asks UA/proxy about its capabilities */
552 static void sipe_options_request(struct sipe_core_private *sipe_private,
553 const char *who)
555 gchar *to = sip_uri(who);
556 gchar *contact = get_contact(sipe_private);
557 gchar *request = g_strdup_printf("Accept: application/sdp\r\n"
558 "Contact: %s\r\n",
559 contact);
560 g_free(contact);
562 sip_transport_request(sipe_private,
563 "OPTIONS",
566 request,
567 NULL,
568 NULL,
569 process_options_response);
571 g_free(to);
572 g_free(request);
575 static gboolean process_get_info_response(struct sipe_core_private *sipe_private,
576 struct sipmsg *msg,
577 struct transaction *trans)
579 const gchar *uri = trans->payload->data;
580 sipe_backend_buddy bbuddy;
581 struct sipe_backend_buddy_info *info;
582 struct sipe_buddy *sbuddy;
583 gchar *alias = NULL;
584 gchar *device_name = NULL;
585 gchar *server_alias = NULL;
586 gchar *phone_number = NULL;
587 gchar *email = NULL;
588 gchar *site;
590 SIPE_DEBUG_INFO("Fetching %s's user info for %s",
591 uri, sipe_private->username);
593 info = sipe_backend_buddy_info_start(SIPE_CORE_PUBLIC);
594 if (!info) return(FALSE);
596 bbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, uri, NULL);
597 alias = sipe_backend_buddy_get_local_alias(SIPE_CORE_PUBLIC, bbuddy);
599 /* will query buddy UA's capabilities and send answer to log */
600 if (sipe_backend_debug_enabled())
601 sipe_options_request(sipe_private, uri);
603 sbuddy = g_hash_table_lookup(sipe_private->buddies, uri);
604 if (sbuddy) {
605 device_name = sbuddy->device_name ? g_strdup(sbuddy->device_name) : NULL;
608 if (msg->response != 200) {
609 SIPE_DEBUG_INFO("process_get_info_response: SERVICE response is %d", msg->response);
610 } else {
611 sipe_xml *searchResults;
612 const sipe_xml *mrow;
614 SIPE_DEBUG_INFO("process_get_info_response: body:\n%s",
615 msg->body ? msg->body : "");
617 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
618 if (!searchResults) {
620 SIPE_DEBUG_INFO_NOFORMAT("process_get_info_response: no parseable searchResults");
622 } else if ((mrow = sipe_xml_child(searchResults, "Body/Array/row"))) {
623 const gchar *value;
625 server_alias = g_strdup(sipe_xml_attribute(mrow, "displayName"));
626 email = g_strdup(sipe_xml_attribute(mrow, "email"));
627 phone_number = g_strdup(sipe_xml_attribute(mrow, "phone"));
630 * For 2007 system we will take this from ContactCard -
631 * it has cleaner tel: URIs at least
633 if (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
634 char *tel_uri = sip_to_tel_uri(phone_number);
635 /* trims its parameters, so call first */
636 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, server_alias);
637 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_EMAIL, email);
638 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE, tel_uri);
639 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, phone_number);
640 g_free(tel_uri);
643 if (server_alias && strlen(server_alias) > 0) {
644 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
645 info,
646 _("Display name"),
647 server_alias);
649 if ((value = sipe_xml_attribute(mrow, "title")) && strlen(value) > 0) {
650 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
651 info,
652 _("Job title"),
653 value);
655 if ((value = sipe_xml_attribute(mrow, "office")) && strlen(value) > 0) {
656 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
657 info,
658 _("Office"),
659 value);
661 if (phone_number && strlen(phone_number) > 0) {
662 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
663 info,
664 _("Business phone"),
665 phone_number);
667 if ((value = sipe_xml_attribute(mrow, "company")) && strlen(value) > 0) {
668 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
669 info,
670 _("Company"),
671 value);
673 if ((value = sipe_xml_attribute(mrow, "city")) && strlen(value) > 0) {
674 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
675 info,
676 _("City"),
677 value);
679 if ((value = sipe_xml_attribute(mrow, "state")) && strlen(value) > 0) {
680 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
681 info,
682 _("State"),
683 value);
685 if ((value = sipe_xml_attribute(mrow, "country")) && strlen(value) > 0) {
686 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
687 info,
688 _("Country"),
689 value);
691 if (email && strlen(email) > 0) {
692 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
693 info,
694 _("Email address"),
695 email);
699 sipe_xml_free(searchResults);
702 sipe_backend_buddy_info_break(SIPE_CORE_PUBLIC, info);
704 if (is_empty(server_alias)) {
705 g_free(server_alias);
706 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC,
707 bbuddy);
708 if (server_alias) {
709 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
710 info,
711 _("Display name"),
712 server_alias);
716 /* present alias if it differs from server alias */
717 if (alias && !sipe_strequal(alias, server_alias))
719 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
720 info,
721 _("Alias"),
722 alias);
725 if (is_empty(email)) {
726 g_free(email);
727 email = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,
728 bbuddy,
729 SIPE_BUDDY_INFO_EMAIL);
730 if (email) {
731 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
732 info,
733 _("Email address"),
734 email);
738 site = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,
739 bbuddy,
740 SIPE_BUDDY_INFO_SITE);
741 if (site) {
742 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
743 info,
744 _("Site"),
745 site);
746 g_free(site);
749 if (device_name) {
750 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
751 info,
752 _("Device"),
753 device_name);
756 sipe_backend_buddy_info_finalize(SIPE_CORE_PUBLIC, info, uri);
758 g_free(phone_number);
759 g_free(server_alias);
760 g_free(email);
761 g_free(device_name);
762 g_free(alias);
764 return TRUE;
768 * AD search first, LDAP based
770 void sipe_core_buddy_get_info(struct sipe_core_public *sipe_public,
771 const gchar *who)
773 char *row = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW,
774 "msRTCSIP-PrimaryUserAddress",
775 who);
776 struct transaction_payload *payload = g_new0(struct transaction_payload, 1);
778 SIPE_DEBUG_INFO("sipe_core_buddy_get_info: row: %s", row ? row : "");
780 payload->destroy = g_free;
781 payload->data = g_strdup(who);
783 sip_soap_directory_search(SIPE_CORE_PRIVATE,
785 row,
786 process_get_info_response,
787 payload);
788 g_free(row);
792 Local Variables:
793 mode: c
794 c-file-style: "bsd"
795 indent-tabs-mode: t
796 tab-width: 8
797 End: