core cleanup: core/backend API changes after review
[siplcs.git] / src / core / sipe-buddy.c
blob82509ed315fc68fa8fbfd3bc42c5ce1e6103eb9e
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 *uri,
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, uri);
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 *uri,
178 const gchar *group_name)
180 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
182 if (!g_hash_table_lookup(sipe_private->buddies, uri)) {
183 struct sipe_buddy *b = g_new0(struct sipe_buddy, 1);
185 SIPE_DEBUG_INFO("sipe_core_buddy_add: %s", uri);
187 b->name = g_strdup(uri);
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 uri);
199 sipe_core_buddy_group(sipe_public,
200 uri,
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 *uri,
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 uri);
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 uri, g->name);
230 if (g_slist_length(b->groups) < 1) {
231 gchar *action_name = sipe_utils_presence_key(uri);
232 sipe_schedule_cancel(sipe_private, action_name);
233 g_free(action_name);
235 g_hash_table_remove(sipe_private->buddies, uri);
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_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 void sipe_core_buddy_tooltip_info(struct sipe_core_public *sipe_public,
275 const gchar *uri,
276 const gchar *status_name,
277 gboolean is_online,
278 struct sipe_backend_buddy_tooltip *tooltip)
280 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
281 gchar *note = NULL;
282 gboolean is_oof_note = FALSE;
283 const gchar *activity = NULL;
284 gchar *calendar = NULL;
285 const gchar *meeting_subject = NULL;
286 const gchar *meeting_location = NULL;
287 gchar *access_text = NULL;
289 #define SIPE_ADD_BUDDY_INFO(l, t) \
291 gchar *tmp = g_markup_escape_text((t), -1); \
292 sipe_backend_buddy_tooltip_add(sipe_public, tooltip, (l), tmp); \
293 g_free(tmp); \
295 #define SIPE_ADD_BUDDY_INFO_NOESCAPE(l, t) \
296 sipe_backend_buddy_tooltip_add(sipe_public, tooltip, (l), (t))
298 if (sipe_public) { /* happens on pidgin exit */
299 struct sipe_buddy *sbuddy = g_hash_table_lookup(sipe_private->buddies, uri);
300 if (sbuddy) {
301 note = sbuddy->note;
302 is_oof_note = sbuddy->is_oof_note;
303 activity = sbuddy->activity;
304 calendar = sipe_cal_get_description(sbuddy);
305 meeting_subject = sbuddy->meeting_subject;
306 meeting_location = sbuddy->meeting_location;
308 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
309 gboolean is_group_access = FALSE;
310 const int container_id = sipe_ocs2007_find_access_level(sipe_private,
311 "user",
312 sipe_get_no_sip_uri(uri),
313 &is_group_access);
314 const char *access_level = sipe_ocs2007_access_level_name(container_id);
315 access_text = is_group_access ?
316 g_strdup(access_level) :
317 g_strdup_printf(SIPE_OCS2007_INDENT_MARKED_FMT,
318 access_level);
322 if (is_online) {
323 const gchar *status_str = activity ? activity : status_name;
325 SIPE_ADD_BUDDY_INFO(_("Status"), status_str);
327 if (is_online && !is_empty(calendar)) {
328 SIPE_ADD_BUDDY_INFO(_("Calendar"), calendar);
330 g_free(calendar);
331 if (!is_empty(meeting_location)) {
332 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting location: '%s'", uri, meeting_location);
333 SIPE_ADD_BUDDY_INFO(_("Meeting in"), meeting_location);
335 if (!is_empty(meeting_subject)) {
336 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting subject: '%s'", uri, meeting_subject);
337 SIPE_ADD_BUDDY_INFO(_("Meeting about"), meeting_subject);
339 if (note) {
340 SIPE_DEBUG_INFO("sipe_tooltip_text: %s note: '%s'", uri, note);
341 SIPE_ADD_BUDDY_INFO_NOESCAPE(is_oof_note ? _("Out of office note") : _("Note"),
342 g_strdup_printf("<i>%s</i>", note));
344 if (access_text) {
345 SIPE_ADD_BUDDY_INFO(_("Access level"), access_text);
346 g_free(access_text);
350 void sipe_buddy_update_property(struct sipe_core_private *sipe_private,
351 const char *uri,
352 sipe_buddy_info_fields propkey,
353 char *property_value)
355 GSList *buddies, *entry;
357 if (property_value)
358 property_value = g_strstrip(property_value);
360 entry = buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC, uri, NULL); /* all buddies in different groups */
361 while (entry) {
362 gchar *prop_str;
363 gchar *server_alias;
364 gchar *alias;
365 sipe_backend_buddy p_buddy = entry->data;
367 /* for Display Name */
368 if (propkey == SIPE_BUDDY_INFO_DISPLAY_NAME) {
369 alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, p_buddy);
370 if (property_value && sipe_is_bad_alias(uri, alias)) {
371 SIPE_DEBUG_INFO("Replacing alias for %s with %s", uri, property_value);
372 sipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
374 g_free(alias);
376 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC, p_buddy);
377 if (!is_empty(property_value) &&
378 (!sipe_strequal(property_value, server_alias) || is_empty(server_alias)) )
380 SIPE_DEBUG_INFO("Replacing service alias for %s with %s", uri, property_value);
381 sipe_backend_buddy_set_server_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
383 g_free(server_alias);
385 /* for other properties */
386 else {
387 if (!is_empty(property_value)) {
388 prop_str = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC, p_buddy, propkey);
389 if (!prop_str || !sipe_strcase_equal(prop_str, property_value)) {
390 sipe_backend_buddy_set_string(SIPE_CORE_PUBLIC, p_buddy, propkey, property_value);
392 g_free(prop_str);
396 entry = entry->next;
398 g_slist_free(buddies);
401 static gboolean process_search_contact_response(struct sipe_core_private *sipe_private,
402 struct sipmsg *msg,
403 SIPE_UNUSED_PARAMETER struct transaction *trans)
405 struct sipe_backend_search_results *results;
406 sipe_xml *searchResults;
407 const sipe_xml *mrow;
408 guint match_count = 0;
409 gboolean more = FALSE;
410 gchar *secondary;
412 /* valid response? */
413 if (msg->response != 200) {
414 SIPE_DEBUG_ERROR("process_search_contact_response: request failed (%d)",
415 msg->response);
416 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
417 _("Contact search failed"),
418 NULL);
419 return(FALSE);
422 SIPE_DEBUG_INFO("process_search_contact_response: body:\n%s", msg->body ? msg->body : "");
424 /* valid XML? */
425 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
426 if (!searchResults) {
427 SIPE_DEBUG_INFO_NOFORMAT("process_search_contact_response: no parseable searchResults");
428 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
429 _("Contact search failed"),
430 NULL);
431 return(FALSE);
434 /* any matches? */
435 mrow = sipe_xml_child(searchResults, "Body/Array/row");
436 if (!mrow) {
437 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: no matches");
438 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
439 _("No contacts found"),
440 NULL);
442 sipe_xml_free(searchResults);
443 return(FALSE);
446 /* OK, we found something - show the results to the user */
447 results = sipe_backend_search_results_start(SIPE_CORE_PUBLIC);
448 if (!results) {
449 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: Unable to display the search results.");
450 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
451 _("Unable to display the search results"),
452 NULL);
454 sipe_xml_free(searchResults);
455 return FALSE;
458 for (/* initialized above */ ; mrow; mrow = sipe_xml_twin(mrow)) {
459 gchar **uri_parts = g_strsplit(sipe_xml_attribute(mrow, "uri"), ":", 2);
460 sipe_backend_search_results_add(SIPE_CORE_PUBLIC,
461 results,
462 uri_parts[1],
463 sipe_xml_attribute(mrow, "displayName"),
464 sipe_xml_attribute(mrow, "company"),
465 sipe_xml_attribute(mrow, "country"),
466 sipe_xml_attribute(mrow, "email"));
467 g_strfreev(uri_parts);
468 match_count++;
471 if ((mrow = sipe_xml_child(searchResults, "Body/directorySearch/moreAvailable")) != NULL) {
472 char *data = sipe_xml_data(mrow);
473 more = (g_strcasecmp(data, "true") == 0);
474 g_free(data);
477 secondary = g_strdup_printf(
478 dngettext(PACKAGE_NAME,
479 "Found %d contact%s:",
480 "Found %d contacts%s:", match_count),
481 match_count, more ? _(" (more matched your query)") : "");
483 sipe_backend_search_results_finalize(SIPE_CORE_PUBLIC,
484 results,
485 secondary,
486 more);
487 g_free(secondary);
488 sipe_xml_free(searchResults);
490 return(TRUE);
493 #define SIPE_SOAP_SEARCH_ROW "<m:row m:attrib=\"%s\" m:value=\"%s\"/>"
495 void sipe_core_buddy_search(struct sipe_core_public *sipe_public,
496 const gchar *given_name,
497 const gchar *surname,
498 const gchar *company,
499 const gchar *country)
501 gchar **attrs = g_new(gchar *, 5);
502 guint i = 0;
504 if (!attrs) return;
506 #define ADD_QUERY_ROW(a, v) \
507 if (v) attrs[i++] = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW, a, v)
509 ADD_QUERY_ROW("givenName", given_name);
510 ADD_QUERY_ROW("sn", surname);
511 ADD_QUERY_ROW("company", company);
512 ADD_QUERY_ROW("c", country);
514 if (i) {
515 gchar *query;
517 attrs[i] = NULL;
518 query = g_strjoinv(NULL, attrs);
519 SIPE_DEBUG_INFO("sipe_core_buddy_search: rows:\n%s",
520 query ? query : "");
521 sip_soap_directory_search(SIPE_CORE_PRIVATE,
522 100,
523 query,
524 process_search_contact_response,
525 NULL);
526 g_free(query);
529 g_strfreev(attrs);
532 static gboolean process_options_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,
533 struct sipmsg *msg,
534 SIPE_UNUSED_PARAMETER struct transaction *trans)
536 if (msg->response != 200) {
537 SIPE_DEBUG_INFO("process_options_response: OPTIONS response is %d",
538 msg->response);
539 return(FALSE);
540 } else {
541 SIPE_DEBUG_INFO("process_options_response: body:\n%s",
542 msg->body ? msg->body : "");
543 return(TRUE);
547 /* Asks UA/proxy about its capabilities */
548 static void sipe_options_request(struct sipe_core_private *sipe_private,
549 const char *who)
551 gchar *to = sip_uri(who);
552 gchar *contact = get_contact(sipe_private);
553 gchar *request = g_strdup_printf("Accept: application/sdp\r\n"
554 "Contact: %s\r\n",
555 contact);
556 g_free(contact);
558 sip_transport_request(sipe_private,
559 "OPTIONS",
562 request,
563 NULL,
564 NULL,
565 process_options_response);
567 g_free(to);
568 g_free(request);
571 static gboolean process_get_info_response(struct sipe_core_private *sipe_private,
572 struct sipmsg *msg,
573 struct transaction *trans)
575 const gchar *uri = trans->payload->data;
576 sipe_backend_buddy bbuddy;
577 struct sipe_backend_buddy_info *info;
578 struct sipe_buddy *sbuddy;
579 gchar *alias = NULL;
580 gchar *device_name = NULL;
581 gchar *server_alias = NULL;
582 gchar *phone_number = NULL;
583 gchar *email = NULL;
584 gchar *site;
586 SIPE_DEBUG_INFO("Fetching %s's user info for %s",
587 uri, sipe_private->username);
589 info = sipe_backend_buddy_info_start(SIPE_CORE_PUBLIC);
590 if (!info) return(FALSE);
592 bbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, uri, NULL);
593 alias = sipe_backend_buddy_get_local_alias(SIPE_CORE_PUBLIC, bbuddy);
595 /* will query buddy UA's capabilities and send answer to log */
596 if (sipe_backend_debug_enabled())
597 sipe_options_request(sipe_private, uri);
599 sbuddy = g_hash_table_lookup(sipe_private->buddies, uri);
600 if (sbuddy) {
601 device_name = sbuddy->device_name ? g_strdup(sbuddy->device_name) : NULL;
604 if (msg->response != 200) {
605 SIPE_DEBUG_INFO("process_get_info_response: SERVICE response is %d", msg->response);
606 } else {
607 sipe_xml *searchResults;
608 const sipe_xml *mrow;
610 SIPE_DEBUG_INFO("process_get_info_response: body:\n%s",
611 msg->body ? msg->body : "");
613 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
614 if (!searchResults) {
616 SIPE_DEBUG_INFO_NOFORMAT("process_get_info_response: no parseable searchResults");
618 } else if ((mrow = sipe_xml_child(searchResults, "Body/Array/row"))) {
619 const gchar *value;
621 server_alias = g_strdup(sipe_xml_attribute(mrow, "displayName"));
622 email = g_strdup(sipe_xml_attribute(mrow, "email"));
623 phone_number = g_strdup(sipe_xml_attribute(mrow, "phone"));
626 * For 2007 system we will take this from ContactCard -
627 * it has cleaner tel: URIs at least
629 if (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
630 char *tel_uri = sip_to_tel_uri(phone_number);
631 /* trims its parameters, so call first */
632 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, server_alias);
633 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_EMAIL, email);
634 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE, tel_uri);
635 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, phone_number);
636 g_free(tel_uri);
639 if (server_alias && strlen(server_alias) > 0) {
640 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
641 info,
642 _("Display name"),
643 server_alias);
645 if ((value = sipe_xml_attribute(mrow, "title")) && strlen(value) > 0) {
646 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
647 info,
648 _("Job title"),
649 value);
651 if ((value = sipe_xml_attribute(mrow, "office")) && strlen(value) > 0) {
652 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
653 info,
654 _("Office"),
655 value);
657 if (phone_number && strlen(phone_number) > 0) {
658 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
659 info,
660 _("Business phone"),
661 phone_number);
663 if ((value = sipe_xml_attribute(mrow, "company")) && strlen(value) > 0) {
664 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
665 info,
666 _("Company"),
667 value);
669 if ((value = sipe_xml_attribute(mrow, "city")) && strlen(value) > 0) {
670 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
671 info,
672 _("City"),
673 value);
675 if ((value = sipe_xml_attribute(mrow, "state")) && strlen(value) > 0) {
676 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
677 info,
678 _("State"),
679 value);
681 if ((value = sipe_xml_attribute(mrow, "country")) && strlen(value) > 0) {
682 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
683 info,
684 _("Country"),
685 value);
687 if (email && strlen(email) > 0) {
688 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
689 info,
690 _("Email address"),
691 email);
695 sipe_xml_free(searchResults);
698 sipe_backend_buddy_info_break(SIPE_CORE_PUBLIC, info);
700 if (is_empty(server_alias)) {
701 g_free(server_alias);
702 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC,
703 bbuddy);
704 if (server_alias) {
705 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
706 info,
707 _("Display name"),
708 server_alias);
712 /* present alias if it differs from server alias */
713 if (alias && !sipe_strequal(alias, server_alias))
715 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
716 info,
717 _("Alias"),
718 alias);
721 if (is_empty(email)) {
722 g_free(email);
723 email = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,
724 bbuddy,
725 SIPE_BUDDY_INFO_EMAIL);
726 if (email) {
727 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
728 info,
729 _("Email address"),
730 email);
734 site = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,
735 bbuddy,
736 SIPE_BUDDY_INFO_SITE);
737 if (site) {
738 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
739 info,
740 _("Site"),
741 site);
742 g_free(site);
745 if (device_name) {
746 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
747 info,
748 _("Device"),
749 device_name);
752 sipe_backend_buddy_info_finalize(SIPE_CORE_PUBLIC, info, uri);
754 g_free(phone_number);
755 g_free(server_alias);
756 g_free(email);
757 g_free(device_name);
758 g_free(alias);
760 return TRUE;
764 * AD search first, LDAP based
766 void sipe_core_buddy_get_info(struct sipe_core_public *sipe_public,
767 const gchar *who)
769 char *row = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW,
770 "msRTCSIP-PrimaryUserAddress",
771 who);
772 struct transaction_payload *payload = g_new0(struct transaction_payload, 1);
774 SIPE_DEBUG_INFO("sipe_core_buddy_get_info: row: %s", row ? row : "");
776 payload->destroy = g_free;
777 payload->data = g_strdup(who);
779 sip_soap_directory_search(SIPE_CORE_PRIVATE,
781 row,
782 process_get_info_response,
783 payload);
784 g_free(row);
788 Local Variables:
789 mode: c
790 c-file-style: "bsd"
791 indent-tabs-mode: t
792 tab-width: 8
793 End: