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
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
;
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
;
41 d
->name
= g_strdup(m
->name
);
42 d
->text
= g_strdup(m
->text
);
43 d
->usable
= m
->usable
;
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
++);
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
84 do nparts
++; while (m
->parts
[nparts
]);
85 d
->parts
= (char **)g_memdup2(m
->parts
,(nparts
+1)*(unsigned)sizeof(void*));
87 while(m
->parts
[nparts
]) {
89 d
->parts
[nparts
] = d
->parts
[nparts
- 1] + (m
->parts
[nparts
] - m
->parts
[nparts
- 1]);
91 d
->parts
[nparts
] = (char *)d
->priv
;
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));
105 static void macro_uat_post_update(void) {
107 for (unsigned i
= 0; i
< num_macros
; i
++) {
108 macro_parse(¯os
[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
;
118 *error
= g_strdup("invalid name");
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");
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",
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
;
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. */
163 char *old_path
= get_persconffile_path(DFILTER_MACRO_FILENAME
, true);
164 if (!file_exists(old_path
)) {
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."),
180 dfilter_macro_uat
= uat_new("Display Filter Macros",
181 sizeof(dfilter_macro_t
),
182 DFILTER_MACRO_FILENAME
,
187 "ChDisplayFilterMacrosSection",
191 macro_uat_post_update
,
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
,
209 ws_filter_list_write(list
);
210 ws_filter_list_free(list
);
214 ws_message("Error loading '%s' UAT: %s", DFILTER_MACRO_FILENAME
, err
);
217 uat_destroy(dfilter_macro_uat
);