OpenSync 0.22
opensync/opensync_filter.c
00001 /*
00002  * libopensync - A synchronization framework
00003  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  * 
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00018  * 
00019  */
00020  
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023 
00031 
00032 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00033 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)
00034 {
00035         OSyncFilter *filter = osync_filter_new();
00036         filter->group = group;
00037         filter->sourcememberid = sourcememberid;
00038         filter->destmemberid = destmemberid;
00039         filter->sourceobjtype = g_strdup(sourceobjtype);
00040         filter->destobjtype = g_strdup(destobjtype);
00041         filter->detectobjtype = g_strdup(detectobjtype);
00042         filter->action = action;
00043         
00044         if (function_name) {
00045                 osync_filter_update_hook(filter, group, function_name);
00046         }
00047         
00048         osync_filter_register(group, filter);
00049         return filter;
00050 }
00051 
00052 void osync_filter_update_hook(OSyncFilter *filter, OSyncGroup *group, const char *function_name)
00053 {
00054         g_assert(filter);
00055         g_assert(group);
00056         g_assert(function_name);
00057         
00058         OSyncFilterFunction hook = NULL;
00059         GList *f;
00060         for (f = group->conv_env->filter_functions; f; f = f->next) {
00061                 OSyncCustomFilter *custom = f->data;
00062                 if (!strcmp(custom->name, function_name)) 
00063                         hook = custom->hook;
00064         }
00065         if (!hook) {
00066                 osync_trace(TRACE_ERROR, "Unable to add custom filter, hook not found!");
00067                 return;
00068         }
00069         filter->hook = hook;
00070         filter->function_name = g_strdup(function_name);
00071 }
00072 
00073 
00074 GList *_osync_filter_find(OSyncMember *member)
00075 {
00076         GList *f = NULL;
00077         GList *ret = NULL;
00078         for (f = member->group->filters; f; f = f->next) {
00079                 OSyncFilter *filter = f->data;
00080                 if (!filter->destmemberid || filter->destmemberid == member->id)
00081                         ret = g_list_append(ret, filter);
00082         }
00083         return ret;
00084 }
00085 
00086 OSyncFilterAction osync_filter_invoke(OSyncFilter *filter, OSyncChange *change, OSyncMember *destmember)
00087 {
00088         g_assert(filter);
00089         g_assert(change);
00090         osync_debug("OSFLT", 3, "Starting to invoke filter for change %s", change->uid);
00091         if (filter->sourcememberid && change->sourcemember && filter->sourcememberid != change->sourcemember->id)
00092                 return OSYNC_FILTER_IGNORE;
00093         if (filter->destmemberid && filter->destmemberid != destmember->id)
00094                 return OSYNC_FILTER_IGNORE;
00095         if (filter->sourceobjtype && strcmp(filter->sourceobjtype, change->sourceobjtype))
00096                 return OSYNC_FILTER_IGNORE;
00097         if (filter->destobjtype && change->destobjtype && strcmp(filter->destobjtype, change->destobjtype))
00098                 return OSYNC_FILTER_IGNORE;
00099         if (filter->detectobjtype) {
00100                 OSyncError *error = NULL;
00101                 OSyncObjType *objtype = osync_change_detect_objtype_full(osync_member_get_format_env(destmember), change, &error);
00102                 if (!objtype) {
00103                         osync_error_free(&error);
00104                         return OSYNC_FILTER_IGNORE;
00105                 }
00106                 if (strcmp(filter->detectobjtype, objtype->name))
00107                         return OSYNC_FILTER_IGNORE;
00108         }
00109         
00110         osync_debug("OSFLT", 3, "Change %s passed the filter!", change->uid);
00111         //We passed the filter. Now we can return the action
00112         if (!filter->hook)
00113                 return filter->action;
00114         
00115         //What exactly do we need to pass to the hook?
00116         return filter->hook(change, filter->config);            
00117 }
00118 
00119 osync_bool osync_filter_change_allowed(OSyncMember *destmember, OSyncChange *change)
00120 {
00121         osync_trace(TRACE_ENTRY, "osync_filter_change_allowed(%p, %p)", destmember, change);
00122         GList *filters = _osync_filter_find(destmember);
00123         GList *f = NULL;
00124         int ret = TRUE;
00125         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));
00126         for (f = filters; f; f = f->next) {
00127                 OSyncFilter *filter = f->data;
00128                 OSyncFilterAction action = osync_filter_invoke(filter, change, destmember);
00129                 if (action == OSYNC_FILTER_ALLOW)
00130                         ret = TRUE;
00131                 if (action == OSYNC_FILTER_DENY)
00132                         ret = FALSE;
00133         }
00134         g_list_free(filters);
00135         osync_trace(TRACE_EXIT, "osync_filter_change_allowed: %s", ret ? "TRUE" : "FALSE");
00136         return ret;
00137 }
00138 
00139 const char *osync_filter_get_sourceobjtype(OSyncFilter *filter)
00140 {
00141         return filter->sourceobjtype;
00142 }
00143 
00144 const char *osync_filter_get_destobjtype(OSyncFilter *filter)
00145 {
00146         return filter->destobjtype;
00147 }
00148 
00149 const char *osync_filter_get_detectobjtype(OSyncFilter *filter)
00150 {
00151         return filter->detectobjtype;
00152 }
00153 
00154 OSyncFilterAction osync_filter_get_action(OSyncFilter *filter)
00155 {
00156         return filter->action;
00157 }
00158 
00159 OSyncMember *osync_filter_get_sourcemember(OSyncFilter *filter)
00160 {
00161         return osync_member_from_id(filter->group, filter->sourcememberid);
00162 }
00163 
00164 OSyncMember *osync_filter_get_destmember(OSyncFilter *filter)
00165 {
00166         return osync_member_from_id(filter->group, filter->destmemberid);
00167 }
00168 #endif
00169 
00179 
00185 void osync_filter_register(OSyncGroup *group, OSyncFilter *filter)
00186 {
00187         osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, filter);
00188         g_assert(group);
00189         group->filters = g_list_append(group->filters, filter);
00190         osync_trace(TRACE_EXIT, "%s", __func__);
00191 }
00192 
00197 OSyncFilter *osync_filter_new(void)
00198 {
00199         osync_trace(TRACE_ENTRY, "%s(void)", __func__);
00200         OSyncFilter *filter = g_malloc0(sizeof(OSyncFilter));
00201         g_assert(filter);
00202         osync_trace(TRACE_EXIT, "%s: %p", __func__, filter);
00203         return filter;
00204 }
00205 
00210 void osync_filter_free(OSyncFilter *filter)
00211 {
00212         osync_trace(TRACE_ENTRY, "%s(%p)", __func__, filter);
00213         g_assert(filter);
00214         if (filter->sourceobjtype)
00215                 g_free(filter->sourceobjtype);
00216         if (filter->destobjtype)
00217                 g_free(filter->destobjtype);
00218         if (filter->detectobjtype)
00219                 g_free(filter->detectobjtype);
00220         
00221         g_free(filter);
00222         osync_trace(TRACE_EXIT, "%s", __func__);
00223 }
00224 
00236 OSyncFilter *osync_filter_add(OSyncGroup *group, OSyncMember *sourcemember, OSyncMember *destmember, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, OSyncFilterAction action)
00237 {
00238         osync_trace(TRACE_ENTRY, "%s(%p, %p:%lli, %p:%lli, %s, %s, %s, %i)", __func__, group, \
00239                 sourcemember, sourcemember ? sourcemember->id : 0, \
00240                 destmember, destmember ? destmember->id : 0, \
00241                 sourceobjtype, destobjtype, detectobjtype, action);
00242                 
00243         long long int sourcememberid = 0;
00244         long long int destmemberid = 0;
00245         if (sourcemember)
00246                 sourcememberid = sourcemember->id;
00247         if (destmember)
00248                 destmemberid = destmember->id;
00249         
00250         OSyncFilter *filter = _osync_filter_add_ids(group, sourcememberid, destmemberid, sourceobjtype, destobjtype, detectobjtype, action, NULL);
00251         osync_trace(TRACE_EXIT, "%s: %p", __func__, filter);
00252         return filter;
00253 }
00254 
00260 void osync_filter_remove(OSyncGroup *group, OSyncFilter *filter)
00261 {
00262         osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, group, filter);
00263         g_assert(group);
00264         group->filters = g_list_remove(group->filters, filter);
00265         osync_trace(TRACE_EXIT, "%s", __func__);
00266 }
00267 
00280 OSyncFilter *osync_filter_add_custom(OSyncGroup *group, OSyncMember *sourcemember, OSyncMember *destmember, const char *sourceobjtype, const char *destobjtype, const char *detectobjtype, const char *function_name)
00281 {
00282         osync_trace(TRACE_ENTRY, "%s(%p, %p:%lli, %p:%lli, %s, %s, %s, %s)", __func__, group, \
00283                 sourcemember, sourcemember ? sourcemember->id : 0, \
00284                 destmember, destmember ? destmember->id : 0, \
00285                 sourceobjtype, destobjtype, detectobjtype, function_name);
00286         long long int sourcememberid = 0;
00287         long long int destmemberid = 0;
00288         if (sourcemember)
00289                 sourcememberid = sourcemember->id;
00290         if (destmember)
00291                 destmemberid = destmember->id;
00292 
00293         OSyncFilter *filter = _osync_filter_add_ids(group, sourcememberid, destmemberid, sourceobjtype, destobjtype, detectobjtype, OSYNC_FILTER_IGNORE, function_name);
00294         osync_trace(TRACE_EXIT, "%s: %p", __func__, filter);
00295         return filter;
00296 }
00297 
00305 void osync_filter_set_config(OSyncFilter *filter, const char *config)
00306 {
00307         osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, filter, config);
00308         g_assert(filter);
00309         if (filter->config)
00310                 g_free(filter->config);
00311         filter->config = g_strdup(config);
00312         osync_trace(TRACE_EXIT, "%s", __func__);
00313 }
00314 
00320 const char *osync_filter_get_config(OSyncFilter *filter)
00321 {
00322         osync_trace(TRACE_ENTRY, "%s(%p)", __func__, filter);
00323         g_assert(filter);
00324         osync_trace(TRACE_EXIT, "%s: %s", __func__, filter->config);
00325         return filter->config;
00326 }
00327