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