summaryrefslogtreecommitdiffstats
path: root/contrib/imhttp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/imhttp')
-rw-r--r--contrib/imhttp/Makefile.am5
-rw-r--r--contrib/imhttp/Makefile.in795
-rw-r--r--contrib/imhttp/imhttp.c1326
3 files changed, 2126 insertions, 0 deletions
diff --git a/contrib/imhttp/Makefile.am b/contrib/imhttp/Makefile.am
new file mode 100644
index 0000000..ce64dc4
--- /dev/null
+++ b/contrib/imhttp/Makefile.am
@@ -0,0 +1,5 @@
+pkglib_LTLIBRARIES = imhttp.la
+
+imhttp_la_SOURCES = imhttp.c
+imhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(APU_CFLAGS)
+imhttp_la_LDFLAGS = -module -avoid-version $(CIVETWEB_LIBS) $(APU_LIBS)
diff --git a/contrib/imhttp/Makefile.in b/contrib/imhttp/Makefile.in
new file mode 100644
index 0000000..8eff726
--- /dev/null
+++ b/contrib/imhttp/Makefile.in
@@ -0,0 +1,795 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = contrib/imhttp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \
+ $(top_srcdir)/m4/atomic_operations.m4 \
+ $(top_srcdir)/m4/atomic_operations_64bit.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(pkglibdir)"
+LTLIBRARIES = $(pkglib_LTLIBRARIES)
+imhttp_la_LIBADD =
+am_imhttp_la_OBJECTS = imhttp_la-imhttp.lo
+imhttp_la_OBJECTS = $(am_imhttp_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+imhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imhttp_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/imhttp_la-imhttp.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imhttp_la_SOURCES)
+DIST_SOURCES = $(imhttp_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APU_CFLAGS = @APU_CFLAGS@
+APU_LIBS = @APU_LIBS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CIVETWEB_LIBS = @CIVETWEB_LIBS@
+CONF_FILE_PATH = @CONF_FILE_PATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURL_CFLAGS = @CURL_CFLAGS@
+CURL_LIBS = @CURL_LIBS@
+CYGPATH_W = @CYGPATH_W@
+CZMQ_CFLAGS = @CZMQ_CFLAGS@
+CZMQ_LIBS = @CZMQ_LIBS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FAUP_LIBS = @FAUP_LIBS@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GSS_LIBS = @GSS_LIBS@
+GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@
+GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@
+HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@
+HIREDIS_CFLAGS = @HIREDIS_CFLAGS@
+HIREDIS_LIBS = @HIREDIS_LIBS@
+IMUDP_LIBS = @IMUDP_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IP = @IP@
+JAVA = @JAVA@
+JAVAC = @JAVAC@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@
+LIBCAPNG_LIBS = @LIBCAPNG_LIBS@
+LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@
+LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@
+LIBDBI_CFLAGS = @LIBDBI_CFLAGS@
+LIBDBI_LIBS = @LIBDBI_LIBS@
+LIBESTR_CFLAGS = @LIBESTR_CFLAGS@
+LIBESTR_LIBS = @LIBESTR_LIBS@
+LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@
+LIBEVENT_LIBS = @LIBEVENT_LIBS@
+LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@
+LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@
+LIBLOGGING_LIBS = @LIBLOGGING_LIBS@
+LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@
+LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@
+LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@
+LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@
+LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@
+LIBLZ4_LIBS = @LIBLZ4_LIBS@
+LIBM = @LIBM@
+LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@
+LIBMONGOC_LIBS = @LIBMONGOC_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@
+LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@
+LIBS = @LIBS@
+LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@
+LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@
+LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@
+LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUUID_CFLAGS = @LIBUUID_CFLAGS@
+LIBUUID_LIBS = @LIBUUID_LIBS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CFLAGS = @MYSQL_CFLAGS@
+MYSQL_CONFIG = @MYSQL_CONFIG@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PGSQL_CFLAGS = @PGSQL_CFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PG_CONFIG = @PG_CONFIG@
+PID_FILE_PATH = @PID_FILE_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTON_CFLAGS = @PROTON_CFLAGS@
+PROTON_LIBS = @PROTON_LIBS@
+PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@
+PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@
+RABBITMQ_LIBS = @RABBITMQ_LIBS@
+RANLIB = @RANLIB@
+READLINK = @READLINK@
+REDIS = @REDIS@
+RELP_CFLAGS = @RELP_CFLAGS@
+RELP_LIBS = @RELP_LIBS@
+RSRT_CFLAGS = @RSRT_CFLAGS@
+RSRT_CFLAGS1 = @RSRT_CFLAGS1@
+RSRT_LIBS = @RSRT_LIBS@
+RSRT_LIBS1 = @RSRT_LIBS1@
+RST2MAN = @RST2MAN@
+RT_LIBS = @RT_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SOL_LIBS = @SOL_LIBS@
+STRIP = @STRIP@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
+TCL_LIB_FILE = @TCL_LIB_FILE@
+TCL_LIB_FLAG = @TCL_LIB_FLAG@
+TCL_LIB_SPEC = @TCL_LIB_SPEC@
+TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@
+TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@
+TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
+TCL_VERSION = @TCL_VERSION@
+UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@
+UDPSPOOF_LIBS = @UDPSPOOF_LIBS@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+WARN_LDFLAGS = @WARN_LDFLAGS@
+WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@
+WGET = @WGET@
+YACC = @YACC@
+YACC_FOUND = @YACC_FOUND@
+YFLAGS = @YFLAGS@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+ZSTD_CFLAGS = @ZSTD_CFLAGS@
+ZSTD_LIBS = @ZSTD_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moddirs = @moddirs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglib_LTLIBRARIES = imhttp.la
+imhttp_la_SOURCES = imhttp.c
+imhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(APU_CFLAGS)
+imhttp_la_LDFLAGS = -module -avoid-version $(CIVETWEB_LIBS) $(APU_LIBS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu contrib/imhttp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu contrib/imhttp/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
+ }
+
+uninstall-pkglibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
+ done
+
+clean-pkglibLTLIBRARIES:
+ -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+ @list='$(pkglib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+imhttp.la: $(imhttp_la_OBJECTS) $(imhttp_la_DEPENDENCIES) $(EXTRA_imhttp_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imhttp_la_LINK) -rpath $(pkglibdir) $(imhttp_la_OBJECTS) $(imhttp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imhttp_la-imhttp.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+imhttp_la-imhttp.lo: imhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imhttp_la-imhttp.lo -MD -MP -MF $(DEPDIR)/imhttp_la-imhttp.Tpo -c -o imhttp_la-imhttp.lo `test -f 'imhttp.c' || echo '$(srcdir)/'`imhttp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imhttp_la-imhttp.Tpo $(DEPDIR)/imhttp_la-imhttp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imhttp.c' object='imhttp_la-imhttp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imhttp_la-imhttp.lo `test -f 'imhttp.c' || echo '$(srcdir)/'`imhttp.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/imhttp_la-imhttp.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-pkglibLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/imhttp_la-imhttp.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pkglibLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-pkglibLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pkglibLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pkglibLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/contrib/imhttp/imhttp.c b/contrib/imhttp/imhttp.c
new file mode 100644
index 0000000..95704af
--- /dev/null
+++ b/contrib/imhttp/imhttp.c
@@ -0,0 +1,1326 @@
+/* imhttp.c
+ * This is an input module for receiving http input.
+ *
+ * This file is contribution of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "rsyslog.h"
+#include "cfsysline.h" /* access to config file objects */
+#include "module-template.h"
+#include "ruleset.h"
+#include "unicode-helper.h"
+#include "rsyslog.h"
+#include "errmsg.h"
+#include "statsobj.h"
+#include "ratelimit.h"
+#include "dirty.h"
+
+#include "civetweb.h"
+#include <apr_base64.h>
+#include <apr_md5.h>
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imhttp")
+
+/* static data */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
+DEFobjCurrIf(statsobj)
+
+#define CIVETWEB_OPTION_NAME_PORTS "listening_ports"
+#define CIVETWEB_OPTION_NAME_DOCUMENT_ROOT "document_root"
+#define MAX_READ_BUFFER_SIZE 16384
+#define INIT_SCRATCH_BUF_SIZE 4096
+/* General purpose buffer size. */
+#define IMHTTP_MAX_BUF_LEN (8192)
+
+struct option {
+ const char *name;
+ const char *val;
+};
+
+struct auth_s {
+ char workbuf[IMHTTP_MAX_BUF_LEN];
+ char* pworkbuf;
+ size_t workbuf_len;
+ char* pszUser;
+ char* pszPasswd;
+};
+
+struct data_parse_s {
+ sbool content_compressed;
+ sbool bzInitDone; /* did we do an init of zstrm already? */
+ z_stream zstrm; /* zip stream to use for tcp compression */
+ // Currently only used for octet specific parsing
+ enum {
+ eAtStrtFram,
+ eInOctetCnt,
+ eInMsg,
+ } inputState;
+ size_t iOctetsRemain; /* Number of Octets remaining in message */
+ enum {
+ TCP_FRAMING_OCTET_STUFFING,
+ TCP_FRAMING_OCTET_COUNTING
+ } framingMode;
+};
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ struct option ports;
+ struct option docroot;
+ struct option *options;
+ int nOptions;
+};
+
+struct instanceConf_s {
+ struct instanceConf_s *next;
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ uchar *pszEndpoint; /* endpoint to configure */
+ uchar *pszBasicAuthFile; /* file containing basic auth users/pass */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ ratelimit_t *ratelimiter;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ prop_t *pInputName;
+ sbool flowControl;
+ sbool bDisableLFDelim;
+ sbool bSuppOctetFram;
+ sbool bAddMetadata;
+};
+
+struct conn_wrkr_s {
+ struct data_parse_s parseState;
+ uchar* pMsg; /* msg scratch buffer */
+ size_t iMsg; /* index of next char to store in msg */
+ uchar zipBuf[64*1024];
+ multi_submit_t multiSub;
+ smsg_t *pMsgs[CONF_NUM_MULTISUB];
+ char *pReadBuf;
+ size_t readBufSize;
+ prop_t *propRemoteAddr;
+ const struct mg_request_info *pri; /* do not free me - used to hold a reference only */
+ char *pScratchBuf;
+ size_t scratchBufSize;
+};
+
+static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */
+static prop_t *pInputName = NULL;
+
+//static size_t s_iMaxLine = 16; /* get maximum size we currently support */
+static size_t s_iMaxLine = 16384; /* get maximum size we currently support */
+
+/* module-global parameters */
+static struct cnfparamdescr modpdescr[] = {
+ { "ports", eCmdHdlrString, 0 },
+ { "documentroot", eCmdHdlrString, 0 },
+ { "liboptions", eCmdHdlrArray, 0 },
+};
+
+static struct cnfparamblk modpblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+};
+
+static struct cnfparamdescr inppdescr[] = {
+ { "endpoint", eCmdHdlrString, 0},
+ { "basicauthfile", eCmdHdlrString, 0},
+ { "ruleset", eCmdHdlrString, 0 },
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "disablelfdelimiter", eCmdHdlrBinary, 0 },
+ { "supportoctetcountedframing", eCmdHdlrBinary, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "addmetadata", eCmdHdlrBinary, 0 }
+};
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+static struct cnfparamblk inppblk = {
+ CNFPARAMBLK_VERSION,
+ sizeof(inppdescr)/sizeof(struct cnfparamdescr),
+ inppdescr
+};
+
+static struct {
+ statsobj_t *stats;
+ STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted)
+ STATSCOUNTER_DEF(ctrFailed, mutCtrFailed);
+ STATSCOUNTER_DEF(ctrDiscarded, mutCtrDiscarded);
+} statsCounter;
+
+#include "im-helper.h" /* must be included AFTER the type definitions! */
+
+#define min(a, b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+#define EXIT_URI "/exit"
+volatile int exitNow = 0;
+
+struct mg_callbacks callbacks;
+
+typedef struct httpserv_s {
+ struct mg_context *ctx;
+ struct mg_callbacks callbacks;
+ const char **civetweb_options;
+ size_t civetweb_options_count;
+} httpserv_t;
+
+static httpserv_t *s_httpserv;
+
+/* FORWARD DECLARATIONS */
+static rsRetVal processData(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len);
+
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst;
+ DEFiRet;
+ CHKmalloc(inst = calloc(1, sizeof(instanceConf_t)));
+ inst->next = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->pBindRuleset = NULL;
+ inst->pszEndpoint = NULL;
+ inst->pszBasicAuthFile = NULL;
+ inst->ratelimiter = NULL;
+ inst->pszInputName = NULL;
+ inst->pInputName = NULL;
+ inst->ratelimitBurst = 10000; /* arbitrary high limit */
+ inst->ratelimitInterval = 0; /* off */
+ inst->flowControl = 1;
+ inst->bDisableLFDelim = 0;
+ inst->bSuppOctetFram = 0;
+ inst->bAddMetadata = 0;
+ // construct statsobj
+
+ /* node created, let's add to config */
+ if(loadModConf->tail == NULL) {
+ loadModConf->tail = loadModConf->root = inst;
+ } else {
+ loadModConf->tail->next = inst;
+ loadModConf->tail = inst;
+ }
+
+ *pinst = inst;
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+processCivetwebOptions(char *const param,
+ const char **const name,
+ const char **const paramval)
+{
+ DEFiRet;
+ char *val = strstr(param, "=");
+ if(val == NULL) {
+ LogError(0, RS_RET_PARAM_ERROR, "missing equal sign in "
+ "parameter '%s'", param);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ *val = '\0'; /* terminates name */
+ ++val; /* now points to begin of value */
+ CHKmalloc(*name = strdup(param));
+ CHKmalloc(*paramval = strdup(val));
+
+finalize_it:
+ RETiRet;
+}
+
+static sbool valid_civetweb_option(const struct mg_option *valid_opts, const char* option)
+{
+ const struct mg_option *pvalid_opts = valid_opts;
+ for (; pvalid_opts != NULL && pvalid_opts->name != NULL; pvalid_opts++) {
+ if (strcmp(pvalid_opts->name, option) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#if 0
+static int
+log_message(__attribute__((unused)) const struct mg_connection *conn, const char *message)
+{
+ puts(message);
+ return 1;
+}
+#endif
+/*
+ * thread_type:
+ * 0 indicates the master thread
+ * 1 indicates a worker thread handling client connections
+ * 2 indicates an internal helper thread (timer thread)
+*/
+static void*
+init_thread(__attribute__((unused)) const struct mg_context *ctx, int thread_type)
+{
+ DEFiRet;
+ struct conn_wrkr_s *data = NULL;
+ if (thread_type == 1) {
+ CHKmalloc(data = calloc(1, sizeof(struct conn_wrkr_s)));
+ data->pMsg = NULL;
+ data->iMsg = 0;
+ data->parseState.bzInitDone = 0;
+ data->parseState.content_compressed = 0;
+ data->parseState.inputState = eAtStrtFram;
+ data->parseState.iOctetsRemain = 0;
+ data->multiSub.maxElem = CONF_NUM_MULTISUB;
+ data->multiSub.ppMsgs = data->pMsgs;
+ data->multiSub.nElem = 0;
+ data->pReadBuf = malloc(MAX_READ_BUFFER_SIZE);
+ data->readBufSize = MAX_READ_BUFFER_SIZE;
+
+ data->parseState.bzInitDone = 0;
+ data->parseState.content_compressed = 0;
+ data->parseState.inputState = eAtStrtFram;
+ data->parseState.iOctetsRemain = 0;
+
+ CHKmalloc(data->pMsg = calloc(1, 1 + s_iMaxLine));
+ data->iMsg = 0;
+ data->propRemoteAddr = NULL;
+ data->pScratchBuf = NULL;
+ data->scratchBufSize = 0;
+ }
+
+finalize_it:
+ if (iRet != RS_RET_OK) {
+ free(data);
+ return NULL;
+ }
+ return data;
+}
+
+static void
+exit_thread(__attribute__((unused)) const struct mg_context *ctx,
+ __attribute__((unused)) int thread_type, void *thread_pointer)
+{
+ if (thread_type == 1) {
+ struct conn_wrkr_s *data = (struct conn_wrkr_s *) thread_pointer;
+ if (data->propRemoteAddr) {
+ prop.Destruct(&data->propRemoteAddr);
+ }
+ if (data->scratchBufSize) {
+ free(data->pScratchBuf);
+ }
+ free(data->pReadBuf);
+ free(data->pMsg);
+ free(data);
+ }
+}
+
+static rsRetVal
+msgAddMetadataFromHttpHeader(smsg_t *const __restrict__ pMsg, struct conn_wrkr_s *connWrkr)
+{
+ struct json_object *json = NULL;
+ DEFiRet;
+ const struct mg_request_info *ri = connWrkr->pri;
+ #define MAX_HTTP_HEADERS 64 /* hard limit */
+ int count = min(ri->num_headers, MAX_HTTP_HEADERS);
+
+ CHKmalloc(json = json_object_new_object());
+ for (int i = 0 ; i < count ; i++ ) {
+ struct json_object *const jval = json_object_new_string(ri->http_headers[i].value);
+ CHKmalloc(jval);
+ /* truncate header names bigger than INIT_SCRATCH_BUF_SIZE */
+ strncpy(connWrkr->pScratchBuf, ri->http_headers[i].name, connWrkr->scratchBufSize - 1);
+ /* make header lowercase */
+ char* pname = connWrkr->pScratchBuf;
+ while (pname && *pname != '\0') {
+ *pname = tolower(*pname);
+ pname++;
+ }
+ json_object_object_add(json, (const char *const)connWrkr->pScratchBuf, jval);
+ }
+ CHKiRet(msgAddJSON(pMsg, (uchar*)"!metadata!httpheaders", json, 0, 0));
+
+finalize_it:
+ if (iRet != RS_RET_OK && json) {
+ json_object_put(json);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+msgAddMetadataFromHttpQueryParams(smsg_t *const __restrict__ pMsg, struct conn_wrkr_s *connWrkr)
+{
+ struct json_object *json = NULL;
+ DEFiRet;
+ const struct mg_request_info *ri = connWrkr->pri;
+
+ if (ri && ri->query_string) {
+ strncpy(connWrkr->pScratchBuf, ri->query_string, connWrkr->scratchBufSize - 1);
+ char *pquery_str = connWrkr->pScratchBuf;
+ if (pquery_str) {
+ CHKmalloc(json = json_object_new_object());
+
+ char* saveptr = NULL;
+ char *kv_pair = strtok_r(pquery_str, "&;", &saveptr);
+
+ for ( ; kv_pair != NULL; kv_pair = strtok_r(NULL, "&;", &saveptr)) {
+ char *saveptr2 = NULL;
+ char *key = strtok_r(kv_pair, "=", &saveptr2);
+ if (key) {
+ char *value = strtok_r(NULL, "=", &saveptr2);
+ struct json_object *const jval = json_object_new_string(value);
+ CHKmalloc(jval);
+ json_object_object_add(json, (const char *)key, jval);
+ }
+ }
+ CHKiRet(msgAddJSON(pMsg, (uchar*)"!metadata!queryparams", json, 0, 0));
+ }
+ }
+finalize_it:
+ if (iRet != RS_RET_OK && json) {
+ json_object_put(json);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+doSubmitMsg(const instanceConf_t *const __restrict__ inst,
+ struct conn_wrkr_s *connWrkr, const uchar* msg, size_t len)
+{
+ smsg_t *pMsg;
+ DEFiRet;
+
+ assert(len <= s_iMaxLine);
+ if (len == 0) {
+ DBGPRINTF("discarding zero-sized message\n");
+ FINALIZE;
+ }
+
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetFlowControlType(pMsg, inst->flowControl
+ ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY);
+ if (inst->pInputName) {
+ MsgSetInputName(pMsg, inst->pInputName);
+ } else {
+ MsgSetInputName(pMsg, pInputName);
+ }
+ MsgSetRawMsg(pMsg, (const char*)msg, len);
+ MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
+ if (connWrkr->propRemoteAddr) {
+ MsgSetRcvFromIP(pMsg, connWrkr->propRemoteAddr);
+ }
+ if (inst) {
+ MsgSetRuleset(pMsg, inst->pBindRuleset);
+ }
+ // TODO: make these flags configurable.
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+
+ if (inst->bAddMetadata) {
+ CHKiRet(msgAddMetadataFromHttpHeader(pMsg, connWrkr));
+ CHKiRet(msgAddMetadataFromHttpQueryParams(pMsg, connWrkr));
+ }
+
+ ratelimitAddMsg(inst->ratelimiter, &connWrkr->multiSub, pMsg);
+ STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
+finalize_it:
+ connWrkr->iMsg = 0;
+ if (iRet != RS_RET_OK) {
+ STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ }
+ RETiRet;
+}
+
+
+static rsRetVal
+processOctetMsgLen(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, char ch)
+{
+ DEFiRet;
+ if (connWrkr->parseState.inputState == eAtStrtFram) {
+ if (inst->bSuppOctetFram && isdigit(ch)) {
+ connWrkr->parseState.inputState = eInOctetCnt;
+ connWrkr->parseState.iOctetsRemain = 0;
+ connWrkr->parseState.framingMode = TCP_FRAMING_OCTET_COUNTING;
+ } else {
+ connWrkr->parseState.inputState = eInMsg;
+ connWrkr->parseState.framingMode = TCP_FRAMING_OCTET_STUFFING;
+ }
+ }
+
+ // parsing character.
+ if (connWrkr->parseState.inputState == eInOctetCnt) {
+ if (isdigit(ch)) {
+ if (connWrkr->parseState.iOctetsRemain <= 200000000) {
+ connWrkr->parseState.iOctetsRemain = connWrkr->parseState.iOctetsRemain * 10 + ch - '0';
+ }
+ // temporarily save this character into the message buffer
+ if(connWrkr->iMsg + 1 < s_iMaxLine) {
+ connWrkr->pMsg[connWrkr->iMsg++] = ch;
+ }
+ } else {
+ const char *remoteAddr = "";
+ if (connWrkr->propRemoteAddr) {
+ remoteAddr = (const char *)propGetSzStr(connWrkr->propRemoteAddr);
+ }
+
+ /* handle space delimeter */
+ if (ch != ' ') {
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message "
+ "from peer: (ip) %s: to input: %s, delimiter is not "
+ "SP but has ASCII value %d.",
+ remoteAddr, inst->pszInputName, ch);
+ }
+
+ if (connWrkr->parseState.iOctetsRemain < 1) {
+ LogError(0, NO_ERRCODE, "Framing Error in received TCP message"
+ " from peer: (ip) %s: delimiter is not "
+ "SP but has ASCII value %d.",
+ remoteAddr, ch);
+ } else if (connWrkr->parseState.iOctetsRemain > s_iMaxLine) {
+ DBGPRINTF("truncating message with %lu octets - max msg size is %lu\n",
+ connWrkr->parseState.iOctetsRemain, s_iMaxLine);
+ LogError(0, NO_ERRCODE, "received oversize message from peer: "
+ "(hostname) (ip) %s: size is %lu bytes, max msg "
+ "size is %lu, truncating...",
+ remoteAddr, connWrkr->parseState.iOctetsRemain, s_iMaxLine);
+ }
+ connWrkr->parseState.inputState = eInMsg;
+ }
+ /* reset msg len for actual message processing */
+ connWrkr->iMsg = 0;
+ /* retrieve next character */
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processOctetCounting(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+ const uchar* pbuf = (const uchar*)buf;
+ const uchar* pbufLast = pbuf + len;
+
+ while (pbuf < pbufLast) {
+ char ch = *pbuf;
+
+ if (connWrkr->parseState.inputState == eAtStrtFram || connWrkr->parseState.inputState == eInOctetCnt) {
+ processOctetMsgLen(inst, connWrkr, ch);
+ if (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING) {
+ pbuf++;
+ }
+ } else if (connWrkr->parseState.inputState == eInMsg) {
+ if (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_STUFFING) {
+ if (connWrkr->iMsg < s_iMaxLine) {
+ if (ch == '\n') {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ connWrkr->parseState.inputState = eAtStrtFram;
+ } else {
+ connWrkr->pMsg[connWrkr->iMsg++] = ch;
+ }
+ } else {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ connWrkr->parseState.inputState = eAtStrtFram;
+ }
+ pbuf++;
+ } else {
+ assert (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING);
+ /* parsing payload */
+ size_t remainingBytes = pbufLast - pbuf;
+ // figure out how much is in block
+ size_t count = min (connWrkr->parseState.iOctetsRemain, remainingBytes);
+ if (connWrkr->iMsg + count >= s_iMaxLine) {
+ count = s_iMaxLine - connWrkr->iMsg;
+ }
+
+ // just copy the bytes
+ if (count) {
+ memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, count);
+ pbuf += count;
+ connWrkr->iMsg += count;
+ connWrkr->parseState.iOctetsRemain -= count;
+ }
+
+ if (connWrkr->parseState.iOctetsRemain == 0) {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ connWrkr->parseState.inputState = eAtStrtFram;
+ }
+ }
+ } else {
+ // unexpected
+ assert(0);
+ break;
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processDisableLF(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+ const uchar *pbuf = (const uchar*)buf;
+ size_t remainingBytes = len;
+ const uchar* pbufLast = pbuf + len;
+
+ while (pbuf < pbufLast) {
+ size_t count = 0;
+ if (connWrkr->iMsg + remainingBytes >= s_iMaxLine) {
+ count = s_iMaxLine - connWrkr->iMsg;
+ } else {
+ count = remainingBytes;
+ }
+
+ if (count) {
+ memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, count);
+ pbuf += count;
+ connWrkr->iMsg += count;
+ remainingBytes -= count;
+ }
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processDataUncompressed(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ const uchar *pbuf = (const uchar*)buf;
+ DEFiRet;
+
+ if (inst->bDisableLFDelim) {
+ /* do block processing */
+ iRet = processDisableLF(inst, connWrkr, buf, len);
+ } else if (inst->bSuppOctetFram) {
+ iRet = processOctetCounting(inst, connWrkr, buf, len);
+ } else {
+ const uchar* pbufLast = pbuf + len;
+ while (pbuf < pbufLast) {
+ char ch = *pbuf;
+ if (connWrkr->iMsg < s_iMaxLine) {
+ if (ch == '\n') {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ } else {
+ connWrkr->pMsg[connWrkr->iMsg++] = ch;
+ }
+ } else {
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ }
+ pbuf++;
+ }
+ }
+ RETiRet;
+}
+
+static rsRetVal
+processDataCompressed(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+
+ if (!connWrkr->parseState.bzInitDone) {
+ /* allocate deflate state */
+ connWrkr->parseState.zstrm.zalloc = Z_NULL;
+ connWrkr->parseState.zstrm.zfree = Z_NULL;
+ connWrkr->parseState.zstrm.opaque = Z_NULL;
+ int rc = inflateInit2(&connWrkr->parseState.zstrm, (MAX_WBITS | 16));
+ if (rc != Z_OK) {
+ dbgprintf("imhttp: error %d returned from zlib/inflateInit()\n", rc);
+ ABORT_FINALIZE(RS_RET_ZLIB_ERR);
+ }
+ connWrkr->parseState.bzInitDone = 1;
+ }
+
+ connWrkr->parseState.zstrm.next_in = (Bytef*) buf;
+ connWrkr->parseState.zstrm.avail_in = len;
+ /* run inflate() on buffer until everything has been uncompressed */
+ int outtotal = 0;
+ do {
+ int zRet = 0;
+ int outavail = 0;
+ dbgprintf("imhttp: in inflate() loop, avail_in %d, total_in %ld\n",
+ connWrkr->parseState.zstrm.avail_in, connWrkr->parseState.zstrm.total_in);
+
+ connWrkr->parseState.zstrm.avail_out = sizeof(connWrkr->zipBuf);
+ connWrkr->parseState.zstrm.next_out = connWrkr->zipBuf;
+ zRet = inflate(&connWrkr->parseState.zstrm, Z_SYNC_FLUSH);
+ dbgprintf("imhttp: inflate(), ret: %d, avail_out: %d\n", zRet, connWrkr->parseState.zstrm.avail_out);
+ outavail = sizeof(connWrkr->zipBuf) - connWrkr->parseState.zstrm.avail_out;
+ if (outavail != 0) {
+ outtotal += outavail;
+ CHKiRet(processDataUncompressed(inst, connWrkr, (const char*)connWrkr->zipBuf, outavail));
+ }
+ } while (connWrkr->parseState.zstrm.avail_out == 0);
+
+ dbgprintf("imhttp: processDataCompressed complete, sizes: in %lld, out %llu\n", (long long) len,
+ (long long unsigned) outtotal);
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+processData(const instanceConf_t *const inst,
+ struct conn_wrkr_s *connWrkr, const char* buf, size_t len)
+{
+ DEFiRet;
+
+ //inst->bDisableLFDelim = 0;
+ if (connWrkr->parseState.content_compressed) {
+ iRet = processDataCompressed(inst, connWrkr, buf, len);
+ } else {
+ iRet = processDataUncompressed(inst, connWrkr, buf, len);
+ }
+
+ RETiRet;
+}
+
+/* Return 1 on success. Always initializes the auth structure. */
+static int
+parse_auth_header(struct mg_connection *conn, struct auth_s *auth)
+{
+ if (!auth || !conn) {
+ return 0;
+ }
+
+ const char *auth_header = NULL;
+ if (((auth_header = mg_get_header(conn, "Authorization")) == NULL) ||
+ strncasecmp(auth_header, "Basic ", 6) != 0) {
+ return 0;
+ }
+
+ /* Parse authorization header */
+ const char* src = auth_header + 6;
+ size_t len = apr_base64_decode_len((const char*)src);
+ auth->pworkbuf = auth->workbuf;
+ if (len > sizeof(auth->workbuf)) {
+ auth->pworkbuf = calloc(0, len);
+ auth->workbuf_len = len;
+ }
+ len = apr_base64_decode(auth->pworkbuf, src);
+ if (len == 0) {
+ return 0;
+ }
+
+ char *passwd = NULL, *saveptr = NULL;
+ char *user = strtok_r(auth->pworkbuf, ":", &saveptr);
+ if (user) {
+ passwd = strtok_r(NULL, ":", &saveptr);
+ }
+
+ auth->pszUser = user;
+ auth->pszPasswd = passwd;
+
+ return 1;
+}
+
+static int
+read_auth_file(FILE* filep, struct auth_s *auth)
+{
+ if (!filep) {
+ return 0;
+ }
+ char workbuf[IMHTTP_MAX_BUF_LEN];
+ size_t l = 0;
+ char* user;
+ char* passwd;
+
+ while (fgets(workbuf, sizeof(workbuf), filep)) {
+ l = strnlen(workbuf, sizeof(workbuf));
+ while (l > 0) {
+ if (isspace(workbuf[l-1]) || iscntrl(workbuf[l-1])) {
+ l--;
+ workbuf[l] = 0;
+ } else {
+ break;
+ }
+ }
+
+ if (l < 1) {
+ continue;
+ }
+
+ if (workbuf[0] == '#') {
+ continue;
+ }
+
+ user = workbuf;
+ passwd = strchr(workbuf, ':');
+ if (!passwd) {
+ continue;
+ }
+ *passwd = '\0';
+ passwd++;
+
+ if (!strcasecmp(auth->pszUser, user)) {
+ return (apr_password_validate(auth->pszPasswd, passwd) == APR_SUCCESS);
+ }
+ }
+ return 0;
+}
+
+/* Authorize against the opened passwords file. Return 1 if authorized. */
+static int
+authorize(struct mg_connection* conn, FILE* filep)
+{
+ if (!conn || !filep) {
+ return 0;
+ }
+
+ struct auth_s auth = { .workbuf_len=0, .pworkbuf=NULL, .pszUser=NULL, .pszPasswd=NULL};
+ if (!parse_auth_header(conn, &auth)) {
+ return 0;
+ }
+
+ /* validate against htpasswd file */
+ return read_auth_file(filep, &auth);
+}
+
+/* Provides Basic Authorization handling that validates against a 'htpasswd' file.
+ see also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
+*/
+static int
+basicAuthHandler(struct mg_connection *conn, void *cbdata)
+{
+ const instanceConf_t* inst = (const instanceConf_t*) cbdata;
+ char errStr[512];
+ FILE *fp = NULL;
+ int ret = 1;
+
+ if (!inst->pszBasicAuthFile) {
+ mg_cry(conn, "warning: 'BasicAuthFile' not configured.\n");
+ ret = 0;
+ goto finalize;
+ }
+
+ fp = fopen((const char *)inst->pszBasicAuthFile, "r");
+ if (fp == NULL) {
+ if (strerror_r(errno, errStr, sizeof(errStr)) == 0) {
+ mg_cry(conn,
+ "error: 'BasicAuthFile' file '%s' could not be accessed: %s\n",
+ inst->pszBasicAuthFile, errStr);
+ } else {
+ mg_cry(conn,
+ "error: 'BasicAuthFile' file '%s' could not be accessed: %d\n",
+ inst->pszBasicAuthFile, errno);
+ }
+ ret = 0;
+ goto finalize;
+ }
+
+ ret = authorize(conn, fp);
+
+finalize:
+ if (!ret) {
+ mg_send_http_error(conn, 401, "WWW-Authenticate: Basic realm=\"User Visible Realm\"\n");
+ }
+ if (fp ) {
+ fclose(fp);
+ }
+ return ret;
+}
+
+/* cbdata should actually contain instance data and we can actually use this instance data
+ * to hold reusable scratch buffer.
+ */
+static int
+postHandler(struct mg_connection *conn, void *cbdata)
+{
+ int rc = 1;
+ instanceConf_t* inst = (instanceConf_t*) cbdata;
+ const struct mg_request_info *ri = mg_get_request_info(conn);
+ struct conn_wrkr_s *connWrkr = mg_get_thread_pointer(conn);
+ connWrkr->multiSub.nElem = 0;
+ memset(&connWrkr->parseState, 0, sizeof(connWrkr->parseState));
+ connWrkr->pri = ri;
+
+ if (inst->bAddMetadata && connWrkr->scratchBufSize == 0) {
+ connWrkr->pScratchBuf = calloc(1, INIT_SCRATCH_BUF_SIZE);
+ if (!connWrkr->pScratchBuf) {
+ mg_cry(conn, "%s() - could not alloc scratch buffer!\n", __FUNCTION__);
+ rc = 500;
+ FINALIZE;
+ }
+ connWrkr->scratchBufSize = INIT_SCRATCH_BUF_SIZE;
+ }
+
+ if (0 != strcmp(ri->request_method, "POST")) {
+ /* Not a POST request */
+ int ret = mg_get_request_link(conn, connWrkr->pReadBuf, connWrkr->readBufSize);
+ mg_printf(conn,
+ "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
+ mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
+ mg_printf(conn,
+ "%s method not allowed in the POST handler\n",
+ ri->request_method);
+ if (ret >= 0) {
+ mg_printf(conn,
+ "use a web tool to send a POST request to %s\n",
+ connWrkr->pReadBuf);
+ }
+ STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed);
+ rc = 405;
+ FINALIZE;
+ }
+
+ if (ri->remote_addr[0] != '\0') {
+ size_t len = strnlen(ri->remote_addr, sizeof(ri->remote_addr));
+ prop.CreateOrReuseStringProp(&connWrkr->propRemoteAddr, (const uchar*)ri->remote_addr, len);
+ }
+
+ if (ri->content_length >= 0) {
+ /* We know the content length in advance */
+ if (ri->content_length > (long long) connWrkr->readBufSize) {
+ connWrkr->pReadBuf = realloc(connWrkr->pReadBuf, ri->content_length+1);
+ if (!connWrkr->pReadBuf) {
+ mg_cry(conn, "%s() - realloc failed!\n", __FUNCTION__);
+ FINALIZE;
+ }
+ connWrkr->readBufSize = ri->content_length+1;
+ }
+ } else {
+ /* We must read until we find the end (chunked encoding
+ * or connection close), indicated my mg_read returning 0 */
+ }
+
+ if (ri->num_headers > 0) {
+ int i;
+ for (i = 0; i < ri->num_headers; i++) {
+ if (!strcasecmp(ri->http_headers[i].name, "content-encoding") &&
+ !strcasecmp(ri->http_headers[i].value, "gzip")) {
+ connWrkr->parseState.content_compressed = 1;
+ }
+ }
+ }
+
+ while (1) {
+ int count = mg_read(conn, connWrkr->pReadBuf, connWrkr->readBufSize);
+ if (count > 0) {
+ processData(inst, connWrkr, (const char*)connWrkr->pReadBuf, count);
+ } else {
+ break;
+ }
+ }
+
+ /* submit remainder */
+ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg);
+ multiSubmitFlush(&connWrkr->multiSub);
+
+ mg_send_http_ok(conn, "text/plain", 0);
+ rc = 200;
+
+finalize_it:
+ if (connWrkr->parseState.bzInitDone) {
+ inflateEnd(&connWrkr->parseState.zstrm);
+ }
+ /* reset */
+ connWrkr->iMsg = 0;
+
+ return rc;
+}
+
+static int runloop(void)
+{
+ dbgprintf("imhttp started.\n");
+
+ /* Add handler for form data */
+ for(instanceConf_t *inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ assert(inst->pszEndpoint);
+ if (inst->pszEndpoint) {
+ dbgprintf("setting request handler: '%s'\n", inst->pszEndpoint);
+ mg_set_request_handler(s_httpserv->ctx, (char *)inst->pszEndpoint, postHandler, inst);
+ if (inst->pszBasicAuthFile) {
+ mg_set_auth_handler(s_httpserv->ctx, (char *)inst->pszEndpoint, basicAuthHandler, inst);
+ }
+ }
+ }
+
+ /* Wait until the server should be closed */
+ while(glbl.GetGlobalInputTermState() == 0) {
+ sleep(1);
+ }
+ return EXIT_SUCCESS;
+}
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imhttp)\n");
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imhttp: required parameter are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imtcp:\n");
+ cnfparamsPrint(&inppblk, pvals);
+ }
+
+ CHKiRet(createInstance(&inst));
+
+ for(i = 0 ; i < inppblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(inppblk.descr[i].name, "endpoint")) {
+ inst->pszEndpoint = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "basicauthfile")) {
+ inst->pszBasicAuthFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ inst->flowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "disablelfdelimiter")) {
+ inst->bDisableLFDelim = (int) pvals[i].val.d.n;
+ } else if (!strcmp(inppblk.descr[i].name, "supportoctetcountedframing")) {
+ inst->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if (!strcmp(inppblk.descr[i].name, "addmetadata")) {
+ inst->bAddMetadata = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imhttp: program error, non-handled "
+ "param '%s'\n", inppblk.descr[i].name);
+ }
+ }
+
+ if (inst->pszInputName) {
+ CHKiRet(prop.Construct(&inst->pInputName));
+ CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(inst->pInputName));
+ }
+ CHKiRet(ratelimitNew(&inst->ratelimiter, "imphttp", NULL));
+ ratelimitSetLinuxLike(inst->ratelimiter, inst->ratelimitInterval, inst->ratelimitBurst);
+
+finalize_it:
+CODE_STD_FINALIZERnewInpInst
+ cnfparamvalsDestruct(pvals, &inppblk);
+ENDnewInpInst
+
+
+BEGINbeginCnfLoad
+CODESTARTbeginCnfLoad
+ loadModConf = pModConf;
+ pModConf->pConf = pConf;
+ loadModConf->ports.name = NULL;
+ loadModConf->docroot.name = NULL;
+ loadModConf->nOptions = 0;
+ loadModConf->options = NULL;
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imhttp: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imhttp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(int i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "ports")) {
+ assert(loadModConf->ports.name == NULL);
+ assert(loadModConf->ports.val == NULL);
+ loadModConf->ports.name = strdup(CIVETWEB_OPTION_NAME_PORTS);
+ loadModConf->ports.val = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if (!strcmp(modpblk.descr[i].name, "documentroot")) {
+ assert(loadModConf->docroot.name == NULL);
+ assert(loadModConf->docroot.val == NULL);
+ loadModConf->docroot.name = strdup(CIVETWEB_OPTION_NAME_DOCUMENT_ROOT);
+ loadModConf->docroot.val = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "liboptions")) {
+ loadModConf->nOptions = pvals[i].val.d.ar->nmemb;
+ CHKmalloc(loadModConf->options = malloc(sizeof(struct option) *
+ pvals[i].val.d.ar->nmemb ));
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(processCivetwebOptions(cstr, &loadModConf->options[j].name,
+ &loadModConf->options[j].val));
+ free(cstr);
+ }
+ } else {
+ dbgprintf("imhttp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+/* function to generate error message if framework does not find requested ruleset */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imhttp: ruleset '%s' for %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->pszEndpoint);
+}
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ }
+ /* verify civetweb options are valid */
+ const struct mg_option *valid_opts = mg_get_valid_options();
+ for (int i = 0; i < pModConf->nOptions; ++i) {
+ if (!valid_civetweb_option(valid_opts, pModConf->options[i].name)) {
+ LogError(0, RS_RET_CONF_PARSE_WARNING, "imhttp: module loaded, but "
+ "invalid civetweb option found - imhttp may not receive connections.");
+ iRet = RS_RET_CONF_PARSE_WARNING;
+ }
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ runModConf = pModConf;
+
+ if (!s_httpserv) {
+ CHKmalloc(s_httpserv = calloc(1, sizeof(httpserv_t)));
+ }
+ /* options represents (key, value) so allocate 2x, and null terminated */
+ size_t count = 1;
+ if (runModConf->ports.val) {
+ count += 2;
+ }
+ if (runModConf->docroot.val) {
+ count += 2;
+ }
+ count += (2 * runModConf->nOptions);
+ CHKmalloc(s_httpserv->civetweb_options = calloc(count, sizeof(*s_httpserv->civetweb_options)));
+
+ const char **pcivetweb_options = s_httpserv->civetweb_options;
+ if (runModConf->nOptions) {
+ s_httpserv->civetweb_options_count = count;
+ for (int i = 0; i < runModConf->nOptions; ++i) {
+ *pcivetweb_options = runModConf->options[i].name;
+ pcivetweb_options++;
+ *pcivetweb_options = runModConf->options[i].val;
+ pcivetweb_options++;
+ }
+ }
+ /* append port, docroot */
+ if (runModConf->ports.val) {
+ *pcivetweb_options = runModConf->ports.name;
+ pcivetweb_options++;
+ *pcivetweb_options = runModConf->ports.val;
+ pcivetweb_options++;
+ }
+ if (runModConf->docroot.val) {
+ *pcivetweb_options = runModConf->docroot.name;
+ pcivetweb_options++;
+ *pcivetweb_options = runModConf->docroot.val;
+ pcivetweb_options++;
+ }
+
+ const char **option = s_httpserv->civetweb_options;
+ for (; option && *option != NULL; option++) {
+ dbgprintf("imhttp: civetweb option: %s\n", *option);
+ }
+
+ CHKiRet(statsobj.Construct(&statsCounter.stats));
+ CHKiRet(statsobj.SetName(statsCounter.stats, UCHAR_CONSTANT("imhttp")));
+ CHKiRet(statsobj.SetOrigin(statsCounter.stats, UCHAR_CONSTANT("imhttp")));
+ STATSCOUNTER_INIT(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("submitted"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrSubmitted)));
+
+ STATSCOUNTER_INIT(statsCounter.ctrFailed, statsCounter.mutCtrFailed);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("failed"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrFailed)));
+
+ STATSCOUNTER_INIT(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("discarded"),
+ ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrDiscarded)));
+
+ CHKiRet(statsobj.ConstructFinalize(statsCounter.stats));
+
+ /* init civetweb libs and start server w/no input */
+ mg_init_library(MG_FEATURES_TLS);
+ memset(&callbacks, 0, sizeof(callbacks));
+ //callbacks.log_message = log_message;
+ //callbacks.init_ssl = init_ssl;
+ callbacks.init_thread = init_thread;
+ callbacks.exit_thread = exit_thread;
+ s_httpserv->ctx = mg_start(&callbacks, NULL, s_httpserv->civetweb_options);
+ /* Check return value: */
+ if (s_httpserv->ctx == NULL) {
+ LogError(0, RS_RET_INTERNAL_ERROR, "Cannot start CivetWeb - mg_start failed.\n");
+ ABORT_FINALIZE(RS_RET_INTERNAL_ERROR);
+ }
+
+ finalize_it:
+ if (iRet != RS_RET_OK) {
+ free(s_httpserv);
+ s_httpserv = NULL;
+ LogError(0, NO_ERRCODE, "imhttp: error %d trying to activate configuration", iRet);
+ }
+ RETiRet;
+ENDactivateCnf
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ if (inst->ratelimiter) {
+ ratelimitDestruct(inst->ratelimiter);
+ }
+ if (inst->pInputName) {
+ prop.Destruct(&inst->pInputName);
+ }
+ free(inst->pszEndpoint);
+ free(inst->pszBasicAuthFile);
+ free(inst->pszBindRuleset);
+ free(inst->pszInputName);
+
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+
+ for (int i = 0; i < pModConf->nOptions; ++i) {
+ free((void*) pModConf->options[i].name);
+ free((void*) pModConf->options[i].val);
+ }
+ free(pModConf->options);
+
+ free((void*)pModConf->ports.name);
+ free((void*)pModConf->ports.val);
+ free((void*)pModConf->docroot.name);
+ free((void*)pModConf->docroot.val);
+
+ if (statsCounter.stats) {
+ statsobj.Destruct(&statsCounter.stats);
+ }
+ENDfreeCnf
+
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ runloop();
+ENDrunInput
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ENDwillRun
+
+BEGINafterRun
+CODESTARTafterRun
+ if (s_httpserv) {
+ mg_stop(s_httpserv->ctx);
+ mg_exit_library();
+ free(s_httpserv->civetweb_options);
+ free(s_httpserv);
+ }
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ // if(eFeat == sFEATURENonCancelInputTermination)
+ // iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINmodExit
+CODESTARTmodExit
+ if(pInputName != NULL) {
+ prop.Destruct(&pInputName);
+ }
+
+ /* release objects we used */
+ objRelease(statsobj, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(statsobj, CORE_COMPONENT));
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imhttp"), sizeof("imhttp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+ENDmodInit