epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dfilter / dfilter-macro-uat.c
blob939975186a1ef46cb084858b0d7b25c31da9aede
1 /* dfilter-macro.c
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 2001 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include "config.h"
11 #define WS_LOG_DOMAIN LOG_DOMAIN_DFILTER
12 #include "dfilter-macro.h"
13 #include "dfilter-macro-uat.h"
14 #include <epan/uat-int.h>
15 #include <wsutil/filter_files.h>
16 #include <wsutil/filesystem.h>
19 * This file is only used to migrate the dfilter_macros UAT file to the
20 * new "dmacros" configuration file. It should be removed eventually.
23 static dfilter_macro_t* macros;
24 static unsigned num_macros;
26 static void macro_uat_free(void* r) {
27 dfilter_macro_t* m = (dfilter_macro_t*)r;
28 g_free(m->name);
29 g_free(m->text);
30 g_free(m->priv);
31 g_free(m->parts);
32 g_free(m->args_pos);
35 static void* macro_uat_copy(void* dest, const void* orig, size_t len _U_) {
36 dfilter_macro_t* d = (dfilter_macro_t*)dest;
37 const dfilter_macro_t* m = (const dfilter_macro_t*)orig;
39 //DUMP_MACRO(m);
41 d->name = g_strdup(m->name);
42 d->text = g_strdup(m->text);
43 d->usable = m->usable;
45 if (m->parts) {
46 unsigned nparts = 0;
49 * Copy the contents of m->priv (a "cooked" version
50 * of m->text) into d->priv.
52 * First we clone m->text into d->priv, this gets
53 * us a NUL terminated string of the proper length.
55 * Then we loop copying bytes from m->priv into
56 * d-priv. Since m->priv contains internal ACSII NULs
57 * we use the length of m->text to stop the copy.
60 d->priv = g_strdup(m->text);
62 const char* oldText = m->text;
63 const char* oldPriv = (const char*)m->priv;
64 char* newPriv = (char*)d->priv;
65 while(oldText && *oldText) {
66 *(newPriv++) = *(oldPriv++);
67 oldText++;
72 * The contents of the m->parts array contains pointers
73 * into various sections of m->priv. Since it's
74 * an argv style array of ponters, this array is
75 * actually one larger than the number of parts
76 * to hold the final NULL terminator.
78 * The following copy clones the original m->parts
79 * array into d->parts but then fixes-up the pointers
80 * so that they point into the appropriate sections
81 * of the d->priv.
84 do nparts++; while (m->parts[nparts]);
85 d->parts = (char **)g_memdup2(m->parts,(nparts+1)*(unsigned)sizeof(void*));
86 nparts = 0;
87 while(m->parts[nparts]) {
88 if(nparts) {
89 d->parts[nparts] = d->parts[nparts - 1] + (m->parts[nparts] - m->parts[nparts - 1]);
90 } else {
91 d->parts[nparts] = (char *)d->priv;
93 nparts++;
97 * Clone the contents of m->args_pos into d->args_pos.
100 d->args_pos = (int *)g_memdup2(m->args_pos,(--nparts)*(unsigned)sizeof(int));
102 return d;
105 static void macro_uat_post_update(void) {
107 for (unsigned i = 0; i < num_macros; i++) {
108 macro_parse(&macros[i]);
112 static bool macro_name_chk(void *mp, const char *in_name, unsigned name_len,
113 const void *u1 _U_, const void *u2 _U_, char **error) {
114 dfilter_macro_t* m = (dfilter_macro_t*)mp;
115 unsigned i;
117 if (name_len == 0) {
118 *error = g_strdup("invalid name");
119 return false;
122 for (i=0; i < name_len; i++) {
123 if (!(in_name[i] == '_' || g_ascii_isalnum(in_name[i]) ) ) {
124 *error = g_strdup("invalid char in name");
125 return false;
129 /* When loading (!m->name) or when adding/changing the an item with a
130 * different name, check for uniqueness. NOTE: if a duplicate already
131 * exists (because the user manually edited the file), then this will
132 * not trigger a warning. */
133 if (!m->name || g_strcmp0(m->name, in_name)) {
134 for (i = 0; i < num_macros; i++) {
135 /* This a string field which is always NUL-terminated,
136 * so no need to check name_len. */
137 if (!g_strcmp0(in_name, macros[i].name)) {
138 *error = ws_strdup_printf("macro '%s' already exists",
139 in_name);
140 return false;
145 return true;
148 UAT_CSTRING_CB_DEF(macro,name,dfilter_macro_t)
149 UAT_CSTRING_CB_DEF(macro,text,dfilter_macro_t)
151 void convert_old_uat_file(void)
153 uat_t *dfilter_macro_uat = NULL;
154 char *err = NULL;
156 /* Check if we need to convert an old dfilter_macro configuration file. */
157 char *new_path = get_persconffile_path(DMACROS_FILE_NAME, true);
158 if (file_exists(new_path)) {
159 /* Already converted. */
160 g_free(new_path);
161 return;
163 char *old_path = get_persconffile_path(DFILTER_MACRO_FILENAME, true);
164 if (!file_exists(old_path)) {
165 /* Nothing to do.*/
166 g_free(new_path);
167 g_free(old_path);
168 return;
171 static uat_field_t uat_fields[] = {
172 UAT_FLD_CSTRING_OTHER(macro,name,"Name",macro_name_chk,"The name of the macro."),
173 /* N.B. it would be nice if there was a field type for display filters (with
174 auto-completion & colouring), but this wouldn't work here as the filter string
175 will contain $1, etc... */
176 UAT_FLD_CSTRING_ISPRINT(macro,text,"Text","The text this macro resolves to."),
177 UAT_END_FIELDS
180 dfilter_macro_uat = uat_new("Display Filter Macros",
181 sizeof(dfilter_macro_t),
182 DFILTER_MACRO_FILENAME,
183 true,
184 &macros,
185 &num_macros,
186 UAT_AFFECTS_FIELDS,
187 "ChDisplayFilterMacrosSection",
188 macro_uat_copy,
189 NULL,
190 macro_uat_free,
191 macro_uat_post_update,
192 NULL,
193 uat_fields);
195 if (uat_load(dfilter_macro_uat, old_path, &err)) {
196 if (num_macros > 0) {
197 // We expect the new list to be empty.
198 filter_list_t *list = ws_filter_list_read(DMACROS_LIST);
199 for (unsigned i = 0; i < num_macros; i++) {
200 if (macros[i].usable) {
201 // Add only if it is a new entry
202 if (ws_filter_list_find(list, macros[i].name) == NULL) {
203 ws_filter_list_add(list,
204 macros[i].name,
205 macros[i].text);
209 ws_filter_list_write(list);
210 ws_filter_list_free(list);
213 else {
214 ws_message("Error loading '%s' UAT: %s", DFILTER_MACRO_FILENAME, err);
215 g_free(err);
217 uat_destroy(dfilter_macro_uat);
218 g_free(new_path);
219 g_free(old_path);