core cleanup: the big status/activity revamp
[siplcs.git] / src / core / sipe-buddy.c
blob9472f22a18a91c65826f5bfa0b7b42d95e2a2331
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-ocs2005.h"
46 #include "sipe-ocs2007.h"
47 #include "sipe-schedule.h"
48 #include "sipe-subscriptions.h"
49 #include "sipe-utils.h"
50 #include "sipe-xml.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 guint 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_ocs2005_apply_calendar_status(sipe_private,
271 sbuddy,
272 status_id);
276 void sipe_core_buddy_tooltip_info(struct sipe_core_public *sipe_public,
277 const gchar *uri,
278 const gchar *status_name,
279 gboolean is_online,
280 struct sipe_backend_buddy_tooltip *tooltip)
282 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
283 gchar *note = NULL;
284 gboolean is_oof_note = FALSE;
285 const gchar *activity = NULL;
286 gchar *calendar = NULL;
287 const gchar *meeting_subject = NULL;
288 const gchar *meeting_location = NULL;
289 gchar *access_text = NULL;
291 #define SIPE_ADD_BUDDY_INFO(l, t) \
293 gchar *tmp = g_markup_escape_text((t), -1); \
294 sipe_backend_buddy_tooltip_add(sipe_public, tooltip, (l), tmp); \
295 g_free(tmp); \
297 #define SIPE_ADD_BUDDY_INFO_NOESCAPE(l, t) \
298 sipe_backend_buddy_tooltip_add(sipe_public, tooltip, (l), (t))
300 if (sipe_public) { /* happens on pidgin exit */
301 struct sipe_buddy *sbuddy = g_hash_table_lookup(sipe_private->buddies, uri);
302 if (sbuddy) {
303 note = sbuddy->note;
304 is_oof_note = sbuddy->is_oof_note;
305 activity = sbuddy->activity;
306 calendar = sipe_cal_get_description(sbuddy);
307 meeting_subject = sbuddy->meeting_subject;
308 meeting_location = sbuddy->meeting_location;
310 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
311 gboolean is_group_access = FALSE;
312 const int container_id = sipe_ocs2007_find_access_level(sipe_private,
313 "user",
314 sipe_get_no_sip_uri(uri),
315 &is_group_access);
316 const char *access_level = sipe_ocs2007_access_level_name(container_id);
317 access_text = is_group_access ?
318 g_strdup(access_level) :
319 g_strdup_printf(SIPE_OCS2007_INDENT_MARKED_FMT,
320 access_level);
324 if (is_online) {
325 const gchar *status_str = activity ? activity : status_name;
327 SIPE_ADD_BUDDY_INFO(_("Status"), status_str);
329 if (is_online && !is_empty(calendar)) {
330 SIPE_ADD_BUDDY_INFO(_("Calendar"), calendar);
332 g_free(calendar);
333 if (!is_empty(meeting_location)) {
334 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting location: '%s'", uri, meeting_location);
335 SIPE_ADD_BUDDY_INFO(_("Meeting in"), meeting_location);
337 if (!is_empty(meeting_subject)) {
338 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting subject: '%s'", uri, meeting_subject);
339 SIPE_ADD_BUDDY_INFO(_("Meeting about"), meeting_subject);
341 if (note) {
342 SIPE_DEBUG_INFO("sipe_tooltip_text: %s note: '%s'", uri, note);
343 SIPE_ADD_BUDDY_INFO_NOESCAPE(is_oof_note ? _("Out of office note") : _("Note"),
344 g_strdup_printf("<i>%s</i>", note));
346 if (access_text) {
347 SIPE_ADD_BUDDY_INFO(_("Access level"), access_text);
348 g_free(access_text);
352 void sipe_buddy_update_property(struct sipe_core_private *sipe_private,
353 const char *uri,
354 sipe_buddy_info_fields propkey,
355 char *property_value)
357 GSList *buddies, *entry;
359 if (property_value)
360 property_value = g_strstrip(property_value);
362 entry = buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC, uri, NULL); /* all buddies in different groups */
363 while (entry) {
364 gchar *prop_str;
365 gchar *server_alias;
366 gchar *alias;
367 sipe_backend_buddy p_buddy = entry->data;
369 /* for Display Name */
370 if (propkey == SIPE_BUDDY_INFO_DISPLAY_NAME) {
371 alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, p_buddy);
372 if (property_value && sipe_is_bad_alias(uri, alias)) {
373 SIPE_DEBUG_INFO("Replacing alias for %s with %s", uri, property_value);
374 sipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
376 g_free(alias);
378 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC, p_buddy);
379 if (!is_empty(property_value) &&
380 (!sipe_strequal(property_value, server_alias) || is_empty(server_alias)) )
382 SIPE_DEBUG_INFO("Replacing service alias for %s with %s", uri, property_value);
383 sipe_backend_buddy_set_server_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
385 g_free(server_alias);
387 /* for other properties */
388 else {
389 if (!is_empty(property_value)) {
390 prop_str = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC, p_buddy, propkey);
391 if (!prop_str || !sipe_strcase_equal(prop_str, property_value)) {
392 sipe_backend_buddy_set_string(SIPE_CORE_PUBLIC, p_buddy, propkey, property_value);
394 g_free(prop_str);
398 entry = entry->next;
400 g_slist_free(buddies);
403 static gboolean process_search_contact_response(struct sipe_core_private *sipe_private,
404 struct sipmsg *msg,
405 SIPE_UNUSED_PARAMETER struct transaction *trans)
407 struct sipe_backend_search_results *results;
408 sipe_xml *searchResults;
409 const sipe_xml *mrow;
410 guint match_count = 0;
411 gboolean more = FALSE;
412 gchar *secondary;
414 /* valid response? */
415 if (msg->response != 200) {
416 SIPE_DEBUG_ERROR("process_search_contact_response: request failed (%d)",
417 msg->response);
418 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
419 _("Contact search failed"),
420 NULL);
421 return(FALSE);
424 SIPE_DEBUG_INFO("process_search_contact_response: body:\n%s", msg->body ? msg->body : "");
426 /* valid XML? */
427 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
428 if (!searchResults) {
429 SIPE_DEBUG_INFO_NOFORMAT("process_search_contact_response: no parseable searchResults");
430 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
431 _("Contact search failed"),
432 NULL);
433 return(FALSE);
436 /* any matches? */
437 mrow = sipe_xml_child(searchResults, "Body/Array/row");
438 if (!mrow) {
439 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: no matches");
440 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
441 _("No contacts found"),
442 NULL);
444 sipe_xml_free(searchResults);
445 return(FALSE);
448 /* OK, we found something - show the results to the user */
449 results = sipe_backend_search_results_start(SIPE_CORE_PUBLIC);
450 if (!results) {
451 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: Unable to display the search results.");
452 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
453 _("Unable to display the search results"),
454 NULL);
456 sipe_xml_free(searchResults);
457 return FALSE;
460 for (/* initialized above */ ; mrow; mrow = sipe_xml_twin(mrow)) {
461 gchar **uri_parts = g_strsplit(sipe_xml_attribute(mrow, "uri"), ":", 2);
462 sipe_backend_search_results_add(SIPE_CORE_PUBLIC,
463 results,
464 uri_parts[1],
465 sipe_xml_attribute(mrow, "displayName"),
466 sipe_xml_attribute(mrow, "company"),
467 sipe_xml_attribute(mrow, "country"),
468 sipe_xml_attribute(mrow, "email"));
469 g_strfreev(uri_parts);
470 match_count++;
473 if ((mrow = sipe_xml_child(searchResults, "Body/directorySearch/moreAvailable")) != NULL) {
474 char *data = sipe_xml_data(mrow);
475 more = (g_strcasecmp(data, "true") == 0);
476 g_free(data);
479 secondary = g_strdup_printf(
480 dngettext(PACKAGE_NAME,
481 "Found %d contact%s:",
482 "Found %d contacts%s:", match_count),
483 match_count, more ? _(" (more matched your query)") : "");
485 sipe_backend_search_results_finalize(SIPE_CORE_PUBLIC,
486 results,
487 secondary,
488 more);
489 g_free(secondary);
490 sipe_xml_free(searchResults);
492 return(TRUE);
495 #define SIPE_SOAP_SEARCH_ROW "<m:row m:attrib=\"%s\" m:value=\"%s\"/>"
497 void sipe_core_buddy_search(struct sipe_core_public *sipe_public,
498 const gchar *given_name,
499 const gchar *surname,
500 const gchar *company,
501 const gchar *country)
503 gchar **attrs = g_new(gchar *, 5);
504 guint i = 0;
506 if (!attrs) return;
508 #define ADD_QUERY_ROW(a, v) \
509 if (v) attrs[i++] = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW, a, v)
511 ADD_QUERY_ROW("givenName", given_name);
512 ADD_QUERY_ROW("sn", surname);
513 ADD_QUERY_ROW("company", company);
514 ADD_QUERY_ROW("c", country);
516 if (i) {
517 gchar *query;
519 attrs[i] = NULL;
520 query = g_strjoinv(NULL, attrs);
521 SIPE_DEBUG_INFO("sipe_core_buddy_search: rows:\n%s",
522 query ? query : "");
523 sip_soap_directory_search(SIPE_CORE_PRIVATE,
524 100,
525 query,
526 process_search_contact_response,
527 NULL);
528 g_free(query);
531 g_strfreev(attrs);
534 static gboolean process_options_response(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private,
535 struct sipmsg *msg,
536 SIPE_UNUSED_PARAMETER struct transaction *trans)
538 if (msg->response != 200) {
539 SIPE_DEBUG_INFO("process_options_response: OPTIONS response is %d",
540 msg->response);
541 return(FALSE);
542 } else {
543 SIPE_DEBUG_INFO("process_options_response: body:\n%s",
544 msg->body ? msg->body : "");
545 return(TRUE);
549 /* Asks UA/proxy about its capabilities */
550 static void sipe_options_request(struct sipe_core_private *sipe_private,
551 const char *who)
553 gchar *to = sip_uri(who);
554 gchar *contact = get_contact(sipe_private);
555 gchar *request = g_strdup_printf("Accept: application/sdp\r\n"
556 "Contact: %s\r\n",
557 contact);
558 g_free(contact);
560 sip_transport_request(sipe_private,
561 "OPTIONS",
564 request,
565 NULL,
566 NULL,
567 process_options_response);
569 g_free(to);
570 g_free(request);
573 static gboolean process_get_info_response(struct sipe_core_private *sipe_private,
574 struct sipmsg *msg,
575 struct transaction *trans)
577 const gchar *uri = trans->payload->data;
578 sipe_backend_buddy bbuddy;
579 struct sipe_backend_buddy_info *info;
580 struct sipe_buddy *sbuddy;
581 gchar *alias = NULL;
582 gchar *device_name = NULL;
583 gchar *server_alias = NULL;
584 gchar *phone_number = NULL;
585 gchar *email = NULL;
586 gchar *site;
588 SIPE_DEBUG_INFO("Fetching %s's user info for %s",
589 uri, sipe_private->username);
591 info = sipe_backend_buddy_info_start(SIPE_CORE_PUBLIC);
592 if (!info) return(FALSE);
594 bbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, uri, NULL);
595 alias = sipe_backend_buddy_get_local_alias(SIPE_CORE_PUBLIC, bbuddy);
597 /* will query buddy UA's capabilities and send answer to log */
598 if (sipe_backend_debug_enabled())
599 sipe_options_request(sipe_private, uri);
601 sbuddy = g_hash_table_lookup(sipe_private->buddies, uri);
602 if (sbuddy) {
603 device_name = sbuddy->device_name ? g_strdup(sbuddy->device_name) : NULL;
606 if (msg->response != 200) {
607 SIPE_DEBUG_INFO("process_get_info_response: SERVICE response is %d", msg->response);
608 } else {
609 sipe_xml *searchResults;
610 const sipe_xml *mrow;
612 SIPE_DEBUG_INFO("process_get_info_response: body:\n%s",
613 msg->body ? msg->body : "");
615 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
616 if (!searchResults) {
618 SIPE_DEBUG_INFO_NOFORMAT("process_get_info_response: no parseable searchResults");
620 } else if ((mrow = sipe_xml_child(searchResults, "Body/Array/row"))) {
621 const gchar *value;
623 server_alias = g_strdup(sipe_xml_attribute(mrow, "displayName"));
624 email = g_strdup(sipe_xml_attribute(mrow, "email"));
625 phone_number = g_strdup(sipe_xml_attribute(mrow, "phone"));
628 * For 2007 system we will take this from ContactCard -
629 * it has cleaner tel: URIs at least
631 if (!SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
632 char *tel_uri = sip_to_tel_uri(phone_number);
633 /* trims its parameters, so call first */
634 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_DISPLAY_NAME, server_alias);
635 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_EMAIL, email);
636 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE, tel_uri);
637 sipe_buddy_update_property(sipe_private, uri, SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, phone_number);
638 g_free(tel_uri);
641 if (server_alias && strlen(server_alias) > 0) {
642 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
643 info,
644 _("Display name"),
645 server_alias);
647 if ((value = sipe_xml_attribute(mrow, "title")) && strlen(value) > 0) {
648 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
649 info,
650 _("Job title"),
651 value);
653 if ((value = sipe_xml_attribute(mrow, "office")) && strlen(value) > 0) {
654 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
655 info,
656 _("Office"),
657 value);
659 if (phone_number && strlen(phone_number) > 0) {
660 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
661 info,
662 _("Business phone"),
663 phone_number);
665 if ((value = sipe_xml_attribute(mrow, "company")) && strlen(value) > 0) {
666 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
667 info,
668 _("Company"),
669 value);
671 if ((value = sipe_xml_attribute(mrow, "city")) && strlen(value) > 0) {
672 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
673 info,
674 _("City"),
675 value);
677 if ((value = sipe_xml_attribute(mrow, "state")) && strlen(value) > 0) {
678 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
679 info,
680 _("State"),
681 value);
683 if ((value = sipe_xml_attribute(mrow, "country")) && strlen(value) > 0) {
684 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
685 info,
686 _("Country"),
687 value);
689 if (email && strlen(email) > 0) {
690 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
691 info,
692 _("Email address"),
693 email);
697 sipe_xml_free(searchResults);
700 sipe_backend_buddy_info_break(SIPE_CORE_PUBLIC, info);
702 if (is_empty(server_alias)) {
703 g_free(server_alias);
704 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC,
705 bbuddy);
706 if (server_alias) {
707 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
708 info,
709 _("Display name"),
710 server_alias);
714 /* present alias if it differs from server alias */
715 if (alias && !sipe_strequal(alias, server_alias))
717 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
718 info,
719 _("Alias"),
720 alias);
723 if (is_empty(email)) {
724 g_free(email);
725 email = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,
726 bbuddy,
727 SIPE_BUDDY_INFO_EMAIL);
728 if (email) {
729 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
730 info,
731 _("Email address"),
732 email);
736 site = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC,
737 bbuddy,
738 SIPE_BUDDY_INFO_SITE);
739 if (site) {
740 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
741 info,
742 _("Site"),
743 site);
744 g_free(site);
747 if (device_name) {
748 sipe_backend_buddy_info_add(SIPE_CORE_PUBLIC,
749 info,
750 _("Device"),
751 device_name);
754 sipe_backend_buddy_info_finalize(SIPE_CORE_PUBLIC, info, uri);
756 g_free(phone_number);
757 g_free(server_alias);
758 g_free(email);
759 g_free(device_name);
760 g_free(alias);
762 return TRUE;
766 * AD search first, LDAP based
768 void sipe_core_buddy_get_info(struct sipe_core_public *sipe_public,
769 const gchar *who)
771 char *row = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW,
772 "msRTCSIP-PrimaryUserAddress",
773 who);
774 struct transaction_payload *payload = g_new0(struct transaction_payload, 1);
776 SIPE_DEBUG_INFO("sipe_core_buddy_get_info: row: %s", row ? row : "");
778 payload->destroy = g_free;
779 payload->data = g_strdup(who);
781 sip_soap_directory_search(SIPE_CORE_PRIVATE,
783 row,
784 process_get_info_response,
785 payload);
786 g_free(row);
790 Local Variables:
791 mode: c
792 c-file-style: "bsd"
793 indent-tabs-mode: t
794 tab-width: 8
795 End: