OpenSync  0.22
opensync_filter.c
1 /*
2  * libopensync - A synchronization framework
3  * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 
21 #include "opensync.h"
22 #include "opensync_internals.h"
23 
31 
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 OSyncFilter *_osync_filter_add_ids(OSyncGroup *group, long long int sourcememberid, long long int destmemberid, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, OSyncFilterAction action, const char *function_name)
34 {
35  OSyncFilter *filter = osync_filter_new();
36  filter->group = group;
37  filter->sourcememberid = sourcememberid;
38  filter->destmemberid = destmemberid;
39  filter->sourceobjtype = g_strdup(sourceobjtype);
40  filter->destobjtype = g_strdup(destobjtype);
41  filter->detectobjtype = g_strdup(detectobjtype);
42  filter->action = action;
43 
44  if (function_name) {
45  osync_filter_update_hook(filter, group, function_name);
46  }
47 
48  osync_filter_register(group, filter);
49  return filter;
50 }
51 
52 void osync_filter_update_hook(OSyncFilter *filter, OSyncGroup *group, const char *function_name)
53 {
54  g_assert(filter);
55  g_assert(group);
56  g_assert(function_name);
57 
58  OSyncFilterFunction hook = NULL;
59  GList *f;
60  for (f = group->conv_env->filter_functions; f; f = f->next) {
61  OSyncCustomFilter *custom = f->data;
62  if (!strcmp(custom->name, function_name))
63  hook = custom->hook;
64  }
65  if (!hook) {
66  osync_trace(TRACE_ERROR, "Unable to add custom filter, hook not found!");
67  return;
68  }
69  filter->hook = hook;
70  filter->function_name = g_strdup(function_name);
71 }
72 
73 
74 GList *_osync_filter_find(OSyncMember *member)
75 {
76  GList *f = NULL;
77  GList *ret = NULL;
78  for (f = member->group->filters; f; f = f->next) {
79  OSyncFilter *filter = f->data;
80  if (!filter->destmemberid || filter->destmemberid == member->id)
81  ret = g_list_append(ret, filter);
82  }
83  return ret;
84 }
85 
86 OSyncFilterAction osync_filter_invoke(OSyncFilter *filter, OSyncChange *change, OSyncMember *destmember)
87 {
88  g_assert(filter);
89  g_assert(change);
90  osync_debug("OSFLT", 3, "Starting to invoke filter for change %s", change->uid);
91  if (filter->sourcememberid && change->sourcemember && filter->sourcememberid != change->sourcemember->id)
92  return OSYNC_FILTER_IGNORE;
93  if (filter->destmemberid && filter->destmemberid != destmember->id)
94  return OSYNC_FILTER_IGNORE;
95  if (filter->sourceobjtype && strcmp(filter->sourceobjtype, change->sourceobjtype))
96  return OSYNC_FILTER_IGNORE;
97  if (filter->destobjtype && change->destobjtype && strcmp(filter->destobjtype, change->destobjtype))
98  return OSYNC_FILTER_IGNORE;
99  if (filter->detectobjtype) {
100  OSyncError *error = NULL;
101  OSyncObjType *objtype = osync_change_detect_objtype_full(osync_member_get_format_env(destmember), change, &error);
102  if (!objtype) {
103  osync_error_free(&error);
104  return OSYNC_FILTER_IGNORE;
105  }
106  if (strcmp(filter->detectobjtype, objtype->name))
107  return OSYNC_FILTER_IGNORE;
108  }
109 
110  osync_debug("OSFLT", 3, "Change %s passed the filter!", change->uid);
111  //We passed the filter. Now we can return the action
112  if (!filter->hook)
113  return filter->action;
114 
115  //What exactly do we need to pass to the hook?
116  return filter->hook(change, filter->config);
117 }
118 
119 osync_bool osync_filter_change_allowed(OSyncMember *destmember, OSyncChange *change)
120 {
121  osync_trace(TRACE_ENTRY, "osync_filter_change_allowed(%p, %p)", destmember, change);
122  GList *filters = _osync_filter_find(destmember);
123  GList *f = NULL;
124  int ret = TRUE;
125  osync_debug("OSFLT", 3, "Checking if change %s is allowed for member %lli. Filters to invoke: %i", change->uid, destmember->id, g_list_length(filters));
126  for (f = filters; f; f = f->next) {
127  OSyncFilter *filter = f->data;
128  OSyncFilterAction action = osync_filter_invoke(filter, change, destmember);
129  if (action == OSYNC_FILTER_ALLOW)
130  ret = TRUE;
131  if (action == OSYNC_FILTER_DENY)
132  ret = FALSE;
133  }
134  g_list_free(filters);
135  osync_trace(TRACE_EXIT, "osync_filter_change_allowed: %s", ret ? "TRUE" : "FALSE");
136  return ret;
137 }
138 
139 const char *osync_filter_get_sourceobjtype(OSyncFilter *filter)
140 {
141  return filter->sourceobjtype;
142 }
143 
144 const char *osync_filter_get_destobjtype(OSyncFilter *filter)
145 {
146  return filter->destobjtype;
147 }
148 
149 const char *osync_filter_get_detectobjtype(OSyncFilter *filter)
150 {
151  return filter->detectobjtype;
152 }
153 
154 OSyncFilterAction osync_filter_get_action(OSyncFilter *filter)
155 {
156  return filter->action;
157 }
158 
159 OSyncMember *osync_filter_get_sourcemember(OSyncFilter *filter)
160 {
161  return osync_member_from_id(filter->group, filter->sourcememberid);
162 }
163 
164 OSyncMember *osync_filter_get_destmember(OSyncFilter *filter)
165 {
166  return osync_member_from_id(filter->group, filter->destmemberid);
167 }
168 #endif
169 
179 
186 {
187  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, filter);
188  g_assert(group);
189  group->filters = g_list_append(group->filters, filter);
190  osync_trace(TRACE_EXIT, "%s", __func__);
191 }
192 
198 {
199  osync_trace(TRACE_ENTRY, "%s(void)", __func__);
200  OSyncFilter *filter = g_malloc0(sizeof(OSyncFilter));
201  g_assert(filter);
202  osync_trace(TRACE_EXIT, "%s: %p", __func__, filter);
203  return filter;
204 }
205 
211 {
212  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, filter);
213  g_assert(filter);
214  if (filter->sourceobjtype)
215  g_free(filter->sourceobjtype);
216  if (filter->destobjtype)
217  g_free(filter->destobjtype);
218  if (filter->detectobjtype)
219  g_free(filter->detectobjtype);
220 
221  g_free(filter);
222  osync_trace(TRACE_EXIT, "%s", __func__);
223 }
224 
236 OSyncFilter *osync_filter_add(OSyncGroup *group, OSyncMember *sourcemember, OSyncMember *destmember, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, OSyncFilterAction action)
237 {
238  osync_trace(TRACE_ENTRY, "%s(%p, %p:%lli, %p:%lli, %s, %s, %s, %i)", __func__, group, \
239  sourcemember, sourcemember ? sourcemember->id : 0, \
240  destmember, destmember ? destmember->id : 0, \
241  sourceobjtype, destobjtype, detectobjtype, action);
242 
243  long long int sourcememberid = 0;
244  long long int destmemberid = 0;
245  if (sourcemember)
246  sourcememberid = sourcemember->id;
247  if (destmember)
248  destmemberid = destmember->id;
249 
250  OSyncFilter *filter = _osync_filter_add_ids(group, sourcememberid, destmemberid, sourceobjtype, destobjtype, detectobjtype, action, NULL);
251  osync_trace(TRACE_EXIT, "%s: %p", __func__, filter);
252  return filter;
253 }
254 
261 {
262  osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, filter);
263  g_assert(group);
264  group->filters = g_list_remove(group->filters, filter);
265  osync_trace(TRACE_EXIT, "%s", __func__);
266 }
267 
280 OSyncFilter *osync_filter_add_custom(OSyncGroup *group, OSyncMember *sourcemember, OSyncMember *destmember, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, const char *function_name)
281 {
282  osync_trace(TRACE_ENTRY, "%s(%p, %p:%lli, %p:%lli, %s, %s, %s, %s)", __func__, group, \
283  sourcemember, sourcemember ? sourcemember->id : 0, \
284  destmember, destmember ? destmember->id : 0, \
285  sourceobjtype, destobjtype, detectobjtype, function_name);
286  long long int sourcememberid = 0;
287  long long int destmemberid = 0;
288  if (sourcemember)
289  sourcememberid = sourcemember->id;
290  if (destmember)
291  destmemberid = destmember->id;
292 
293  OSyncFilter *filter = _osync_filter_add_ids(group, sourcememberid, destmemberid, sourceobjtype, destobjtype, detectobjtype, OSYNC_FILTER_IGNORE, function_name);
294  osync_trace(TRACE_EXIT, "%s: %p", __func__, filter);
295  return filter;
296 }
297 
305 void osync_filter_set_config(OSyncFilter *filter, const char *config)
306 {
307  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, filter, config);
308  g_assert(filter);
309  if (filter->config)
310  g_free(filter->config);
311  filter->config = g_strdup(config);
312  osync_trace(TRACE_EXIT, "%s", __func__);
313 }
314 
321 {
322  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, filter);
323  g_assert(filter);
324  osync_trace(TRACE_EXIT, "%s: %s", __func__, filter->config);
325  return filter->config;
326 }
327 
void osync_filter_register(OSyncGroup *group, OSyncFilter *filter)
Registers a filter with a group.
Represent an error.
void osync_filter_set_config(OSyncFilter *filter, const char *config)
Sets the config for a filter.
OSyncMember * sourcemember
OSyncObjType * osync_change_detect_objtype_full(OSyncFormatEnv *env, OSyncChange *change, OSyncError **error)
Tries to detect the encapsulated object type of the given change.
void osync_filter_free(OSyncFilter *filter)
Frees a filter.
OSyncFilter * osync_filter_add_custom(OSyncGroup *group, OSyncMember *sourcemember, OSyncMember *destmember, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, const char *function_name)
Register a new custom filter.
Represent a group of members that should be synchronized.
void osync_filter_remove(OSyncGroup *group, OSyncFilter *filter)
Removes a filter from a group.
void osync_error_free(OSyncError **error)
Frees the error so it can be reused.
A member of a group which represent a single device.
Represents a filter to filter changes.
Represents a custom filter that can be used to call hooks.
void osync_debug(const char *subpart, int level, const char *message,...)
Used for debugging.
A change object.
OSyncFilter * osync_filter_add(OSyncGroup *group, OSyncMember *sourcemember, OSyncMember *destmember, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, OSyncFilterAction action)
Register a new filter.
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.
Represent a abstract object type (like "contact")
const char * osync_filter_get_config(OSyncFilter *filter)
Gets the config of a filter.
OSyncFilterAction
The action that should be invoked.
OSyncMember * osync_member_from_id(OSyncGroup *group, int id)
Searches for a member by its id.
OSyncFilter * osync_filter_new(void)
Creates a new filter.