More GLIB_CHECK_VERSION cleanups. Update the minimum GLib/GTK+ versions
[obnox/wireshark/wip.git] / epan / ftypes / ftype-pcre.c
1 /*
2  * $Id$
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2001 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
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.
17  *
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.
21  */
22
23 /* Perl-Compatible Regular Expression (PCRE) internal field type.
24  * Used with the "matches" dfilter operator, allowing efficient
25  * compilation and studying of a PCRE pattern in dfilters.
26  *
27  * PCRE is provided with libpcre (http://www.pcre.org/).
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <ftypes-int.h>
35
36 #ifdef HAVE_LIBPCRE
37
38 #include <string.h>
39
40 #include <pcre.h>
41
42 /* Create a pcre_tuple_t object based on the given string pattern */
43 static pcre_tuple_t *
44 pcre_tuple_new(const char *value)
45 {
46         pcre_tuple_t *tuple;
47         const char *pcre_error_text;
48         int pcre_error_offset;
49
50         tuple = g_malloc(sizeof(pcre_tuple_t));
51         tuple->string = g_strdup(value); /* The RE as string */
52         tuple->ex = NULL;
53         /* Compile the RE */
54         tuple->re = pcre_compile(
55                         value,                          /* pattern */
56                         0,                                      /* PCRE options */
57                         &pcre_error_text,       /* PCRE constant error string */
58                         &pcre_error_offset,     /* Start offset of error in pattern */
59                         NULL                            /* Default char tables (C locale) */
60                         );
61         if (pcre_error_text) {
62                 tuple->error = g_strdup_printf("In regular expression \"%s\":\n"
63                                 "%s (character position %d)",
64                                 value, pcre_error_text, pcre_error_offset);
65                 return tuple;
66         } else {
67                 tuple->error = NULL;
68         }
69         /* Study the RE */
70         tuple->ex = pcre_study(tuple->re, 0, &pcre_error_text);
71         if (pcre_error_text) {
72                 if (tuple->error) {
73                         tuple->error = g_strdup_printf("In regular expression \"%s\":\n"
74                                         "%s. %s",
75                                         value, tuple->error, pcre_error_text);
76                 } else {
77                         tuple->error = g_strdup_printf("In regular expression \"%s\":\n"
78                                         "%s",
79                                         value, pcre_error_text);
80                 }
81         }
82         return tuple;
83 }
84
85 static void
86 pcre_tuple_free(pcre_tuple_t *tuple)
87 {
88         if (tuple) {
89                 g_free(tuple->string);
90                 g_free(tuple->re);
91                 g_free(tuple->ex);
92                 g_free(tuple->error);
93                 g_free(tuple);
94         }
95 }
96
97 static void
98 pcre_fvalue_new(fvalue_t *fv)
99 {
100         fv->value.re = NULL;
101 }
102
103 static void
104 pcre_fvalue_free(fvalue_t *fv)
105 {
106         if (fv->value.re) {
107                 pcre_tuple_free(fv->value.re);
108         }
109 }
110
111 /* Generate a FT_PCRE from a parsed string pattern.
112  * Uses the specified logfunc() to report errors. */
113 static gboolean
114 val_from_string(fvalue_t *fv, char *pattern, LogFunc logfunc)
115 {
116         /* Free up the old value, if we have one */
117         pcre_fvalue_free(fv);
118
119         fv->value.re = pcre_tuple_new(pattern);
120         if (fv->value.re->error) {
121                 logfunc(fv->value.re->error);
122                 return FALSE;
123         }
124         return TRUE;
125 }
126
127 /* Generate a FT_PCRE from an unparsed string pattern.
128  * Uses the specified logfunc() to report errors. */
129 static gboolean
130 val_from_unparsed(fvalue_t *fv, char *pattern, gboolean allow_partial_value _U_, LogFunc logfunc)
131 {
132         /* Free up the old value, if we have one */
133         pcre_fvalue_free(fv);
134         g_assert(! allow_partial_value);
135
136         fv->value.re = pcre_tuple_new(pattern);
137         if (fv->value.re->error) {
138                 logfunc(fv->value.re->error);
139                 return FALSE;
140         }
141         return TRUE;
142 }
143
144 static int
145 pcre_repr_len(fvalue_t *fv, ftrepr_t rtype)
146 {
147         g_assert(rtype == FTREPR_DFILTER);
148         return (int)strlen(fv->value.re->string);
149 }
150
151 static void
152 pcre_to_repr(fvalue_t *fv, ftrepr_t rtype, char *buf)
153 {
154         g_assert(rtype == FTREPR_DFILTER);
155         strcpy(buf, fv->value.re->string);
156 }
157
158 /* BEHOLD - value contains the string representation of the regular expression,
159  * and we want to store the compiled PCRE RE object into the value. */
160 static void
161 pcre_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
162 {
163         g_assert(value != NULL);
164         /* Free up the old value, if we have one */
165         pcre_fvalue_free(fv);
166         g_assert(! already_copied);
167         fv->value.re = pcre_tuple_new(value);
168 }
169
170 static gpointer
171 pcre_fvalue_get(fvalue_t *fv)
172 {
173         return fv->value.re;
174 }
175
176 void
177 ftype_register_pcre(void)
178 {
179         static ftype_t pcre_type = {
180                 FT_PCRE,                /* ftype */
181                 "FT_PCRE",              /* name */
182                 "Compiled Perl-Compatible Regular Expression object", /* pretty_name */
183                 0,                      /* wire_size */
184                 pcre_fvalue_new,        /* new_value */
185                 pcre_fvalue_free,       /* free_value */
186                 val_from_unparsed,      /* val_from_unparsed */
187                 val_from_string,        /* val_from_string */
188                 pcre_to_repr,           /* val_to_string_repr */
189                 pcre_repr_len,          /* len_string_repr */
190
191                 pcre_fvalue_set,        /* set_value */
192                 NULL,                           /* set_value_uinteger */
193                 NULL,                           /* set_value_sinteger */
194                 NULL,                   /* set_value_integer64 */
195                 NULL,                   /* set_value_floating */
196
197                 pcre_fvalue_get,        /* get_value */
198                 NULL,                           /* get_value_uinteger */
199                 NULL,                           /* get_value_sinteger */
200                 NULL,                   /* get_value_integer64 */
201                 NULL,                   /* get_value_floating */
202
203                 NULL,                   /* cmp_eq */
204                 NULL,                   /* cmp_ne */
205                 NULL,                   /* cmp_gt */
206                 NULL,                   /* cmp_ge */
207                 NULL,                   /* cmp_lt */
208                 NULL,                   /* cmp_le */
209                 NULL,                   /* cmp_bitwise_and */
210                 NULL,                   /* cmp_contains */
211                 NULL,                   /* cmp_matches */
212
213                 NULL,                   /* len */
214                 NULL,                   /* slice */
215         };
216         ftype_register(FT_PCRE, &pcre_type);
217 }
218
219 #else /* No HAVE_LIBPCRE. Try falling back to GRegex. */
220
221
222 #include <glib.h>
223 #include <string.h>
224
225 static void
226 gregex_fvalue_new(fvalue_t *fv)
227 {
228         fv->value.re = NULL;
229 }
230
231 static void
232 gregex_fvalue_free(fvalue_t *fv)
233 {
234         if (fv->value.re) {
235                 g_regex_unref(fv->value.re);
236                 fv->value.re = NULL;
237         }
238 }
239
240 /* Generate a FT_PCRE from a parsed string pattern.
241  * Uses the specified logfunc() to report errors. */
242 static gboolean
243 val_from_string(fvalue_t *fv, char *pattern, LogFunc logfunc)
244 {
245         GError *regex_error = NULL;
246         /* Free up the old value, if we have one */
247         gregex_fvalue_free(fv);
248
249         fv->value.re = g_regex_new(
250                         pattern,                        /* pattern */
251                         G_REGEX_OPTIMIZE,       /* Compile options (G_REGEX_OPTIMIZE = pcre_study) */
252                         0,                                      /* Match options */
253                         &regex_error            /* Compile / study errors */
254                         );
255
256         if (regex_error) {
257                 if (logfunc) {
258                         logfunc(regex_error->message);
259                 }
260                 g_error_free(regex_error);
261                 if (fv->value.re) {
262                         g_regex_unref(fv->value.re);
263                 }
264                 return FALSE;
265         }
266         return TRUE;
267 }
268
269 /* Generate a FT_PCRE from an unparsed string pattern.
270  * Uses the specified logfunc() to report errors. */
271 static gboolean
272 val_from_unparsed(fvalue_t *fv, char *pattern, gboolean allow_partial_value _U_, LogFunc logfunc)
273 {
274         g_assert(! allow_partial_value);
275
276         return val_from_string(fv, pattern, logfunc);
277 }
278
279 static int
280 gregex_repr_len(fvalue_t *fv, ftrepr_t rtype)
281 {
282         g_assert(rtype == FTREPR_DFILTER);
283         return (int)strlen(g_regex_get_pattern(fv->value.re));
284 }
285
286 static void
287 gregex_to_repr(fvalue_t *fv, ftrepr_t rtype, char *buf)
288 {
289         g_assert(rtype == FTREPR_DFILTER);
290         strcpy(buf, g_regex_get_pattern(fv->value.re));
291 }
292
293 /* BEHOLD - value contains the string representation of the regular expression,
294  * and we want to store the compiled PCRE RE object into the value. */
295 static void
296 gregex_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
297 {
298         g_assert(value != NULL);
299         /* Free up the old value, if we have one */
300         gregex_fvalue_free(fv);
301         g_assert(! already_copied);
302         val_from_unparsed(fv, value, FALSE, NULL);
303 }
304
305 static gpointer
306 gregex_fvalue_get(fvalue_t *fv)
307 {
308         return fv->value.re;
309 }
310
311 void
312 ftype_register_pcre(void)
313 {
314         static ftype_t pcre_type = {
315                 FT_PCRE,                /* ftype */
316                 "FT_PCRE",              /* name */
317                 "Compiled Perl-Compatible Regular Expression (GRegex) object", /* pretty_name */
318                 0,                      /* wire_size */
319                 gregex_fvalue_new,      /* new_value */
320                 gregex_fvalue_free,     /* free_value */
321                 val_from_unparsed,      /* val_from_unparsed */
322                 val_from_string,        /* val_from_string */
323                 gregex_to_repr,         /* val_to_string_repr */
324                 gregex_repr_len,        /* len_string_repr */
325
326                 gregex_fvalue_set,      /* set_value */
327                 NULL,                           /* set_value_uinteger */
328                 NULL,                           /* set_value_sinteger */
329                 NULL,                           /* set_value_integer64 */
330                 NULL,                           /* set_value_floating */
331
332                 gregex_fvalue_get,      /* get_value */
333                 NULL,                           /* get_value_uinteger */
334                 NULL,                           /* get_value_sinteger */
335                 NULL,                           /* get_value_integer64 */
336                 NULL,                           /* get_value_floating */
337
338                 NULL,                           /* cmp_eq */
339                 NULL,                           /* cmp_ne */
340                 NULL,                           /* cmp_gt */
341                 NULL,                           /* cmp_ge */
342                 NULL,                           /* cmp_lt */
343                 NULL,                           /* cmp_le */
344                 NULL,                           /* cmp_bitwise_and */
345                 NULL,                           /* cmp_contains */
346                 NULL,                           /* cmp_matches */
347
348                 NULL,                           /* len */
349                 NULL,                           /* slice */
350         };
351         ftype_register(FT_PCRE, &pcre_type);
352 }
353
354 #endif /* HAVE_LIBPCRE */
355
356 /*
357  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
358  *
359  * Local variables:
360  * c-basic-offset: 4
361  * tab-width: 4
362  * indent-tabs-mode: t
363  * End:
364  *
365  * vi: set shiftwidth=4 tabstop=4 noexpandtab
366  * :indentSize=4:tabSize=4:noTabs=false:
367  */