Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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)
add_compile_options("-D_CRT_SECURE_NO_WARNINGS")
endif(UNIX)
52 changes: 52 additions & 0 deletions Makefile.mak
Original file line number Diff line number Diff line change
@@ -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

36 changes: 36 additions & 0 deletions Plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Miniweb plugin sytem
To add a plugin just use a C dynamic library interface.
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.

The C interface:

int YourUrlHandler(UrlHandlerParam* param); // PFNURLCALLBACK
int YourUrlHandlerEvent(MW_EVENT msg, int argi, void* argp) // PFNEVENTHANDLER

The second is optional.

## Usage
From command line:

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`

The plugin is registered with prefix `myplugin` which means that you can access it at http://localhost/myplugin

### func1
An other simple plugin example:

miniweb.exe -c "func1: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"
2 changes: 1 addition & 1 deletion bin/htdocs/demodyn.htm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1>MiniWeb Demo Page
<hr>
</P>
<P>
<iframe name="frame1" src="/~stats" scrolling="no" width="300" height="250" frameborder="0"></iframe></P>
<iframe name="frame1" src="/stats" scrolling="no" width="300" height="250" frameborder="0"></iframe></P>
<HR>
<script language="javascript">setInterval('frame1.location.reload()',5000);</script>
</body>
Expand Down
4 changes: 2 additions & 2 deletions httppil.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
#ifdef WINCE
#include <winsock2.h>
#include <windows.h>
#define snprintf _snprintf

#elif defined(WIN32)
#include <winsock2.h>
#include <ws2tcpip.h> /* socklen_t */
#include <windows.h>
#include <io.h>

#if _MSC_VER < 1900
#define snprintf _snprintf

#endif
#else
#include <stdlib.h>
#include <unistd.h>
Expand Down
126 changes: 126 additions & 0 deletions loadplugin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "loadplugin.h"

#ifdef _MSC_VER
# include <windows.h>
#else
# include <dlfcn.h>
#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);
}
23 changes: 23 additions & 0 deletions loadplugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#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 __GNUC__
# define PLUGIN_VISIBILITY __attribute__((visibility("default")))
#elif defined _MSC_VER
# define PLUGIN_VISIBILITY __declspec(dllexport)
#endif

#ifdef __cplusplus
}
#endif

#endif
64 changes: 37 additions & 27 deletions miniweb.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <fcntl.h>
#include "httppil.h"
#include "httpapi.h"
#include "loadplugin.h"
#include "revision.h"
#ifdef MEDIA_SERVER
#include "mediaserver.h"
Expand Down Expand Up @@ -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", ""},
Expand Down Expand Up @@ -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 <stanleyhuangyc@gmail.com>\n\n",
APP_NAME, __DATE__);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
}
Expand Down
Loading