diff options
author | Guy Harris <guy@alum.mit.edu> | 2018-12-17 10:57:20 -0800 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2018-12-17 21:55:23 +0000 |
commit | 5953756305388724545f0df46d286be2f02c048a (patch) | |
tree | 092b7a2e0b064faa81c3c3ee7bb95ee0c302d4f4 /epan/wslua | |
parent | 0ba97f9a45614f18e71f1e5bb816c823c9a74c1c (diff) |
Add routines to load Lua programs that assume the path is UTF-8 on Windows.
Add ws_dofile() and ws_loadfile(), which are like the substitute
dofile() and loadfile() we provide, but that, on Windows, take a UTF-8
path rather than a path in the local code page.
Use that to load console.lua.
This means we can load console.lua on Windows even if the full path to
it includes non-ASCII characters.
Bug: 15118
Change-Id: Iaa00639563fe53a34e1e24e42022f3886a38e7c5
Reviewed-on: https://code.wireshark.org/review/31075
Petri-Dish: Guy Harris <guy@alum.mit.edu>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'epan/wslua')
-rw-r--r-- | epan/wslua/template-init.lua | 6 | ||||
-rw-r--r-- | epan/wslua/wslua_util.c | 162 |
2 files changed, 166 insertions, 2 deletions
diff --git a/epan/wslua/template-init.lua b/epan/wslua/template-init.lua index a06f62265e..fe0ca3fe05 100644 --- a/epan/wslua/template-init.lua +++ b/epan/wslua/template-init.lua @@ -30,7 +30,9 @@ if running_superuser then setmetatable(disabled_lib,{ __index = function() error("this package ".. hint) end } ); dofile = function() error("dofile " .. hint) end + ws_dofile = function() error("ws_dofile " .. hint) end loadfile = function() error("loadfile " .. hint) end + ws_loadfile = function() error("ws_loadfile " .. hint) end loadlib = function() error("loadlib " .. hint) end require = function() error("require " .. hint) end os = disabled_lib @@ -130,5 +132,5 @@ datafile_path = Dir.global_config_path persconffile_path = Dir.personal_config_path -dofile(DATA_DIR.."console.lua") ---dofile(DATA_DIR.."dtd_gen.lua") +ws_dofile(DATA_DIR.."console.lua") +--ws_dofile(DATA_DIR.."dtd_gen.lua") diff --git a/epan/wslua/wslua_util.c b/epan/wslua/wslua_util.c index de30b5df81..69845024c1 100644 --- a/epan/wslua/wslua_util.c +++ b/epan/wslua/wslua_util.c @@ -17,6 +17,7 @@ #include "wslua.h" #include <math.h> #include <epan/stat_tap_ui.h> +#include <wsutil/file_util.h> WSLUA_FUNCTION wslua_get_version(lua_State* L) { /* Gets a string of the Wireshark version. */ @@ -218,6 +219,167 @@ WSLUA_FUNCTION wslua_dofile(lua_State* L) { return lua_gettop(L) - n; } +/* + * These routines here are based on code from: + * lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto + * lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto + * See Copyright Notice in lua.h + * + * All we did was 1) rename luaL_loadfilex to loadfilex, 2) make it + * static, and 3) make it call ws_fopen() so that, on Windows, it takes + * a UTF-8 pathname, rather than a pathname in the local code page, as + * the file name argument. + */ + +typedef struct LoadF { + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[LUAL_BUFFERSIZE]; /* area for reading file */ +} LoadF; + +static const char *getF(lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + +static int errfile(lua_State *L, const char *what, int fnameindex) { + const char *serr = g_strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + +static int skipBOM(LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment(LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n') ; + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + +static int our_loadfilex(lua_State *L, const char *filename, const char *mode) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = ws_fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = ws_freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + +#define our_loadfile(L,f) our_loadfilex(L,f,NULL) + +WSLUA_FUNCTION wslua_ws_loadfile(lua_State* L) { + /* This is like Lua's loadfile(), except that 1) if a file does not + exist in the current directory it will look for it in Wireshark's + user and system directories and 2) pathnames are, on Windows, treated + as UTF-8 strings rather than strings in the current code page. */ +#define WSLUA_ARG_loadfile_FILENAME 1 /* Name of the file to be loaded. */ + const char *given_fname = luaL_checkstring(L, WSLUA_ARG_loadfile_FILENAME); + char* filename; + + filename = wslua_get_actual_filename(given_fname); + + if (!filename) { + WSLUA_ARG_ERROR(loadfile,FILENAME,"file does not exist"); + return 0; + } + + /* Use our loadfile, so that, on Windows, we handle UTF-8 file names. */ + if (our_loadfile(L, filename) == 0) { + g_free(filename); + return 1; + } else { + g_free(filename); + lua_pushnil(L); + lua_insert(L, -2); + return 2; + } +} + +WSLUA_FUNCTION wslua_ws_dofile(lua_State* L) { + /* This is like Lua's dofile(), except that 1) if a file does not + exist in the current directory it will look for it in Wireshark's + user and system directories and 2) pathnames are, on Windows, treated + as UTF-8 strings rather than strings in the current code page. */ +#define WSLUA_ARG_dofile_FILENAME 1 /* Name of the file to be run. */ + const char *given_fname = luaL_checkstring(L, WSLUA_ARG_dofile_FILENAME); + char* filename = wslua_get_actual_filename(given_fname); + int n; + + if (!filename) { + WSLUA_ARG_ERROR(dofile,FILENAME,"file does not exist"); + return 0; + } + + n = lua_gettop(L); + /* Use our loadfile, so that, on Windows, we handle UTF-8 file names. */ + if (our_loadfile(L, filename) != 0) lua_error(L); + g_free(filename); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} typedef struct _statcmd_t { lua_State* L; |