ucs: add RemoveImGroup operation
[siplcs.git] / src / core / sipe-group.c
blob7885d86d8d307bc6c70abf70d07167fdb07e11ee
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 && ctx->user_name) {
97 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
98 ctx->user_name);
99 if (buddy) {
100 buddy->groups = sipe_utils_slist_insert_unique_sorted(buddy->groups,
101 group,
102 (GCompareFunc)sipe_group_compare,
103 NULL);
104 sipe_group_update_buddy(sipe_private, buddy);
108 sipe_xml_free(xml);
109 return TRUE;
111 return FALSE;
115 sipe_group_compare(struct sipe_group *group1, struct sipe_group *group2) {
116 return group1->id - group2->id;
119 struct sipe_group*
120 sipe_group_find_by_id(struct sipe_core_private *sipe_private,
121 guint id)
123 struct sipe_group *group;
124 GSList *entry;
126 if (!sipe_private)
127 return NULL;
129 entry = sipe_private->groups->list;
130 while (entry) {
131 group = entry->data;
132 if (group->id == id) {
133 return group;
135 entry = entry->next;
137 return NULL;
140 struct sipe_group*
141 sipe_group_find_by_name(struct sipe_core_private *sipe_private,
142 const gchar * name)
144 struct sipe_group *group;
145 GSList *entry;
147 if (!sipe_private || !name)
148 return NULL;
150 entry = sipe_private->groups->list;
151 while (entry) {
152 group = entry->data;
153 if (sipe_strequal(group->name, name)) {
154 return group;
156 entry = entry->next;
158 return NULL;
161 void
162 sipe_group_create(struct sipe_core_private *sipe_private,
163 const gchar *name,
164 const gchar *who)
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;
169 gchar *request;
170 ctx->group_name = g_strdup(name);
171 ctx->user_name = g_strdup(who);
172 payload->destroy = sipe_group_context_destroy;
173 payload->data = ctx;
175 /* soap_name can contain restricted characters */
176 request = g_markup_printf_escaped("<m:name>%s</m:name>"
177 "<m:externalURI />",
178 soap_name);
179 sip_soap_request_cb(sipe_private,
180 "addGroup",
181 request,
182 process_add_group_response,
183 payload);
184 g_free(request);
187 gboolean sipe_group_rename(struct sipe_core_private *sipe_private,
188 struct sipe_group *group,
189 const gchar *name)
191 gboolean renamed = sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC,
192 group->name,
193 name);
194 if (renamed) {
195 g_free(group->name);
196 group->name = g_strdup(name);
198 return(renamed);
201 struct sipe_group *sipe_group_add(struct sipe_core_private *sipe_private,
202 const gchar *name,
203 const gchar *exchange_key,
204 const gchar *change_key,
205 guint id)
207 struct sipe_group *group = NULL;
209 if (!is_empty(name) &&
210 sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC, name)) {
212 group = g_new0(struct sipe_group, 1);
213 group->name = g_strdup(name);
214 group->id = id;
216 if (exchange_key)
217 group->exchange_key = g_strdup(exchange_key);
218 if (change_key)
219 group->change_key = g_strdup(change_key);
221 sipe_private->groups->list = g_slist_append(sipe_private->groups->list,
222 group);
224 SIPE_DEBUG_INFO("sipe_group_add: created backend group '%s' with id %d",
225 group->name, group->id);
226 } else
227 SIPE_DEBUG_INFO("sipe_group_add: backend group '%s' already exists",
228 name ? name : "");
230 return(group);
233 static void group_free(struct sipe_core_private *sipe_private,
234 struct sipe_group *group)
236 sipe_private->groups->list = g_slist_remove(sipe_private->groups->list,
237 group);
238 g_free(group->name);
239 g_free(group->exchange_key);
240 g_free(group->change_key);
241 g_free(group);
244 void sipe_group_remove(struct sipe_core_private *sipe_private,
245 struct sipe_group *group)
247 if (group) {
248 SIPE_DEBUG_INFO("removing group %s (id %d)", group->name, group->id);
249 sipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC, group->name);
250 group_free(sipe_private, group);
254 void
255 sipe_core_group_rename(struct sipe_core_public *sipe_public,
256 const gchar *old_name,
257 const gchar *new_name)
259 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
260 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, old_name);
262 if (s_group) {
263 SIPE_DEBUG_INFO("sipe_core_group_rename: from '%s' to '%s'", old_name, new_name);
265 if (sipe_ucs_is_migrated(sipe_private)) {
266 sipe_ucs_group_rename(sipe_private,
267 s_group,
268 new_name);
269 } else {
270 /* new_name can contain restricted characters */
271 gchar *request = g_markup_printf_escaped("<m:groupID>%d</m:groupID>"
272 "<m:name>%s</m:name>"
273 "<m:externalURI />",
274 s_group->id,
275 new_name);
276 sip_soap_request(sipe_private,
277 "modifyGroup",
278 request);
279 g_free(request);
282 g_free(s_group->name);
283 s_group->name = g_strdup(new_name);
284 } else {
285 SIPE_DEBUG_INFO("sipe_core_group_rename: cannot find group '%s'", old_name);
289 void
290 sipe_core_group_remove(struct sipe_core_public *sipe_public,
291 const gchar *name)
293 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
294 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, name);
296 if (s_group) {
297 SIPE_DEBUG_INFO("sipe_core_group_remove: delete '%s'", name);
299 if (sipe_ucs_is_migrated(sipe_private)) {
300 sipe_ucs_group_remove(sipe_private,
301 s_group);
302 } else {
303 gchar *request = g_strdup_printf("<m:groupID>%d</m:groupID>",
304 s_group->id);
305 sip_soap_request(sipe_private,
306 "deleteGroup",
307 request);
308 g_free(request);
311 group_free(sipe_private, s_group);
312 } else {
313 SIPE_DEBUG_INFO("sipe_core_group_remove: cannot find group '%s'", name);
318 * Returns string like "2 4 7 8" - group ids buddy belong to.
320 static gchar *sipe_get_buddy_groups_string(struct sipe_buddy *buddy)
322 int i = 0;
323 gchar *res;
324 //creating array from GList, converting int to gchar*
325 gchar **ids_arr = g_new(gchar *, g_slist_length(buddy->groups) + 1);
326 GSList *entry = buddy->groups;
328 if (!ids_arr) return NULL;
330 while (entry) {
331 struct sipe_group * group = entry->data;
332 ids_arr[i] = g_strdup_printf("%d", group->id);
333 entry = entry->next;
334 i++;
336 ids_arr[i] = NULL;
337 res = g_strjoinv(" ", ids_arr);
338 g_strfreev(ids_arr);
339 return res;
343 * Sends buddy update to server
345 static void send_buddy_update(struct sipe_core_private *sipe_private,
346 struct sipe_buddy *buddy,
347 const gchar *alias)
349 gchar *groups = sipe_get_buddy_groups_string(buddy);
351 if (groups) {
352 gchar *request;
353 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
354 buddy->name, alias, groups);
356 /* alias can contain restricted characters */
357 request = g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
358 "<m:groups>%s</m:groups>"
359 "<m:subscribed>true</m:subscribed>"
360 "<m:URI>%s</m:URI>"
361 "<m:externalURI />",
362 alias, groups, buddy->name);
363 g_free(groups);
365 sip_soap_request(sipe_private,
366 "setContact",
367 request);
368 g_free(request);
372 /* indicates that buddy information on the server needs updating */
373 void sipe_group_update_buddy(struct sipe_core_private *sipe_private,
374 struct sipe_buddy *buddy)
376 if (buddy) {
377 sipe_backend_buddy backend_buddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,
378 buddy->name,
379 NULL);
380 if (backend_buddy) {
381 gchar *alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,
382 backend_buddy);
383 send_buddy_update(sipe_private, buddy, alias);
384 g_free(alias);
389 void sipe_core_group_set_alias(struct sipe_core_public *sipe_public,
390 const gchar *who,
391 const gchar *alias)
393 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
394 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
395 who);
397 if (buddy)
398 send_buddy_update(sipe_private, buddy, alias);
401 struct sipe_group *sipe_group_first(struct sipe_core_private *sipe_private)
403 return(sipe_private->groups->list ? sipe_private->groups->list->data : NULL);
406 guint sipe_group_count(struct sipe_core_private *sipe_private)
408 return(g_slist_length(sipe_private->groups->list));
411 void sipe_group_init(struct sipe_core_private *sipe_private)
413 sipe_private->groups = g_new0(struct sipe_groups, 1);
416 void sipe_group_free(struct sipe_core_private *sipe_private)
418 GSList *entry;
420 while ((entry = sipe_private->groups->list) != NULL)
421 group_free(sipe_private, entry->data);
423 g_free(sipe_private->groups);
424 sipe_private->groups = NULL;
428 Local Variables:
429 mode: c
430 c-file-style: "bsd"
431 indent-tabs-mode: t
432 tab-width: 8
433 End: