1 /*
2  * Copyright (c) 2011-2013 Balabit
3  * Copyright (c) 2011-2013 Gergely Nagy <algernon@balabit.hu>
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * As an additional exemption you are allowed to compile & link against the
20  * OpenSSL libraries as published by the OpenSSL project. See the file
21  * COPYING for details.
22  *
23  */
24 
25 #include "transforms.h"
26 #include "template/templates.h"
27 #include "cfg-parser.h"
28 #include "str-utils.h"
29 #include "scratch-buffers.h"
30 
31 #include <string.h>
32 
33 typedef void (*VPTransFunc)(ValuePairsTransform *t, GString *name);
34 typedef void (*VPTransDestroyFunc)(ValuePairsTransform *t);
35 
36 struct _ValuePairsTransformSet
37 {
38   GPatternSpec *pattern;
39 
40   GList *transforms;
41 };
42 
43 struct _ValuePairsTransform
44 {
45   VPTransFunc transform;
46   VPTransDestroyFunc destroy;
47 };
48 
49 typedef struct
50 {
51   ValuePairsTransform super;
52   gint amount;
53 } VPTransShift;
54 
55 typedef struct
56 {
57   ValuePairsTransform super;
58 
59   gchar *prefix;
60 } VPTransAddPrefix;
61 
62 typedef struct
63 {
64   ValuePairsTransform super;
65 
66   gchar *old_prefix;
67   gchar *new_prefix;
68   gint new_prefix_len;
69   gint old_prefix_len;
70 } VPTransReplacePrefix;
71 
72 static void
vp_trans_init(ValuePairsTransform * t,VPTransFunc trans,VPTransDestroyFunc dest)73 vp_trans_init(ValuePairsTransform *t,
74               VPTransFunc trans,
75               VPTransDestroyFunc dest)
76 {
77   if (!t)
78     return;
79 
80   t->transform = trans;
81   t->destroy = dest;
82 }
83 
84 void
value_pairs_transform_free(ValuePairsTransform * t)85 value_pairs_transform_free(ValuePairsTransform *t)
86 {
87   if (t->destroy)
88     t->destroy(t);
89   g_free(t);
90 }
91 
92 static inline void
value_pairs_transform_apply(ValuePairsTransform * t,GString * key)93 value_pairs_transform_apply(ValuePairsTransform *t, GString *key)
94 {
95   t->transform(t, key);
96 }
97 
98 /* add_prefix() */
99 
100 static void
vp_trans_add_prefix(ValuePairsTransform * t,GString * key)101 vp_trans_add_prefix(ValuePairsTransform *t, GString *key)
102 {
103   VPTransAddPrefix *self = (VPTransAddPrefix *)t;
104 
105   g_string_prepend(key, self->prefix);
106 }
107 
108 static void
vp_trans_add_prefix_destroy(ValuePairsTransform * t)109 vp_trans_add_prefix_destroy(ValuePairsTransform *t)
110 {
111   VPTransAddPrefix *self = (VPTransAddPrefix *)t;
112 
113   g_free(self->prefix);
114 }
115 
116 ValuePairsTransform *
value_pairs_new_transform_add_prefix(const gchar * prefix)117 value_pairs_new_transform_add_prefix (const gchar *prefix)
118 {
119   VPTransAddPrefix *vpt;
120 
121   vpt = g_new(VPTransAddPrefix, 1);
122   vp_trans_init((ValuePairsTransform *)vpt,
123                 vp_trans_add_prefix,
124                 vp_trans_add_prefix_destroy);
125   vpt->prefix = g_strdup(prefix);
126 
127   return (ValuePairsTransform *)vpt;
128 }
129 
130 /* shift() */
131 
132 static void
vp_trans_shift(ValuePairsTransform * t,GString * key)133 vp_trans_shift(ValuePairsTransform *t, GString *key)
134 {
135   VPTransShift *self = (VPTransShift *)t;
136 
137   g_string_erase(key, 0, self->amount);
138 }
139 
140 ValuePairsTransform *
value_pairs_new_transform_shift(gint amount)141 value_pairs_new_transform_shift (gint amount)
142 {
143   VPTransShift *vpt;
144 
145   vpt = g_new(VPTransShift, 1);
146   vp_trans_init((ValuePairsTransform *)vpt,
147                 vp_trans_shift, NULL);
148 
149   vpt->amount = amount;
150 
151   return (ValuePairsTransform *)vpt;
152 }
153 
154 /* shift-levels() */
155 
156 static void
vp_trans_shift_levels(ValuePairsTransform * t,GString * key)157 vp_trans_shift_levels(ValuePairsTransform *t, GString *key)
158 {
159   VPTransShift *self = (VPTransShift *)t;
160   const gchar *dot;
161   gint levels_left = self->amount - 1;
162 
163   dot = strchr(key->str, '.');
164   while (dot && levels_left > 0)
165     {
166       dot = strchr(dot + 1, '.');
167       levels_left--;
168     }
169 
170   if (dot)
171     g_string_erase(key, 0, dot + 1 - key->str);
172 }
173 
174 ValuePairsTransform *
value_pairs_new_transform_shift_levels(gint amount)175 value_pairs_new_transform_shift_levels(gint amount)
176 {
177   VPTransShift *vpt;
178 
179   vpt = g_new(VPTransShift, 1);
180   vp_trans_init((ValuePairsTransform *)vpt,
181                 vp_trans_shift_levels, NULL);
182 
183   vpt->amount = amount;
184 
185   return (ValuePairsTransform *)vpt;
186 }
187 
188 /* replace-prefix() */
189 
190 static void
vp_trans_replace_prefix(ValuePairsTransform * t,GString * key)191 vp_trans_replace_prefix(ValuePairsTransform *t, GString *key)
192 {
193   VPTransReplacePrefix *self = (VPTransReplacePrefix *)t;
194 
195   if (strncmp(self->old_prefix, key->str,
196               self->old_prefix_len) != 0)
197     return;
198 
199   g_string_erase(key, 0, self->old_prefix_len);
200   g_string_prepend_len(key,
201                        self->new_prefix, self->new_prefix_len);
202 }
203 
204 static void
vp_trans_replace_prefix_destroy(ValuePairsTransform * t)205 vp_trans_replace_prefix_destroy(ValuePairsTransform *t)
206 {
207   VPTransReplacePrefix *self = (VPTransReplacePrefix *)t;
208 
209   g_free(self->old_prefix);
210   g_free(self->new_prefix);
211 }
212 
213 ValuePairsTransform *
value_pairs_new_transform_replace_prefix(const gchar * prefix,const gchar * new_prefix)214 value_pairs_new_transform_replace_prefix(const gchar *prefix, const gchar *new_prefix)
215 {
216   VPTransReplacePrefix *vpt;
217 
218   vpt = g_new(VPTransReplacePrefix, 1);
219   vp_trans_init((ValuePairsTransform *)vpt,
220                 vp_trans_replace_prefix,
221                 vp_trans_replace_prefix_destroy);
222 
223   vpt->old_prefix = g_strdup(prefix);
224   vpt->old_prefix_len = strlen(prefix);
225   vpt->new_prefix = g_strdup(new_prefix);
226   vpt->new_prefix_len = strlen(vpt->new_prefix);
227 
228   return (ValuePairsTransform *)vpt;
229 }
230 
231 /*
232  * ValuePairsTransformSet
233  */
234 
235 ValuePairsTransformSet *
value_pairs_transform_set_new(const gchar * glob)236 value_pairs_transform_set_new(const gchar *glob)
237 {
238   ValuePairsTransformSet *vpts;
239 
240   vpts = g_new(ValuePairsTransformSet, 1);
241   vpts->transforms = NULL;
242   vpts->pattern = g_pattern_spec_new(glob);
243 
244   return vpts;
245 }
246 
247 void
value_pairs_transform_set_add_func(ValuePairsTransformSet * vpts,ValuePairsTransform * vpt)248 value_pairs_transform_set_add_func(ValuePairsTransformSet *vpts,
249                                    ValuePairsTransform *vpt)
250 {
251   vpts->transforms = g_list_append(vpts->transforms, vpt);
252 }
253 
254 void
value_pairs_transform_set_free(ValuePairsTransformSet * vpts)255 value_pairs_transform_set_free(ValuePairsTransformSet *vpts)
256 {
257   GList *l;
258 
259   l = vpts->transforms;
260   while (l)
261     {
262       value_pairs_transform_free((ValuePairsTransform *)l->data);
263       l = g_list_delete_link(l, l);
264     }
265   g_pattern_spec_free(vpts->pattern);
266   g_free(vpts);
267 }
268 
269 void
value_pairs_transform_set_apply(ValuePairsTransformSet * vpts,GString * key)270 value_pairs_transform_set_apply(ValuePairsTransformSet *vpts, GString *key)
271 {
272   if (g_pattern_match_string(vpts->pattern, key->str))
273     {
274       GList *l;
275 
276       l = vpts->transforms;
277       while (l)
278         {
279           value_pairs_transform_apply((ValuePairsTransform *)l->data, key);
280           l = l->next;
281         }
282     }
283 }
284