core cleanup: move sipe_core_buddy_info()
[siplcs.git] / src / core / sipe-buddy.c
blob75127f334a7b86346fb32c5252d437e1550f1f4e
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 <time.h>
29 #include <glib.h>
31 #include "sipe-common.h"
32 #include "http-conn.h" /* sipe-cal.h requires this */
33 #include "sipmsg.h"
34 #include "sip-soap.h"
35 #include "sipe-backend.h"
36 #include "sipe-buddy.h"
37 #include "sipe-cal.h"
38 #include "sipe-core.h"
39 #include "sipe-core-private.h"
40 #include "sipe-group.h"
41 #include "sipe-nls.h"
42 #include "sipe-ocs2007.h"
43 #include "sipe-utils.h"
44 #include "sipe-xml.h"
46 gchar *sipe_core_buddy_status(struct sipe_core_public *sipe_public,
47 const gchar *name,
48 const sipe_activity activity,
49 const gchar *status_text)
51 struct sipe_buddy *sbuddy;
52 const char *activity_str;
54 if (!sipe_public) return NULL; /* happens on pidgin exit */
56 sbuddy = g_hash_table_lookup(SIPE_CORE_PRIVATE->buddies, name);
57 if (!sbuddy) return NULL;
59 activity_str = sbuddy->activity ? sbuddy->activity :
60 (activity == SIPE_ACTIVITY_BUSY) || (activity == SIPE_ACTIVITY_BRB) ?
61 status_text : NULL;
63 if (activity_str && sbuddy->note) {
64 return g_strdup_printf("%s - <i>%s</i>", activity_str, sbuddy->note);
65 } else if (activity_str) {
66 return g_strdup(activity_str);
67 } else if (sbuddy->note) {
68 return g_strdup_printf("<i>%s</i>", sbuddy->note);
69 } else {
70 return NULL;
74 gchar *sipe_buddy_get_alias(struct sipe_core_private *sipe_private,
75 const gchar *with)
77 sipe_backend_buddy pbuddy;
78 gchar *alias = NULL;
79 if ((pbuddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC, with, NULL))) {
80 alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, pbuddy);
82 return alias;
85 void sipe_core_buddy_group(struct sipe_core_public *sipe_public,
86 const gchar *who,
87 const gchar *old_group_name,
88 const gchar *new_group_name)
90 struct sipe_buddy * buddy = g_hash_table_lookup(SIPE_CORE_PRIVATE->buddies, who);
91 struct sipe_group * old_group = NULL;
92 struct sipe_group * new_group;
94 SIPE_DEBUG_INFO("sipe_core_buddy_group: who:%s old_group_name:%s new_group_name:%s",
95 who ? who : "", old_group_name ? old_group_name : "", new_group_name ? new_group_name : "");
97 if(!buddy) { // buddy not in roaming list
98 return;
101 if (old_group_name) {
102 old_group = sipe_group_find_by_name(SIPE_CORE_PRIVATE, old_group_name);
104 new_group = sipe_group_find_by_name(SIPE_CORE_PRIVATE, new_group_name);
106 if (old_group) {
107 buddy->groups = g_slist_remove(buddy->groups, old_group);
108 SIPE_DEBUG_INFO("sipe_core_buddy_group: buddy %s removed from old group %s", who, old_group_name);
111 if (!new_group) {
112 sipe_group_create(SIPE_CORE_PRIVATE, new_group_name, who);
113 } else {
114 buddy->groups = slist_insert_unique_sorted(buddy->groups, new_group, (GCompareFunc)sipe_group_compare);
115 sipe_core_group_set_user(sipe_public, who);
119 GSList *sipe_core_buddy_info(struct sipe_core_public *sipe_public,
120 const gchar *name,
121 const gchar *status_name,
122 gboolean is_online)
124 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
125 gchar *note = NULL;
126 gboolean is_oof_note = FALSE;
127 const gchar *activity = NULL;
128 gchar *calendar = NULL;
129 const gchar *meeting_subject = NULL;
130 const gchar *meeting_location = NULL;
131 gchar *access_text = NULL;
132 GSList *info = NULL;
134 #define SIPE_ADD_BUDDY_INFO_COMMON(l, t) \
136 struct sipe_buddy_info *sbi = g_malloc(sizeof(struct sipe_buddy_info)); \
137 sbi->label = (l); \
138 sbi->text = (t); \
139 info = g_slist_append(info, sbi); \
141 #define SIPE_ADD_BUDDY_INFO(l, t) SIPE_ADD_BUDDY_INFO_COMMON((l), g_markup_escape_text((t), -1))
142 #define SIPE_ADD_BUDDY_INFO_NOESCAPE(l, t) SIPE_ADD_BUDDY_INFO_COMMON((l), (t))
144 if (sipe_public) { //happens on pidgin exit
145 struct sipe_buddy *sbuddy = g_hash_table_lookup(sipe_private->buddies, name);
146 if (sbuddy) {
147 note = sbuddy->note;
148 is_oof_note = sbuddy->is_oof_note;
149 activity = sbuddy->activity;
150 calendar = sipe_cal_get_description(sbuddy);
151 meeting_subject = sbuddy->meeting_subject;
152 meeting_location = sbuddy->meeting_location;
154 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007)) {
155 gboolean is_group_access = FALSE;
156 const int container_id = sipe_ocs2007_find_access_level(sipe_private, "user", sipe_get_no_sip_uri(name), &is_group_access);
157 const char *access_level = sipe_ocs2007_access_level_name(container_id);
158 access_text = is_group_access ?
159 g_strdup(access_level) :
160 g_strdup_printf(SIPE_OCS2007_INDENT_MARKED_FMT,
161 access_level);
165 if (is_online)
167 const gchar *status_str = activity ? activity : status_name;
169 SIPE_ADD_BUDDY_INFO(_("Status"), status_str);
171 if (is_online && !is_empty(calendar))
173 SIPE_ADD_BUDDY_INFO(_("Calendar"), calendar);
175 g_free(calendar);
176 if (!is_empty(meeting_location))
178 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting location: '%s'", name, meeting_location);
179 SIPE_ADD_BUDDY_INFO(_("Meeting in"), meeting_location);
181 if (!is_empty(meeting_subject))
183 SIPE_DEBUG_INFO("sipe_tooltip_text: %s meeting subject: '%s'", name, meeting_subject);
184 SIPE_ADD_BUDDY_INFO(_("Meeting about"), meeting_subject);
186 if (note)
188 SIPE_DEBUG_INFO("sipe_tooltip_text: %s note: '%s'", name, note);
189 SIPE_ADD_BUDDY_INFO_NOESCAPE(is_oof_note ? _("Out of office note") : _("Note"),
190 g_strdup_printf("<i>%s</i>", note));
192 if (access_text) {
193 SIPE_ADD_BUDDY_INFO(_("Access level"), access_text);
194 g_free(access_text);
197 return(info);
200 void sipe_buddy_update_property(struct sipe_core_private *sipe_private,
201 const char *uri,
202 sipe_buddy_info_fields propkey,
203 char *property_value)
205 GSList *buddies, *entry;
207 if (property_value)
208 property_value = g_strstrip(property_value);
210 entry = buddies = sipe_backend_buddy_find_all(SIPE_CORE_PUBLIC, uri, NULL); /* all buddies in different groups */
211 while (entry) {
212 gchar *prop_str;
213 gchar *server_alias;
214 gchar *alias;
215 sipe_backend_buddy p_buddy = entry->data;
217 /* for Display Name */
218 if (propkey == SIPE_BUDDY_INFO_DISPLAY_NAME) {
219 alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC, p_buddy);
220 if (property_value && sipe_is_bad_alias(uri, alias)) {
221 SIPE_DEBUG_INFO("Replacing alias for %s with %s", uri, property_value);
222 sipe_backend_buddy_set_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
224 g_free(alias);
226 server_alias = sipe_backend_buddy_get_server_alias(SIPE_CORE_PUBLIC, p_buddy);
227 if (!is_empty(property_value) &&
228 (!sipe_strequal(property_value, server_alias) || is_empty(server_alias)) )
230 SIPE_DEBUG_INFO("Replacing service alias for %s with %s", uri, property_value);
231 sipe_backend_buddy_set_server_alias(SIPE_CORE_PUBLIC, p_buddy, property_value);
233 g_free(server_alias);
235 /* for other properties */
236 else {
237 if (!is_empty(property_value)) {
238 prop_str = sipe_backend_buddy_get_string(SIPE_CORE_PUBLIC, p_buddy, propkey);
239 if (!prop_str || !sipe_strcase_equal(prop_str, property_value)) {
240 sipe_backend_buddy_set_string(SIPE_CORE_PUBLIC, p_buddy, propkey, property_value);
242 g_free(prop_str);
246 entry = entry->next;
248 g_slist_free(buddies);
251 static gboolean process_search_contact_response(struct sipe_core_private *sipe_private,
252 struct sipmsg *msg,
253 SIPE_UNUSED_PARAMETER struct transaction *trans)
255 struct sipe_backend_search_results *results;
256 sipe_xml *searchResults;
257 const sipe_xml *mrow;
258 guint match_count = 0;
259 gboolean more = FALSE;
260 gchar *secondary;
262 /* valid response? */
263 if (msg->response != 200) {
264 SIPE_DEBUG_ERROR("process_search_contact_response: request failed (%d)",
265 msg->response);
266 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
267 _("Contact search failed"),
268 NULL);
269 return(FALSE);
272 SIPE_DEBUG_INFO("process_search_contact_response: body:\n%s", msg->body ? msg->body : "");
274 /* valid XML? */
275 searchResults = sipe_xml_parse(msg->body, msg->bodylen);
276 if (!searchResults) {
277 SIPE_DEBUG_INFO_NOFORMAT("process_search_contact_response: no parseable searchResults");
278 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
279 _("Contact search failed"),
280 NULL);
281 return(FALSE);
284 /* any matches? */
285 mrow = sipe_xml_child(searchResults, "Body/Array/row");
286 if (!mrow) {
287 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: no matches");
288 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
289 _("No contacts found"),
290 NULL);
292 sipe_xml_free(searchResults);
293 return(FALSE);
296 /* OK, we found something - show the results to the user */
297 results = sipe_backend_search_results_start(SIPE_CORE_PUBLIC);
298 if (!results) {
299 SIPE_DEBUG_ERROR_NOFORMAT("process_search_contact_response: Unable to display the search results.");
300 sipe_backend_notify_error(SIPE_CORE_PUBLIC,
301 _("Unable to display the search results"),
302 NULL);
304 sipe_xml_free(searchResults);
305 return FALSE;
308 for (/* initialized above */ ; mrow; mrow = sipe_xml_twin(mrow)) {
309 gchar **uri_parts = g_strsplit(sipe_xml_attribute(mrow, "uri"), ":", 2);
310 sipe_backend_search_results_add(SIPE_CORE_PUBLIC,
311 results,
312 uri_parts[1],
313 sipe_xml_attribute(mrow, "displayName"),
314 sipe_xml_attribute(mrow, "company"),
315 sipe_xml_attribute(mrow, "country"),
316 sipe_xml_attribute(mrow, "email"));
317 g_strfreev(uri_parts);
318 match_count++;
321 if ((mrow = sipe_xml_child(searchResults, "Body/directorySearch/moreAvailable")) != NULL) {
322 char *data = sipe_xml_data(mrow);
323 more = (g_strcasecmp(data, "true") == 0);
324 g_free(data);
327 secondary = g_strdup_printf(
328 dngettext(PACKAGE_NAME,
329 "Found %d contact%s:",
330 "Found %d contacts%s:", match_count),
331 match_count, more ? _(" (more matched your query)") : "");
333 sipe_backend_search_results_finalize(SIPE_CORE_PUBLIC,
334 results,
335 secondary);
336 g_free(secondary);
337 sipe_xml_free(searchResults);
339 return(TRUE);
342 #define SIPE_SOAP_SEARCH_ROW "<m:row m:attrib=\"%s\" m:value=\"%s\"/>"
344 void sipe_core_buddy_search(struct sipe_core_public *sipe_public,
345 const gchar *given_name,
346 const gchar *surname,
347 const gchar *company,
348 const gchar *country)
350 gchar **attrs = g_new(gchar *, 5);
351 guint i = 0;
353 if (!attrs) return;
355 #define ADD_QUERY_ROW(a, v) \
356 if (v) attrs[i++] = g_markup_printf_escaped(SIPE_SOAP_SEARCH_ROW, a, v)
358 ADD_QUERY_ROW("givenName", given_name);
359 ADD_QUERY_ROW("sn", surname);
360 ADD_QUERY_ROW("company", company);
361 ADD_QUERY_ROW("c", country);
363 if (i) {
364 gchar *query;
366 attrs[i] = NULL;
367 query = g_strjoinv(NULL, attrs);
368 SIPE_DEBUG_INFO("sipe_core_buddy_search: rows:\n%s",
369 query ? query : "");
370 sip_soap_directory_search(SIPE_CORE_PRIVATE,
371 100,
372 query,
373 process_search_contact_response,
374 NULL);
375 g_free(query);
378 g_strfreev(attrs);
382 Local Variables:
383 mode: c
384 c-file-style: "bsd"
385 indent-tabs-mode: t
386 tab-width: 8
387 End: