group: start cleaning up the interface
[siplcs.git] / src / core / sipe-group.c
blob077f31e772ee77fe2a5aa84848aedb033df62031
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 group_user_context {
42 gchar *group_name;
43 gchar *user_name;
46 static void
47 sipe_group_context_destroy(gpointer data)
49 struct group_user_context *ctx = data;
50 g_free(ctx->group_name);
51 g_free(ctx->user_name);
52 g_free(ctx);
55 static gboolean
56 process_add_group_response(struct sipe_core_private *sipe_private,
57 struct sipmsg *msg,
58 struct transaction *trans)
60 if (msg->response == 200) {
61 struct sipe_group *group;
62 struct group_user_context *ctx = trans->payload->data;
63 sipe_xml *xml;
64 const sipe_xml *node;
65 char *group_id;
66 struct sipe_buddy *buddy;
68 xml = sipe_xml_parse(msg->body, msg->bodylen);
69 if (!xml) {
70 return FALSE;
73 node = sipe_xml_child(xml, "Body/addGroup/groupID");
74 if (!node) {
75 sipe_xml_free(xml);
76 return FALSE;
79 group_id = sipe_xml_data(node);
80 if (!group_id) {
81 sipe_xml_free(xml);
82 return FALSE;
85 group = g_new0(struct sipe_group, 1);
86 group->id = (int)g_ascii_strtod(group_id, NULL);
87 g_free(group_id);
88 group->name = g_strdup(ctx->group_name);
90 sipe_group_add(sipe_private, group);
92 if (ctx->user_name) {
93 buddy = sipe_buddy_find_by_uri(sipe_private,
94 ctx->user_name);
95 if (buddy) {
96 buddy->groups = sipe_utils_slist_insert_unique_sorted(buddy->groups,
97 group,
98 (GCompareFunc)sipe_group_compare,
99 NULL);
100 sipe_group_update_buddy(sipe_private, buddy);
104 sipe_xml_free(xml);
105 return TRUE;
107 return FALSE;
111 sipe_group_compare(struct sipe_group *group1, struct sipe_group *group2) {
112 return group1->id - group2->id;
115 struct sipe_group*
116 sipe_group_find_by_id(struct sipe_core_private *sipe_private,
117 int id)
119 struct sipe_group *group;
120 GSList *entry;
122 if (!sipe_private)
123 return NULL;
125 entry = sipe_private->groups;
126 while (entry) {
127 group = entry->data;
128 if (group->id == id) {
129 return group;
131 entry = entry->next;
133 return NULL;
136 struct sipe_group*
137 sipe_group_find_by_name(struct sipe_core_private *sipe_private,
138 const gchar * name)
140 struct sipe_group *group;
141 GSList *entry;
143 if (!sipe_private || !name)
144 return NULL;
146 entry = sipe_private->groups;
147 while (entry) {
148 group = entry->data;
149 if (sipe_strequal(group->name, name)) {
150 return group;
152 entry = entry->next;
154 return NULL;
157 void
158 sipe_group_create(struct sipe_core_private *sipe_private,
159 const gchar *name,
160 const gchar *who)
162 struct transaction_payload *payload = g_new0(struct transaction_payload, 1);
163 struct group_user_context *ctx = g_new0(struct group_user_context, 1);
164 const gchar *soap_name = sipe_strequal(name, _("Other Contacts")) ? "~" : name;
165 gchar *request;
166 ctx->group_name = g_strdup(name);
167 ctx->user_name = g_strdup(who);
168 payload->destroy = sipe_group_context_destroy;
169 payload->data = ctx;
171 /* soap_name can contain restricted characters */
172 request = g_markup_printf_escaped("<m:name>%s</m:name>"
173 "<m:externalURI />",
174 soap_name);
175 sip_soap_request_cb(sipe_private,
176 "addGroup",
177 request,
178 process_add_group_response,
179 payload);
180 g_free(request);
183 gboolean sipe_group_rename(struct sipe_core_private *sipe_private,
184 struct sipe_group *group,
185 const gchar *name)
187 gboolean renamed = sipe_backend_buddy_group_rename(SIPE_CORE_PUBLIC,
188 group->name,
189 name);
190 if (renamed) {
191 g_free(group->name);
192 group->name = g_strdup(name);
194 return(renamed);
197 void
198 sipe_group_add(struct sipe_core_private *sipe_private,
199 struct sipe_group * group)
201 if (sipe_backend_buddy_group_add(SIPE_CORE_PUBLIC,group->name))
203 SIPE_DEBUG_INFO("added group %s (id %d)", group->name, group->id);
204 sipe_private->groups = g_slist_append(sipe_private->groups,
205 group);
207 else
209 SIPE_DEBUG_INFO("did not add group %s", group->name ? group->name : "");
213 static void group_free(struct sipe_core_private *sipe_private,
214 struct sipe_group *group)
216 sipe_private->groups = g_slist_remove(sipe_private->groups,
217 group);
218 g_free(group->name);
219 g_free(group);
222 void sipe_group_remove(struct sipe_core_private *sipe_private,
223 struct sipe_group *group)
225 if (group) {
226 SIPE_DEBUG_INFO("removing group %s (id %d)", group->name, group->id);
227 sipe_backend_buddy_group_remove(SIPE_CORE_PUBLIC, group->name);
228 group_free(sipe_private, group);
232 void
233 sipe_core_group_rename(struct sipe_core_public *sipe_public,
234 const gchar *old_name,
235 const gchar *new_name)
237 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
238 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, old_name);
240 if (s_group) {
241 gchar *request;
242 SIPE_DEBUG_INFO("Renaming group %s to %s", old_name, new_name);
243 /* new_name can contain restricted characters */
244 request = g_markup_printf_escaped("<m:groupID>%d</m:groupID>"
245 "<m:name>%s</m:name>"
246 "<m:externalURI />",
247 s_group->id, new_name);
248 sip_soap_request(sipe_private,
249 "modifyGroup",
250 request);
251 g_free(request);
253 g_free(s_group->name);
254 s_group->name = g_strdup(new_name);
255 } else {
256 SIPE_DEBUG_INFO("Cannot find group %s to rename", old_name);
260 void
261 sipe_core_group_remove(struct sipe_core_public *sipe_public,
262 const gchar *name)
264 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
265 struct sipe_group *s_group = sipe_group_find_by_name(sipe_private, name);
267 if (s_group) {
268 gchar *request;
269 SIPE_DEBUG_INFO("Deleting group %s", name);
270 request = g_strdup_printf("<m:groupID>%d</m:groupID>",
271 s_group->id);
272 sip_soap_request(sipe_private,
273 "deleteGroup",
274 request);
275 g_free(request);
277 group_free(sipe_private, s_group);
278 } else {
279 SIPE_DEBUG_INFO("Cannot find group %s to delete", name);
284 * Returns string like "2 4 7 8" - group ids buddy belong to.
286 static gchar *sipe_get_buddy_groups_string(struct sipe_buddy *buddy)
288 int i = 0;
289 gchar *res;
290 //creating array from GList, converting int to gchar*
291 gchar **ids_arr = g_new(gchar *, g_slist_length(buddy->groups) + 1);
292 GSList *entry = buddy->groups;
294 if (!ids_arr) return NULL;
296 while (entry) {
297 struct sipe_group * group = entry->data;
298 ids_arr[i] = g_strdup_printf("%d", group->id);
299 entry = entry->next;
300 i++;
302 ids_arr[i] = NULL;
303 res = g_strjoinv(" ", ids_arr);
304 g_strfreev(ids_arr);
305 return res;
309 * Sends buddy update to server
311 static void send_buddy_update(struct sipe_core_private *sipe_private,
312 struct sipe_buddy *buddy,
313 const gchar *alias)
315 gchar *groups = sipe_get_buddy_groups_string(buddy);
317 if (groups) {
318 gchar *request;
319 SIPE_DEBUG_INFO("Saving buddy %s with alias '%s' and groups '%s'",
320 buddy->name, alias, groups);
322 /* alias can contain restricted characters */
323 request = g_markup_printf_escaped("<m:displayName>%s</m:displayName>"
324 "<m:groups>%s</m:groups>"
325 "<m:subscribed>true</m:subscribed>"
326 "<m:URI>%s</m:URI>"
327 "<m:externalURI />",
328 alias, groups, buddy->name);
329 g_free(groups);
331 sip_soap_request(sipe_private,
332 "setContact",
333 request);
334 g_free(request);
338 /* indicates that buddy information on the server needs updating */
339 void sipe_group_update_buddy(struct sipe_core_private *sipe_private,
340 struct sipe_buddy *buddy)
342 if (buddy) {
343 sipe_backend_buddy backend_buddy = sipe_backend_buddy_find(SIPE_CORE_PUBLIC,
344 buddy->name,
345 NULL);
346 if (backend_buddy) {
347 gchar *alias = sipe_backend_buddy_get_alias(SIPE_CORE_PUBLIC,
348 backend_buddy);
349 send_buddy_update(sipe_private, buddy, alias);
350 g_free(alias);
355 void sipe_core_group_set_alias(struct sipe_core_public *sipe_public,
356 const gchar *who,
357 const gchar *alias)
359 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
360 struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private,
361 who);
363 if (buddy)
364 send_buddy_update(sipe_private, buddy, alias);
367 void sipe_group_init(struct sipe_core_private *sipe_private)
369 sipe_private->groups = NULL;
372 void sipe_group_free(struct sipe_core_private *sipe_private)
374 GSList *entry;
375 while ((entry = sipe_private->groups) != NULL)
376 group_free(sipe_private, entry->data);
380 Local Variables:
381 mode: c
382 c-file-style: "bsd"
383 indent-tabs-mode: t
384 tab-width: 8
385 End: