diff --git a/configure.ac b/configure.ac index eb5e2f2a9..eacab6cba 100644 --- a/configure.ac +++ b/configure.ac @@ -228,8 +228,10 @@ fi # hack to define a short filename also for out-of-tree build if test `dirname $0` = `pwd`; then HWLIB_CFLAGS="$HWLIB_CFLAGS "'-D__file__=__FILE__' + HWLIB_CFLAGS="$HWLIB_CFLAGS "'-D__path_file__=__FILE__' else HWLIB_CFLAGS="$HWLIB_CFLAGS "'-D__file__="\"$(subst $(srcdir)/,,$(abspath $<))\""' + HWLIB_CFLAGS="$HWLIB_CFLAGS "'-D__path_file__="\"$(subst $(top_srcdir)/,,$(abspath $<))\""' fi # # Check for libtdservicedb - the new one - for testing only diff --git a/src/gui/lua/Makefile.am b/src/gui/lua/Makefile.am index e3861cb76..05a3b91a8 100644 --- a/src/gui/lua/Makefile.am +++ b/src/gui/lua/Makefile.am @@ -32,10 +32,12 @@ libneutrino_gui_lua_a_SOURCES = \ lua_cc_window.cpp \ lua_configfile.cpp \ lua_curl.cpp \ + lua_filehelpers.cpp \ lua_hintbox.cpp \ lua_menue.cpp \ lua_messagebox.cpp \ lua_misc.cpp \ + lua_stringinput.cpp \ lua_threads.cpp \ lua_threads_copy.cpp \ lua_threads_functions.cpp \ diff --git a/src/gui/lua/lua_api_version.h b/src/gui/lua/lua_api_version.h index dd5ac6fa7..b5e974561 100644 --- a/src/gui/lua/lua_api_version.h +++ b/src/gui/lua/lua_api_version.h @@ -4,4 +4,4 @@ * to luainstance.h changes */ #define LUA_API_VERSION_MAJOR 1 -#define LUA_API_VERSION_MINOR 47 +#define LUA_API_VERSION_MINOR 56 diff --git a/src/gui/lua/lua_filehelpers.cpp b/src/gui/lua/lua_filehelpers.cpp new file mode 100644 index 000000000..c8d1cd252 --- /dev/null +++ b/src/gui/lua/lua_filehelpers.cpp @@ -0,0 +1,474 @@ +/* + * lua file helpers functions + * + * (C) 2016 M. Liebmann (micha-bbg) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "luainstance.h" +#include "lua_filehelpers.h" + +CLuaInstFileHelpers* CLuaInstFileHelpers::getInstance() +{ + static CLuaInstFileHelpers* LuaInstFileHelpers = NULL; + + if (!LuaInstFileHelpers) + LuaInstFileHelpers = new CLuaInstFileHelpers(); + return LuaInstFileHelpers; +} + +CLuaFileHelpers *CLuaInstFileHelpers::FileHelpersCheckData(lua_State *L, int n) +{ + return *(CLuaFileHelpers **) luaL_checkudata(L, n, LUA_FILEHELPER_CLASSNAME); +} + +void CLuaInstFileHelpers::LuaFileHelpersRegister(lua_State *L) +{ + luaL_Reg meth[] = { + { "new", CLuaInstFileHelpers::FileHelpersNew }, + { "cp", CLuaInstFileHelpers::FileHelpersCp }, + { "chmod", CLuaInstFileHelpers::FileHelpersChmod }, + { "touch", CLuaInstFileHelpers::FileHelpersTouch }, + { "rmdir", CLuaInstFileHelpers::FileHelpersRmdir }, + { "mkdir", CLuaInstFileHelpers::FileHelpersMkdir }, + { "readlink", CLuaInstFileHelpers::FileHelpersReadlink }, + { "ln", CLuaInstFileHelpers::FileHelpersLn }, + { "exist", CLuaInstFileHelpers::FileHelpersExist }, + { "__gc", CLuaInstFileHelpers::FileHelpersDelete }, + { NULL, NULL } + }; + + luaL_newmetatable(L, LUA_FILEHELPER_CLASSNAME); + luaL_setfuncs(L, meth, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -1, "__index"); + lua_setglobal(L, LUA_FILEHELPER_CLASSNAME); +} + +int CLuaInstFileHelpers::FileHelpersNew(lua_State *L) +{ + CLuaFileHelpers **udata = (CLuaFileHelpers **) lua_newuserdata(L, sizeof(CLuaFileHelpers *)); + *udata = new CLuaFileHelpers(); + luaL_getmetatable(L, LUA_FILEHELPER_CLASSNAME); + lua_setmetatable(L, -2); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersCp(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 2; + if (numargs < min_numargs) { + printf("luascript cp: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushboolean(L, false); + return 1; + } + + if (!lua_isstring(L, 2)) { + printf("luascript cp: argument 1 is not a string.\n"); + lua_pushboolean(L, false); + return 1; + } + const char *from = ""; + from = luaL_checkstring(L, 2); + + if (!lua_isstring(L, 3)) { + printf("luascript cp: argument 2 is not a string.\n"); + lua_pushboolean(L, false); + return 1; + } + const char *to = ""; + to = luaL_checkstring(L, 3); + + const char *flags = ""; + if (numargs > min_numargs) + flags = luaL_checkstring(L, 4); + + bool ret = false; + CFileHelpers fh; + fh.setConsoleQuiet(true); + ret = fh.cp(from, to, flags); + if (ret == false) { + helpersDebugInfo di; + fh.readDebugInfo(&di); + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line); + } + + lua_pushboolean(L, ret); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersChmod(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 2; + if (numargs < min_numargs) { + printf("luascript chmod: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushboolean(L, false); + return 1; + } + + const char *file = ""; + file = luaL_checkstring(L, 2); + + int mode_i = luaL_checkint(L, 3); + /* Hack for convert lua number to octal */ + std::string mode_s = itoa(mode_i, 10); + mode_t mode = (mode_t)(strtol(mode_s.c_str(), (char **)NULL, 8) & 0x0FFF); + //printf("\n##### [%s:%d] str: %s, okt: %o \n \n", __func__, __LINE__, mode_s.c_str(), (int)mode); + + bool ret = true; + if (chmod(file, mode) != 0) { + ret = false; + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + const char* s = strerror(errno); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, s, __path_file__, __LINE__); + } + + lua_pushboolean(L, ret); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersTouch(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 1; + if (numargs < min_numargs) { + printf("luascript touch: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushboolean(L, false); + return 1; + } + + const char *file = ""; + file = luaL_checkstring(L, 2); + + bool ret = true; + lua_Debug ar; + + if (!file_exists(file)) { + FILE *f = fopen(file, "w"); + if (f == NULL) { + ret = false; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + const char* s = strerror(errno); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, s, __path_file__, __LINE__); + lua_pushboolean(L, ret); + return 1; + } + fclose(f); + if (numargs == min_numargs) { + lua_pushboolean(L, ret); + return 1; + } + } + + time_t modTime; + if (numargs == min_numargs) + /* current time */ + modTime = time(NULL); + else + /* new time */ + modTime = (time_t)luaL_checkint(L, 3); + + utimbuf utb; + utb.actime = modTime; + utb.modtime = modTime; + if (utime(file, &utb) != 0) { + ret = false; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + const char* s = strerror(errno); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, s, __path_file__, __LINE__); + } + + lua_pushboolean(L, ret); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersRmdir(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 1; + if (numargs < min_numargs) { + printf("luascript rmdir: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushboolean(L, false); + return 1; + } + + const char *dir = ""; + dir = luaL_checkstring(L, 2); + + bool ret = false; + CFileHelpers* fh = CFileHelpers::getInstance(); + fh->setConsoleQuiet(true); + ret = fh->removeDir(dir); + if (ret == false) { + helpersDebugInfo di; + fh->readDebugInfo(&di); + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line); + } + + lua_pushboolean(L, ret); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersMkdir(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 1; + if (numargs < min_numargs) { + printf("luascript mkdir: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushboolean(L, false); + return 1; + } + + const char *dir = ""; + dir = luaL_checkstring(L, 2); + + mode_t mode = 0755; + if (numargs > min_numargs) { + int mode_i = luaL_checkint(L, 3); + /* Hack for convert lua number to octal */ + std::string mode_s = itoa(mode_i, 10); + mode = (mode_t)(strtol(mode_s.c_str(), (char **)NULL, 8) & 0x0FFF); + //printf("\n##### [%s:%d] str: %s, okt: %o \n \n", __func__, __LINE__, mode_s.c_str(), (int)mode); + } + + bool ret = false; + CFileHelpers* fh = CFileHelpers::getInstance(); + fh->setConsoleQuiet(true); + ret = fh->createDir(dir, mode); + if (ret == false) { + helpersDebugInfo di; + fh->readDebugInfo(&di); + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line); + } + + lua_pushboolean(L, ret); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersReadlink(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 1; + if (numargs < min_numargs) { + printf("luascript readlink: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushnil(L); + return 1; + } + + const char *link = ""; + link = luaL_checkstring(L, 2); + + char buf[PATH_MAX]; + memset(buf, '\0', sizeof(buf)); + if (readlink(link, buf, sizeof(buf)-1) == -1) { + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + const char* s = strerror(errno); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, s, __path_file__, __LINE__); + + lua_pushnil(L); + return 1; + } + + lua_pushstring(L, buf); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersLn(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 2; + if (numargs < min_numargs) { + printf("luascript ln: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushboolean(L, false); + return 1; + } + + const char *src = ""; + src = luaL_checkstring(L, 2); + const char *link = ""; + link = luaL_checkstring(L, 3); + + const char *flags = ""; + if (numargs > min_numargs) + flags = luaL_checkstring(L, 4); + + bool symlnk = (strchr(flags, 's') != NULL); + bool force = (strchr(flags, 'f') != NULL); + lua_Debug ar; + + if (!symlnk) { + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + const char* s = "Currently only supports symlinks."; + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, s, __path_file__, __LINE__); + lua_pushboolean(L, false); + return 1; + } + + bool ret = true; + if (symlink(src, link) != 0) { + if (force && (errno == EEXIST)) { + if (unlink(link) == 0) { + if (symlink(src, link) == 0) { + lua_pushboolean(L, ret); + return 1; + } + } + } + ret = false; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + const char* s = strerror(errno); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, s, __path_file__, __LINE__); + + } + + lua_pushboolean(L, ret); + return 1; +} + +int CLuaInstFileHelpers::FileHelpersExist(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + + int numargs = lua_gettop(L) - 1; + int min_numargs = 2; + if (numargs < min_numargs) { + printf("luascript exist: not enough arguments (%d, expected %d)\n", numargs, min_numargs); + lua_pushnil(L); + return 1; + } + + bool ret = false; + bool err = false; + int errLine = 0; + std::string errMsg = ""; + + const char *file = ""; + file = luaL_checkstring(L, 2); + const char *flag = ""; + flag = luaL_checkstring(L, 3); + + if (file_exists(file)) { + struct stat FileInfo; + if (lstat(file, &FileInfo) == -1) { + err = true; + errLine = __LINE__; + errMsg = (std::string)strerror(errno); + } + else if (strchr(flag, 'f') != NULL) { + if (S_ISREG(FileInfo.st_mode)) + ret = true; + } + else if (strchr(flag, 'l') != NULL) { + if (S_ISLNK(FileInfo.st_mode)) + ret = true; + } + else if (strchr(flag, 'd') != NULL) { + if (S_ISDIR(FileInfo.st_mode)) + ret = true; + } + else { + err = true; + errLine = __LINE__; + errMsg = (strlen(flag) == 0) ? "no" : "unknown"; + errMsg += " flag given."; + } + } + + if (err) { + lua_Debug ar; + lua_getstack(L, 1, &ar); + lua_getinfo(L, "Sl", &ar); + printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", + ar.short_src, ar.currentline, errMsg.c_str(), __path_file__, errLine); + lua_pushnil(L); + return 1; + } + + lua_pushboolean(L, ret); + return 1; +} + + +int CLuaInstFileHelpers::FileHelpersDelete(lua_State *L) +{ + CLuaFileHelpers *D = FileHelpersCheckData(L, 1); + if (!D) return 0; + delete D; + return 0; +} diff --git a/src/gui/lua/lua_filehelpers.h b/src/gui/lua/lua_filehelpers.h new file mode 100644 index 000000000..853f9768e --- /dev/null +++ b/src/gui/lua/lua_filehelpers.h @@ -0,0 +1,53 @@ +/* + * lua file helpers functions + * + * (C) 2016 M. Liebmann (micha-bbg) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _LUAFILEHELPERS_H +#define _LUAFILEHELPERS_H + +class CLuaFileHelpers +{ + public: + CLuaFileHelpers() {}; + ~CLuaFileHelpers() {}; +}; + +class CLuaInstFileHelpers +{ + public: + + CLuaInstFileHelpers() {}; + ~CLuaInstFileHelpers() {}; + static CLuaInstFileHelpers* getInstance(); + static void LuaFileHelpersRegister(lua_State *L); + + private: + static CLuaFileHelpers *FileHelpersCheckData(lua_State *L, int n); + static int FileHelpersNew(lua_State *L); + static int FileHelpersCp(lua_State *L); + static int FileHelpersChmod(lua_State *L); + static int FileHelpersTouch(lua_State *L); + static int FileHelpersRmdir(lua_State *L); + static int FileHelpersMkdir(lua_State *L); + static int FileHelpersReadlink(lua_State *L); + static int FileHelpersLn(lua_State *L); + static int FileHelpersExist(lua_State *L); + static int FileHelpersDelete(lua_State *L); +}; + +#endif //_LUAFILEHELPERS_H diff --git a/src/gui/lua/lua_stringinput.cpp b/src/gui/lua/lua_stringinput.cpp new file mode 100644 index 000000000..e61264b50 --- /dev/null +++ b/src/gui/lua/lua_stringinput.cpp @@ -0,0 +1,106 @@ +/* + * lua stringinput + * + * (C) 2016 Sven Hoefer (svenhoefer) + * (C) 2016 M. Liebmann (micha-bbg) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "luainstance.h" +#include "lua_stringinput.h" + +CLuaInstStringInput* CLuaInstStringInput::getInstance() +{ + static CLuaInstStringInput* LuaInstStringInput = NULL; + + if (!LuaInstStringInput) + LuaInstStringInput = new CLuaInstStringInput(); + return LuaInstStringInput; +} + +void CLuaInstStringInput::StringInputRegister(lua_State *L) +{ + luaL_Reg meth[] = { + { "exec", CLuaInstStringInput::StringInputExec }, + { NULL, NULL } + }; + + luaL_newmetatable(L, "stringinput"); + luaL_setfuncs(L, meth, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -1, "__index"); + lua_setglobal(L, "stringinput"); +} + +/* + local return_value = stringinput.exec{ + caption="Title", + value="value", + icon="settings", + valid_chars="0123456789", + size=4 + } +*/ +int CLuaInstStringInput::StringInputExec(lua_State *L) +{ + lua_assert(lua_istable(L,1)); + + std::string name; + tableLookup(L, "name", name) || tableLookup(L, "title", name) || tableLookup(L, "caption", name); + + std::string value; + tableLookup(L, "value", value); + + lua_Integer size = 30; + tableLookup(L, "size", size); + + // TODO: Locales? + + std::string valid_chars = "abcdefghijklmnopqrstuvwxyz0123456789!\"§$%&/()=?-.@,_: "; + tableLookup(L, "valid_chars", valid_chars); + + // TODO: CChangeObserver? + + std::string icon = std::string(NEUTRINO_ICON_INFO); + tableLookup(L, "icon", icon); + + lua_Integer sms = 0; + tableLookup(L, "sms", sms); + + CStringInput *i; + if (sms) + i = new CStringInputSMS(name, &value, size, + NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, valid_chars.c_str(), NULL, icon.c_str()); + else + i = new CStringInput(name, &value, size, + NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, valid_chars.c_str(), NULL, icon.c_str()); + i->exec(NULL, ""); + delete i; + + lua_pushstring(L, value.c_str()); + + return 1; +} diff --git a/src/gui/lua/lua_stringinput.h b/src/gui/lua/lua_stringinput.h new file mode 100644 index 000000000..c49ad7dc0 --- /dev/null +++ b/src/gui/lua/lua_stringinput.h @@ -0,0 +1,44 @@ +/* + * lua stringinput + * + * (C) 2016 Sven Hoefer (svenhoefer) + * (C) 2016 M. Liebmann (micha-bbg) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _LUASTRINGINPUT_H +#define _LUASTRINGINPUT_H + +class CLuaStringInput +{ + public: + CStringInput *b; + CLuaStringInput(); + ~CLuaStringInput(); +}; + +class CLuaInstStringInput +{ + public: + CLuaInstStringInput() {}; + ~CLuaInstStringInput() {}; + static CLuaInstStringInput* getInstance(); + static void StringInputRegister(lua_State *L); + + private: + static int StringInputExec(lua_State *L); +}; + +#endif //_LUASTRINGINPUT_H diff --git a/src/gui/lua/luainstance.cpp b/src/gui/lua/luainstance.cpp index d5de296b6..a21cac683 100644 --- a/src/gui/lua/luainstance.cpp +++ b/src/gui/lua/luainstance.cpp @@ -44,10 +44,12 @@ #include "lua_cc_window.h" #include "lua_configfile.h" #include "lua_curl.h" +#include "lua_filehelpers.h" #include "lua_hintbox.h" #include "lua_menue.h" #include "lua_messagebox.h" #include "lua_misc.h" +#include "lua_stringinput.h" #include "lua_threads.h" #include "lua_video.h" @@ -621,9 +623,11 @@ void LuaInstRegisterFunctions(lua_State *L, bool fromThreads/*=false*/) CLuaInstCCWindow::getInstance()->CCWindowRegister(L); CLuaInstConfigFile::getInstance()->LuaConfigFileRegister(L); CLuaInstCurl::getInstance()->LuaCurlRegister(L); + CLuaInstFileHelpers::getInstance()->LuaFileHelpersRegister(L); CLuaInstHintbox::getInstance()->HintboxRegister(L); CLuaInstMenu::getInstance()->MenuRegister(L); CLuaInstMessagebox::getInstance()->MessageboxRegister(L); + CLuaInstStringInput::getInstance()->StringInputRegister(L); CLuaInstMisc::getInstance()->LuaMiscRegister(L); CLuaInstVideo::getInstance()->LuaVideoRegister(L); if (!fromThreads) diff --git a/src/gui/lua/luainstance_helpers.h b/src/gui/lua/luainstance_helpers.h index cf6b9ba30..fa54bb690 100644 --- a/src/gui/lua/luainstance_helpers.h +++ b/src/gui/lua/luainstance_helpers.h @@ -2,7 +2,7 @@ * lua instance helper functions * * (C) 2013 Stefan Seyfried (seife) - * (C) 2014-2015 M. Liebmann (micha-bbg) + * (C) 2014-2016 M. Liebmann (micha-bbg) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,6 +30,7 @@ #define LUA_MISC_CLASSNAME "misc" #define LUA_CURL_CLASSNAME "curl" #define LUA_HEADER_CLASSNAME "header" +#define LUA_FILEHELPER_CLASSNAME "filehelpers" #define LUA_WIKI "https://wiki.neutrino-hd.de/wiki" //#define LUA_WIKI "https://wiki.slknet.de/wiki" diff --git a/src/system/helpers.cpp b/src/system/helpers.cpp index 266ffbf14..c9d736c85 100644 --- a/src/system/helpers.cpp +++ b/src/system/helpers.cpp @@ -667,6 +667,8 @@ CFileHelpers::CFileHelpers() FileBufSize = 0xFFFF; FileBuf = new char[FileBufSize]; doCopyFlag = true; + ConsoleQuiet = false; + clearDebugInfo(); } CFileHelpers::~CFileHelpers() @@ -683,12 +685,188 @@ CFileHelpers* CFileHelpers::getInstance() return FileHelpers; } -bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t mode) +void CFileHelpers::clearDebugInfo() +{ + DebugInfo.msg.clear(); + DebugInfo.file.clear(); + DebugInfo.func.clear(); + DebugInfo.line = 0; +} + +void CFileHelpers::setDebugInfo(const char* msg, const char* file, const char* func, int line) +{ + DebugInfo.msg = msg; + DebugInfo.file = file; + DebugInfo.func = func; + DebugInfo.line = line; +} + +void CFileHelpers::readDebugInfo(helpersDebugInfo* di) +{ + di->msg = DebugInfo.msg; + di->file = DebugInfo.file; + di->func = DebugInfo.func; + di->line = DebugInfo.line; +} + +void CFileHelpers::printDebugInfo() +{ + if (!ConsoleQuiet) + printf(">>>> [%s:%d] %s\n", DebugInfo.func.c_str(), DebugInfo.line, DebugInfo.msg.c_str()); +} + +bool CFileHelpers::cp(const char *Src, const char *Dst, const char *Flags/*=""*/) +{ + clearDebugInfo(); + if ((Src == NULL) || (Dst == NULL)) { + setDebugInfo("One or more parameters are NULL", __path_file__, __func__, __LINE__); + printDebugInfo(); + return false; + } + + std::string src = Src; + src = trim(src); + if (src.find_first_of("/") != 0) + src = "./" + src; + size_t pos = src.find_last_of("/"); + if (pos == src.length()-1) + src = src.substr(0, pos); + + std::string dst = Dst; + dst = trim(dst); + if (dst.find_first_of("/") != 0) + dst = "./" + dst; + pos = dst.find_last_of("/"); + if (pos == dst.length()-1) + dst = dst.substr(0, pos); + + bool wildcards = (src.find("*") != std::string::npos); + bool recursive = ((strchr(Flags, 'r') != NULL) || (strchr(Flags, 'a') != NULL)); + bool no_dereference = ((strchr(Flags, 'd') != NULL) || (strchr(Flags, 'a') != NULL)); + + static struct stat FileInfo; + char buf[PATH_MAX]; + if (wildcards == false) { + if (!file_exists(src.c_str())) { + setDebugInfo("Source file not exist", __path_file__, __func__, __LINE__); + printDebugInfo(); + return false; + } + if (lstat(src.c_str(), &FileInfo) == -1) { + setDebugInfo("lstat error", __path_file__, __func__, __LINE__); + printDebugInfo(); + return false; + } + + pos = src.find_last_of("/"); + std::string fname = src.substr(pos); + + static struct stat FileInfo2; + // is symlink + if (S_ISLNK(FileInfo.st_mode)) { + int len = readlink(src.c_str(), buf, sizeof(buf)-1); + if (len != -1) { + buf[len] = '\0'; + if (!no_dereference) { /* copy */ + std::string buf_ = (std::string)buf; + char buf2[PATH_MAX + 1]; + if (buf[0] != '/') + buf_ = getPathName(src) + "/" + buf_; + buf_ = (std::string)realpath(buf_.c_str(), buf2); + //printf("\n>>>> RealPath: %s\n \n", buf_.c_str()); + if (file_exists(dst.c_str()) && (lstat(dst.c_str(), &FileInfo2) != -1)){ + if (S_ISDIR(FileInfo2.st_mode)) + copyFile(buf_.c_str(), (dst + fname).c_str()); + else { + unlink(dst.c_str()); + copyFile(buf_.c_str(), dst.c_str()); + } + } + else + copyFile(buf_.c_str(), dst.c_str()); + } + else { /* link */ + if (file_exists(dst.c_str()) && (lstat(dst.c_str(), &FileInfo2) != -1)){ + if (S_ISDIR(FileInfo2.st_mode)) + symlink(buf, (dst + fname).c_str()); + else { + unlink(dst.c_str()); + symlink(buf, dst.c_str()); + } + } + else + symlink(buf, dst.c_str()); + } + } + } + // is directory + else if (S_ISDIR(FileInfo.st_mode)) { + if (recursive) + copyDir(src.c_str(), dst.c_str()); + else { + setDebugInfo("'recursive flag' must be set to copy dir.", __path_file__, __func__, __LINE__); + printDebugInfo(); + return false; + } + } + // is file + else if (S_ISREG(FileInfo.st_mode)) { + if (file_exists(dst.c_str()) && (lstat(dst.c_str(), &FileInfo2) != -1)){ + if (S_ISDIR(FileInfo2.st_mode)) + copyFile(src.c_str(), (dst + fname).c_str()); + else { + unlink(dst.c_str()); + copyFile(src.c_str(), dst.c_str()); + } + } + else + copyFile(src.c_str(), dst.c_str()); + } + else { + setDebugInfo("Currently unsupported st_mode.", __path_file__, __func__, __LINE__); + printDebugInfo(); + return false; + } + } + else { + setDebugInfo("Wildcard feature not yet realized.", __path_file__, __func__, __LINE__); + printDebugInfo(); + return false; + } + + return true; +} + +bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t forceMode/*=0*/) { doCopyFlag = true; - unlink(Dst); + + /* + set mode for Dst + ---------------- + when forceMode==0 (default) then + when Dst exists + mode = mode from Dst + else + mode = mode from Src + else + mode = forceMode + */ + mode_t mode = forceMode & 0x0FFF; + if (mode == 0) { + static struct stat FileInfo; + const char *f = Dst; + if (!file_exists(Dst)) + f = Src; + if (lstat(f, &FileInfo) == -1) + return false; + mode = FileInfo.st_mode & 0x0FFF; + } + if ((fd1 = open(Src, O_RDONLY)) < 0) return false; + if (file_exists(Dst)) + unlink(Dst); if ((fd2 = open(Dst, O_WRONLY | O_CREAT, mode)) < 0) { close(fd1); return false; @@ -821,7 +999,7 @@ bool CFileHelpers::copyDir(const char *Src, const char *Dst, bool backupMode) std::string save = ""; if (backupMode && (CExtUpdate::getInstance()->isBlacklistEntry(srcPath))) save = ".save"; - copyFile(srcPath, (dstPath + save).c_str(), FileInfo.st_mode & 0x0FFF); + copyFile(srcPath, (dstPath + save).c_str()); /* mode is set by copyFile */ } } } @@ -833,6 +1011,8 @@ bool CFileHelpers::copyDir(const char *Src, const char *Dst, bool backupMode) // false - errno is set bool CFileHelpers::createDir(string& Dir, mode_t mode) { + CFileHelpers* fh = CFileHelpers::getInstance(); + fh->clearDebugInfo(); int res = 0; for(string::iterator iter = Dir.begin() ; iter != Dir.end();) { string::iterator newIter = find(iter, Dir.end(), '/' ); @@ -846,7 +1026,12 @@ bool CFileHelpers::createDir(string& Dir, mode_t mode) // We can assume that if an error // occured, following will fail too, // so break here. - dprintf(DEBUG_NORMAL, "[CFileHelpers %s] creating directory %s: %s\n", __func__, newPath.c_str(), strerror(errno)); + if (!fh->getConsoleQuiet()) + dprintf(DEBUG_NORMAL, "[CFileHelpers %s] creating directory %s: %s\n", __func__, newPath.c_str(), strerror(errno)); + char buf[1024]; + memset(buf, '\0', sizeof(buf)); + snprintf(buf, sizeof(buf)-1, "creating directory %s: %s", newPath.c_str(), strerror(errno)); + fh->setDebugInfo(buf, __path_file__, __func__, __LINE__); break; } } @@ -861,13 +1046,16 @@ bool CFileHelpers::createDir(string& Dir, mode_t mode) bool CFileHelpers::removeDir(const char *Dir) { + CFileHelpers* fh = CFileHelpers::getInstance(); + fh->clearDebugInfo(); DIR *dir; struct dirent *entry; char path[PATH_MAX]; dir = opendir(Dir); if (dir == NULL) { - printf("Error opendir()\n"); + fh->setDebugInfo("Error opendir().", __path_file__, __func__, __LINE__); + fh->printDebugInfo(); return false; } while ((entry = readdir(dir)) != NULL) { @@ -1080,6 +1268,38 @@ std::string to_string(unsigned long long i) return s.str(); } +/** + * C++ version 0.4 std::string style "itoa": + * Contributions from Stuart Lowe, Ray-Yuan Sheu, + + * Rodrigo de Salvo Braz, Luc Gallant, John Maloney + * and Brian Hunt + */ +std::string itoa(int value, int base) +{ + std::string buf; + + // check that the base if valid + if (base < 2 || base > 16) return buf; + + enum { kMaxDigits = 35 }; + buf.reserve( kMaxDigits ); // Pre-allocate enough space. + + int quotient = value; + + // Translating number to string with base: + do { + buf += "0123456789abcdef"[ std::abs( quotient % base ) ]; + quotient /= base; + } while ( quotient ); + + // Append the negative sign + if ( value < 0) buf += '-'; + + std::reverse( buf.begin(), buf.end() ); + return buf; +} + std::string getJFFS2MountPoint(int mtdPos) { FILE* fd = fopen("/proc/mounts", "r"); diff --git a/src/system/helpers.h b/src/system/helpers.h index c3abdb41f..5fd773953 100644 --- a/src/system/helpers.h +++ b/src/system/helpers.h @@ -76,6 +76,13 @@ time_t toEpoch(std::string &date); std::string& str_replace(const std::string &search, const std::string &replace, std::string &text); std::string& htmlEntityDecode(std::string& text); +struct helpersDebugInfo { + std::string msg; + std::string file; + std::string func; + int line; +}; + class CFileHelpers { private: @@ -83,16 +90,27 @@ class CFileHelpers char *FileBuf; int fd1, fd2; + bool ConsoleQuiet; + helpersDebugInfo DebugInfo; + void setDebugInfo(const char* msg, const char* file, const char* func, int line); + void printDebugInfo(); + public: CFileHelpers(); ~CFileHelpers(); static CFileHelpers* getInstance(); bool doCopyFlag; - bool copyFile(const char *Src, const char *Dst, mode_t mode); + void clearDebugInfo(); + void readDebugInfo(helpersDebugInfo* di); + void setConsoleQuiet(bool q) { ConsoleQuiet = q; }; + bool getConsoleQuiet() { return ConsoleQuiet; }; + + bool cp(const char *Src, const char *Dst, const char *Flags=""); + bool copyFile(const char *Src, const char *Dst, mode_t forceMode=0); bool copyDir(const char *Src, const char *Dst, bool backupMode=false); - static bool createDir(std::string& Dir, mode_t mode = 755); - static bool createDir(const char *Dir, mode_t mode = 755){std::string dir = std::string(Dir);return createDir(dir, mode);} + static bool createDir(std::string& Dir, mode_t mode = 0755); + static bool createDir(const char *Dir, mode_t mode = 0755){std::string dir = std::string(Dir);return createDir(dir, mode);} static bool removeDir(const char *Dir); static uint64_t getDirSize(const char *dir); static uint64_t getDirSize(const std::string& dir){return getDirSize(dir.c_str());}; @@ -107,6 +125,8 @@ std::string to_string(unsigned long); std::string to_string(long long); std::string to_string(unsigned long long); +std::string itoa(int value, int base); + inline int atoi(std::string &s) { return atoi(s.c_str()); } inline int atoi(const std::string &s) { return atoi(s.c_str()); } inline int access(std::string &s, int mode) { return access(s.c_str(), mode); }