From 7980e2c9af0e1c1bf6f53d0d14df8872752f7e17 Mon Sep 17 00:00:00 2001 From: gaebor Date: Sat, 10 Mar 2018 09:44:25 +0100 Subject: [PATCH 1/7] snprintf --- httppil.h | 4 ++-- processpil.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/httppil.h b/httppil.h index e829a87..2be1c5c 100644 --- a/httppil.h +++ b/httppil.h @@ -18,7 +18,6 @@ #ifdef WINCE #include #include -#define snprintf _snprintf #elif defined(WIN32) #include @@ -26,8 +25,9 @@ #include #include +#if _MSC_VER < 1900 #define snprintf _snprintf - +#endif #else #include #include diff --git a/processpil.c b/processpil.c index d10b80b..67bc9eb 100644 --- a/processpil.c +++ b/processpil.c @@ -7,7 +7,9 @@ #ifdef WIN32 #include #include +#if _MSC_VER < 1900 #define snprintf _snprintf +#endif #else #include #include From b86f393c89ac60dc8cc7d63ef3c19d8d10c203be Mon Sep 17 00:00:00 2001 From: gaebor Date: Sat, 10 Mar 2018 09:46:43 +0100 Subject: [PATCH 2/7] dynamic plugin system --- Makefile.mak | 52 +++++++++++++++++ Plugin.md | 39 +++++++++++++ loadplugin.c | 124 +++++++++++++++++++++++++++++++++++++++++ loadplugin.h | 17 ++++++ miniweb.c | 64 ++++++++++++--------- plugin/plugin.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 414 insertions(+), 27 deletions(-) create mode 100644 Makefile.mak create mode 100644 Plugin.md create mode 100644 loadplugin.c create mode 100644 loadplugin.h create mode 100644 plugin/plugin.c diff --git a/Makefile.mak b/Makefile.mak new file mode 100644 index 0000000..715a284 --- /dev/null +++ b/Makefile.mak @@ -0,0 +1,52 @@ +CC=cl +LD=link +ALLFLAGS=/O2 /W3 /Ilibctb/include /nologo /MT /DNDEBUG +CFLAGS=$(ALLFLAGS) /TC +CPPFLAGS=$(ALLFLAGS) /TP /EHsc +HTTPOBJ=httppil.obj http.obj httpxml.obj httphandler.obj httppost.obj httpauth.obj loadplugin.obj +HEADERS=httpint.h httpapi.h httpxml.h + +OUTDIR=bin\\ + +DEFINES= /D_CRT_SECURE_NO_DEPRECATE /DNDEBUG /DNODEBUG /DWIN32 +LDFLAGS= WSock32.Lib shell32.lib Iphlpapi.lib + +!ifdef ENABLE_SERIAL +HTTPOBJ=$(HTTPOBJ) httpserial.obj libctb/src/fifo.obj libctb/src/serportx.obj +HEADERS=$(HEADERS) httpserial.h +DEFINES=$(DEFINES) /Ilibctb/include +!endif + +default: miniweb + +miniweb: miniweb.exe + +min: $(HTTPOBJ) httpmin.obj + $(LD) $(LDFLAGS) $(HTTPOBJ) httpmin.obj /OUT:$(OUTDIR)httpmin.exe + +miniweb.exe: $(HTTPOBJ) miniweb.obj + $(LD) $(LDFLAGS) $(HTTPOBJ) miniweb.obj /OUT:$(OUTDIR)miniweb.exe + +all : miniweb postfile plugin + +must_build: + +postfile : must_build + $(CC) $(CFLAGS) $(DEFINES) /Ipostfile postfile/*.c /link $(LDFLAGS) /OUT:$(OUTDIR)postfile.exe + +plugin : must_build + $(CC) $(CFLAGS) /I. $(DEFINES) plugin/plugin.c /link $(LDFLAGS) /DLL /OUT:$(OUTDIR)plugin.dll + +.c.obj:: + $(CC) $(DEFINES) $(CFLAGS) $< + +.cpp.obj:: + $(CC) $(DEFINES) $(CPPFLAGS) $< + +clean: + del /Q *.obj + del /Q $(OUTDIR)*.exe + del /Q $(OUTDIR)*.obj + del /Q $(OUTDIR)*.dll + del /Q $(OUTDIR)*.lib + diff --git a/Plugin.md b/Plugin.md new file mode 100644 index 0000000..14431ba --- /dev/null +++ b/Plugin.md @@ -0,0 +1,39 @@ +# Miniweb plugin sytem +To add a plugin just use a C dynamic library interface. +See `plugin.c` + +## How to write plugin +Compile your plugin in a separate binary. + +The C interface: + + int YourUrlHandler(UrlHandlerParam* param); // PFNURLCALLBACK + int YourUrlHandlerEvent(MW_EVENT msg, int argi, void* argp) // PFNEVENTHANDLER + +The second is optional. + +See `plugin` + + nmake /F Makefile.mak plugin + +## Usage +From command line: + + bin\miniweb.exe -c "myplugin:bin\plugin.dll:MyUrlHandler|MyUrlHandlerEvent" + +This start the default `miniweb` but loads your plugin. +You can have many `-c` arguments. See `miniweb -h` + +The plugin is registered with prefix `myplugin` which means that you can access it at http://localhost/myplugin + +### func1 +An other simple plugin example: + + bin\miniweb.exe -c "func:bin\plugin.dll:func1" + +Go to http://localhost/func?v=dQw4w9WgXcQ + +This will parse and print the http request parameters. + + [624] request path: func1?v=ZgQMW4eVrzw + v: "ZgQMW4eVrzw" diff --git a/loadplugin.c b/loadplugin.c new file mode 100644 index 0000000..27d9128 --- /dev/null +++ b/loadplugin.c @@ -0,0 +1,124 @@ +#include "loadplugin.h" + +#ifdef _MSC_VER +# include +#else +# include +#endif // _MSC_VER + +void* LoadDll(const char* arg) +{ +#ifdef _MSC_VER + return LoadLibraryA(arg); +#else + return dlopen(arg, RTLD_LAZY); +#endif // _MSC_VER +} + +int FreeDll(void* handle) +{ +#ifdef _MSC_VER + return FreeLibrary((HANDLE)handle); +#else + return dlclose(handle); +#endif // _MSC_VER +} + +const char* GetError() +{ +#ifdef _MSC_VER + static char error[10]; + sprintf_s(error, 10, "%d", GetLastError()); + return error; +#else + return dlerror(); +#endif // _MSC_VER +} + +#ifdef _MSC_VER +# define GetSymbol GetProcAddress +#else +# define GetSymbol dlsym +#endif // _MSC_VER + +int get_handler_list_length(UrlHandler* urlHandlerList) +{ + int n = 0; + if (urlHandlerList) + for (n = 0; urlHandlerList[n].pchUrlPrefix; n++) + ; + return n; +} + +void add_handler(UrlHandler** urlHandlerList, const char* prefix, PFNURLCALLBACK uhf, PFNEVENTHANDLER ehf) +{ + int n, length; + length = get_handler_list_length(*urlHandlerList); + UrlHandler* new_list = (UrlHandler*)calloc(length + 2, sizeof(UrlHandler)); + if (new_list) + { + for (n = 0; n < length; ++n) + { + new_list[n] = (*urlHandlerList)[n]; + } + new_list[n].pchUrlPrefix = prefix; + new_list[n].pfnUrlHandler = uhf; + new_list[n].pfnEventHandler = ehf; + new_list[n].p_sys = NULL; + + new_list[n + 1].pchUrlPrefix = NULL; + + free(*urlHandlerList); + *urlHandlerList = new_list; + } +} + +void add_handler_from_dll(UrlHandler** urlHandlerList, const char* arg) +{ + char* name, *function_name, *prefix, *tmp, *event_handler_name; + void* library; + PFNEVENTHANDLER ehf = NULL; + PFNURLCALLBACK uhf; + + name = malloc(strlen(arg) + 1); + strcpy(name, arg); + function_name = strrchr(name, ':'); + prefix = strchr(name, ':'); + + if (prefix != NULL && function_name > prefix + 1) + { + *function_name = '\0'; + ++function_name; + *prefix = '\0'; + if (*function_name) + { + ++prefix; + tmp = prefix; + prefix = name; + name = tmp; + fprintf(stderr, "Loading handler... prefix: %s, dll: %s, function: %s\n", prefix, name, function_name); + library = LoadDll(name); + if (library) + { + event_handler_name = strrchr(function_name, '|'); + if (event_handler_name) + *event_handler_name++ = '\0'; + ehf = (PFNEVENTHANDLER)GetSymbol(library, event_handler_name); + uhf = (PFNURLCALLBACK)GetSymbol(library, function_name); + if (uhf) + add_handler(urlHandlerList, prefix, uhf, ehf); + else + { + fprintf(stderr, "couldn't load %s (Error: %s)!\n", function_name, GetError()); + FreeDll(library); + } + } + else + fprintf(stderr, "couldn't load \"%s\" (Error: %s)!\n", name, GetError()); + } + else + fprintf(stderr, "function name shouldn't be empty in \"%s\"!\n", arg); + } + else + fprintf(stderr, "Two colons should be in \"%s\"!\n", arg); +} diff --git a/loadplugin.h b/loadplugin.h new file mode 100644 index 0000000..c6a12e2 --- /dev/null +++ b/loadplugin.h @@ -0,0 +1,17 @@ +#ifndef _LOADPLUGIN_H_ +#define _LOADPLUGIN_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "httpapi.h" + +void add_handler(UrlHandler** urlHandlerList, const char* prefix, PFNURLCALLBACK uhf, PFNEVENTHANDLER ehf); +void add_handler_from_dll(UrlHandler** urlHandlerList, const char* arg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/miniweb.c b/miniweb.c index 3c92a81..5d86f09 100644 --- a/miniweb.c +++ b/miniweb.c @@ -11,6 +11,7 @@ #include #include "httppil.h" #include "httpapi.h" +#include "loadplugin.h" #include "revision.h" #ifdef MEDIA_SERVER #include "mediaserver.h" @@ -39,33 +40,6 @@ int uhAsyncDataTest(UrlHandlerParam* param); int uhRTSP(UrlHandlerParam* param); int uhSerial(UrlHandlerParam* param); -UrlHandler urlHandlerList[]={ - {"stats", uhStats, NULL}, -#ifdef ENABLE_SERIAL - {"serial", uhSerial, NULL}, -#endif -#ifdef HAVE_THREAD - {"async", uhAsyncDataTest, NULL}, -#endif -#ifdef MEDIA_SERVER - {"test.sdp", uhRTSP, NULL}, - {"MediaServer/VideoItems/", uhMediaItemsTranscode, ehMediaItemsEvent}, -#endif -#ifdef _7Z - {"7z", uh7Zip, NULL}, -#endif -#ifdef _MPD - {"mpd", uhMpd, ehMpd}, -#endif -#ifdef _VOD - {"vodstream", uhVodStream,NULL}, - {"vodlib", uhLib,0}, - {"vodplay", uhVod,ehVod}, - {"stream", uhStream,NULL}, -#endif - {NULL}, -}; - #ifndef DISABLE_BASIC_WWWAUTH AuthHandler authHandlerList[]={ {"stats", "user", "pass", "group=admin", ""}, @@ -289,8 +263,34 @@ static int print_interfaces(const char *prefix, int port) #endif +UrlHandler* urlHandlerList = NULL; + int cc_main(int argc,char* argv[]) { + add_handler(&urlHandlerList, "stats", uhStats, NULL); +#ifdef ENABLE_SERIAL + add_handler(&urlHandlerList, "serial", uhSerial, NULL); +#endif +#ifdef HAVE_THREAD + add_handler(&urlHandlerList, "async", uhAsyncDataTest, NULL); +#endif +#ifdef MEDIA_SERVER + add_handler(&urlHandlerList, "test.sdp", uhRTSP, NULL); + add_handler(&urlHandlerList, "MediaServer/VideoItems/", uhMediaItemsTranscode, ehMediaItemsEvent); +#endif +#ifdef _7Z + add_handler(&urlHandlerList, "7z", uh7Zip, NULL); +#endif +#ifdef _MPD + add_handler(&urlHandlerList, "mpd", uhMpd, ehMpd); +#endif +#ifdef _VOD + add_handler(&urlHandlerList, "vodstream", uhVodStream, NULL); + add_handler(&urlHandlerList, "vodlib", uhLib, 0); + add_handler(&urlHandlerList, "vodplay", uhVod, ehVod); + add_handler(&urlHandlerList, "stream", uhStream, NULL); +#endif + fprintf(stderr,"%s https://github.com/avih/miniweb (built on %s)\n" "Originally: (C)2005-2013 Written by Stanley Huang \n\n", APP_NAME, __DATE__); @@ -341,6 +341,9 @@ int cc_main(int argc,char* argv[]) " -s : specifiy download speed limit in KB/s [default: none]\n" " -n : disallow multi-part download [default: allow]\n" " -d : disallow directory listing [default: allow]\n\n" + " -c : register callback for urlHandler\n" + " : format is the following \"prefix:dll:urlhandler|eventhandler\"\n" + " : event handler is optional, prefix may be empty\n" ); fflush(stderr); exit(1); @@ -373,6 +376,13 @@ int cc_main(int argc,char* argv[]) case 'd': httpParam.flags &= ~FLAG_DIR_LISTING; break; + case 'c': + if ((++i) < argc) + { + add_handler_from_dll(&urlHandlerList, argv[i]); + httpParam.pxUrlHandler = urlHandlerList; + } + break; } } } diff --git a/plugin/plugin.c b/plugin/plugin.c new file mode 100644 index 0000000..f3c8451 --- /dev/null +++ b/plugin/plugin.c @@ -0,0 +1,145 @@ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include "httpapi.h" + +#define DLL_EXPORT __declspec(dllexport) + +char* mwGetVarValue(HttpVariables* vars, const char *varname, const char *defval) +{ + int i; + if (vars && varname) { + for (i = 0; (vars + i)->name; i++) { + if (!strcmp((vars + i)->name, varname)) { + return (vars + i)->value; + } + } + } + return (char*)defval; +} + +DLL_EXPORT int func1(UrlHandlerParam* hp) +{ + int ret = 0; + int i; + for (i = 0; i < hp->iVarCount; ++i) + printf("%s: \"%s\"\n", hp->pxVars[i].name, hp->pxVars[i].value); + return ret; +} + +static HttpParam httpParam; + +static int fdStream; + +DLL_EXPORT int StreamHandlerEvent(MW_EVENT msg, int argi, void* argp) +{ + switch (msg) { + case MW_INIT: + fdStream = _open("test.txt", _O_BINARY | _O_RDONLY); + break; + case MW_UNINIT: + _close(fdStream); + break; + } + return 0; +} + +DLL_EXPORT int StreamHandler(UrlHandlerParam* param) +{ + param->dataBytes = _read(fdStream, param->pucBuffer, param->dataBytes); + param->fileType = HTTPFILETYPE_TEXT; + return FLAG_DATA_STREAM | FLAG_CONN_CLOSE; +} + +struct { + int ethif; + char ip[16]; + int mode; + char tvmode[4]; +} cfgdata; + +DLL_EXPORT int MyUrlHandlerEvent(MW_EVENT msg, int argi, void* argp) +{ + switch (msg) { + case MW_INIT: + memset(&cfgdata, 0, sizeof(cfgdata)); + strcpy(cfgdata.ip, "192.168.0.100"); + cfgdata.tvmode[0] = 1; + cfgdata.tvmode[1] = 1; + break; + case MW_UNINIT: + //nothing to uninit + break; + } + return 0; //0 on success, -1 on failure +} + +DLL_EXPORT int MyUrlHandler(UrlHandlerParam* param) +{ + static const char *html_head = "

STB Configuration


"; + static const char *html_form_start = "
"; + static const char *html_ethif[] = { + "Network Interface: DHCP ", + "PPPoE ", + "Static IP: " }; + static const char *html_ip = "

"; + static const char *html_mode[] = { + "

Startup Mode:

" }; + static const char *html_tvmode[] = { + "

TV Mode Supported: PAL ", + "NTSC ", + "720p ", + "1080i

" }; + static const char *html_form_end = "


"; + static const char *html_tail = ""; + static const char *tvmodes[] = { "PAL", "NTSC", "720p", "1080i" }; + char *p = param->pucBuffer, *v; + int i; + + if (param->pxVars) { + // processing settings + if ((v = mwGetVarValue(param->pxVars, "if", 0))) + cfgdata.ethif = atoi(v); + if ((v = mwGetVarValue(param->pxVars, "mode", 0))) + cfgdata.mode = atoi(v); + if ((v = mwGetVarValue(param->pxVars, "ip", 0))) + strcpy(cfgdata.ip, v); + for (i = 0; i < 4; i++) { + char buf[4]; + sprintf(buf, "m%d", i); + cfgdata.tvmode[i] = mwGetVarValue(param->pxVars, buf, 0) ? 1 : 0; + } + // print new settings in console + printf("\n--- Configuration ---\nNetwork Interface: %d\n", cfgdata.ethif); + if (cfgdata.ethif == 2) printf("IP: %s\n", cfgdata.ip); + printf("Startup Mode: %d\nTV Modes:", cfgdata.mode); + for (i = 0; i < 4; i++) { + if (cfgdata.tvmode[i]) printf(" %s", tvmodes[i]); + } + printf("\n---------------------\n\n"); + } + + p += sprintf(p, "%s%s", html_head, html_form_start); + for (i = 0; i < 3; i++) { + p += sprintf(p, html_ethif[i], (cfgdata.ethif == i) ? " checked" : ""); + } + p += sprintf(p, html_ip, cfgdata.ip); + for (i = 0; i < 3; i++) { + p += sprintf(p, html_mode[i], (cfgdata.mode == i) ? " selected" : ""); + } + for (i = 0; i < 4; i++) { + p += sprintf(p, html_tvmode[i], cfgdata.tvmode[i] ? " checked" : ""); + } + p += sprintf(p, "%s%s%s", html_form_end, param->pxVars ? "

New settings applied

" : "", html_tail); + param->dataBytes = (int)p - (int)(param->pucBuffer); + param->fileType = HTTPFILETYPE_HTML; + return FLAG_DATA_RAW; +} + +#ifdef __cplusplus +} +#endif // __cplusplus From 2da99dcba2b941dea24bff2e2f9d7c990f7de620 Mon Sep 17 00:00:00 2001 From: gaebor Date: Sat, 10 Mar 2018 09:49:30 +0100 Subject: [PATCH 3/7] vc15 sln --- miniweb.vcxproj | 17 +++--- miniweb_vc11.sln | 20 ------- miniweb_vc15.sln | 34 ++++++++++++ plugin/plugin.vcxproj | 98 +++++++++++++++++++++++++++++++++++ plugin/plugin.vcxproj.filters | 22 ++++++++ plugin/plugin.vcxproj.user | 4 ++ 6 files changed, 168 insertions(+), 27 deletions(-) delete mode 100644 miniweb_vc11.sln create mode 100644 miniweb_vc15.sln create mode 100644 plugin/plugin.vcxproj create mode 100644 plugin/plugin.vcxproj.filters create mode 100644 plugin/plugin.vcxproj.user diff --git a/miniweb.vcxproj b/miniweb.vcxproj index c3d1a35..0310f07 100644 --- a/miniweb.vcxproj +++ b/miniweb.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -14,17 +14,18 @@ {06E5025D-53D7-4B39-8D4C-D06E39A3023A} miniweb Win32Proj + 10.0.15063.0 Application MultiByte - v100 + v141 Application MultiByte - v100 + v141 @@ -41,11 +42,11 @@ <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)bin\ - $(TEMP)\$(Platform)\$(ProjectName)\$(Configuration)\ + $(Platform)\$(Configuration)\ true false $(SolutionDir)bin\ - $(TEMP)\$(Platform)\$(ProjectName)\$(Configuration)\ + $(Platform)\$(Configuration)\ false @@ -62,7 +63,7 @@ libctb/include - WSock32.Lib;%(AdditionalDependencies) + Iphlpapi.lib;WSock32.Lib;%(AdditionalDependencies) $(OutDir)$(TargetFileName) %(IgnoreSpecificDefaultLibraries) true @@ -93,7 +94,7 @@ OldStyle - WSock32.Lib;%(AdditionalDependencies) + Iphlpapi.lib;WSock32.Lib;%(AdditionalDependencies) $(OutDir)$(TargetFileName) %(IgnoreSpecificDefaultLibraries) true @@ -117,6 +118,7 @@ + @@ -126,6 +128,7 @@ + diff --git a/miniweb_vc11.sln b/miniweb_vc11.sln deleted file mode 100644 index 153eda1..0000000 --- a/miniweb_vc11.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2012 for Windows Desktop -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniweb", "miniweb.vcxproj", "{06E5025D-53D7-4B39-8D4C-D06E39A3023A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Debug|Win32.ActiveCfg = Debug|Win32 - {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Debug|Win32.Build.0 = Debug|Win32 - {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Release|Win32.ActiveCfg = Release|Win32 - {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/miniweb_vc15.sln b/miniweb_vc15.sln new file mode 100644 index 0000000..c6e1220 --- /dev/null +++ b/miniweb_vc15.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2002 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniweb", "miniweb.vcxproj", "{06E5025D-53D7-4B39-8D4C-D06E39A3023A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin", "plugin\plugin.vcxproj", "{5802AFF8-6E80-4974-A7BB-D2BB73021327}" + ProjectSection(ProjectDependencies) = postProject + {06E5025D-53D7-4B39-8D4C-D06E39A3023A} = {06E5025D-53D7-4B39-8D4C-D06E39A3023A} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Debug|Win32.ActiveCfg = Debug|Win32 + {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Debug|Win32.Build.0 = Debug|Win32 + {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Release|Win32.ActiveCfg = Release|Win32 + {06E5025D-53D7-4B39-8D4C-D06E39A3023A}.Release|Win32.Build.0 = Release|Win32 + {5802AFF8-6E80-4974-A7BB-D2BB73021327}.Debug|Win32.ActiveCfg = Debug|Win32 + {5802AFF8-6E80-4974-A7BB-D2BB73021327}.Debug|Win32.Build.0 = Debug|Win32 + {5802AFF8-6E80-4974-A7BB-D2BB73021327}.Release|Win32.ActiveCfg = Release|Win32 + {5802AFF8-6E80-4974-A7BB-D2BB73021327}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C5895650-EE96-4807-9DAB-A8173760D906} + EndGlobalSection +EndGlobal diff --git a/plugin/plugin.vcxproj b/plugin/plugin.vcxproj new file mode 100644 index 0000000..4ecd438 --- /dev/null +++ b/plugin/plugin.vcxproj @@ -0,0 +1,98 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + 15.0 + {5802AFF8-6E80-4974-A7BB-D2BB73021327} + Win32Proj + plugin + 10.0.16299.0 + + + + DynamicLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + true + $(SolutionDir)$bin + $(Platform)\$(Configuration)\ + + + false + $(SolutionDir)$bin + $(Platform)\$(Configuration)\ + + + + NotUsing + Level3 + Disabled + true + _CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;PLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + CompileAsC + $(SolutionDir);C:\Program Files (x86)\Visual Leak Detector\include;%(AdditionalIncludeDirectories) + + + Windows + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + _CRT_SECURE_NO_DEPRECATE;WIN32;NDEBUG;PLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + CompileAsC + $(SolutionDir);C:\Program Files (x86)\Visual Leak Detector\include;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/plugin/plugin.vcxproj.filters b/plugin/plugin.vcxproj.filters new file mode 100644 index 0000000..bb3c188 --- /dev/null +++ b/plugin/plugin.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/plugin/plugin.vcxproj.user b/plugin/plugin.vcxproj.user new file mode 100644 index 0000000..6e2aec7 --- /dev/null +++ b/plugin/plugin.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From d9ee34fda70a0046302bf3ce4eec97bf5fa249b3 Mon Sep 17 00:00:00 2001 From: gaebor Date: Tue, 13 Mar 2018 19:45:36 +0100 Subject: [PATCH 4/7] type-o --- bin/htdocs/demodyn.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/htdocs/demodyn.htm b/bin/htdocs/demodyn.htm index 4939ff8..f003234 100644 --- a/bin/htdocs/demodyn.htm +++ b/bin/htdocs/demodyn.htm @@ -8,7 +8,7 @@

MiniWeb Demo Page

-

+


From 77f60a13ce6db03198e0f033143f3a3b9f3dcda7 Mon Sep 17 00:00:00 2001 From: gaebor Date: Tue, 13 Mar 2018 20:02:32 +0100 Subject: [PATCH 5/7] cmake --- CMakeLists.txt | 17 +++++++++++++ loadplugin.h | 6 +++++ plugin/CMakeLists.txt | 6 +++++ plugin/plugin.c | 56 +++++++++++++++++++++++-------------------- 4 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 plugin/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..23c655f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required (VERSION 2.6) +project (miniweb) + +add_executable(miniweb + miniweb.c + httppil.c http.c httpxml.c httphandler.c httppost.c httpauth.c loadplugin.c + win32/win_compat.h httpint.h httpapi.h httpxml.h + ) + +add_subdirectory(plugin) + +if(UNIX) + add_compile_options("-pthread" "-DHAS_POSIX_TIMERS") + target_link_libraries(miniweb dl pthread rt) +elseif(WIN32) + target_link_libraries(miniweb Iphlpapi WSock32 Shell32) +endif(UNIX) diff --git a/loadplugin.h b/loadplugin.h index c6a12e2..f08d1be 100644 --- a/loadplugin.h +++ b/loadplugin.h @@ -10,6 +10,12 @@ extern "C" { void add_handler(UrlHandler** urlHandlerList, const char* prefix, PFNURLCALLBACK uhf, PFNEVENTHANDLER ehf); void add_handler_from_dll(UrlHandler** urlHandlerList, const char* arg); +#ifdef __GNUC__ +# define PLUGIN_VISIBILITY __attribute__((visibility("default"))) +#elif defined _MSC_VER +# define PLUGIN_VISIBILITY __declspec(dllexport) +#endif + #ifdef __cplusplus } #endif diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt new file mode 100644 index 0000000..20d7ecc --- /dev/null +++ b/plugin/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required (VERSION 2.6) +project (plugin) + +include_directories(${CMAKE_SOURCE_DIR}) + +add_library(plugin SHARED plugin.c) diff --git a/plugin/plugin.c b/plugin/plugin.c index f3c8451..c0d7da9 100644 --- a/plugin/plugin.c +++ b/plugin/plugin.c @@ -3,9 +3,9 @@ extern "C" { #endif // __cplusplus -#include "httpapi.h" +#include -#define DLL_EXPORT __declspec(dllexport) +#include "loadplugin.h" char* mwGetVarValue(HttpVariables* vars, const char *varname, const char *defval) { @@ -20,7 +20,7 @@ char* mwGetVarValue(HttpVariables* vars, const char *varname, const char *defval return (char*)defval; } -DLL_EXPORT int func1(UrlHandlerParam* hp) +PLUGIN_VISIBILITY int func1(UrlHandlerParam* hp) { int ret = 0; int i; @@ -33,26 +33,30 @@ static HttpParam httpParam; static int fdStream; -DLL_EXPORT int StreamHandlerEvent(MW_EVENT msg, int argi, void* argp) -{ - switch (msg) { - case MW_INIT: - fdStream = _open("test.txt", _O_BINARY | _O_RDONLY); - break; - case MW_UNINIT: - _close(fdStream); - break; - } - return 0; -} - -DLL_EXPORT int StreamHandler(UrlHandlerParam* param) -{ - param->dataBytes = _read(fdStream, param->pucBuffer, param->dataBytes); - param->fileType = HTTPFILETYPE_TEXT; - return FLAG_DATA_STREAM | FLAG_CONN_CLOSE; -} - +//#ifdef __GNUC__ +//# define _O_BINARY 0 +//#endif +// +//PLUGIN_VISIBILITY int StreamHandlerEvent(MW_EVENT msg, int argi, void* argp) +//{ +// switch (msg) { +// case MW_INIT: +// fdStream = open("test.txt", O_BINARY | O_RDONLY); +// break; +// case MW_UNINIT: +// _close(fdStream); +// break; +// } +// return 0; +//} +// +//PLUGIN_VISIBILITY int StreamHandler(UrlHandlerParam* param) +//{ +// param->dataBytes = _read(fdStream, param->pucBuffer, param->dataBytes); +// param->fileType = HTTPFILETYPE_TEXT; +// return FLAG_DATA_STREAM | FLAG_CONN_CLOSE; +//} +// struct { int ethif; char ip[16]; @@ -60,7 +64,7 @@ struct { char tvmode[4]; } cfgdata; -DLL_EXPORT int MyUrlHandlerEvent(MW_EVENT msg, int argi, void* argp) +PLUGIN_VISIBILITY int MyUrlHandlerEvent(MW_EVENT msg, int argi, void* argp) { switch (msg) { case MW_INIT: @@ -76,7 +80,7 @@ DLL_EXPORT int MyUrlHandlerEvent(MW_EVENT msg, int argi, void* argp) return 0; //0 on success, -1 on failure } -DLL_EXPORT int MyUrlHandler(UrlHandlerParam* param) +PLUGIN_VISIBILITY int MyUrlHandler(UrlHandlerParam* param) { static const char *html_head = "

STB Configuration


"; static const char *html_form_start = "
"; @@ -135,7 +139,7 @@ DLL_EXPORT int MyUrlHandler(UrlHandlerParam* param) p += sprintf(p, html_tvmode[i], cfgdata.tvmode[i] ? " checked" : ""); } p += sprintf(p, "%s%s%s", html_form_end, param->pxVars ? "

New settings applied

" : "", html_tail); - param->dataBytes = (int)p - (int)(param->pucBuffer); + param->dataBytes = (int)(p - (param->pucBuffer)); param->fileType = HTTPFILETYPE_HTML; return FLAG_DATA_RAW; } From 2ee298cf28eb922b870a09e78447adb881ada7e8 Mon Sep 17 00:00:00 2001 From: gaebor Date: Tue, 13 Mar 2018 21:19:24 +0100 Subject: [PATCH 6/7] info --- CMakeLists.txt | 1 + Plugin.md | 11 ++++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23c655f..bf98cda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,4 +14,5 @@ if(UNIX) target_link_libraries(miniweb dl pthread rt) elseif(WIN32) target_link_libraries(miniweb Iphlpapi WSock32 Shell32) + add_compile_options("-D_CRT_SECURE_NO_WARNINGS") endif(UNIX) diff --git a/Plugin.md b/Plugin.md index 14431ba..255ab49 100644 --- a/Plugin.md +++ b/Plugin.md @@ -1,6 +1,7 @@ # Miniweb plugin sytem To add a plugin just use a C dynamic library interface. -See `plugin.c` +See `PFNEVENTHANDLER` and `PFNEVENTHANDLER` in `loadplugin.h` +or `httpapi.h` or example: `plugin/plugin.c` ## How to write plugin Compile your plugin in a separate binary. @@ -12,14 +13,10 @@ The C interface: The second is optional. -See `plugin` - - nmake /F Makefile.mak plugin - ## Usage From command line: - bin\miniweb.exe -c "myplugin:bin\plugin.dll:MyUrlHandler|MyUrlHandlerEvent" + miniweb.exe -c "myplugin:plugin.dll:MyUrlHandler|MyUrlHandlerEvent" This start the default `miniweb` but loads your plugin. You can have many `-c` arguments. See `miniweb -h` @@ -29,7 +26,7 @@ The plugin is registered with prefix `myplugin` which means that you can access ### func1 An other simple plugin example: - bin\miniweb.exe -c "func:bin\plugin.dll:func1" + miniweb.exe -c "func1:plugin.dll:func1" Go to http://localhost/func?v=dQw4w9WgXcQ From 79cdd6a03cb847e3d41e2b22989f1ae2560f9002 Mon Sep 17 00:00:00 2001 From: gaebor Date: Wed, 12 Dec 2018 23:58:40 +0100 Subject: [PATCH 7/7] small wixes --- loadplugin.c | 4 +++- win32/win_compat.h | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/loadplugin.c b/loadplugin.c index 27d9128..dc37cb1 100644 --- a/loadplugin.c +++ b/loadplugin.c @@ -102,8 +102,10 @@ void add_handler_from_dll(UrlHandler** urlHandlerList, const char* arg) { event_handler_name = strrchr(function_name, '|'); if (event_handler_name) + { *event_handler_name++ = '\0'; - ehf = (PFNEVENTHANDLER)GetSymbol(library, event_handler_name); + ehf = (PFNEVENTHANDLER)GetSymbol(library, event_handler_name); + } uhf = (PFNURLCALLBACK)GetSymbol(library, function_name); if (uhf) add_handler(urlHandlerList, prefix, uhf, ehf); diff --git a/win32/win_compat.h b/win32/win_compat.h index 214977f..eb22e10 100644 --- a/win32/win_compat.h +++ b/win32/win_compat.h @@ -155,7 +155,7 @@ static wchar_t *mp_from_utf8(const char *s) int count = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); if (count <= 0) return NULL; - wchar_t *ret = malloc(sizeof(wchar_t) * (count + 1)); + wchar_t *ret = (wchar_t*)malloc(sizeof(wchar_t) * (count + 1)); MultiByteToWideChar(CP_UTF8, 0, s, -1, ret, count); return ret; } @@ -172,7 +172,7 @@ static char *mp_to_utf8(const wchar_t *s) int count = _cc_WCTU8(0, s, 0); if (count <= 0) return NULL; - char *ret = malloc(sizeof(char) * count); + char *ret = (char*)malloc(sizeof(char) * count); _cc_WCTU8(ret, s, count); return ret; } @@ -211,7 +211,7 @@ static int mp_vfprintf(FILE *f, const char *format, va_list args) if (h != INVALID_HANDLE_VALUE) { size_t len = vsnprintf(NULL, 0, format, args) + 1; - char *buf = malloc(sizeof(char) * len); + char *buf = (char*)malloc(sizeof(char) * len); if (buf) { rv = vsnprintf(buf, len, format, args); @@ -240,7 +240,7 @@ static char **cc_get_argvutf8(int argc_validation, char **argv_orig, int *out_su return argv_orig; } - char **argvu = malloc(sizeof(char*) * (nArgs + 1)); + char **argvu = (char**)malloc(sizeof(char*) * (nArgs + 1)); int i; for (i = 0; i < nArgs; i++) { argvu[i] = mp_to_utf8(szArglist[i]);