Added support for uat preferences type, to the Lua scripts.
This commit is contained in:
parent
b95179da68
commit
81ec7d15f0
@ -6,6 +6,7 @@
|
||||
* (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
|
||||
* (c) 2007, Tamas Regos <tamas.regos@ericsson.com>
|
||||
* (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
|
||||
* (c) 2025, Bartis Csaba <bracsek@bracsek.eu>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
@ -37,6 +38,7 @@
|
||||
#include <epan/packet.h>
|
||||
#include <epan/strutil.h>
|
||||
#include <epan/to_str.h>
|
||||
#include <epan/uat.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/proto.h>
|
||||
#include <epan/epan_dissect.h>
|
||||
@ -175,6 +177,7 @@ typedef enum {
|
||||
PREF_STRING,
|
||||
PREF_RANGE,
|
||||
PREF_STATIC_TEXT,
|
||||
PREF_UAT,
|
||||
PREF_OBSOLETE
|
||||
} pref_type_t;
|
||||
|
||||
@ -200,6 +203,9 @@ typedef struct _wslua_pref_t {
|
||||
option menu or combo box in
|
||||
the preferences tab */
|
||||
} enum_info; /**< for PREF_ENUM */
|
||||
struct {
|
||||
uat_field_t *uat_field_list; /**< list of field configurations */
|
||||
} uat_field_list_info; /**< for PREF_UAT */
|
||||
char* default_s; /**< default value for value.s */
|
||||
} info; /**< display/text file information */
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
* (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
|
||||
* (c) 2011, Stig Bjorlykke <stig@bjorlykke.org>
|
||||
* (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com>
|
||||
* (c) 2025, Bartis Csaba <bracsek@bracsek.eu>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
@ -19,6 +20,121 @@
|
||||
|
||||
#include "wslua.h"
|
||||
|
||||
#define MAXIMUM_ALLOWED_UAT_FIELD_COUNT 10
|
||||
|
||||
/*
|
||||
* Definition of a UAT string container structure.
|
||||
*
|
||||
* "field_data" is the pointer array to the fields values
|
||||
* "uat_filename" is the file name of currently ussed uat
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *field_data[MAXIMUM_ALLOWED_UAT_FIELD_COUNT];
|
||||
char *uat_filename;
|
||||
} uat_container_t;
|
||||
|
||||
/*
|
||||
* Sanity-checks a UAT record.
|
||||
*
|
||||
* This function do a record checks with the uat_update_cb function from
|
||||
* preferences_uat_callbacks.lua Lua file.
|
||||
*
|
||||
* r is the record from uat
|
||||
* err a pointer for showing checks error messages
|
||||
*/
|
||||
static bool uat_update_cb(void *r, char **err)
|
||||
{
|
||||
uat_container_t *record = (uat_container_t *)r;
|
||||
lua_State *L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
char *full_path = g_strjoin(G_DIR_SEPARATOR_S,
|
||||
get_persconffile_path("", false),
|
||||
"plugins", "preferences_uat_callbacks.lua", NULL);
|
||||
/* if checker file not exist we will accept all walues! */
|
||||
if (!file_exists(full_path)) {
|
||||
return true;
|
||||
}
|
||||
/* search checker function from file */
|
||||
if (luaL_dofile(L, full_path) != LUA_OK) {
|
||||
lua_close(L);
|
||||
return false;
|
||||
}
|
||||
lua_getglobal(L, "uat_update_cb");
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
return false;
|
||||
}
|
||||
/* prepare values for checker function */
|
||||
/* first parameter with records values */
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < MAXIMUM_ALLOWED_UAT_FIELD_COUNT; i++) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_pushstring(L, record->field_data[i]);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
/* second parameter uat filename */
|
||||
lua_pushstring(L, record->uat_filename);
|
||||
/* call the function with 2 parameter */
|
||||
if (lua_pcall(L, 2, 2, 0) != LUA_OK) {
|
||||
lua_pop(L, 1);
|
||||
lua_close(L);
|
||||
return false;
|
||||
}
|
||||
/* 1th parameter the received result as boolean */
|
||||
if (!lua_isboolean(L, -2)) {
|
||||
return false;
|
||||
}
|
||||
bool bool_result = lua_toboolean(L, -2);
|
||||
if (lua_isstring(L, -1)) {
|
||||
const char *str_result = lua_tostring(L, -1);
|
||||
/* returned error as string showed on gui */
|
||||
*err = g_strdup(str_result);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
lua_close(L);
|
||||
return bool_result;
|
||||
}
|
||||
|
||||
static void txtmod_string_set_cb(
|
||||
void* rec,
|
||||
const char* buf,
|
||||
unsigned len,
|
||||
const void* u1,
|
||||
const void* u2)
|
||||
{
|
||||
const uint8_t * index = (const uint8_t *)u1;
|
||||
char * uat_file_name = (char *)u2;
|
||||
uat_container_t * record = (uat_container_t*)rec;
|
||||
unsigned field_data_length;
|
||||
char* new_val = uat_unesc(buf,len,&field_data_length);
|
||||
g_free((record->field_data[*index]));
|
||||
record->field_data[*index] = new_val;
|
||||
record->uat_filename = uat_file_name;
|
||||
}
|
||||
|
||||
static void txtmod_string_tostr_cb(
|
||||
void* rec,
|
||||
char** out_ptr,
|
||||
unsigned* out_len,
|
||||
const void* u1,
|
||||
const void* UNUSED_PARAMETER(u2))
|
||||
{
|
||||
const uint8_t * index = (const uint8_t *)u1;
|
||||
uat_container_t * record = (uat_container_t*)rec;
|
||||
if (record->field_data[*index]) {
|
||||
*out_ptr = uat_esc(record->field_data[*index], (unsigned)strlen(record->field_data[*index]));
|
||||
*out_len = (unsigned)strlen(*out_ptr);
|
||||
} else {
|
||||
*out_ptr = g_strdup("");
|
||||
*out_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* UAT variables */
|
||||
static uat_t *uat;
|
||||
static uat_container_t *perf_uat_data;
|
||||
static unsigned num_perf_uat_data;
|
||||
|
||||
/* WSLUA_CONTINUE_MODULE Proto */
|
||||
|
||||
|
||||
@ -83,6 +199,63 @@ static enum_val_t* get_enum(lua_State *L, int idx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uat_field_t* get_uat_flds_array(lua_State *L, int idx, char * uat_filename)
|
||||
{
|
||||
const char *str1, *str2;
|
||||
uint8_t index = 0;
|
||||
uat_field_t *ret, last = {NULL, NULL, PT_TXTMOD_STRING,
|
||||
{0, txtmod_string_set_cb, txtmod_string_tostr_cb}, {0, 0, 0}, 0, NULL, NULL};
|
||||
/* Container to store fields */
|
||||
GArray* fs = g_array_new(true,true,sizeof(uat_field_t));
|
||||
luaL_checktype(L, idx, LUA_TTABLE);
|
||||
lua_pushnil(L);
|
||||
|
||||
while (lua_next(L, idx)) {
|
||||
uat_field_t f = {NULL, NULL, PT_TXTMOD_STRING,
|
||||
{0, txtmod_string_set_cb, txtmod_string_tostr_cb}, {0, 0, 0}, 0, NULL, NULL};
|
||||
/* field title */
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
lua_pushnil(L);
|
||||
lua_next(L, -2);
|
||||
if (! lua_isstring(L,-1)) {
|
||||
luaL_argerror(L,idx,"First value of an UAT table config must be string");
|
||||
g_array_free(fs,true);
|
||||
return NULL;
|
||||
}
|
||||
str1 = lua_tostring(L, -1);
|
||||
/* field description */
|
||||
lua_pop(L, 1);
|
||||
lua_next(L, -2);
|
||||
if (! lua_isstring(L,-1)) {
|
||||
luaL_argerror(L,idx,"Second value of an UAT table config must be string");
|
||||
g_array_free(fs,true);
|
||||
return NULL;
|
||||
}
|
||||
str2 = lua_tostring(L, -1);
|
||||
/* configure fields, attach index and filename pointer to each field */
|
||||
f.title = g_strdup(str1);
|
||||
f.desc = g_strdup(str2);
|
||||
f.cbdata.chk = g_new(uint8_t, 1);
|
||||
*(uint8_t *)f.cbdata.chk = index;
|
||||
f.cbdata.set = g_new(uint8_t, 1);
|
||||
*(uint8_t *)f.cbdata.set = index;
|
||||
f.cbdata.tostr = g_new(uint8_t, 1);
|
||||
*(uint8_t *)f.cbdata.tostr = index;
|
||||
f.fld_data = uat_filename;
|
||||
|
||||
g_array_append_val(fs,f);
|
||||
index = index + 1;
|
||||
/* limiting fields count */
|
||||
if(index >= MAXIMUM_ALLOWED_UAT_FIELD_COUNT) {
|
||||
return NULL;
|
||||
}
|
||||
lua_pop(L, 3);
|
||||
}
|
||||
g_array_append_val(fs,last);
|
||||
ret = (uat_field_t*)(void*)g_array_free(fs, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int new_pref(lua_State* L, pref_type_t type) {
|
||||
const char* label = luaL_optstring(L,1,NULL);
|
||||
const char* descr = luaL_optstring(L,3,"");
|
||||
@ -151,6 +324,15 @@ static int new_pref(lua_State* L, pref_type_t type) {
|
||||
/* This is just a static text. */
|
||||
break;
|
||||
}
|
||||
case PREF_UAT: {
|
||||
/* get filename */
|
||||
const char* uat_file_name = luaL_optstring(L,4,"");
|
||||
pref->value.s = g_strdup(uat_file_name);
|
||||
/* process fields */
|
||||
uat_field_t *flds_array = get_uat_flds_array(L,2, pref->value.s);
|
||||
pref->info.uat_field_list_info.uat_field_list = flds_array;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ws_assert_not_reached();
|
||||
break;
|
||||
@ -264,6 +446,51 @@ WSLUA_CONSTRUCTOR Pref_statictext(lua_State* L) {
|
||||
return new_pref(L,PREF_STATIC_TEXT);
|
||||
}
|
||||
|
||||
WSLUA_CONSTRUCTOR Pref_uat(lua_State* L) {
|
||||
/*
|
||||
Creates an uat preference to be added to a <<lua_class_attrib_proto_prefs,`Proto.prefs`>> Lua table.
|
||||
|
||||
===== Example:
|
||||
|
||||
[source,lua]
|
||||
----
|
||||
local fieldlist = {
|
||||
{"field 1", "Description 1"},
|
||||
{"field 2", "Description 2"},
|
||||
}
|
||||
|
||||
-- Create a uat preference that appears as a button on the Foo Protocol preference page.
|
||||
-- The user accessible table can be edited with this button.
|
||||
proto_foo.prefs.preference_uat_name = Pref.uat("Label", fieldlist, "Description", "uat_filename")
|
||||
|
||||
-- Value checker:
|
||||
|
||||
-- Create a file in Personal Lua plugins directory named as preferences_uat_callbacks.lua
|
||||
-- Create a checker function named as uat_update_cb:
|
||||
-- The uat editor will call this function for checks the values.
|
||||
function uat_update_cb(records, uat_filename)
|
||||
print("UAT filename: " .. uat_filename)
|
||||
print("UAT record 0 = " .. records[0])
|
||||
print("UAT record 1 = " .. records[1])
|
||||
local result = true
|
||||
local errstring = ""
|
||||
-- do not allow 5 in the "field 1
|
||||
if (tonumber(records[0]) == 5) then
|
||||
result = false
|
||||
errstring = "Firsct collumn cannot be 5!"
|
||||
end
|
||||
print("Check result = " .. tostring(result))
|
||||
-- return check result as boolean and errstring if needed
|
||||
return result, errstring
|
||||
end
|
||||
----
|
||||
*/
|
||||
#define WSLUA_ARG_Pref_uat_FIELD_CONFIG 2 /* Fields names and description table. */
|
||||
#define WSLUA_ARG_Pref_uat_DESCRIPTION 3 /* A description of what this preference is. */
|
||||
#define WSLUA_ARG_Pref_uat_FILE_NAME 4 /* The name of the uat file. */
|
||||
return new_pref(L,PREF_UAT);
|
||||
}
|
||||
|
||||
static range_t* get_range(lua_State *L, int idx_r, int idx_m)
|
||||
{
|
||||
static range_t *ret = NULL;
|
||||
@ -322,6 +549,24 @@ static int Pref__gc(lua_State* L) {
|
||||
g_free((enum_val_t *)pref->info.enum_info.enumvals);
|
||||
break;
|
||||
}
|
||||
case PREF_UAT: {
|
||||
/*
|
||||
* Free the uat values allocated in get_uat_flds_array().
|
||||
*/
|
||||
const uat_field_t *field_valp = pref->info.uat_field_list_info.uat_field_list;
|
||||
while (field_valp->name) {
|
||||
g_free((char *)field_valp->title);
|
||||
g_free((char *)field_valp->desc);
|
||||
g_free((uint8_t *)field_valp->cbdata.chk);
|
||||
g_free((uint8_t *)field_valp->cbdata.set);
|
||||
g_free((uint8_t *)field_valp->cbdata.tostr);
|
||||
g_free((char *)field_valp->fld_data);
|
||||
field_valp++;
|
||||
}
|
||||
g_free((uat_field_t *)pref->info.uat_field_list_info.uat_field_list);
|
||||
g_free(pref->value.s);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -337,6 +582,7 @@ WSLUA_METHODS Pref_methods[] = {
|
||||
WSLUA_CLASS_FNREG(Pref,enum),
|
||||
WSLUA_CLASS_FNREG(Pref,range),
|
||||
WSLUA_CLASS_FNREG(Pref,statictext),
|
||||
WSLUA_CLASS_FNREG(Pref,uat),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@ -469,6 +715,29 @@ WSLUA_METAMETHOD Prefs__newindex(lua_State* L) {
|
||||
pref->label,
|
||||
pref->desc);
|
||||
break;
|
||||
case PREF_UAT:
|
||||
/* Create a UAT for preferences */
|
||||
{
|
||||
uat = uat_new(pref->label,
|
||||
sizeof(uat_container_t), /* record size */
|
||||
pref->value.s, /* filename */
|
||||
true, /* from_profile */
|
||||
&perf_uat_data, /* data_ptr */
|
||||
&num_perf_uat_data, /* numitems_ptr */
|
||||
UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
|
||||
NULL, /* help */
|
||||
NULL, /* copy callback */
|
||||
uat_update_cb, /* update callback */
|
||||
NULL, /* free callback */
|
||||
NULL, /* post update callback */
|
||||
NULL, /* reset callback */
|
||||
pref->info.uat_field_list_info.uat_field_list); /* UAT field definitions */
|
||||
prefs_register_uat_preference(prefs_p->proto->prefs_module, pref->value.s,
|
||||
pref->label,
|
||||
pref->desc,
|
||||
uat);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WSLUA_ERROR(Prefs__newindex,"Unknown Pref type");
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user