6 * Copyright (C) 2011-2013 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
31 #include "sip-transport.h"
32 #include "sipe-backend.h"
33 #include "sipe-buddy.h"
34 #include "sipe-core.h"
35 #include "sipe-core-private.h"
36 #include "sipe-group.h"
39 #include "sipe-utils.h"
46 struct group_user_context
{
52 sipe_group_context_destroy(gpointer data
)
54 struct group_user_context
*ctx
= data
;
55 g_free(ctx
->group_name
);
56 g_free(ctx
->user_name
);
61 process_add_group_response(struct sipe_core_private
*sipe_private
,
63 struct transaction
*trans
)
65 if (msg
->response
== 200) {
66 struct sipe_group
*group
;
67 struct group_user_context
*ctx
= trans
->payload
->data
;
72 xml
= sipe_xml_parse(msg
->body
, msg
->bodylen
);
77 node
= sipe_xml_child(xml
, "Body/addGroup/groupID");
83 group_id
= sipe_xml_data(node
);
89 group
= sipe_group_add(sipe_private
,
93 g_ascii_strtoull(group_id
, NULL
, 10));
97 struct sipe_buddy
*buddy
= sipe_buddy_find_by_uri(sipe_private
,
100 sipe_buddy_insert_group(buddy
, group
);
101 sipe_group_update_buddy(sipe_private
, buddy
);
112 sipe_group_find_by_id(struct sipe_core_private
*sipe_private
,
115 struct sipe_group
*group
;
121 entry
= sipe_private
->groups
->list
;
124 if (group
->id
== id
) {
133 sipe_group_find_by_name(struct sipe_core_private
*sipe_private
,
136 struct sipe_group
*group
;
139 if (!sipe_private
|| !name
)
142 entry
= sipe_private
->groups
->list
;
145 if (sipe_strequal(group
->name
, name
)) {
154 sipe_group_create(struct sipe_core_private
*sipe_private
,
158 if (sipe_ucs_is_migrated(sipe_private
)) {
159 sipe_ucs_group_create(sipe_private
,
163 struct transaction_payload
*payload
= g_new0(struct transaction_payload
, 1);
164 struct group_user_context
*ctx
= g_new0(struct group_user_context
, 1);
165 const gchar
*soap_name
= sipe_strequal(name
, _("Other Contacts")) ? "~" : name
;
167 ctx
->group_name
= g_strdup(name
);
168 ctx
->user_name
= g_strdup(who
);
169 payload
->destroy
= sipe_group_context_destroy
;
172 /* soap_name can contain restricted characters */
173 request
= g_markup_printf_escaped("<m:name>%s</m:name>"
176 sip_soap_request_cb(sipe_private
,
179 process_add_group_response
,
185 gboolean
sipe_group_rename(struct sipe_core_private
*sipe_private
,
186 struct sipe_group
*group
,
189 gboolean renamed
= sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC
,
194 group
->name
= g_strdup(name
);
199 struct sipe_group
*sipe_group_add(struct sipe_core_private
*sipe_private
,
201 const gchar
*exchange_key
,
202 const gchar
*change_key
,
205 struct sipe_group
*group
= NULL
;
207 if (!is_empty(name
)) {
208 group
= sipe_group_find_by_name(sipe_private
, name
);
211 sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC
, name
)) {
213 group
= g_new0(struct sipe_group
, 1);
214 group
->name
= g_strdup(name
);
218 group
->exchange_key
= g_strdup(exchange_key
);
220 group
->change_key
= g_strdup(change_key
);
222 sipe_private
->groups
->list
= g_slist_append(sipe_private
->groups
->list
,
225 SIPE_DEBUG_INFO("sipe_group_add: created backend group '%s' with id %d",
226 group
->name
, group
->id
);
228 SIPE_DEBUG_INFO("sipe_group_add: backend group '%s' already exists",
231 group
->is_obsolete
= FALSE
;
238 static void group_free(struct sipe_core_private
*sipe_private
,
239 struct sipe_group
*group
)
241 sipe_private
->groups
->list
= g_slist_remove(sipe_private
->groups
->list
,
244 g_free(group
->exchange_key
);
245 g_free(group
->change_key
);
249 void sipe_group_remove(struct sipe_core_private
*sipe_private
,
250 struct sipe_group
*group
)
253 SIPE_DEBUG_INFO("sipe_group_remove: %s (id %d)", group
->name
, group
->id
);
254 sipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC
, group
->name
);
255 group_free(sipe_private
, group
);
260 sipe_core_group_rename(struct sipe_core_public
*sipe_public
,
261 const gchar
*old_name
,
262 const gchar
*new_name
)
264 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
265 struct sipe_group
*s_group
= sipe_group_find_by_name(sipe_private
, old_name
);
268 SIPE_DEBUG_INFO("sipe_core_group_rename: from '%s' to '%s'", old_name
, new_name
);
270 if (sipe_ucs_is_migrated(sipe_private
)) {
271 sipe_ucs_group_rename(sipe_private
,
275 /* new_name can contain restricted characters */
276 gchar
*request
= g_markup_printf_escaped("<m:groupID>%d</m:groupID>"
277 "<m:name>%s</m:name>"
281 sip_soap_request(sipe_private
,
287 g_free(s_group
->name
);
288 s_group
->name
= g_strdup(new_name
);
290 SIPE_DEBUG_INFO("sipe_core_group_rename: cannot find group '%s'", old_name
);
295 sipe_core_group_remove(struct sipe_core_public
*sipe_public
,
298 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
299 struct sipe_group
*s_group
= sipe_group_find_by_name(sipe_private
, name
);
303 /* ignore backend events while deleting obsoleted groups */
304 if (!s_group
->is_obsolete
) {
305 SIPE_DEBUG_INFO("sipe_core_group_remove: delete '%s'", name
);
307 if (sipe_ucs_is_migrated(sipe_private
)) {
308 sipe_ucs_group_remove(sipe_private
,
311 gchar
*request
= g_strdup_printf("<m:groupID>%d</m:groupID>",
313 sip_soap_request(sipe_private
,
319 group_free(sipe_private
, s_group
);
322 SIPE_DEBUG_INFO("sipe_core_group_remove: cannot find group '%s'", name
);
327 * Sends buddy update to server
329 * NOTE: must not be called when contact list has been migrated to UCS
331 static void send_buddy_update(struct sipe_core_private
*sipe_private
,
332 struct sipe_buddy
*buddy
,
335 gchar
*groups
= sipe_buddy_groups_string(buddy
);
339 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
340 buddy
->name
, alias
, groups
);
342 /* alias can contain restricted characters */
343 request
= g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
344 "<m:groups>%s</m:groups>"
345 "<m:subscribed>true</m:subscribed>"
353 sip_soap_request(sipe_private
,
361 * indicates that buddy information on the server needs updating
363 * NOTE: must not be called when contact list has been migrated to UCS
365 void sipe_group_update_buddy(struct sipe_core_private
*sipe_private
,
366 struct sipe_buddy
*buddy
)
369 sipe_backend_buddy backend_buddy
= sipe_backend_buddy_find(SIPE_CORE_PUBLIC
,
373 gchar
*alias
= sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC
,
375 send_buddy_update(sipe_private
, buddy
, alias
);
382 * @param alias new alias (may be @c NULL)
384 void sipe_core_group_set_alias(struct sipe_core_public
*sipe_public
,
388 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
390 /* UCS does not support setting of display name/alias */
391 if (sipe_ucs_is_migrated(sipe_private
))
392 SIPE_DEBUG_INFO("sipe_core_group_set_alias: not supported for UCS (uri '%s' alias '%s')",
393 who
, alias
? alias
: "<UNDEFINED>");
395 struct sipe_buddy
*buddy
= sipe_buddy_find_by_uri(sipe_private
,
399 send_buddy_update(sipe_private
, buddy
, alias
);
403 void sipe_group_update_start(struct sipe_core_private
*sipe_private
)
405 GSList
*entry
= sipe_private
->groups
->list
;
408 ((struct sipe_group
*) entry
->data
)->is_obsolete
= TRUE
;
413 void sipe_group_update_finish(struct sipe_core_private
*sipe_private
)
415 GSList
*entry
= sipe_private
->groups
->list
;
418 struct sipe_group
*group
= entry
->data
;
420 /* next group entry */
423 if (group
->is_obsolete
)
424 sipe_group_remove(sipe_private
, group
);
428 struct sipe_group
*sipe_group_first(struct sipe_core_private
*sipe_private
)
430 return(sipe_private
->groups
->list
? sipe_private
->groups
->list
->data
: NULL
);
433 guint
sipe_group_count(struct sipe_core_private
*sipe_private
)
435 return(g_slist_length(sipe_private
->groups
->list
));
438 void sipe_group_init(struct sipe_core_private
*sipe_private
)
440 sipe_private
->groups
= g_new0(struct sipe_groups
, 1);
443 void sipe_group_free(struct sipe_core_private
*sipe_private
)
447 while ((entry
= sipe_private
->groups
->list
) != NULL
)
448 group_free(sipe_private
, entry
->data
);
450 g_free(sipe_private
->groups
);
451 sipe_private
->groups
= NULL
;