group: refactor group creation code
[siplcs.git] / src / core / sipe-group.c
blob5c2845585d73283e8e583b700e468a9e1e005f9c
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-utils.h"
39 #include "sipe-xml.h"
41 struct sipe_groups {
42 GSList *list;
45 struct group_user_context {
46 gchar *group_name;
47 gchar *user_name;
50 static void
51 sipe_group_context_destroy(gpointer data)
53 struct group_user_context *ctx = data;
54 g_free(ctx->group_name);
55 g_free(ctx->user_name);
56 g_free(ctx);
59 static gboolean
60 process_add_group_response(struct sipe_core_private *sipe_private,
61 struct sipmsg *msg,
62 struct transaction *trans)
64 if (msg->response == 200) {
65 struct sipe_group *group;
66 struct group_user_context *ctx = trans->payload->data;
67 sipe_xml *xml;
68 const sipe_xml *node;
69 char *group_id;
71 xml = sipe_xml_parse(msg->body, msg->bodylen);
72 if (!xml) {
73 return FALSE;
76 node = sipe_xml_child(xml, "Body/addGroup/groupID");
77 if (!node) {
78 sipe_xml_free(xml);
79 return FALSE;
82 group_id = sipe_xml_data(node);
83 if (!group_id) {
84 sipe_xml_free(xml);
85 return FALSE;
88 group = sipe_group_add(sipe_private,
89 ctx->group_name,
90 g_ascii_strtoull(group_id, NULL, 10));
91 g_free(group_id);
93 if (group && ctx->user_name) {
94 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
95 ctx->user_name);
96 if (buddy) {
97 buddy->groups = sipe_utils_slist_insert_unique_sorted(buddy->groups,
98 group,
99 (GCompareFunc)sipe_group_compare,
100 NULL);
101 sipe_group_update_buddy(sipe_private, buddy);
105 sipe_xml_free(xml);
106 return TRUE;
108 return FALSE;
112 sipe_group_compare(struct sipe_group *group1, struct sipe_group *group2) {
113 return group1->id - group2->id;
116 struct sipe_group*
117 sipe_group_find_by_id(struct sipe_core_private *sipe_private,
118 guint id)
120 struct sipe_group *group;
121 GSList *entry;
123 if (!sipe_private)
124 return NULL;
126 entry = sipe_private->groups->list;
127 while (entry) {
128 group = entry->data;
129 if (group->id == id) {
130 return group;
132 entry = entry->next;
134 return NULL;
137 struct sipe_group*
138 sipe_group_find_by_name(struct sipe_core_private *sipe_private,
139 const gchar * name)
141 struct sipe_group *group;
142 GSList *entry;
144 if (!sipe_private || !name)
145 return NULL;
147 entry = sipe_private->groups->list;
148 while (entry) {
149 group = entry->data;
150 if (sipe_strequal(group->name, name)) {
151 return group;
153 entry = entry->next;
155 return NULL;
158 void
159 sipe_group_create(struct sipe_core_private *sipe_private,
160 const gchar *name,
161 const gchar *who)
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);
184 gboolean sipe_group_rename(struct sipe_core_private *sipe_private,
185 struct sipe_group *group,
186 const gchar *name)
188 gboolean renamed = sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC,
189 group->name,
190 name);
191 if (renamed) {
192 g_free(group->name);
193 group->name = g_strdup(name);
195 return(renamed);
198 struct sipe_group *sipe_group_add(struct sipe_core_private *sipe_private,
199 const gchar *name,
200 guint id)
202 struct sipe_group *group = NULL;
204 if (!is_empty(name) &&
205 sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC, name)) {
207 group = g_new0(struct sipe_group, 1);
208 group->name = g_strdup(name);
209 group->id = id;
211 sipe_private->groups->list = g_slist_append(sipe_private->groups->list,
212 group);
214 SIPE_DEBUG_INFO("sipe_group_add: created backend group '%s' with id %d",
215 group->name, group->id);
216 } else
217 SIPE_DEBUG_INFO("sipe_group_add: backend group '%s' already exists",
218 name ? name : "");
220 return(group);
223 static void group_free(struct sipe_core_private *sipe_private,
224 struct sipe_group *group)
226 sipe_private->groups->list = g_slist_remove(sipe_private->groups->list,
227 group);
228 g_free(group->name);
229 g_free(group);
232 void sipe_group_remove(struct sipe_core_private *sipe_private,
233 struct sipe_group *group)
235 if (group) {
236 SIPE_DEBUG_INFO("removing group %s (id %d)", group->name, group->id);
237 sipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC, group->name);
238 group_free(sipe_private, group);
242 void
243 sipe_core_group_rename(struct sipe_core_public *sipe_public,
244 const gchar *old_name,
245 const gchar *new_name)
247 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
248 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, old_name);
250 if (s_group) {
251 gchar *request;
252 SIPE_DEBUG_INFO("Renaming group %s to %s", old_name, new_name);
253 /* new_name can contain restricted characters */
254 request = g_markup_printf_escaped("<m:groupID>%d</m:groupID>"
255 "<m:name>%s</m:name>"
256 "<m:externalURI />",
257 s_group->id, new_name);
258 sip_soap_request(sipe_private,
259 "modifyGroup",
260 request);
261 g_free(request);
263 g_free(s_group->name);
264 s_group->name = g_strdup(new_name);
265 } else {
266 SIPE_DEBUG_INFO("Cannot find group %s to rename", old_name);
270 void
271 sipe_core_group_remove(struct sipe_core_public *sipe_public,
272 const gchar *name)
274 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
275 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, name);
277 if (s_group) {
278 gchar *request;
279 SIPE_DEBUG_INFO("Deleting group %s", name);
280 request = g_strdup_printf("<m:groupID>%d</m:groupID>",
281 s_group->id);
282 sip_soap_request(sipe_private,
283 "deleteGroup",
284 request);
285 g_free(request);
287 group_free(sipe_private, s_group);
288 } else {
289 SIPE_DEBUG_INFO("Cannot find group %s to delete", name);
294 * Returns string like "2 4 7 8" - group ids buddy belong to.
296 static gchar *sipe_get_buddy_groups_string(struct sipe_buddy *buddy)
298 int i = 0;
299 gchar *res;
300 //creating array from GList, converting int to gchar*
301 gchar **ids_arr = g_new(gchar *, g_slist_length(buddy->groups) + 1);
302 GSList *entry = buddy->groups;
304 if (!ids_arr) return NULL;
306 while (entry) {
307 struct sipe_group * group = entry->data;
308 ids_arr[i] = g_strdup_printf("%d", group->id);
309 entry = entry->next;
310 i++;
312 ids_arr[i] = NULL;
313 res = g_strjoinv(" ", ids_arr);
314 g_strfreev(ids_arr);
315 return res;
319 * Sends buddy update to server
321 static void send_buddy_update(struct sipe_core_private *sipe_private,
322 struct sipe_buddy *buddy,
323 const gchar *alias)
325 gchar *groups = sipe_get_buddy_groups_string(buddy);
327 if (groups) {
328 gchar *request;
329 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
330 buddy->name, alias, groups);
332 /* alias can contain restricted characters */
333 request = g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
334 "<m:groups>%s</m:groups>"
335 "<m:subscribed>true</m:subscribed>"
336 "<m:URI>%s</m:URI>"
337 "<m:externalURI />",
338 alias, groups, buddy->name);
339 g_free(groups);
341 sip_soap_request(sipe_private,
342 "setContact",
343 request);
344 g_free(request);
348 /* indicates that buddy information on the server needs updating */
349 void sipe_group_update_buddy(struct sipe_core_private *sipe_private,
350 struct sipe_buddy *buddy)
352 if (buddy) {
353 sipe_backend_buddy backend_buddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,
354 buddy->name,
355 NULL);
356 if (backend_buddy) {
357 gchar *alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,
358 backend_buddy);
359 send_buddy_update(sipe_private, buddy, alias);
360 g_free(alias);
365 void sipe_core_group_set_alias(struct sipe_core_public *sipe_public,
366 const gchar *who,
367 const gchar *alias)
369 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
370 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
371 who);
373 if (buddy)
374 send_buddy_update(sipe_private, buddy, alias);
377 struct sipe_group *sipe_group_first(struct sipe_core_private *sipe_private)
379 return(sipe_private->groups->list ? sipe_private->groups->list->data : NULL);
382 guint sipe_group_count(struct sipe_core_private *sipe_private)
384 return(g_slist_length(sipe_private->groups->list));
387 void sipe_group_init(struct sipe_core_private *sipe_private)
389 sipe_private->groups = g_new0(struct sipe_groups, 1);
392 void sipe_group_free(struct sipe_core_private *sipe_private)
394 GSList *entry;
396 while ((entry = sipe_private->groups->list) != NULL)
397 group_free(sipe_private, entry->data);
399 g_free(sipe_private->groups);
400 sipe_private->groups = NULL;
404 Local Variables:
405 mode: c
406 c-file-style: "bsd"
407 indent-tabs-mode: t
408 tab-width: 8
409 End: