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
,
155 struct sipe_ucs_transaction
*trans
,
159 /* "trans" is always set for UCS code paths, otherwise NULL */
161 sipe_ucs_group_create(sipe_private
,
166 struct transaction_payload
*payload
= g_new0(struct transaction_payload
, 1);
167 struct group_user_context
*ctx
= g_new0(struct group_user_context
, 1);
168 const gchar
*soap_name
= sipe_strequal(name
, _("Other Contacts")) ? "~" : name
;
170 ctx
->group_name
= g_strdup(name
);
171 ctx
->user_name
= g_strdup(who
);
172 payload
->destroy
= sipe_group_context_destroy
;
175 /* soap_name can contain restricted characters */
176 request
= g_markup_printf_escaped("<m:name>%s</m:name>"
179 sip_soap_request_cb(sipe_private
,
182 process_add_group_response
,
188 gboolean
sipe_group_rename(struct sipe_core_private
*sipe_private
,
189 struct sipe_group
*group
,
192 gboolean renamed
= sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC
,
197 group
->name
= g_strdup(name
);
202 struct sipe_group
*sipe_group_add(struct sipe_core_private
*sipe_private
,
204 const gchar
*exchange_key
,
205 const gchar
*change_key
,
208 struct sipe_group
*group
= NULL
;
210 if (!is_empty(name
)) {
211 group
= sipe_group_find_by_name(sipe_private
, name
);
214 sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC
, name
)) {
216 group
= g_new0(struct sipe_group
, 1);
217 group
->name
= g_strdup(name
);
221 group
->exchange_key
= g_strdup(exchange_key
);
223 group
->change_key
= g_strdup(change_key
);
225 sipe_private
->groups
->list
= g_slist_append(sipe_private
->groups
->list
,
228 SIPE_DEBUG_INFO("sipe_group_add: created backend group '%s' with id %d",
229 group
->name
, group
->id
);
231 SIPE_DEBUG_INFO("sipe_group_add: backend group '%s' already exists",
234 group
->is_obsolete
= FALSE
;
241 static void group_free(struct sipe_core_private
*sipe_private
,
242 struct sipe_group
*group
)
244 sipe_private
->groups
->list
= g_slist_remove(sipe_private
->groups
->list
,
247 g_free(group
->exchange_key
);
248 g_free(group
->change_key
);
252 void sipe_group_remove(struct sipe_core_private
*sipe_private
,
253 struct sipe_group
*group
)
256 SIPE_DEBUG_INFO("sipe_group_remove: %s (id %d)", group
->name
, group
->id
);
257 sipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC
, group
->name
);
258 group_free(sipe_private
, group
);
263 sipe_core_group_rename(struct sipe_core_public
*sipe_public
,
264 const gchar
*old_name
,
265 const gchar
*new_name
)
267 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
268 struct sipe_group
*s_group
= sipe_group_find_by_name(sipe_private
, old_name
);
271 SIPE_DEBUG_INFO("sipe_core_group_rename: from '%s' to '%s'", old_name
, new_name
);
273 if (sipe_ucs_is_migrated(sipe_private
)) {
274 sipe_ucs_group_rename(sipe_private
,
278 /* new_name can contain restricted characters */
279 gchar
*request
= g_markup_printf_escaped("<m:groupID>%d</m:groupID>"
280 "<m:name>%s</m:name>"
284 sip_soap_request(sipe_private
,
290 g_free(s_group
->name
);
291 s_group
->name
= g_strdup(new_name
);
293 SIPE_DEBUG_INFO("sipe_core_group_rename: cannot find group '%s'", old_name
);
298 sipe_core_group_remove(struct sipe_core_public
*sipe_public
,
301 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
302 struct sipe_group
*s_group
= sipe_group_find_by_name(sipe_private
, name
);
306 /* ignore backend events while deleting obsoleted groups */
307 if (!s_group
->is_obsolete
) {
308 SIPE_DEBUG_INFO("sipe_core_group_remove: delete '%s'", name
);
310 if (sipe_ucs_is_migrated(sipe_private
)) {
311 sipe_ucs_group_remove(sipe_private
,
314 gchar
*request
= g_strdup_printf("<m:groupID>%d</m:groupID>",
316 sip_soap_request(sipe_private
,
322 group_free(sipe_private
, s_group
);
325 SIPE_DEBUG_INFO("sipe_core_group_remove: cannot find group '%s'", name
);
330 * Sends buddy update to server
332 * NOTE: must not be called when contact list has been migrated to UCS
334 static void send_buddy_update(struct sipe_core_private
*sipe_private
,
335 struct sipe_buddy
*buddy
,
338 gchar
*groups
= sipe_buddy_groups_string(buddy
);
342 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
343 buddy
->name
, alias
, groups
);
345 /* alias can contain restricted characters */
346 request
= g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
347 "<m:groups>%s</m:groups>"
348 "<m:subscribed>true</m:subscribed>"
356 sip_soap_request(sipe_private
,
364 * indicates that buddy information on the server needs updating
366 * NOTE: must not be called when contact list has been migrated to UCS
368 void sipe_group_update_buddy(struct sipe_core_private
*sipe_private
,
369 struct sipe_buddy
*buddy
)
372 sipe_backend_buddy backend_buddy
= sipe_backend_buddy_find(SIPE_CORE_PUBLIC
,
376 gchar
*alias
= sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC
,
378 send_buddy_update(sipe_private
, buddy
, alias
);
385 * @param alias new alias (may be @c NULL)
387 void sipe_core_group_set_alias(struct sipe_core_public
*sipe_public
,
391 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
393 /* UCS does not support setting of display name/alias */
394 if (sipe_ucs_is_migrated(sipe_private
))
395 SIPE_DEBUG_INFO("sipe_core_group_set_alias: not supported for UCS (uri '%s' alias '%s')",
396 who
, alias
? alias
: "<UNDEFINED>");
398 struct sipe_buddy
*buddy
= sipe_buddy_find_by_uri(sipe_private
,
402 send_buddy_update(sipe_private
, buddy
, alias
);
406 void sipe_group_update_start(struct sipe_core_private
*sipe_private
)
408 GSList
*entry
= sipe_private
->groups
->list
;
411 ((struct sipe_group
*) entry
->data
)->is_obsolete
= TRUE
;
416 void sipe_group_update_finish(struct sipe_core_private
*sipe_private
)
418 GSList
*entry
= sipe_private
->groups
->list
;
421 struct sipe_group
*group
= entry
->data
;
423 /* next group entry */
426 if (group
->is_obsolete
)
427 sipe_group_remove(sipe_private
, group
);
431 struct sipe_group
*sipe_group_first(struct sipe_core_private
*sipe_private
)
433 return(sipe_private
->groups
->list
? sipe_private
->groups
->list
->data
: NULL
);
436 guint
sipe_group_count(struct sipe_core_private
*sipe_private
)
438 return(g_slist_length(sipe_private
->groups
->list
));
441 void sipe_group_init(struct sipe_core_private
*sipe_private
)
443 sipe_private
->groups
= g_new0(struct sipe_groups
, 1);
446 void sipe_group_free(struct sipe_core_private
*sipe_private
)
450 while ((entry
= sipe_private
->groups
->list
) != NULL
)
451 group_free(sipe_private
, entry
->data
);
453 g_free(sipe_private
->groups
);
454 sipe_private
->groups
= NULL
;