added include_shell option to configfiles (merged the rest of the trunk changesets)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@530 152afb58-edef-0310-8abb-c4023f1b3aa9
This commit is contained in:
parent
360aba360f
commit
75c3a8393a
140
configure.in
140
configure.in
|
@ -96,7 +96,7 @@ AC_ARG_WITH(mysql,
|
|||
if test \! -x $withval; then
|
||||
echo "--with-mysql=path-to-mysql_config"
|
||||
fi
|
||||
if $withval | grep -- '--include' ; then
|
||||
if $withval | grep -- '--include' > /dev/null ; then
|
||||
MYSQL_INCLUDE="`$withval --include | sed s/\'//g`"
|
||||
else
|
||||
MYSQL_INCLUDE="`$withval --cflags | sed s/\'//g`"
|
||||
|
@ -364,6 +364,9 @@ AC_ARG_ENABLE(lfs,
|
|||
esac],[CPPFLAGS="${CPPFLAGS} -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES"])
|
||||
AC_MSG_RESULT($enableval)
|
||||
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(off_t)
|
||||
|
||||
if test "x$ac_cv_func_sendfile" = xyes; then
|
||||
# check if sendfile works
|
||||
AC_MSG_CHECKING(if sendfile works)
|
||||
|
@ -409,6 +412,7 @@ if test x$ipv6 = xtrue; then
|
|||
fi
|
||||
fi
|
||||
|
||||
|
||||
AM_CONDITIONAL(CROSS_COMPILING, test "x$cross_compiling" = xyes)
|
||||
|
||||
dnl check for fastcgi lib, for the tests only
|
||||
|
@ -440,51 +444,121 @@ AC_CONFIG_FILES([Makefile debian/Makefile src/Makefile doc/Makefile tests/Makefi
|
|||
openwrt/Makefile openwrt/control openwrt/lighttpd.mk])
|
||||
AC_OUTPUT
|
||||
|
||||
$ECHO
|
||||
$ECHO "Plugins:"
|
||||
$ECHO
|
||||
|
||||
do_build="mod_cgi mod_fastcgi mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir"
|
||||
|
||||
plugins="mod_rewrite mod_redirect mod_ssi"
|
||||
features="regex-conditionals"
|
||||
if test ! "x$PCRE_LIB" = x; then
|
||||
$ECHO "mod_rewrite : enabled"
|
||||
$ECHO "mod_redirect : enabled"
|
||||
$ECHO "mod_ssi : enabled"
|
||||
do_build="$do_build $plugins"
|
||||
enable_feature="$features"
|
||||
else
|
||||
$ECHO "mod_rewrite : disabled (libpcre missing)"
|
||||
$ECHO "mod_redirect : disabled (libpcre missing)"
|
||||
$ECHO "mod_ssi : disabled (libpcre missing)"
|
||||
no_build="$no_build $plugins"
|
||||
disable_feature="$features"
|
||||
fi
|
||||
|
||||
$ECHO "mod_cgi : enabled"
|
||||
$ECHO "mod_fastcgi : enabled"
|
||||
$ECHO "mod_proxy : enabled"
|
||||
$ECHO "mod_evhost : enabled"
|
||||
$ECHO "mod_simple_vhost: enabled"
|
||||
|
||||
if test "x$MYSQL_LIBS" = x; then
|
||||
$ECHO "mod_mysql_vhost : disabled (libmysqlclient missing or mysql support disabled)"
|
||||
plugins="mod_mysql_vhost"
|
||||
if test ! "x$MYSQL_LIBS" = x; then
|
||||
do_build="$do_build $plugins"
|
||||
else
|
||||
$ECHO "mod_mysql_vhost : enabled"
|
||||
no_build="$no_build $plugins"
|
||||
fi
|
||||
|
||||
$ECHO "mod_access : enabled"
|
||||
$ECHO "mod_alias : enabled"
|
||||
$ECHO "mod_setenv : enabled"
|
||||
$ECHO "mod_usertrack : enabled"
|
||||
if test "x$Z_LIB" = x; then
|
||||
$ECHO "mod_compress : disabled (libz missing)"
|
||||
plugins="mod_trigger_b4_dl"
|
||||
if test ! "x$GDBM_LIB" = x; then
|
||||
do_build="$do_build $plugins"
|
||||
else
|
||||
$ECHO "mod_compress : enabled"
|
||||
no_build="$no_build $plugins"
|
||||
fi
|
||||
|
||||
|
||||
features="compress-gzip compress-deflate"
|
||||
if test ! "x$Z_LIB" = x; then
|
||||
enable_feature="$enable_feature $features"
|
||||
else
|
||||
disable_feature="$disable_feature $features"
|
||||
fi
|
||||
|
||||
features="compress-bzip2"
|
||||
if test ! "x$BZ_LIB" = x; then
|
||||
enable_feature="$enable_feature $features"
|
||||
else
|
||||
disable_feature="$disable_feature $features"
|
||||
fi
|
||||
|
||||
features="auth-ldap"
|
||||
if test ! "x$LDAP_LIB" = x; then
|
||||
enable_feature="$enable_feature $features"
|
||||
else
|
||||
disable_feature="$disable_feature $features"
|
||||
fi
|
||||
|
||||
features="network-openssl"
|
||||
if test ! "x$SSL_LIB" = x; then
|
||||
enable_feature="$enable_feature $features"
|
||||
else
|
||||
disable_feature="$disable_feature $features"
|
||||
fi
|
||||
|
||||
# no crypt call
|
||||
features="auth-crypt"
|
||||
if test "$ac_cv_search_crypt" = no; then
|
||||
$ECHO "mod_auth : enabled, crypt() support disabled"
|
||||
disable_feature="$disable_feature $features"
|
||||
else
|
||||
$ECHO "mod_auth : enabled"
|
||||
enable_feature="$enable_feature $features"
|
||||
fi
|
||||
$ECHO "mod_status : enabled"
|
||||
$ECHO "mod_accesslog : enabled"
|
||||
$ECHO "mod_rrdtool : enabled"
|
||||
$ECHO "mod_secdownload : enabled"
|
||||
$ECHO "mod_expire : enabled"
|
||||
|
||||
features="network-ipv6"
|
||||
if test "$ac_cv_ipv6_support" = yes; then
|
||||
enable_feature="$enable_feature $features"
|
||||
else
|
||||
disable_feature="$disable_feature $features"
|
||||
fi
|
||||
|
||||
features="large-files"
|
||||
if test "$enable_lfs" = yes; then
|
||||
enable_feature="$enable_feature $features"
|
||||
else
|
||||
disable_feature="$disable_feature $features"
|
||||
fi
|
||||
|
||||
## post processing
|
||||
do_build=`echo $do_build | sed 's/ /\n/g' | sort`
|
||||
no_build=`echo $no_build | sed 's/ /\n/g' | sort`
|
||||
enable_feature=`echo $enable_feature | sed 's/ /\n/g' | sort`
|
||||
disable_feature=`echo $disable_feature | sed 's/ /\n/g' | sort`
|
||||
|
||||
## output
|
||||
|
||||
$ECHO
|
||||
$ECHO "Plugins:"
|
||||
$ECHO
|
||||
|
||||
$ECHO "enabled: "
|
||||
i=0
|
||||
for p in $do_build; do
|
||||
$ECHO " $p"
|
||||
done
|
||||
|
||||
$ECHO "disabled: "
|
||||
for p in $no_build; do
|
||||
$ECHO " $p"
|
||||
done
|
||||
|
||||
$ECHO
|
||||
$ECHO "Features:"
|
||||
$ECHO
|
||||
|
||||
$ECHO "enabled: "
|
||||
i=0
|
||||
p=""
|
||||
for p in $enable_feature; do
|
||||
$ECHO " $p"
|
||||
done
|
||||
|
||||
$ECHO "disabled: "
|
||||
for p in $disable_feature; do
|
||||
$ECHO " $p"
|
||||
done
|
||||
|
||||
$ECHO
|
||||
|
|
|
@ -35,6 +35,7 @@ A BNF like notation: ::
|
|||
<boolean>: ( "enable" | "disable" )
|
||||
<array> : "(" [ <string> "=>" ] <value> [, [ <string> "=>" ] <value> ]* ")"
|
||||
INCLUDE : "include" VALUE
|
||||
INCLUDE_SHELL : "include_shell" STRING_VALUE
|
||||
|
||||
Example
|
||||
-------
|
||||
|
@ -60,6 +61,9 @@ Example
|
|||
# include, relative to dirname of main config file
|
||||
include "mime.types.conf"
|
||||
|
||||
# read configuration from output of a command
|
||||
include_shell "/usr/local/bin/confmimetype /etc/mime.types"
|
||||
|
||||
|
||||
Conditional Configuration
|
||||
=========================
|
||||
|
|
|
@ -301,3 +301,8 @@ $HTTP["url"] =~ "\.pdf$" {
|
|||
#include /etc/lighttpd/lighttpd-inc.conf
|
||||
## same as above if you run: "lighttpd -f /etc/lighttpd/lighttpd.conf"
|
||||
#include "lighttpd-inc.conf"
|
||||
|
||||
#### include_shell
|
||||
#include_shell "echo var.a=1"
|
||||
## the above is same as:
|
||||
#var.a=1
|
||||
|
|
|
@ -9,6 +9,8 @@ lighttpd
|
|||
.deps
|
||||
.libs
|
||||
array
|
||||
proc_open
|
||||
regex
|
||||
mod_ssi_exprparser.c
|
||||
mod_ssi_exprparser.h
|
||||
configparser.c
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
noinst_PROGRAMS=array chunk lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license
|
||||
noinst_PROGRAMS=proc_open lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license
|
||||
sbin_PROGRAMS=lighttpd
|
||||
bin_PROGRAMS=spawn-fcgi
|
||||
LEMON=$(top_builddir)/src/lemon
|
||||
|
@ -47,8 +47,7 @@ src = server.c response.c connections.c network.c \
|
|||
network_write.c network_linux_sendfile.c \
|
||||
network_freebsd_sendfile.c network_writev.c \
|
||||
network_solaris_sendfilev.c network_openssl.c \
|
||||
configfile.c request.c
|
||||
|
||||
configfile.c request.c proc_open.c
|
||||
|
||||
spawn_fcgi_SOURCES=spawn-fcgi.c
|
||||
|
||||
|
@ -208,7 +207,7 @@ hdr = server.h buffer.h network.h log.h keyvalue.h \
|
|||
mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
|
||||
configparser.h mod_ssi_exprparser.h \
|
||||
sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
|
||||
splaytree.h
|
||||
splaytree.h proc_open.h
|
||||
|
||||
DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
|
||||
|
||||
|
@ -217,11 +216,8 @@ lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_liba
|
|||
lighttpd_LDFLAGS = -export-dynamic
|
||||
lighttpd_CCPFLAGS = $(FAM_CFLAGS)
|
||||
|
||||
array_SOURCES = array.c buffer.c data_string.c data_count.c
|
||||
array_CPPFLAGS= -DDEBUG_ARRAY
|
||||
|
||||
chunk_SOURCES = buffer.c chunk.c
|
||||
chunk_CPPFLAGS= -DDEBUG_CHUNK
|
||||
proc_open_SOURCES = proc_open.c buffer.c
|
||||
proc_open_CPPFLAGS= -DDEBUG_PROC_OPEN
|
||||
|
||||
#gen_license_SOURCES = license.c md5.c buffer.c gen_license.c
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ typedef struct {
|
|||
data_array *data_array_init(void);
|
||||
|
||||
typedef enum { CONFIG_COND_UNSET, CONFIG_COND_EQ, CONFIG_COND_MATCH, CONFIG_COND_NE, CONFIG_COND_NOMATCH } config_cond_t;
|
||||
typedef enum { COND_RESULT_FALSE, COND_RESULT_TRUE, COND_RESULT_UNSET } cond_result_t;
|
||||
|
||||
#define PATCHES NULL, "SERVERsocket", "HTTPurl", "HTTPhost", "HTTPreferer", "HTTPuseragent", "HTTPcookie", "HTTPremoteip"
|
||||
typedef enum {
|
||||
|
|
11
src/base.h
11
src/base.h
|
@ -290,6 +290,14 @@ typedef struct {
|
|||
|
||||
typedef enum { CON_STATE_CONNECT, CON_STATE_REQUEST_START, CON_STATE_READ, CON_STATE_REQUEST_END, CON_STATE_READ_POST, CON_STATE_HANDLE_REQUEST, CON_STATE_RESPONSE_START, CON_STATE_WRITE, CON_STATE_RESPONSE_END, CON_STATE_ERROR, CON_STATE_CLOSE } connection_state_t;
|
||||
|
||||
typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
|
||||
typedef struct {
|
||||
cond_result_t result;
|
||||
int patterncount;
|
||||
int matches[3 * 10];
|
||||
buffer *comp_value; /* just a pointer */
|
||||
} cond_cache_t;
|
||||
|
||||
typedef struct {
|
||||
connection_state_t state;
|
||||
|
||||
|
@ -336,6 +344,7 @@ typedef struct {
|
|||
int http_status;
|
||||
|
||||
sock_addr dst_addr;
|
||||
buffer *dst_addr_buf;
|
||||
|
||||
/* request */
|
||||
buffer *parse_request;
|
||||
|
@ -361,7 +370,7 @@ typedef struct {
|
|||
void **plugin_ctx; /* plugin connection specific config */
|
||||
|
||||
specific_config conf; /* global connection specific config */
|
||||
cond_result_t *cond_results_cache;
|
||||
cond_cache_t *cond_cache;
|
||||
|
||||
buffer *server_name;
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ int config_insert_values_global(server *srv, array *ca, const config_values_t cv
|
|||
return config_insert_values_internal(srv, ca, cv);
|
||||
}
|
||||
|
||||
static int config_check_cond_cached(server *srv, connection *con, data_config *dc);
|
||||
static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc);
|
||||
|
||||
static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) {
|
||||
buffer *l;
|
||||
|
@ -155,21 +155,21 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
/* check parent first */
|
||||
if (dc->parent && dc->parent->context_ndx) {
|
||||
if (con->conf.log_condition_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "go parent", dc->parent->string);
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "go parent", dc->parent->key);
|
||||
}
|
||||
if (!config_check_cond_cached(srv, con, dc->parent)) {
|
||||
if (config_check_cond_cached(srv, con, dc->parent) == COND_RESULT_FALSE) {
|
||||
return COND_RESULT_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (dc->prev) {
|
||||
if (con->conf.log_condition_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->string);
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->key);
|
||||
}
|
||||
/* make sure prev is checked first */
|
||||
config_check_cond_cached(srv, con, dc->prev);
|
||||
/* one of prev set me to FALSE */
|
||||
if (con->cond_results_cache[dc->context_ndx] == COND_RESULT_FALSE) {
|
||||
if (COND_RESULT_FALSE == con->cond_cache[dc->context_ndx].result) {
|
||||
return COND_RESULT_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,8 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
|
||||
l = srv->empty_string;
|
||||
|
||||
if (COMP_HTTP_HOST == dc->comp) {
|
||||
switch (dc->comp) {
|
||||
case COMP_HTTP_HOST: {
|
||||
l = con->uri.authority;
|
||||
#if 0
|
||||
/* FIXME: get this working again */
|
||||
|
@ -208,7 +209,9 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (COMP_HTTP_REMOTEIP == dc->comp) {
|
||||
break;
|
||||
}
|
||||
case COMP_HTTP_REMOTEIP: {
|
||||
char *nm_slash;
|
||||
/* handle remoteip limitations
|
||||
*
|
||||
|
@ -283,27 +286,40 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
buffer_copy_string(srv->cond_check_buf, s);
|
||||
}
|
||||
#endif
|
||||
} else if (COMP_HTTP_URL == dc->comp) {
|
||||
break;
|
||||
}
|
||||
case COMP_HTTP_URL:
|
||||
l = con->uri.path;
|
||||
} else if (COMP_SERVER_SOCKET == dc->comp) {
|
||||
break;
|
||||
|
||||
case COMP_SERVER_SOCKET:
|
||||
l = srv_sock->srv_token;
|
||||
} else if (COMP_HTTP_REFERER == dc->comp) {
|
||||
break;
|
||||
|
||||
case COMP_HTTP_REFERER: {
|
||||
data_string *ds;
|
||||
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else if (COMP_HTTP_COOKIE == dc->comp) {
|
||||
break;
|
||||
}
|
||||
case COMP_HTTP_COOKIE: {
|
||||
data_string *ds;
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else if (COMP_HTTP_USERAGENT == dc->comp) {
|
||||
break;
|
||||
}
|
||||
case COMP_HTTP_USERAGENT: {
|
||||
data_string *ds;
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return COND_RESULT_FALSE;
|
||||
}
|
||||
|
||||
|
@ -322,15 +338,21 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
#ifdef HAVE_PCRE_H
|
||||
case CONFIG_COND_NOMATCH:
|
||||
case CONFIG_COND_MATCH: {
|
||||
#define N 10
|
||||
int ovec[N * 3];
|
||||
cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
|
||||
int n;
|
||||
|
||||
n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, ovec, N * 3);
|
||||
#ifndef elementsof
|
||||
#define elementsof(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
|
||||
cache->matches, elementsof(cache->matches));
|
||||
|
||||
if (n > 0) {
|
||||
cache->patterncount = n;
|
||||
cache->comp_value = l;
|
||||
return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
|
||||
} else {
|
||||
/* cache is already cleared */
|
||||
return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
|
||||
}
|
||||
break;
|
||||
|
@ -344,36 +366,56 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
return COND_RESULT_FALSE;
|
||||
}
|
||||
|
||||
static int config_check_cond_cached(server *srv, connection *con, data_config *dc) {
|
||||
cond_result_t *cache = con->cond_results_cache;
|
||||
static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc) {
|
||||
cond_cache_t *caches = con->cond_cache;
|
||||
|
||||
if (cache[dc->context_ndx] == COND_RESULT_UNSET) {
|
||||
if (COND_RESULT_TRUE == (cache[dc->context_ndx] = config_check_cond_nocache(srv, con, dc))) {
|
||||
if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
|
||||
if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
|
||||
if (dc->next) {
|
||||
data_config *c;
|
||||
if (con->conf.log_condition_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "setting remains of chaining to FALSE");
|
||||
log_error_write(srv, __FILE__, __LINE__, "s",
|
||||
"setting remains of chaining to false");
|
||||
}
|
||||
for (c = dc->next; c; c = c->next) {
|
||||
cache[c->context_ndx] = COND_RESULT_FALSE;
|
||||
caches[c->context_ndx].result = COND_RESULT_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (con->conf.log_condition_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "dsd", dc->context_ndx, "(uncached) result:", cache[dc->context_ndx]);
|
||||
log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
|
||||
"(uncached) result:",
|
||||
caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (con->conf.log_condition_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "dsd", dc->context_ndx, "(cached) result:", cache[dc->context_ndx]);
|
||||
log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
|
||||
"(cached) result:",
|
||||
caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
|
||||
}
|
||||
}
|
||||
return cache[dc->context_ndx];
|
||||
return caches[dc->context_ndx].result;
|
||||
}
|
||||
|
||||
int config_check_cond(server *srv, connection *con, data_config *dc) {
|
||||
if (con->conf.log_condition_handling) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ===");
|
||||
}
|
||||
return config_check_cond_cached(srv, con, dc);
|
||||
return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
|
||||
}
|
||||
|
||||
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n)
|
||||
{
|
||||
cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
|
||||
if (n > cache->patterncount) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
n <<= 1; /* n *= 2 */
|
||||
buffer_append_string_len(buf,
|
||||
cache->comp_value->ptr + cache->matches[n],
|
||||
cache->matches[n + 1] - cache->matches[n]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
135
src/configfile.c
135
src/configfile.c
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "configparser.h"
|
||||
#include "configfile.h"
|
||||
#include "proc_open.h"
|
||||
|
||||
|
||||
static int config_insert(server *srv) {
|
||||
|
@ -225,11 +226,6 @@ static int config_insert(server *srv) {
|
|||
#define PATCH(x) con->conf.x = s->x
|
||||
int config_setup_connection(server *srv, connection *con) {
|
||||
specific_config *s = srv->config_storage[0];
|
||||
int i;
|
||||
|
||||
for (i = srv->config_context->used - 1; i >= 0; i --) {
|
||||
con->cond_results_cache[i] = COND_RESULT_UNSET;
|
||||
}
|
||||
|
||||
PATCH(allow_http11);
|
||||
PATCH(mimetypes);
|
||||
|
@ -351,12 +347,12 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
|
|||
return 0;
|
||||
}
|
||||
#undef PATCH
|
||||
|
||||
typedef struct {
|
||||
int foo;
|
||||
int bar;
|
||||
|
||||
buffer *file;
|
||||
stream s;
|
||||
const buffer *source;
|
||||
const char *input;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
|
@ -369,6 +365,7 @@ typedef struct {
|
|||
int in_cond;
|
||||
} tokenizer_t;
|
||||
|
||||
#if 0
|
||||
static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) {
|
||||
if (buffer_is_empty(basedir) &&
|
||||
(fn[0] == '/' || fn[0] == '\\') &&
|
||||
|
@ -404,7 +401,7 @@ static int tokenizer_close(server *srv, tokenizer_t *t) {
|
|||
buffer_free(t->file);
|
||||
return stream_close(&(t->s));
|
||||
}
|
||||
|
||||
#endif
|
||||
static int config_skip_newline(tokenizer_t *t) {
|
||||
int skipped = 1;
|
||||
assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n');
|
||||
|
@ -445,7 +442,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
tid = TK_ARRAY_ASSIGN;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"use => for assignments in arrays");
|
||||
return -1;
|
||||
|
@ -465,7 +462,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
tid = TK_MATCH;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"only =~ and == are allow in the condition");
|
||||
return -1;
|
||||
|
@ -481,7 +478,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
t->line_pos++;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"unexpected equal-sign: =");
|
||||
return -1;
|
||||
|
@ -504,7 +501,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
tid = TK_NOMATCH;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"only !~ and != are allow in the condition");
|
||||
return -1;
|
||||
|
@ -513,7 +510,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
t->in_cond = 0;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"unexpected exclamation-marks: !");
|
||||
return -1;
|
||||
|
@ -603,7 +600,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
/* ERROR */
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"missing closing quote");
|
||||
|
||||
|
@ -646,8 +643,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
t->offset += 2;
|
||||
buffer_copy_string(token, "+=");
|
||||
tid = TK_APPEND;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
t->offset++;
|
||||
tid = TK_PLUS;
|
||||
buffer_copy_string(token, "+");
|
||||
|
@ -708,7 +704,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
} else {
|
||||
/* ERROR */
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"invalid character in condition");
|
||||
return -1;
|
||||
|
@ -728,7 +724,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
} else {
|
||||
/* ERROR */
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"unexpected EOF");
|
||||
|
||||
|
@ -748,6 +744,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
|
||||
if (strcmp(token->ptr, "include") == 0) {
|
||||
tid = TK_INCLUDE;
|
||||
} else if (strcmp(token->ptr, "include_shell") == 0) {
|
||||
tid = TK_INCLUDE_SHELL;
|
||||
} else if (strcmp(token->ptr, "else") == 0) {
|
||||
tid = TK_ELSE;
|
||||
} else {
|
||||
|
@ -759,7 +757,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
} else {
|
||||
/* ERROR */
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"invalid character in variable name");
|
||||
return -1;
|
||||
|
@ -773,7 +771,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
*token_id = tid;
|
||||
#if 0
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
|
||||
"file:", t->file,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
token, token->used - 1, tid);
|
||||
#endif
|
||||
|
@ -787,21 +785,16 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_file(server *srv, config_t *context, const char *fn) {
|
||||
tokenizer_t t;
|
||||
static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
|
||||
void *pParser;
|
||||
int token_id;
|
||||
buffer *token, *lasttoken;
|
||||
int ret;
|
||||
|
||||
if (tokenizer_open(srv, &t, context->basedir, fn) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pParser = configparserAlloc( malloc );
|
||||
lasttoken = buffer_init();
|
||||
token = buffer_init();
|
||||
while((1 == (ret = config_tokenizer(srv, &t, &token_id, token))) && context->ok) {
|
||||
while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
|
||||
buffer_copy_string_buffer(lasttoken, token);
|
||||
configparser(pParser, token_id, token, context);
|
||||
|
||||
|
@ -821,20 +814,98 @@ int config_parse_file(server *srv, config_t *context, const char *fn) {
|
|||
if (ret == -1) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
"configfile parser failed:", lasttoken);
|
||||
}
|
||||
else if (context->ok == 0) {
|
||||
} else if (context->ok == 0) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
|
||||
"file:", t.file,
|
||||
"line:", t.line, "pos:", t.line_pos,
|
||||
"source:", t->source,
|
||||
"line:", t->line, "pos:", t->line_pos,
|
||||
"parser failed somehow near here:", lasttoken);
|
||||
ret = -1;
|
||||
}
|
||||
buffer_free(lasttoken);
|
||||
|
||||
tokenizer_close(srv, &t);
|
||||
return ret == -1 ? -1 : 0;
|
||||
}
|
||||
|
||||
static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) {
|
||||
|
||||
t->source = source;
|
||||
t->input = input;
|
||||
t->size = size;
|
||||
t->offset = 0;
|
||||
t->line = 1;
|
||||
t->line_pos = 1;
|
||||
|
||||
t->in_key = 1;
|
||||
t->in_brace = 0;
|
||||
t->in_cond = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_file(server *srv, config_t *context, const char *fn) {
|
||||
tokenizer_t t;
|
||||
stream s;
|
||||
int ret;
|
||||
buffer *filename;
|
||||
|
||||
if (buffer_is_empty(context->basedir) &&
|
||||
(fn[0] == '/' || fn[0] == '\\') &&
|
||||
(fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
|
||||
filename = buffer_init_string(fn);
|
||||
} else {
|
||||
filename = buffer_init_buffer(context->basedir);
|
||||
buffer_append_string(filename, fn);
|
||||
}
|
||||
|
||||
if (0 != stream_open(&s, filename)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbss",
|
||||
"opening configfile ", filename, "failed:", strerror(errno));
|
||||
ret = -1;
|
||||
} else {
|
||||
tokenizer_init(&t, filename, s.start, s.size);
|
||||
ret = config_parse(srv, context, &t);
|
||||
}
|
||||
|
||||
stream_close(&s);
|
||||
buffer_free(filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
|
||||
proc_handler_t proc;
|
||||
tokenizer_t t;
|
||||
int ret;
|
||||
buffer *source;
|
||||
buffer *out;
|
||||
char oldpwd[PATH_MAX];
|
||||
|
||||
if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s",
|
||||
"cannot get cwd", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
source = buffer_init_string(cmd);
|
||||
out = buffer_init();
|
||||
|
||||
if (!buffer_is_empty(context->basedir)) {
|
||||
chdir(context->basedir->ptr);
|
||||
}
|
||||
|
||||
if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sbss",
|
||||
"opening", source, "failed:", strerror(errno));
|
||||
ret = -1;
|
||||
} else {
|
||||
tokenizer_init(&t, source, out->ptr, out->used);
|
||||
ret = config_parse(srv, context, &t);
|
||||
}
|
||||
|
||||
buffer_free(source);
|
||||
buffer_free(out);
|
||||
chdir(oldpwd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void context_init(server *srv, config_t *context) {
|
||||
context->srv = srv;
|
||||
context->ok = 1;
|
||||
|
|
|
@ -18,5 +18,6 @@ void *configparserAlloc(void *(*mallocProc)(size_t));
|
|||
void configparserFree(void *p, void (*freeProc)(void*));
|
||||
void configparser(void *yyp, int yymajor, buffer *yyminor, config_t *ctx);
|
||||
int config_parse_file(server *srv, config_t *context, const char *fn);
|
||||
int config_parse_cmd(server *srv, config_t *context, const char *cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -131,6 +131,7 @@ metalines ::= .
|
|||
metaline ::= varline.
|
||||
metaline ::= condlines(A) EOL. { A = NULL; }
|
||||
metaline ::= include.
|
||||
metaline ::= include_shell.
|
||||
metaline ::= EOL.
|
||||
|
||||
%type value {data_unset *}
|
||||
|
@ -141,17 +142,17 @@ metaline ::= EOL.
|
|||
%type aelements {array *}
|
||||
%type array {array *}
|
||||
%type key {buffer *}
|
||||
%type stringop {buffer *}
|
||||
|
||||
%type cond {config_cond_t }
|
||||
|
||||
%destructor value { $$->free($$); }
|
||||
%destructor expression { $$->free($$); }
|
||||
%destructor aelement { $$->free($$); }
|
||||
%destructor condline { $$->free((data_unset *)$$); }
|
||||
%destructor condlines { $$->free((data_unset *)$$); }
|
||||
%destructor aelements { array_free($$); }
|
||||
%destructor array { array_free($$); }
|
||||
%destructor key { buffer_free($$); }
|
||||
%destructor stringop { buffer_free($$); }
|
||||
|
||||
%token_type {buffer *}
|
||||
%token_destructor { buffer_free($$); }
|
||||
|
@ -347,7 +348,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET STRING(C) RBRACKET cond(E) expression(
|
|||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
b = buffer_init();
|
||||
|
@ -470,18 +471,36 @@ cond(A) ::= NOMATCH. {
|
|||
A = CONFIG_COND_NOMATCH;
|
||||
}
|
||||
|
||||
include ::= INCLUDE expression(A). {
|
||||
stringop(A) ::= expression(B). {
|
||||
A = NULL;
|
||||
if (ctx->ok) {
|
||||
if (A->type != TYPE_STRING) {
|
||||
fprintf(stderr, "file must be string");
|
||||
if (B->type != TYPE_STRING) {
|
||||
fprintf(stderr, "operand must be string");
|
||||
ctx->ok = 0;
|
||||
} else {
|
||||
buffer *file = ((data_string*)A)->value;
|
||||
if (0 != config_parse_file(ctx->srv, ctx, file->ptr)) {
|
||||
ctx->ok = 0;
|
||||
}
|
||||
A = buffer_init_buffer(((data_string*)B)->value);
|
||||
}
|
||||
}
|
||||
A->free(A);
|
||||
A = NULL;
|
||||
B->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
include ::= INCLUDE stringop(A). {
|
||||
if (ctx->ok) {
|
||||
if (0 != config_parse_file(ctx->srv, ctx, A->ptr)) {
|
||||
ctx->ok = 0;
|
||||
}
|
||||
buffer_free(A);
|
||||
A = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
include_shell ::= INCLUDE_SHELL stringop(A). {
|
||||
if (ctx->ok) {
|
||||
if (0 != config_parse_cmd(ctx->srv, ctx, A->ptr)) {
|
||||
ctx->ok = 0;
|
||||
}
|
||||
buffer_free(A);
|
||||
A = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include "plugin.h"
|
||||
|
||||
#include "inet_ntop_cache.h"
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/err.h>
|
||||
|
@ -479,6 +481,7 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
|
|||
break;
|
||||
}
|
||||
|
||||
case 207:
|
||||
break;
|
||||
default:
|
||||
if (con->request.http_method == HTTP_METHOD_HEAD ||
|
||||
|
@ -603,7 +606,8 @@ connection *connection_init(server *srv) {
|
|||
|
||||
con->plugin_ctx = calloc(srv->plugins.used + 1, sizeof(void *));
|
||||
|
||||
con->cond_results_cache = calloc(srv->config_context->used, sizeof(cond_result_t));
|
||||
con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
|
||||
con->dst_addr_buf = buffer_init();
|
||||
config_setup_connection(srv, con);
|
||||
|
||||
return con;
|
||||
|
@ -653,7 +657,7 @@ void connections_free(server *srv) {
|
|||
CLEAN(error_handler);
|
||||
#undef CLEAN
|
||||
free(con->plugin_ctx);
|
||||
free(con->cond_results_cache);
|
||||
free(con->cond_cache);
|
||||
|
||||
free(con);
|
||||
}
|
||||
|
@ -753,6 +757,15 @@ int connection_reset(server *srv, connection *con) {
|
|||
con->plugin_ctx[i] = NULL;
|
||||
}
|
||||
|
||||
#if COND_RESULT_UNSET
|
||||
for (i = srv->config_context->used - 1; i >= 0; i --) {
|
||||
con->cond_cache[i].result = COND_RESULT_UNSET;
|
||||
con->cond_cache[i].patterncount = 0;
|
||||
}
|
||||
#else
|
||||
memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
|
||||
#endif
|
||||
|
||||
con->header_len = 0;
|
||||
con->in_error_handler = 0;
|
||||
|
||||
|
@ -1132,6 +1145,7 @@ connection *connection_accept(server *srv, server_socket *srv_socket) {
|
|||
|
||||
con->connection_start = srv->cur_ts;
|
||||
con->dst_addr = cnt_addr;
|
||||
buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
|
||||
con->srv_socket = srv_socket;
|
||||
|
||||
if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
|
||||
|
|
|
@ -73,10 +73,13 @@ static void data_config_print(const data_unset *d, int depth) {
|
|||
for (i = 0; i < ds->childs->used; i ++) {
|
||||
data_unset *du = ds->childs->data[i];
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
array_print_indent(depth + 1);
|
||||
du->print(du, depth + 1);
|
||||
fprintf(stderr, "\n");
|
||||
/* only the 1st block of chaining */
|
||||
if (NULL == ((data_config *)du)->prev) {
|
||||
fprintf(stderr, "\n");
|
||||
array_print_indent(depth + 1);
|
||||
du->print(du, depth + 1);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -292,6 +292,7 @@ int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, cons
|
|||
size_t i;
|
||||
const char *errptr;
|
||||
int erroff;
|
||||
pcre_keyvalue *kv;
|
||||
#endif
|
||||
|
||||
if (!key) return -1;
|
||||
|
@ -316,14 +317,20 @@ int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, cons
|
|||
}
|
||||
}
|
||||
|
||||
if (NULL == (kvb->kv[kvb->used]->key = pcre_compile(key,
|
||||
kv = kvb->kv[kvb->used];
|
||||
if (NULL == (kv->key = pcre_compile(key,
|
||||
0, &errptr, &erroff, NULL))) {
|
||||
|
||||
fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
|
||||
errptr != NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
kvb->kv[kvb->used]->value = strdup(value);
|
||||
kv->value = buffer_init_string(value);
|
||||
|
||||
kvb->used++;
|
||||
|
||||
|
@ -339,11 +346,14 @@ int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, cons
|
|||
void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) {
|
||||
#ifdef HAVE_PCRE_H
|
||||
size_t i;
|
||||
pcre_keyvalue *kv;
|
||||
|
||||
for (i = 0; i < kvb->size; i++) {
|
||||
if (kvb->kv[i]->key) pcre_free(kvb->kv[i]->key);
|
||||
if (kvb->kv[i]->value) free(kvb->kv[i]->value);
|
||||
free(kvb->kv[i]);
|
||||
kv = kvb->kv[i];
|
||||
if (kv->key) pcre_free(kv->key);
|
||||
if (kv->key_extra) pcre_free(kv->key_extra);
|
||||
if (kv->value) buffer_free(kv->value);
|
||||
free(kv);
|
||||
}
|
||||
|
||||
if (kvb->kv) free(kvb->kv);
|
||||
|
|
|
@ -25,9 +25,10 @@ typedef struct {
|
|||
typedef struct {
|
||||
#ifdef HAVE_PCRE_H
|
||||
pcre *key;
|
||||
pcre_extra *key_extra;
|
||||
#endif
|
||||
|
||||
char *value;
|
||||
buffer *value;
|
||||
} pcre_keyvalue;
|
||||
|
||||
typedef enum { HTTP_AUTH_BASIC, HTTP_AUTH_DIGEST } httpauth_type;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "log.h"
|
||||
|
@ -86,6 +87,31 @@ SETDEFAULTS_FUNC(mod_alias_set_defaults) {
|
|||
if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
if (s->alias->used >= 2) {
|
||||
const array *a = s->alias;
|
||||
size_t j, k;
|
||||
|
||||
for (j = 0; j < a->used; j ++) {
|
||||
const buffer *prefix = a->data[a->sorted[j]]->key;
|
||||
for (k = j + 1; k < a->used; k ++) {
|
||||
const buffer *key = a->data[a->sorted[k]]->key;
|
||||
|
||||
if (key->used < prefix->used) {
|
||||
break;
|
||||
}
|
||||
if (memcmp(key->ptr, prefix->ptr, prefix->used - 1) != 0) {
|
||||
break;
|
||||
}
|
||||
/* ok, they have same prefix. check position */
|
||||
if (a->sorted[j] < a->sorted[k]) {
|
||||
fprintf(stderr, "url.alias: `%s' will never match as `%s' matched first\n",
|
||||
key->ptr,
|
||||
prefix->ptr);
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HANDLER_GO_ON;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
typedef struct {
|
||||
pcre_keyvalue_buffer *redirect;
|
||||
data_config *context; /* to which apply me */
|
||||
} plugin_config;
|
||||
|
||||
typedef struct {
|
||||
|
@ -165,6 +166,7 @@ static int mod_redirect_patch_connection(server *srv, connection *con, plugin_da
|
|||
|
||||
if (0 == strcmp(du->key->ptr, "url.redirect")) {
|
||||
p->conf.redirect = s->redirect;
|
||||
p->conf.context = dc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,19 +192,22 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_
|
|||
|
||||
for (i = 0; i < p->conf.redirect->used; i++) {
|
||||
pcre *match;
|
||||
pcre_extra *extra;
|
||||
const char *pattern;
|
||||
size_t pattern_len;
|
||||
int n;
|
||||
pcre_keyvalue *kv = p->conf.redirect->kv[i];
|
||||
# define N 10
|
||||
int ovec[N * 3];
|
||||
|
||||
match = p->conf.redirect->kv[i]->key;
|
||||
pattern = p->conf.redirect->kv[i]->value;
|
||||
pattern_len = strlen(pattern);
|
||||
match = kv->key;
|
||||
extra = kv->key_extra;
|
||||
pattern = kv->value->ptr;
|
||||
pattern_len = kv->value->used - 1;
|
||||
|
||||
if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
|
||||
if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
|
||||
if (n != PCRE_ERROR_NOMATCH) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sd"
|
||||
log_error_write(srv, __FILE__, __LINE__, "sd",
|
||||
"execution error while matching: ", n);
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
|
@ -210,6 +215,7 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_
|
|||
const char **list;
|
||||
size_t start, end;
|
||||
size_t k;
|
||||
|
||||
/* it matched */
|
||||
pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
|
||||
|
||||
|
@ -219,7 +225,7 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_
|
|||
|
||||
start = 0; end = pattern_len;
|
||||
for (k = 0; k < pattern_len; k++) {
|
||||
if (pattern[k] == '$' &&
|
||||
if ((pattern[k] == '$' || pattern[k] == '%') &&
|
||||
isdigit((unsigned char)pattern[k + 1])) {
|
||||
/* got one */
|
||||
|
||||
|
@ -229,9 +235,13 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_
|
|||
|
||||
buffer_append_string_len(p->location, pattern + start, end - start);
|
||||
|
||||
/* n is always > 0 */
|
||||
if (num < (size_t)n) {
|
||||
buffer_append_string(p->location, list[num]);
|
||||
if (pattern[k] == '$') {
|
||||
/* n is always > 0 */
|
||||
if (num < (size_t)n) {
|
||||
buffer_append_string(p->location, list[num]);
|
||||
}
|
||||
} else {
|
||||
config_append_cond_match_buffer(con, p->conf.context, p->location, num);
|
||||
}
|
||||
|
||||
k++;
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
rewrite_rule_buffer *rewrite;
|
||||
data_config *context; /* to which apply me */
|
||||
} plugin_config;
|
||||
|
||||
typedef struct {
|
||||
|
@ -377,7 +378,7 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) {
|
|||
|
||||
start = 0; end = pattern_len;
|
||||
for (k = 0; k < pattern_len; k++) {
|
||||
if (pattern[k] == '$' &&
|
||||
if ((pattern[k] == '$' || pattern[k] == '%') &&
|
||||
isdigit((unsigned char)pattern[k + 1])) {
|
||||
/* got one */
|
||||
|
||||
|
@ -387,9 +388,13 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) {
|
|||
|
||||
buffer_append_string_len(con->request.uri, pattern + start, end - start);
|
||||
|
||||
/* n is always larger than 0 */
|
||||
if (num < (size_t)n) {
|
||||
buffer_append_string(con->request.uri, list[num]);
|
||||
if (pattern[k] == '$') {
|
||||
/* n is always > 0 */
|
||||
if (num < (size_t)n) {
|
||||
buffer_append_string(con->request.uri, list[num]);
|
||||
}
|
||||
} else {
|
||||
config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
|
||||
}
|
||||
|
||||
k++;
|
||||
|
|
|
@ -62,7 +62,7 @@ static void plugin_free(plugin *p) {
|
|||
int use_dlclose = 1;
|
||||
if (p->name) buffer_free(p->name);
|
||||
#ifdef HAVE_VALGRIND_VALGRIND_H
|
||||
if (RUNNING_ON_VALGRIND) use_dlclose = 0;
|
||||
/*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
|
||||
#endif
|
||||
|
||||
if (use_dlclose && p->lib) {
|
||||
|
|
|
@ -89,5 +89,6 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t
|
|||
int config_setup_connection(server *srv, connection *con);
|
||||
int config_patch_connection(server *srv, connection *con, comp_key_t comp);
|
||||
int config_check_cond(server *srv, connection *con, data_config *dc);
|
||||
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,386 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include "proc_open.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
/* {{{ win32 stuff */
|
||||
# define SHELLENV "ComSpec"
|
||||
# define SECURITY_DC , SECURITY_ATTRIBUTES *security
|
||||
# define SECURITY_CC , security
|
||||
# define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
|
||||
static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
|
||||
{
|
||||
HANDLE copy, self = GetCurrentProcess();
|
||||
|
||||
if (!DuplicateHandle(self, src, self, ©, 0, inherit, DUPLICATE_SAME_ACCESS |
|
||||
(closeorig ? DUPLICATE_CLOSE_SOURCE : 0)))
|
||||
return NULL;
|
||||
return copy;
|
||||
}
|
||||
# define close_descriptor(fd) CloseHandle(fd)
|
||||
static void pipe_close_parent(pipe_t *p) {
|
||||
/* don't let the child inherit the parent side of the pipe */
|
||||
p->parent = dup_handle(p->parent, FALSE, TRUE);
|
||||
}
|
||||
static void pipe_close_child(pipe_t *p) {
|
||||
close_descriptor(p->child);
|
||||
p->fd = _open_osfhandle((long)p->parent,
|
||||
(p->fd == 0 ? O_RDONLY : O_WRONLY)|O_BINARY);
|
||||
}
|
||||
/* }}} */
|
||||
#else /* WIN32 */
|
||||
/* {{{ unix way */
|
||||
# define SHELLENV "SHELL"
|
||||
# define SECURITY_DC
|
||||
# define SECURITY_CC
|
||||
# define close_descriptor(fd) close(fd)
|
||||
static void pipe_close_parent(pipe_t *p) {
|
||||
/* don't close stdin */
|
||||
close_descriptor(p->parent);
|
||||
if (dup2(p->child, p->fd) != p->fd) {
|
||||
perror("pipe_child dup2");
|
||||
} else {
|
||||
close_descriptor(p->child);
|
||||
p->child = p->fd;
|
||||
}
|
||||
}
|
||||
static void pipe_close_child(pipe_t *p) {
|
||||
close_descriptor(p->child);
|
||||
p->fd = p->parent;
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* {{{ pipe_close */
|
||||
static void pipe_close(pipe_t *p) {
|
||||
close_descriptor(p->parent);
|
||||
close_descriptor(p->child);
|
||||
#ifdef WIN32
|
||||
close(p->fd);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
/* {{{ pipe_open */
|
||||
static int pipe_open(pipe_t *p, int fd SECURITY_DC) {
|
||||
descriptor_t newpipe[2];
|
||||
|
||||
if (0 != pipe(newpipe)) {
|
||||
fprintf(stderr, "can't open pipe");
|
||||
return -1;
|
||||
}
|
||||