group: refactor add buddy to group code
[siplcs.git] / src / core / sipe-group.c
blobbea3fcb7308ccb0f42fec81c14ec1d272dbd1026
1 /**
2 * @file sipe-group.c
4 * pidgin-sipe
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
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include <glib.h>
29 #include "sipmsg.h"
30 #include "sip-soap.h"
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"
37 #include "sipe-nls.h"
38 #include "sipe-ucs.h"
39 #include "sipe-utils.h"
40 #include "sipe-xml.h"
42 struct sipe_groups {
43 GSList *list;
46 struct group_user_context {
47 gchar *group_name;
48 gchar *user_name;
51 static void
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);
57 g_free(ctx);
60 static gboolean
61 process_add_group_response(struct sipe_core_private *sipe_private,
62 struct sipmsg *msg,
63 struct transaction *trans)
65 if (msg->response == 200) {
66 struct sipe_group *group;
67 struct group_user_context *ctx = trans->payload->data;
68 sipe_xml *xml;
69 const sipe_xml *node;
70 char *group_id;
72 xml = sipe_xml_parse(msg->body, msg->bodylen);
73 if (!xml) {
74 return FALSE;
77 node = sipe_xml_child(xml, "Body/addGroup/groupID");
78 if (!node) {
79 sipe_xml_free(xml);
80 return FALSE;
83 group_id = sipe_xml_data(node);
84 if (!group_id) {
85 sipe_xml_free(xml);
86 return FALSE;
89 group = sipe_group_add(sipe_private,
90 ctx->group_name,
91 NULL,
92 NULL,
93 g_ascii_strtoull(group_id, NULL, 10));
94 g_free(group_id);
96 if (group) {
97 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
98 ctx->user_name);
99 if (buddy) {
100 sipe_buddy_insert_group(buddy, group);
101 sipe_group_update_buddy(sipe_private, buddy);
105 sipe_xml_free(xml);
106 return TRUE;
108 return FALSE;
111 struct sipe_group*
112 sipe_group_find_by_id(struct sipe_core_private *sipe_private,
113 guint id)
115 struct sipe_group *group;
116 GSList *entry;
118 if (!sipe_private)
119 return NULL;
121 entry = sipe_private->groups->list;
122 while (entry) {
123 group = entry->data;
124 if (group->id == id) {
125 return group;
127 entry = entry->next;
129 return NULL;
132 struct sipe_group*
133 sipe_group_find_by_name(struct sipe_core_private *sipe_private,
134 const gchar * name)
136 struct sipe_group *group;
137 GSList *entry;
139 if (!sipe_private || !name)
140 return NULL;
142 entry = sipe_private->groups->list;
143 while (entry) {
144 group = entry->data;
145 if (sipe_strequal(group->name, name)) {
146 return group;
148 entry = entry->next;
150 return NULL;
153 void
154 sipe_group_create(struct sipe_core_private *sipe_private,
155 const gchar *name,
156 const gchar *who)
158 if (sipe_ucs_is_migrated(sipe_private)) {
159 sipe_ucs_group_create(sipe_private,
160 name,
161 who);
162 } else {
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;
166 gchar *request;
167 ctx->group_name = g_strdup(name);
168 ctx->user_name = g_strdup(who);
169 payload->destroy = sipe_group_context_destroy;
170 payload->data = ctx;
172 /* soap_name can contain restricted characters */
173 request = g_markup_printf_escaped("<m:name>%s</m:name>"
174 "<m:externalURI />",
175 soap_name);
176 sip_soap_request_cb(sipe_private,
177 "addGroup",
178 request,
179 process_add_group_response,
180 payload);
181 g_free(request);
185 gboolean sipe_group_rename(struct sipe_core_private *sipe_private,
186 struct sipe_group *group,
187 const gchar *name)
189 gboolean renamed = sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC,
190 group->name,
191 name);
192 if (renamed) {
193 g_free(group->name);
194 group->name = g_strdup(name);
196 return(renamed);
199 struct sipe_group *sipe_group_add(struct sipe_core_private *sipe_private,
200 const gchar *name,
201 const gchar *exchange_key,
202 const gchar *change_key,
203 guint id)
205 struct sipe_group *group = NULL;
207 if (!is_empty(name)) {
208 group = sipe_group_find_by_name(sipe_private, name);
210 if (!group &&
211 sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC, name)) {
213 group = g_new0(struct sipe_group, 1);
214 group->name = g_strdup(name);
215 group->id = id;
217 if (exchange_key)
218 group->exchange_key = g_strdup(exchange_key);
219 if (change_key)
220 group->change_key = g_strdup(change_key);
222 sipe_private->groups->list = g_slist_append(sipe_private->groups->list,
223 group);
225 SIPE_DEBUG_INFO("sipe_group_add: created backend group '%s' with id %d",
226 group->name, group->id);
227 } else {
228 SIPE_DEBUG_INFO("sipe_group_add: backend group '%s' already exists",
229 name ? name : "");
230 if (group)
231 group->is_obsolete = FALSE;
235 return(group);
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,
242 group);
243 g_free(group->name);
244 g_free(group->exchange_key);
245 g_free(group->change_key);
246 g_free(group);
249 void sipe_group_remove(struct sipe_core_private *sipe_private,
250 struct sipe_group *group)
252 if (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);
259 void
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);
267 if (s_group) {
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,
272 s_group,
273 new_name);
274 } else {
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>"
278 "<m:externalURI />",
279 s_group->id,
280 new_name);
281 sip_soap_request(sipe_private,
282 "modifyGroup",
283 request);
284 g_free(request);
287 g_free(s_group->name);
288 s_group->name = g_strdup(new_name);
289 } else {
290 SIPE_DEBUG_INFO("sipe_core_group_rename: cannot find group '%s'", old_name);
294 void
295 sipe_core_group_remove(struct sipe_core_public *sipe_public,
296 const gchar *name)
298 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
299 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, name);
301 if (s_group) {
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,
309 s_group);
310 } else {
311 gchar *request = g_strdup_printf("<m:groupID>%d</m:groupID>",
312 s_group->id);
313 sip_soap_request(sipe_private,
314 "deleteGroup",
315 request);
316 g_free(request);
319 group_free(sipe_private, s_group);
321 } else {
322 SIPE_DEBUG_INFO("sipe_core_group_remove: cannot find group '%s'", name);
327 * Sends buddy update to server
329 static void send_buddy_update(struct sipe_core_private *sipe_private,
330 struct sipe_buddy *buddy,
331 const gchar *alias)
333 gchar *groups = sipe_buddy_groups_string(buddy);
335 if (groups) {
336 gchar *request;
337 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
338 buddy->name, alias, groups);
340 /* alias can contain restricted characters */
341 request = g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
342 "<m:groups>%s</m:groups>"
343 "<m:subscribed>true</m:subscribed>"
344 "<m:URI>%s</m:URI>"
345 "<m:externalURI />",
346 alias, groups, buddy->name);
347 g_free(groups);
349 sip_soap_request(sipe_private,
350 "setContact",
351 request);
352 g_free(request);
356 /* indicates that buddy information on the server needs updating */
357 void sipe_group_update_buddy(struct sipe_core_private *sipe_private,
358 struct sipe_buddy *buddy)
360 if (buddy) {
361 sipe_backend_buddy backend_buddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,
362 buddy->name,
363 NULL);
364 if (backend_buddy) {
365 gchar *alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,
366 backend_buddy);
367 send_buddy_update(sipe_private, buddy, alias);
368 g_free(alias);
373 void sipe_core_group_set_alias(struct sipe_core_public *sipe_public,
374 const gchar *who,
375 const gchar *alias)
377 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
378 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
379 who);
381 if (buddy)
382 send_buddy_update(sipe_private, buddy, alias);
385 void sipe_group_update_start(struct sipe_core_private *sipe_private)
387 GSList *entry = sipe_private->groups->list;
389 while (entry) {
390 ((struct sipe_group *) entry->data)->is_obsolete = TRUE;
391 entry = entry->next;
395 void sipe_group_update_finish(struct sipe_core_private *sipe_private)
397 GSList *entry = sipe_private->groups->list;
399 while (entry) {
400 struct sipe_group *group = entry->data;
402 /* next group entry */
403 entry = entry->next;
405 if (group->is_obsolete)
406 sipe_group_remove(sipe_private, group);
410 struct sipe_group *sipe_group_first(struct sipe_core_private *sipe_private)
412 return(sipe_private->groups->list ? sipe_private->groups->list->data : NULL);
415 guint sipe_group_count(struct sipe_core_private *sipe_private)
417 return(g_slist_length(sipe_private->groups->list));
420 void sipe_group_init(struct sipe_core_private *sipe_private)
422 sipe_private->groups = g_new0(struct sipe_groups, 1);
425 void sipe_group_free(struct sipe_core_private *sipe_private)
427 GSList *entry;
429 while ((entry = sipe_private->groups->list) != NULL)
430 group_free(sipe_private, entry->data);
432 g_free(sipe_private->groups);
433 sipe_private->groups = NULL;
437 Local Variables:
438 mode: c
439 c-file-style: "bsd"
440 indent-tabs-mode: t
441 tab-width: 8
442 End: