buddy: add interface to insert group
[siplcs.git] / src / core / sipe-group.c
blob65b7298b1f376145db0bf975f5e751789fa33754
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 void sipe_group_add_buddy(struct sipe_core_private *sipe_private,
61 struct sipe_group *group,
62 const gchar *who)
64 if (group && who) {
65 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
66 who);
67 if (buddy) {
68 sipe_buddy_insert_group(buddy, group);
69 sipe_group_update_buddy(sipe_private, buddy);
74 static gboolean
75 process_add_group_response(struct sipe_core_private *sipe_private,
76 struct sipmsg *msg,
77 struct transaction *trans)
79 if (msg->response == 200) {
80 struct sipe_group *group;
81 struct group_user_context *ctx = trans->payload->data;
82 sipe_xml *xml;
83 const sipe_xml *node;
84 char *group_id;
86 xml = sipe_xml_parse(msg->body, msg->bodylen);
87 if (!xml) {
88 return FALSE;
91 node = sipe_xml_child(xml, "Body/addGroup/groupID");
92 if (!node) {
93 sipe_xml_free(xml);
94 return FALSE;
97 group_id = sipe_xml_data(node);
98 if (!group_id) {
99 sipe_xml_free(xml);
100 return FALSE;
103 group = sipe_group_add(sipe_private,
104 ctx->group_name,
105 NULL,
106 NULL,
107 g_ascii_strtoull(group_id, NULL, 10));
108 g_free(group_id);
110 sipe_group_add_buddy(sipe_private,
111 group,
112 ctx->user_name);
114 sipe_xml_free(xml);
115 return TRUE;
117 return FALSE;
120 struct sipe_group*
121 sipe_group_find_by_id(struct sipe_core_private *sipe_private,
122 guint id)
124 struct sipe_group *group;
125 GSList *entry;
127 if (!sipe_private)
128 return NULL;
130 entry = sipe_private->groups->list;
131 while (entry) {
132 group = entry->data;
133 if (group->id == id) {
134 return group;
136 entry = entry->next;
138 return NULL;
141 struct sipe_group*
142 sipe_group_find_by_name(struct sipe_core_private *sipe_private,
143 const gchar * name)
145 struct sipe_group *group;
146 GSList *entry;
148 if (!sipe_private || !name)
149 return NULL;
151 entry = sipe_private->groups->list;
152 while (entry) {
153 group = entry->data;
154 if (sipe_strequal(group->name, name)) {
155 return group;
157 entry = entry->next;
159 return NULL;
162 void
163 sipe_group_create(struct sipe_core_private *sipe_private,
164 const gchar *name,
165 const gchar *who)
167 if (sipe_ucs_is_migrated(sipe_private)) {
168 sipe_ucs_group_create(sipe_private,
169 name,
170 who);
171 } else {
172 struct transaction_payload *payload = g_new0(struct transaction_payload, 1);
173 struct group_user_context *ctx = g_new0(struct group_user_context, 1);
174 const gchar *soap_name = sipe_strequal(name, _("Other Contacts")) ? "~" : name;
175 gchar *request;
176 ctx->group_name = g_strdup(name);
177 ctx->user_name = g_strdup(who);
178 payload->destroy = sipe_group_context_destroy;
179 payload->data = ctx;
181 /* soap_name can contain restricted characters */
182 request = g_markup_printf_escaped("<m:name>%s</m:name>"
183 "<m:externalURI />",
184 soap_name);
185 sip_soap_request_cb(sipe_private,
186 "addGroup",
187 request,
188 process_add_group_response,
189 payload);
190 g_free(request);
194 gboolean sipe_group_rename(struct sipe_core_private *sipe_private,
195 struct sipe_group *group,
196 const gchar *name)
198 gboolean renamed = sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC,
199 group->name,
200 name);
201 if (renamed) {
202 g_free(group->name);
203 group->name = g_strdup(name);
205 return(renamed);
208 struct sipe_group *sipe_group_add(struct sipe_core_private *sipe_private,
209 const gchar *name,
210 const gchar *exchange_key,
211 const gchar *change_key,
212 guint id)
214 struct sipe_group *group = NULL;
216 if (!is_empty(name)) {
217 group = sipe_group_find_by_name(sipe_private, name);
219 if (!group &&
220 sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC, name)) {
222 group = g_new0(struct sipe_group, 1);
223 group->name = g_strdup(name);
224 group->id = id;
226 if (exchange_key)
227 group->exchange_key = g_strdup(exchange_key);
228 if (change_key)
229 group->change_key = g_strdup(change_key);
231 sipe_private->groups->list = g_slist_append(sipe_private->groups->list,
232 group);
234 SIPE_DEBUG_INFO("sipe_group_add: created backend group '%s' with id %d",
235 group->name, group->id);
236 } else
237 SIPE_DEBUG_INFO("sipe_group_add: backend group '%s' already exists",
238 name ? name : "");
241 return(group);
244 static void group_free(struct sipe_core_private *sipe_private,
245 struct sipe_group *group)
247 sipe_private->groups->list = g_slist_remove(sipe_private->groups->list,
248 group);
249 g_free(group->name);
250 g_free(group->exchange_key);
251 g_free(group->change_key);
252 g_free(group);
255 void sipe_group_remove(struct sipe_core_private *sipe_private,
256 struct sipe_group *group)
258 if (group) {
259 SIPE_DEBUG_INFO("removing group %s (id %d)", group->name, group->id);
260 sipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC, group->name);
261 group_free(sipe_private, group);
265 void
266 sipe_core_group_rename(struct sipe_core_public *sipe_public,
267 const gchar *old_name,
268 const gchar *new_name)
270 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
271 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, old_name);
273 if (s_group) {
274 SIPE_DEBUG_INFO("sipe_core_group_rename: from '%s' to '%s'", old_name, new_name);
276 if (sipe_ucs_is_migrated(sipe_private)) {
277 sipe_ucs_group_rename(sipe_private,
278 s_group,
279 new_name);
280 } else {
281 /* new_name can contain restricted characters */
282 gchar *request = g_markup_printf_escaped("<m:groupID>%d</m:groupID>"
283 "<m:name>%s</m:name>"
284 "<m:externalURI />",
285 s_group->id,
286 new_name);
287 sip_soap_request(sipe_private,
288 "modifyGroup",
289 request);
290 g_free(request);
293 g_free(s_group->name);
294 s_group->name = g_strdup(new_name);
295 } else {
296 SIPE_DEBUG_INFO("sipe_core_group_rename: cannot find group '%s'", old_name);
300 void
301 sipe_core_group_remove(struct sipe_core_public *sipe_public,
302 const gchar *name)
304 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
305 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, name);
307 if (s_group) {
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,
312 s_group);
313 } else {
314 gchar *request = g_strdup_printf("<m:groupID>%d</m:groupID>",
315 s_group->id);
316 sip_soap_request(sipe_private,
317 "deleteGroup",
318 request);
319 g_free(request);
322 group_free(sipe_private, s_group);
323 } else {
324 SIPE_DEBUG_INFO("sipe_core_group_remove: cannot find group '%s'", name);
329 * Returns string like "2 4 7 8" - group ids buddy belong to.
331 static gchar *sipe_get_buddy_groups_string(struct sipe_buddy *buddy)
333 int i = 0;
334 gchar *res;
335 //creating array from GList, converting int to gchar*
336 gchar **ids_arr = g_new(gchar *, g_slist_length(buddy->groups) + 1);
337 GSList *entry = buddy->groups;
339 if (!ids_arr) return NULL;
341 while (entry) {
342 struct sipe_group * group = entry->data;
343 ids_arr[i] = g_strdup_printf("%d", group->id);
344 entry = entry->next;
345 i++;
347 ids_arr[i] = NULL;
348 res = g_strjoinv(" ", ids_arr);
349 g_strfreev(ids_arr);
350 return res;
354 * Sends buddy update to server
356 static void send_buddy_update(struct sipe_core_private *sipe_private,
357 struct sipe_buddy *buddy,
358 const gchar *alias)
360 gchar *groups = sipe_get_buddy_groups_string(buddy);
362 if (groups) {
363 gchar *request;
364 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
365 buddy->name, alias, groups);
367 /* alias can contain restricted characters */
368 request = g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
369 "<m:groups>%s</m:groups>"
370 "<m:subscribed>true</m:subscribed>"
371 "<m:URI>%s</m:URI>"
372 "<m:externalURI />",
373 alias, groups, buddy->name);
374 g_free(groups);
376 sip_soap_request(sipe_private,
377 "setContact",
378 request);
379 g_free(request);
383 /* indicates that buddy information on the server needs updating */
384 void sipe_group_update_buddy(struct sipe_core_private *sipe_private,
385 struct sipe_buddy *buddy)
387 if (buddy) {
388 sipe_backend_buddy backend_buddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,
389 buddy->name,
390 NULL);
391 if (backend_buddy) {
392 gchar *alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,
393 backend_buddy);
394 send_buddy_update(sipe_private, buddy, alias);
395 g_free(alias);
400 void sipe_core_group_set_alias(struct sipe_core_public *sipe_public,
401 const gchar *who,
402 const gchar *alias)
404 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
405 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
406 who);
408 if (buddy)
409 send_buddy_update(sipe_private, buddy, alias);
412 struct sipe_group *sipe_group_first(struct sipe_core_private *sipe_private)
414 return(sipe_private->groups->list ? sipe_private->groups->list->data : NULL);
417 guint sipe_group_count(struct sipe_core_private *sipe_private)
419 return(g_slist_length(sipe_private->groups->list));
422 void sipe_group_init(struct sipe_core_private *sipe_private)
424 sipe_private->groups = g_new0(struct sipe_groups, 1);
427 void sipe_group_free(struct sipe_core_private *sipe_private)
429 GSList *entry;
431 while ((entry = sipe_private->groups->list) != NULL)
432 group_free(sipe_private, entry->data);
434 g_free(sipe_private->groups);
435 sipe_private->groups = NULL;
439 Local Variables:
440 mode: c
441 c-file-style: "bsd"
442 indent-tabs-mode: t
443 tab-width: 8
444 End: