Lua: Add get_preference() and set_preference() utility functions.

Support uint, bool, enum, string, range, filename and directory preferences.
Added apply_preferences() to write to file and apply changes.
This commit is contained in:
Stig Bjørlykke 2020-10-30 14:46:29 +01:00 committed by Wireshark GitLab Utility
parent c7e6b79825
commit 9cafd342ac
6 changed files with 355 additions and 0 deletions

View File

@ -1085,6 +1085,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
prefs_set_effect_flags@Base 2.5.0
prefs_set_effect_flags_by_name@Base 2.5.0
prefs_set_enum_value@Base 2.3.0
prefs_set_enum_string_value@Base 3.5.0
prefs_set_gui_theme_is_dark@Base 2.5.0
prefs_set_module_effect_flags@Base 2.5.0
prefs_set_pref@Base 1.9.1

View File

@ -231,6 +231,7 @@ WS_DLL_PUBLIC guint prefs_get_uint_value_real(pref_t *pref, pref_source_t source
WS_DLL_PUBLIC unsigned int prefs_set_enum_value(pref_t *pref, gint value, pref_source_t source);
WS_DLL_PUBLIC unsigned int prefs_set_enum_string_value(pref_t *pref, const gchar *value, pref_source_t source);
WS_DLL_PUBLIC gint prefs_get_enum_value(pref_t *pref, pref_source_t source);
WS_DLL_PUBLIC const enum_val_t* prefs_get_enumvals(pref_t *pref);
WS_DLL_PUBLIC gboolean prefs_get_enum_radiobuttons(pref_t *pref);

View File

@ -65,6 +65,7 @@ static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
static void try_convert_to_custom_column(gpointer *el_data);
static guint prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
gpointer user_data, gboolean skip_obsolete);
static gint find_val_for_string(const char *needle, const enum_val_t *haystack, gint default_value);
#define IS_PREF_OBSOLETE(p) ((p) & PREF_OBSOLETE)
#define SET_PREF_OBSOLETE(p) ((p) |= PREF_OBSOLETE)
@ -1349,6 +1350,13 @@ unsigned int prefs_set_enum_value(pref_t *pref, gint value, pref_source_t source
return changed;
}
unsigned int prefs_set_enum_string_value(pref_t *pref, const gchar *value, pref_source_t source)
{
gint enum_val = find_val_for_string(value, pref->info.enum_info.enumvals, *pref->varp.enump);
return prefs_set_enum_value(pref, enum_val, source);
}
gint prefs_get_enum_value(pref_t *pref, pref_source_t source)
{
switch (source)

View File

@ -17,6 +17,8 @@
#include "wslua.h"
#include <math.h>
#include <epan/stat_tap_ui.h>
#include <epan/prefs.h>
#include <epan/prefs-int.h>
WSLUA_FUNCTION wslua_get_version(lua_State* L) { /* Gets the Wireshark version as a string. */
@ -123,6 +125,222 @@ WSLUA_FUNCTION wslua_format_time(lua_State* LS) { /* Formats a relative timestam
WSLUA_RETURN(1); /* A string with the formated time */
}
WSLUA_FUNCTION wslua_get_preference(lua_State *L) {
/* Get a preference value. @since 3.5.0 */
#define WSLUA_ARG_Prefs_get_PREFERENCE 1 /* The name of the preference. */
const gchar* preference = luaL_checkstring(L,WSLUA_ARG_Prefs_get_PREFERENCE);
/* Split preference from module.preference */
gchar *module_name = g_strdup(preference);
gchar *preference_name = strchr(module_name, '.');
pref_t *pref = NULL;
if (preference_name) {
*preference_name = '\0';
preference_name++;
module_t *module = prefs_find_module(module_name);
pref = prefs_find_preference(module, preference_name);
}
if (pref) {
switch (prefs_get_type(pref)) {
case PREF_UINT:
{
guint uint_value = prefs_get_uint_value_real(pref, pref_current);
lua_pushinteger(L, uint_value);
break;
}
case PREF_BOOL:
{
gboolean bool_value = prefs_get_bool_value(pref, pref_current);
lua_pushboolean(L, bool_value);
break;
}
case PREF_ENUM:
{
const enum_val_t *enums;
gint enum_value = prefs_get_enum_value(pref, pref_current);
for (enums = prefs_get_enumvals(pref); enums->name; enums++) {
if (enums->value == enum_value) {
lua_pushstring(L,enums->name);
break;
}
}
if (!enums || !enums->name) {
/* Enum preference has an unknown value. */
lua_pushstring(L,"");
}
break;
}
case PREF_STRING:
case PREF_SAVE_FILENAME:
case PREF_OPEN_FILENAME:
case PREF_DIRNAME:
{
const gchar *string_value = prefs_get_string_value(pref, pref_current);
lua_pushstring(L,string_value);
break;
}
case PREF_RANGE:
{
char *range_value = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current));
lua_pushstring(L,range_value);
wmem_free(NULL, range_value);
break;
}
default:
/* Get not supported for this type. */
return luaL_error(L, "preference type %d is not supported.", prefs_get_type(pref));
}
} else {
/* No such preference. */
lua_pushnil(L);
}
g_free (module_name);
WSLUA_RETURN(1); /* The preference value, or nil if not found. */
}
WSLUA_FUNCTION wslua_set_preference(lua_State *L) {
/* Set a preference value. @since 3.5.0 */
#define WSLUA_ARG_Prefs_set_PREFERENCE 1 /* The name of the preference. */
#define WSLUA_ARG_Prefs_set_VALUE 2 /* The preference value to set. */
const gchar* preference = luaL_checkstring(L,WSLUA_ARG_Prefs_get_PREFERENCE);
/* Split preference from module.preference */
gchar *module_name = g_strdup(preference);
gchar *preference_name = strchr(module_name, '.');
module_t *module = NULL;
pref_t *pref = NULL;
if (preference_name) {
*preference_name = '\0';
preference_name++;
module = prefs_find_module(module_name);
pref = prefs_find_preference(module, preference_name);
}
if (pref) {
unsigned int changed = 0;
switch (prefs_get_type(pref)) {
case PREF_UINT:
{
guint uint_value = (guint)luaL_checkinteger(L,WSLUA_ARG_Prefs_set_VALUE);
changed = prefs_set_uint_value(pref, uint_value, pref_current);
module->prefs_changed_flags |= changed;
lua_pushboolean(L, changed);
break;
}
case PREF_BOOL:
{
gboolean bool_value = wslua_checkboolean(L, WSLUA_ARG_Prefs_set_VALUE);
changed = prefs_set_bool_value(pref, bool_value, pref_current);
module->prefs_changed_flags |= changed;
lua_pushboolean(L, changed);
break;
}
case PREF_ENUM:
{
const gchar *enum_value = luaL_checkstring(L,WSLUA_ARG_Prefs_set_VALUE);
changed = prefs_set_enum_string_value(pref, enum_value, pref_current);
module->prefs_changed_flags |= changed;
lua_pushboolean(L, changed);
break;
}
case PREF_STRING:
case PREF_SAVE_FILENAME:
case PREF_OPEN_FILENAME:
case PREF_DIRNAME:
{
const gchar *string_value = luaL_checkstring(L,WSLUA_ARG_Prefs_set_VALUE);
changed = prefs_set_string_value(pref, string_value, pref_current);
module->prefs_changed_flags |= changed;
lua_pushboolean(L, changed);
break;
}
case PREF_RANGE:
{
const gchar *range_value = luaL_checkstring(L,WSLUA_ARG_Prefs_set_VALUE);
range_t *range = NULL;
convert_ret_t ret = range_convert_str(NULL, &range, range_value, prefs_get_max_value(pref));
if (ret == CVT_NUMBER_TOO_BIG) {
return luaL_error(L, "illegal range (number too big)");
} else if (ret != CVT_NO_ERROR) {
return luaL_error(L, "illegal range (syntax error)");
}
changed = prefs_set_range_value(pref, range, pref_current);
wmem_free(NULL, range);
module->prefs_changed_flags |= changed;
lua_pushboolean(L, changed);
break;
}
default:
/* Set not supported for this type. */
return luaL_error(L, "preference type %d is not supported.", prefs_get_type(pref));
}
} else {
/* No such preference. */
lua_pushnil(L);
}
g_free(module_name);
WSLUA_RETURN(1); /* true if changed, false if unchanged or nil if not found. */
}
WSLUA_FUNCTION wslua_reset_preference(lua_State *L) {
/* Reset a preference to default value. @since 3.5.0 */
#define WSLUA_ARG_Prefs_set_PREFERENCE 1 /* The name of the preference. */
const gchar* preference = luaL_checkstring(L,WSLUA_ARG_Prefs_get_PREFERENCE);
// Split preference from module.preference
gchar *module_name = g_strdup(preference);
gchar *preference_name = strchr(module_name, '.');
pref_t *pref = NULL;
if (preference_name) {
*preference_name = '\0';
preference_name++;
module_t *module = prefs_find_module(module_name);
pref = prefs_find_preference(module, preference_name);
}
if (pref) {
reset_pref(pref);
lua_pushboolean(L, TRUE);
} else {
/* No such preference. */
lua_pushnil(L);
}
g_free(module_name);
WSLUA_RETURN(1); /* true if valid preference */
}
WSLUA_FUNCTION wslua_apply_preferences(lua_State *L) {
/* Write preferences to file and apply changes. @since 3.5.0 */
char *pf_path = NULL;
int err = write_prefs(&pf_path);
if (err) {
/* Make a copy of pf_path because luaL_error() will return */
gchar pf_path_copy[256];
g_strlcpy(pf_path_copy, pf_path, sizeof pf_path_copy);
g_free(pf_path);
return luaL_error(L, "can't open preferences file\n\"%s\": %s.",
pf_path_copy, g_strerror(err));
} else {
prefs_apply_all();
}
return 0;
}
WSLUA_FUNCTION wslua_report_failure(lua_State* LS) { /* Reports a failure to the user. */
#define WSLUA_ARG_report_failure_TEXT 1 /* Message text to report. */
const gchar* s = luaL_checkstring(LS,WSLUA_ARG_report_failure_TEXT);

123
test/lua/util.lua Normal file
View File

@ -0,0 +1,123 @@
-- test script for wslua utility functions
------------- helper funcs ------------
local function testing(...)
print("---- Testing "..tostring(...).." ----")
end
local function test(name, ...)
io.stdout:write("test "..name.."...")
if (...) == true then
io.stdout:write("passed\n")
else
io.stdout:write("failed!\n")
error(name.." test failed!")
end
end
--------------------------
-- Note: This tests expects some specific default values
testing("get_preference")
success = pcall(get_preference)
test("get_preference-empty-0", not success)
test("get_preference-empty-1",get_preference("") == nil)
test("get_preference-unknown-0",get_preference("g") == nil)
test("get_preference-unknown-1",get_preference("gui") == nil)
test("get_preference-unknown-2",get_preference("gui.") == nil)
test("get_preference-unknown-3",get_preference("gui.ask") == nil)
test("get_preference-unknown-4",get_preference("ugi.ask_unsaved") == nil)
test("get_preference-uint-0",get_preference("gui.fileopen.preview") == 3)
test("get_preference-bool-0",get_preference("gui.ask_unsaved") == true)
test("get_preference-bool-1",get_preference("gui.interfaces_show_hidden") == false)
test("get_preference-enum-1",get_preference("gui.console_open") == "NEVER")
test("get_preference-string-0",get_preference("gui.window_title") == "")
test("get_preference-range-0",get_preference("http.tls.port") == "443")
success = pcall(get_preference, "user_dlt.encaps_table")
test("get_preference-uat-0", not success)
--------------------------
testing("set_preference")
success = pcall(set_preference)
test("set_preference-empty-0", not success)
test("set_preference-empty-1",set_preference("") == nil)
test("set_preference-unknown-0",set_preference("g") == nil)
test("set_preference-unknown-1",set_preference("gui") == nil)
test("set_preference-unknown-2",set_preference("gui.") == nil)
test("set_preference-unknown-3",set_preference("gui.ask") == nil)
test("set_preference-unknown-4",set_preference("ugi.ask_unsaved") == nil)
success = pcall(set_preference,"gui.fileopen.preview")
test("set_preference-uint-0", not success)
success = pcall(set_preference,"gui.fileopen.preview",true)
test("set_preference-uint-1", not success)
success = pcall(set_preference,"gui.fileopen.preview","string")
test("set_preference-uint-2", not success)
test("set_preference-uint-3",set_preference("gui.fileopen.preview",3) == false)
test("set_preference-uint-4",set_preference("gui.fileopen.preview",42) == true)
test("set_preference-uint-4-get",get_preference("gui.fileopen.preview") == 42)
success = pcall(set_preference,"gui.ask_unsaved")
test("set_preference-bool-0", not success)
success = pcall(set_preference,"gui.ask_unsaved",42)
test("set_preference-bool-1", not success)
success = pcall(set_preference,"gui.ask_unsaved","string")
test("set_preference-bool-2", not success)
test("set_preference-bool-3",set_preference("gui.ask_unsaved", true) == false)
test("set_preference-bool-4",set_preference("gui.ask_unsaved", false) == true)
success = pcall(set_preference,"gui.console_open")
test("set_preference-enum-0", not success)
success = pcall(set_preference,"gui.console_open",true)
test("set_preference-enum-1", not success)
test("set_preference-enum-2",set_preference("gui.console_open","NEVER") == false)
test("set_preference-enum-3",set_preference("gui.console_open","AUTOMATIC") == true)
test("set_preference-enum-3-get",get_preference("gui.console_open") == "AUTOMATIC")
test("set_preference-enum-4",set_preference("gui.console_open","ALWAYS") == true)
test("set_preference-enum-5",set_preference("gui.console_open","unknown") == false)
test("set_preference-enum-6",set_preference("gui.console_open",42) == false)
success = pcall(set_preference,"gui.window_title")
test("set_preference-string-0", not success)
success = pcall(set_preference,"gui.window_title",true)
test("set_preference-string-1", not success)
test("set_preference-string-2",set_preference("gui.window_title","Title") == true)
test("set_preference-string-2-get",get_preference("gui.window_title") == "Title")
test("set_preference-string-3",set_preference("gui.window_title","Title") == false)
test("set_preference-string-4",set_preference("gui.window_title","") == true)
test("set_preference-string-4-get",get_preference("gui.window_title") == "")
test("set_preference-string-5",set_preference("gui.window_title","") == false)
success = pcall(set_preference,"http.tls.port")
test("set_preference-range-0", not success)
success = pcall(set_preference,"http.tls.port","65536") -- Number too big
test("set_preference-range-1", not success)
success = pcall(set_preference,"http.tls.port","http") -- Syntax error
test("set_preference-range-2", not success)
test("set_preference-range-3",set_preference("http.tls.port","443") == false)
test("set_preference-range-4",set_preference("http.tls.port","443-444") == true)
test("set_preference-range-4-get",get_preference("http.tls.port") == "443-444")
test("set_preference-range-5",set_preference("http.tls.port","443-444") == false)
success = pcall(set_preference, "user_dlt.encaps_table")
test("set_preference-uat-0", not success)
--------------------------
testing("reset_preference")
success = pcall(set_preference)
test("reset_preference-empty-0", not success)
test("reset_preference-empty-1",reset_preference("") == nil)
test("reset_preference-unknown-0",reset_preference("unknown") == nil)
test("reset_preference-uint-0",reset_preference("gui.fileopen.preview") == true)
test("reset_preference-uint-0-get",get_preference("gui.fileopen.preview") == 3)
test("reset_preference-bool-0",reset_preference("gui.ask_unsaved") == true)
test("reset_preference-bool-0-get",get_preference("gui.ask_unsaved") == true)
test("reset_preference-enum-0",reset_preference("gui.console_open") == true)
test("reset_preference-enum-0-get",get_preference("gui.console_open") == "NEVER")
test("reset_preference-string-0",reset_preference("gui.window_title") == true)
test("reset_preference-string-0-get",get_preference("gui.window_title") == "")
test("reset_preference-range-0",reset_preference("http.tls.port") == true)
test("reset_preference-range-0-get",get_preference("http.tls.port") == "443")
print("\n-----------------------------\n")
print("All tests passed!\n\n")

View File

@ -83,6 +83,10 @@ class case_wslua(subprocesstest.SubprocessTestCase):
'''wslua directory functions'''
check_lua_script(self, 'dir.lua', empty_pcap, True)
def test_wslua_util(self, check_lua_script):
'''wslua utility functions'''
check_lua_script(self, 'util.lua', empty_pcap, True)
# Mode_1, mode_2, and mode_3, and fpm were all under wslua_step_dissector_test
# in the Bash version.
def test_wslua_dissector_mode_1(self, check_lua_script_verify):