summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in2
-rw-r--r--NEWS49
-rw-r--r--SConstruct277
-rwxr-xr-xautogen.sh27
-rwxr-xr-xconfigure108
-rw-r--r--configure.in33
-rw-r--r--cygwin/lighttpd.README10
-rw-r--r--debian/changelog6
-rw-r--r--doc/configuration.txt6
-rw-r--r--doc/lighttpd.conf1
-rw-r--r--lighttpd.spec33
-rw-r--r--lighttpd.spec.in31
-rw-r--r--openwrt/control4
-rw-r--r--openwrt/lighttpd.mk2
-rw-r--r--src/Makefile.am14
-rw-r--r--src/Makefile.in14
-rw-r--r--src/SConscript195
-rw-r--r--src/array.h8
-rw-r--r--src/base.h1
-rw-r--r--src/configfile-glue.c20
-rw-r--r--src/configparser.c191
-rw-r--r--src/configparser.y50
-rw-r--r--src/connections.c29
-rw-r--r--src/etag.c9
-rw-r--r--src/fdevent_solaris_devpoll.c2
-rw-r--r--src/http_auth.c5
-rw-r--r--src/mod_auth.c4
-rw-r--r--src/mod_cgi.c9
-rw-r--r--src/mod_compress.c118
-rw-r--r--src/mod_extforward.c100
-rw-r--r--src/mod_fastcgi.c76
-rw-r--r--src/mod_proxy.c16
-rw-r--r--src/mod_scgi.c8
-rw-r--r--src/mod_secure_download.c3
-rw-r--r--src/mod_ssi.c108
-rw-r--r--src/mod_staticfile.c24
-rw-r--r--src/mod_status.c18
-rw-r--r--src/mod_userdir.c16
-rw-r--r--src/network_linux_sendfile.c5
-rw-r--r--src/network_openssl.c27
-rw-r--r--src/response.c46
-rw-r--r--src/server.c43
-rw-r--r--src/spawn-fcgi.c258
-rw-r--r--src/stream.c3
-rwxr-xr-xtests/LightyTest.pm4
-rw-r--r--tests/Makefile.am10
-rw-r--r--tests/Makefile.in9
-rw-r--r--tests/SConscript45
-rwxr-xr-xtests/cachable.t8
-rw-r--r--tests/core-404-handler.t8
-rwxr-xr-xtests/core-condition.t8
-rwxr-xr-xtests/core-keepalive.t9
-rwxr-xr-xtests/core-request.t8
-rwxr-xr-xtests/core-response.t9
-rwxr-xr-xtests/core-var-include.t8
-rwxr-xr-xtests/core.t9
-rw-r--r--tests/env-variables.conf1
-rw-r--r--tests/env-variables.t21
-rw-r--r--tests/fcgi-auth.c2
-rw-r--r--tests/fcgi-responder.c2
-rwxr-xr-xtests/lowercase.t8
-rwxr-xr-xtests/mod-access.t8
-rwxr-xr-xtests/mod-auth.t20
-rwxr-xr-xtests/mod-cgi.t8
-rwxr-xr-xtests/mod-compress.t8
-rwxr-xr-xtests/mod-fastcgi.t21
-rwxr-xr-xtests/mod-proxy.t53
-rwxr-xr-xtests/mod-redirect.t8
-rwxr-xr-xtests/mod-rewrite.t8
-rwxr-xr-xtests/mod-secdownload.t79
-rwxr-xr-xtests/mod-setenv.t9
-rwxr-xr-xtests/mod-ssi.t8
-rwxr-xr-xtests/mod-userdir.t8
-rw-r--r--tests/proxy.conf156
-rwxr-xr-xtests/request.t8
-rwxr-xr-xtests/run-tests.pl2
-rw-r--r--tests/symlink.t115
78 files changed, 2049 insertions, 650 deletions
diff --git a/Makefile.am b/Makefile.am
index 3ed6331..252cbfe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,3 @@
SUBDIRS=src doc tests cygwin openwrt
-EXTRA_DIST=lighttpd.spec
+EXTRA_DIST=lighttpd.spec autogen.sh SConstruct
diff --git a/Makefile.in b/Makefile.in
index b50af37..a9b2eea 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -211,7 +211,7 @@ target_vendor = @target_vendor@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = src doc tests cygwin openwrt
-EXTRA_DIST = lighttpd.spec
+EXTRA_DIST = lighttpd.spec autogen.sh SConstruct
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
diff --git a/NEWS b/NEWS
index 227152d..3312481 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,55 @@
NEWS
====
+- 1.4.19 -
+
+ * added support for If-Range: <date> (#1346)
+ * added support for matching $HTTP["scheme"] in configs
+ * fixed initgroups() called after chroot (#1384)
+ * fixed case-sensitive check for Auth-Method (#1456)
+ * execute fcgi app without /bin/sh if used as argument to spawn-fcgi (#1428)
+ * fixed a bug that made /-prefixed extensions being handled also when
+ matching the end of the uri in fcgi,scgi and proxy modules (#1489)
+ * print error if X-LIGHTTPD-send-file cannot be done; reset header
+ Content-Length for send-file. Patches by Stefan Buehler
+ * prevent crash in certain php-fcgi configurations (#841)
+ * add IdleServers and Scoreboard directives in ?auto mode for mod_status (#1507)
+ * open log immediately after daemonizing, fixes SIGPIPEs on startup (#165)
+ * HTTPS env var should be "on" when using mod_extforward and the X-Forwarded-Proto header is set. (#1499)
+ * generate ETag and Last-Modified headers for mod_ssi based on newest modified include (#1491)
+ * support letterhomes in mod_userdir (#1473)
+ * support chained proxies in mod_extforward (#1528)
+ * fixed bogus "cgi died ?" if we kill the CGI process on shutdown
+ * fixed ECONNRESET handling in network-openssl
+ * fixed handling of EAGAIN in network-linux-sendfile (#657)
+ * reset conditional cache (#1164)
+ * create directories in mod_compress (was broken with alias/userdir) (#1027)
+ * fixed out of range access in fd array (#1562, #372) (CVE-2008-0983)
+ * mod_compress should check if the request is already handled, e.g. by fastcgi (#1565)
+ * remove broken workaround for buggy Opera version with ssl/chunked encoding (#285)
+ * generate etag/last-modified header for on-the-fly-compressed files (#1171)
+ * req-method OPTIONS: do not insert default response if request was denied, do not deny OPTIONS by default (#1324)
+ * fixed memory leak on windows (#1347)
+ * fixed building outside of the src dir (#1349)
+ * fixed including of stdint.h/inttypes.h in etag.c (#1413)
+ * do not add Accept-Ranges header if range-request is disabled (#1449)
+ * log the ip of failed auth tries in error.log (enhancement #1544)
+ * fixed RoundRobin in mod_proxy (#516)
+ * check for symlinks after successful pathinfo matching (#1574)
+ * fixed mod-proxy.t to run with a builddir outside of the src dir
+ * do not suppress content on "307 Temporary Redirect" (#1412)
+ * fixed Content-Length header if response body gets removed in connections.c (#1412, part 2)
+ * do not generate a "Content-Length: 0" header for HEAD requests, added test too
+ * remove compress cache file if compression or write failed (#1150)
+ * fixed body handling of status 300 requests
+ * spawn-fcgi: only try to connect to unix socket (not tcp) before spawning (#1575)
+ * fix sending source of cgi script instead of 500 error if fork fails (CVE-2008-1111)
+ * fix min-procs handling in mod_scgi.c, just set to max-procs (patch from #623)
+ * fix sending "408 - Timeout" instead of "410 - Gone" for timedout urls in mod_secdownload (#1440)
+ * workaround #1587: require userdir.path to be set to enable mod_userdir (empty string allowed) (CVE-2008-1270)
+ * make configure checks for --with-pcre, --with-zlib and --with-bzip2 failing if the headers aren't found
+ * fixed handling of waitpid() == EINTR mod_ssi on solaris
+
- 1.4.18 - 2007-09-09
* fixed compile error on IRIX 6.5.x on prctl() (#1333)
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 0000000..04eb15a
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,277 @@
+import os
+import sys
+import re
+import string
+from stat import *
+
+package = 'lighttpd'
+version = '1.4.19'
+
+def checkCHeaders(autoconf, hdrs):
+ p = re.compile('[^A-Z0-9]')
+ for hdr in hdrs:
+ if not hdr:
+ continue
+ _hdr = Split(hdr)
+ if autoconf.CheckCHeader(_hdr):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', _hdr[-1].upper()) ])
+
+def checkFuncs(autoconf, funcs):
+ p = re.compile('[^A-Z0-9]')
+ for func in funcs:
+ if autoconf.CheckFunc(func):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', func.upper()) ])
+
+def checkTypes(autoconf, types):
+ p = re.compile('[^A-Z0-9]')
+ for type in types:
+ if autoconf.CheckType(type, '#include <sys/types.h>'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_' + p.sub('_', type.upper()) ])
+
+def checkProgram(env, withname, progname):
+ withname = 'with_' + withname
+ binpath = None
+
+ if env[withname] != 1:
+ binpath = env[withname]
+ else:
+ prog = env.Detect(progname)
+ if prog:
+ binpath = env.WhereIs(prog)
+
+ if binpath:
+ mode = os.stat(binpath)[ST_MODE]
+ if S_ISDIR(mode):
+ print >> sys.stderr, "* error: path `%s' is a directory" % (binpath)
+ env.Exit(-1)
+ if not S_ISREG(mode):
+ print >> sys.stderr, "* error: path `%s' is not a file or not exists" % (binpath)
+ env.Exit(-1)
+
+ if not binpath:
+ print >> sys.stderr, "* error: can't find program `%s'" % (progname)
+ env.Exit(-1)
+
+ return binpath
+
+def checkStructMember(context):
+ struct_member = """
+#include <time.h>
+int main() {
+ struct tm a;
+ a.tm_gmtoff = 0;
+ return 0;
+}
+"""
+ context.Message('Checking for tm_gmtoff in struct tm...')
+ result = context.TryLink(struct_member, '.c')
+ context.Result(result)
+
+ return result
+
+
+BuildDir('build', 'src', duplicate = 0)
+
+opts = Options('config.py')
+opts.AddOptions(
+ ('prefix', 'prefix', '/usr/local'),
+ ('bindir', 'binary directory', '${prefix}/bin'),
+ ('sbindir', 'binary directory', '${prefix}/sbin'),
+ ('libdir', 'library directory', '${prefix}/lib'),
+ PackageOption('with_mysql', 'enable mysql support', 'no'),
+ PackageOption('with_xml', 'enable xml support', 'no'),
+ PackageOption('with_pcre', 'enable pcre support', 'yes'),
+ PathOption('CC', 'path to the c-compiler', None),
+ BoolOption('build_dynamic', 'enable dynamic build', 'yes'),
+ BoolOption('build_static', 'enable static build', 'no'),
+ BoolOption('build_fullstatic', 'enable fullstatic build', 'no'),
+ BoolOption('with_sqlite3', 'enable sqlite3 support', 'no'),
+ BoolOption('with_memcache', 'enable memcache support', 'no'),
+ BoolOption('with_fam', 'enable FAM/gamin support', 'no'),
+ BoolOption('with_openssl', 'enable memcache support', 'no'),
+ BoolOption('with_gzip', 'enable gzip compression', 'no'),
+ BoolOption('with_bzip2', 'enable bzip2 compression', 'no'),
+ BoolOption('with_lua', 'enable lua support for mod_cml', 'no'),
+ BoolOption('with_ldap', 'enable ldap auth support', 'no'))
+
+env = Environment(
+ env = os.environ,
+ options = opts,
+ CPPPATH = Split('#build')
+)
+
+env.Help(opts.GenerateHelpText(env))
+
+if env.subst('${CC}') is not '':
+ env['CC'] = env.subst('${CC}')
+
+env['package'] = package
+env['version'] = version
+if env['CC'] == 'gcc':
+ ## we need x-open 6 and bsd 4.3 features
+ env.Append(CCFLAGS = Split('-Wall -O2 -g -W -pedantic -Wunused -Wshadow -std=gnu99'))
+
+# cache configure checks
+if 1:
+ autoconf = Configure(env, custom_tests = {'CheckStructMember': checkStructMember })
+ autoconf.headerfile = "foo.h"
+ checkCHeaders(autoconf, string.split("""
+ arpa/inet.h
+ fcntl.h
+ netinet/in.h
+ sys/types.h netinet/in.h
+ stdlib.h
+ string.h
+ sys/socket.h
+ sys/types.h sys/socket.h
+ sys/time.h
+ unistd.h
+ sys/sendfile.h
+ sys/uio.h
+ sys/types.h sys/uio.h
+ getopt.h
+ sys/epoll.h
+ sys/select.h
+ sys/types.h sys/select.h
+ poll.h
+ sys/poll.h
+ sys/devpoll.h
+ sys/filio.h
+ sys/mman.h
+ sys/types.h sys/mman.h
+ sys/event.h
+ sys/types.h sys/event.h
+ sys/port.h
+ winsock2.h
+ pwd.h
+ sys/syslimits.h
+ sys/resource.h
+ sys/time.h sys/types.h sys/resource.h
+ sys/un.h
+ sys/types.h sys/un.h
+ syslog.h
+ stdint.h
+ inttypes.h
+ sys/prctl.h
+ sys/wait.h""", "\n"))
+
+ checkFuncs(autoconf, Split('fork stat lstat strftime dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
+ strdup strerror strstr strtol sendfile getopt socket \
+ gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
+ getuid select signal pathconf madvise prctl\
+ writev sigaction sendfile64 send_file kqueue port_create localtime_r posix_fadvise'))
+
+ checkTypes(autoconf, Split('pid_t size_t off_t'))
+
+ autoconf.env.Append( LIBSQLITE3 = '', LIBXML2 = '', LIBMYSQL = '', LIBZ = '',
+ LIBBZ2 = '', LIBCRYPT = '', LIBMEMCACHE = '', LIBFCGI = '', LIBPCRE = '',
+ LIBLDAP = '', LIBLBER = '', LIBLUA = '', LIBLUALIB = '', LIBDL = '')
+
+ if env['with_fam']:
+ if autoconf.CheckLibWithHeader('fam', 'fam.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_FAM_H', '-DHAVE_LIBFAM' ], LIBS = 'fam')
+ checkFuncs(autoconf, ['FAMNoExists']);
+
+
+ if autoconf.CheckLibWithHeader('crypt', 'crypt.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_CRYPT_H', '-DHAVE_LIBCRYPT' ], LIBCRYPT = 'crypt')
+
+ if autoconf.CheckLibWithHeader('uuid', 'uuid/uuid.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_UUID_UUID_H', '-DHAVE_LIBUUID' ], LIBUUID = 'uuid')
+
+ if env['with_openssl']:
+ if autoconf.CheckLibWithHeader('ssl', 'openssl/ssl.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_OPENSSL_SSL_H', '-DHAVE_LIBSSL'] , LIBS = [ 'ssl', 'crypto' ])
+
+ if env['with_gzip']:
+ if autoconf.CheckLibWithHeader('z', 'zlib.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_ZLIB_H', '-DHAVE_LIBZ' ], LIBZ = 'z')
+
+ if env['with_ldap']:
+ if autoconf.CheckLibWithHeader('ldap', 'ldap.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_LDAP_H', '-DHAVE_LIBLDAP' ], LIBLDAP = 'ldap')
+ if autoconf.CheckLibWithHeader('lber', 'lber.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_LBER_H', '-DHAVE_LIBLBER' ], LIBLBER = 'lber')
+
+ if env['with_bzip2']:
+ if autoconf.CheckLibWithHeader('bz2', 'bzlib.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_BZLIB_H', '-DHAVE_LIBBZ2' ], LIBBZ2 = 'bz2')
+
+ if env['with_memcache']:
+ if autoconf.CheckLibWithHeader('memcache', 'memcache.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_MEMCACHE_H', '-DHAVE_LIBMEMCACHE' ], LIBMEMCACHE = 'memcache')
+
+ if env['with_sqlite3']:
+ if autoconf.CheckLibWithHeader('sqlite3', 'sqlite3.h', 'C'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_SQLITE3_H', '-DHAVE_LIBSQLITE3' ], LIBSQLITE3 = 'sqlite3')
+
+ ol = env['LIBS']
+ if autoconf.CheckLibWithHeader('fcgi', 'fastcgi.h', 'C'):
+ autoconf.env.Append(LIBFCGI = 'fcgi')
+ env['LIBS'] = ol
+
+ ol = env['LIBS']
+ if autoconf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'):
+ autoconf.env.Append(LIBDL = 'dl')
+ env['LIBS'] = ol
+
+ if autoconf.CheckType('socklen_t', '#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/types.h>'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_SOCKLEN_T' ])
+
+ if autoconf.CheckType('struct sockaddr_storage', '#include <sys/socket.h>\n'):
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_STRUCT_SOCKADDR_STORAGE' ])
+
+ if autoconf.CheckStructMember():
+ autoconf.env.Append(CPPFLAGS = [ '-DHAVE_STRUCT_TM_GMTOFF' ])
+
+ env = autoconf.Finish()
+
+ if env['with_lua']:
+ oldlibs = env['LIBS']
+ env.ParseConfig("pkg-config 'lua >= 5.0' --cflags --libs")
+ lualibs = env['LIBS'][len(oldlibs):]
+ env.Append(LIBLUA = lualibs)
+ env.Append(CPPFLAGS = [ '-DHAVE_LUA_H' ])
+ env['LIBS'] = oldlibs
+
+
+if env['with_pcre']:
+ pcre_config = checkProgram(env, 'pcre', 'pcre-config')
+ env.ParseConfig(pcre_config + ' --cflags --libs')
+ env.Append(CPPFLAGS = [ '-DHAVE_PCRE_H', '-DHAVE_LIBPCRE' ], LIBPCRE = 'pcre')
+
+if env['with_xml']:
+ xml2_config = checkProgram(env, 'xml', 'xml2-config')
+ oldlib = env['LIBS']
+ env['LIBS'] = []
+ env.ParseConfig(xml2_config + ' --cflags --libs')
+ env.Append(CPPFLAGS = [ '-DHAVE_LIBXML_H', '-DHAVE_LIBXML2' ], LIBXML2 = env['LIBS'])
+ env['LIBS'] = oldlib
+
+if env['with_mysql']:
+ mysql_config = checkProgram(env, 'mysql', 'mysql_config')
+ oldlib = env['LIBS']
+ env['LIBS'] = []
+ env.ParseConfig(mysql_config + ' --cflags --libs')
+ env.Append(CPPFLAGS = [ '-DHAVE_MYSQL_H', '-DHAVE_LIBMYSQL' ], LIBMYSQL = 'mysqlclient')
+ env['LIBS'] = oldlib
+
+if re.compile("cygwin|mingw").search(env['PLATFORM']):
+ env.Append(COMMON_LIB = 'bin')
+elif re.compile("darwin|aix").search(env['PLATFORM']):
+ env.Append(COMMON_LIB = 'lib')
+else:
+ env.Append(COMMON_LIB = False)
+
+versions = string.split(version, '.')
+version_id = int(versions[0]) << 16 | int(versions[1]) << 8 | int(versions[2])
+env.Append(CPPFLAGS = [
+ '-DLIGHTTPD_VERSION_ID=' + str(version_id),
+ '-DPACKAGE_NAME=\\"' + package + '\\"',
+ '-DPACKAGE_VERSION=\\"' + version + '\\"',
+ '-DLIBRARY_DIR="\\"${libdir}\\""',
+ '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE', '-D_LARGE_FILES'
+ ] )
+
+SConscript( 'src/SConscript', 'env', build_dir = 'build', duplicate = 0)
+SConscript( 'tests/SConscript', 'env' )
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..ae2d948
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
+LIBTOOLIZE_FLAGS="--copy --force"
+ACLOCAL=${ACLOCAL:-aclocal}
+AUTOHEADER=${AUTOHEADER:-autoheader}
+AUTOMAKE=${AUTOMAKE:-automake}
+AUTOMAKE_FLAGS="--add-missing --copy"
+AUTOCONF=${AUTOCONF:-autoconf}
+
+ARGV0=$0
+
+set -e
+
+
+run() {
+ echo "$ARGV0: running \`$@'"
+ $@
+}
+
+run $LIBTOOLIZE $LIBTOOLIZE_FLAGS
+run $ACLOCAL $ACLOCAL_FLAGS
+run $AUTOHEADER
+run $AUTOMAKE $AUTOMAKE_FLAGS
+run $AUTOCONF
+echo "Now type './configure ...' and 'make' to compile."
diff --git a/configure b/configure
index 96401f2..5078b87 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for lighttpd 1.4.18.
+# Generated by GNU Autoconf 2.61 for lighttpd 1.4.19.
#
# Report bugs to <jan@kneschke.de>.
#
@@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='lighttpd'
PACKAGE_TARNAME='lighttpd'
-PACKAGE_VERSION='1.4.18'
-PACKAGE_STRING='lighttpd 1.4.18'
+PACKAGE_VERSION='1.4.19'
+PACKAGE_STRING='lighttpd 1.4.19'
PACKAGE_BUGREPORT='jan@kneschke.de'
ac_unique_file="src/server.c"
@@ -1440,7 +1440,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures lighttpd 1.4.18 to adapt to many kinds of systems.
+\`configure' configures lighttpd 1.4.19 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1511,7 +1511,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of lighttpd 1.4.18:";;
+ short | recursive ) echo "Configuration of lighttpd 1.4.19:";;
esac
cat <<\_ACEOF
@@ -1548,6 +1548,7 @@ Optional Packages:
--with-openssl-libs=DIR OpenSSL libraries
--with-kerberos5 use Kerberos5 support with OpenSSL
--with-pcre Enable pcre support (default yes)
+ --with-zlib Enable zlib support for mod_compress
--with-bzip2 Enable bzip2 support for mod_compress
--with-fam fam/gamin for reducing number of stat() calls
--with-webdav-props properties in mod_webdav
@@ -1645,7 +1646,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-lighttpd configure 1.4.18
+lighttpd configure 1.4.19
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1659,7 +1660,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by lighttpd $as_me 1.4.18, which was
+It was created by lighttpd $as_me 1.4.19, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2478,7 +2479,7 @@ fi
# Define the identity of the package.
PACKAGE='lighttpd'
- VERSION='1.4.18'
+ VERSION='1.4.19'
cat >>confdefs.h <<_ACEOF
@@ -5668,7 +5669,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5671 "configure"' > conftest.$ac_ext
+ echo '#line 5672 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7925,11 +7926,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7928: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7929: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7932: \$? = $ac_status" >&5
+ echo "$as_me:7933: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8193,11 +8194,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8196: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8197: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8200: \$? = $ac_status" >&5
+ echo "$as_me:8201: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8297,11 +8298,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8300: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8301: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8304: \$? = $ac_status" >&5
+ echo "$as_me:8305: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10605,7 +10606,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10608 "configure"
+#line 10609 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10705,7 +10706,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10708 "configure"
+#line 10709 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13041,11 +13042,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13044: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13045: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:13048: \$? = $ac_status" >&5
+ echo "$as_me:13049: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -13145,11 +13146,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13148: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13149: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:13152: \$? = $ac_status" >&5
+ echo "$as_me:13153: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -14715,11 +14716,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14718: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14719: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14722: \$? = $ac_status" >&5
+ echo "$as_me:14723: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14819,11 +14820,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14822: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14823: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14826: \$? = $ac_status" >&5
+ echo "$as_me:14827: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -17017,11 +17018,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17020: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17021: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17024: \$? = $ac_status" >&5
+ echo "$as_me:17025: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -17285,11 +17286,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17288: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17289: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17292: \$? = $ac_status" >&5
+ echo "$as_me:17293: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -17389,11 +17390,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17392: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17393: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:17396: \$? = $ac_status" >&5
+ echo "$as_me:17397: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -24239,12 +24240,30 @@ done
fi
LIBS="$OLDLIBS"
+ else
+ { { echo "$as_me:$LINENO: error: pcre-config not found, install the pcre-devel package and build with --without-pcre" >&5
+echo "$as_me: error: pcre-config not found, install the pcre-devel package and build with --without-pcre" >&2;}
+ { (exit 1); exit 1; }; }
fi
fi
-{ echo "$as_me:$LINENO: checking for deflate in -lz" >&5
+{ echo "$as_me:$LINENO: checking for zlib support" >&5
+echo $ECHO_N "checking for zlib support... $ECHO_C" >&6; }
+
+# Check whether --with-zlib was given.
+if test "${with_zlib+set}" = set; then
+ withval=$with_zlib; WITH_ZLIB=$withval
+else
+ WITH_ZLIB=yes
+fi
+
+{ echo "$as_me:$LINENO: result: $WITH_ZLIB" >&5
+echo "${ECHO_T}$WITH_ZLIB" >&6; }
+
+if test "$WITH_ZLIB" != "no"; then
+ { echo "$as_me:$LINENO: checking for deflate in -lz" >&5
echo $ECHO_N "checking for deflate in -lz... $ECHO_C" >&6; }
if test "${ac_cv_lib_z_deflate+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -24448,13 +24467,13 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
- Z_LIB=-lz
+ Z_LIB=-lz
cat >>confdefs.h <<\_ACEOF
#define HAVE_LIBZ 1
_ACEOF
- cat >>confdefs.h <<\_ACEOF
+ cat >>confdefs.h <<\_ACEOF
#define HAVE_ZLIB_H 1
_ACEOF
@@ -24466,6 +24485,12 @@ done
fi
+ if test x$Z_LIB = x; then
+ { { echo "$as_me:$LINENO: error: zlib-headers and/or libs where not found, install them or build with --without-zlib" >&5
+echo "$as_me: error: zlib-headers and/or libs where not found, install them or build with --without-zlib" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
{ echo "$as_me:$LINENO: checking for bzip2 support" >&5
@@ -24704,6 +24729,11 @@ done
fi
+ if test x$BZ_LIB = x; then
+ { { echo "$as_me:$LINENO: error: bzip2-headers and/or libs where not found, install them or build with --without-bzip2" >&5
+echo "$as_me: error: bzip2-headers and/or libs where not found, install them or build with --without-bzip2" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
fi
@@ -25329,6 +25359,12 @@ fi
done
LIBS=$OLD_LIBS
+
+ if test x$FAM_LIBS = x; then
+ { { echo "$as_me:$LINENO: error: fam/gamin-headers and/or libs where not found, install them or build with --without-fam" >&5
+echo "$as_me: error: fam/gamin-headers and/or libs where not found, install them or build with --without-fam" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
fi
{ echo "$as_me:$LINENO: checking for properties in mod_webdav" >&5
@@ -28619,7 +28655,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by lighttpd $as_me 1.4.18, which was
+This file was extended by lighttpd $as_me 1.4.19, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -28672,7 +28708,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-lighttpd config.status 1.4.18
+lighttpd config.status 1.4.19
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.in b/configure.in
index f9189ac..2dcebac 100644
--- a/configure.in
+++ b/configure.in
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
-AC_INIT(lighttpd, 1.4.18, jan@kneschke.de)
+AC_INIT(lighttpd, 1.4.19, jan@kneschke.de)
AC_CONFIG_SRCDIR([src/server.c])
AC_CANONICAL_TARGET
@@ -266,18 +266,30 @@ if test "x$cross_compiling" = xno -a "$WITH_PCRE" != "no"; then
])
])
LIBS="$OLDLIBS"
+ else
+ AC_MSG_ERROR([pcre-config not found, install the pcre-devel package and build with --without-pcre])
fi
fi
AC_SUBST(PCRE_LIB)
-AC_CHECK_LIB(z, deflate, [
- AC_CHECK_HEADERS([zlib.h],[
- Z_LIB=-lz
- AC_DEFINE([HAVE_LIBZ], [1], [libz])
- AC_DEFINE([HAVE_ZLIB_H], [1])
+AC_MSG_CHECKING(for zlib support)
+AC_ARG_WITH(zlib, AC_HELP_STRING([--with-zlib],[Enable zlib support for mod_compress]),
+ [WITH_ZLIB=$withval],[WITH_ZLIB=yes])
+AC_MSG_RESULT([$WITH_ZLIB])
+
+if test "$WITH_ZLIB" != "no"; then
+ AC_CHECK_LIB(z, deflate, [
+ AC_CHECK_HEADERS([zlib.h],[
+ Z_LIB=-lz
+ AC_DEFINE([HAVE_LIBZ], [1], [libz])
+ AC_DEFINE([HAVE_ZLIB_H], [1])
+ ])
])
-])
+ if test x$Z_LIB = x; then
+ AC_MSG_ERROR([zlib-headers and/or libs where not found, install them or build with --without-zlib])
+ fi
+fi
AC_SUBST(Z_LIB)
AC_MSG_CHECKING(for bzip2 support)
@@ -293,6 +305,9 @@ if test "$WITH_BZIP2" != "no"; then
AC_DEFINE([HAVE_BZLIB_H], [1])
])
])
+ if test x$BZ_LIB = x; then
+ AC_MSG_ERROR([bzip2-headers and/or libs where not found, install them or build with --without-bzip2])
+ fi
fi
AC_SUBST(BZ_LIB)
@@ -324,6 +339,10 @@ if test "$WITH_FAM" != "no"; then
LIBS=$FAM_LIBS
AC_CHECK_FUNCS([FAMNoExists])
LIBS=$OLD_LIBS
+
+ if test x$FAM_LIBS = x; then
+ AC_MSG_ERROR([fam/gamin-headers and/or libs where not found, install them or build with --without-fam])
+ fi
fi
AC_MSG_CHECKING(for properties in mod_webdav)
diff --git a/cygwin/lighttpd.README b/cygwin/lighttpd.README
index 8fc9339..812c5c2 100644
--- a/cygwin/lighttpd.README
+++ b/cygwin/lighttpd.README
@@ -31,17 +31,17 @@ Canonical download:
------------------------------------
Build instructions:
- unpack lighttpd-1.4.18-<REL>-src.tar.bz2
+ unpack lighttpd-1.4.19-<REL>-src.tar.bz2
if you use setup to install this src package, it will be
unpacked under /usr/src automatically
cd /usr/src
- ./lighttpd-1.4.18-<REL>.sh all
+ ./lighttpd-1.4.19-<REL>.sh all
This will create:
- /usr/src/lighttpd-1.4.18-<REL>.tar.bz2
- /usr/src/lighttpd-1.4.18-<REL>-src.tar.bz2
+ /usr/src/lighttpd-1.4.19-<REL>.tar.bz2
+ /usr/src/lighttpd-1.4.19-<REL>-src.tar.bz2
-Or use './lighttpd-1.4.18-<REL>.sh prep' to get a patched source directory
+Or use './lighttpd-1.4.19-<REL>.sh prep' to get a patched source directory
-------------------------------------------
diff --git a/debian/changelog b/debian/changelog
index 247c804..0120e98 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+lighttpd (1.4.19-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Pierre Habouzit <madcoder@debian.org> Sun, 16 Mar 2008 10:11:45 +0100
+
lighttpd (1.4.18-4) unstable; urgency=high
* The “I HATE DPATCH”-release.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 416329b..8aac874 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -7,8 +7,8 @@ Module: core
------------
:Author: Jan Kneschke
-:Date: $Date: 2006-10-04 15:26:23 +0200 (Wed, 04 Oct 2006) $
-:Revision: $Revision: 1371 $
+:Date: $Date: 2007-11-04 17:53:17 +0100 (Sun, 04 Nov 2007) $
+:Revision: $Revision: 2012 $
:abstract:
the layout of the configuration file
@@ -85,6 +85,8 @@ where <field> is one of one of the following:
$HTTP["cookie"]
match on cookie
+$HTTP["scheme"]
+ match on scheme
$HTTP["host"]
match on host
$HTTP["useragent"]
diff --git a/doc/lighttpd.conf b/doc/lighttpd.conf
index 767e100..7fa7471 100644
--- a/doc/lighttpd.conf
+++ b/doc/lighttpd.conf
@@ -72,6 +72,7 @@ mimetype.assign = (
".ogg" => "application/ogg",
".wav" => "audio/x-wav",
".gif" => "image/gif",
+ ".jar" => "application/x-java-archive",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".png" => "image/png",
diff --git a/lighttpd.spec b/lighttpd.spec
index 1a32b5d..3b58c3d 100644
--- a/lighttpd.spec
+++ b/lighttpd.spec
@@ -1,26 +1,24 @@
Summary: A fast webserver with minimal memory-footprint (lighttpd)
Name: lighttpd
-Version: 1.4.18
+Version: 1.4.19
Release: 1
Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
Packager: Jan Kneschke <jan@kneschke.de>
License: BSD
Group: Networking/Daemons
-URL: http://jan.kneschke.de/projects/lighttpd/
+URL: http://www.lighttpd.net/
Requires: pcre >= 3.1 zlib
-BuildPrereq: libtool zlib-devel
+BuildRequires: libtool zlib-devel
BuildRoot: %{_tmppath}/%{name}-root
-
%description
lighttpd is intented to be a frontend for ad-servers which have to deliver
small files concurrently to many connections.
-Available rpmbuild rebuild options :
---with : ssl mysql lua memcache
+Available rpmbuild rebuild options:
+--with: ssl mysql lua memcache
%prep
-
%setup -q
%build
@@ -33,14 +31,13 @@ rm -rf %{buildroot}
make
%install
-
%makeinstall
mkdir -p %{buildroot}%{_sysconfdir}/{init.d,sysconfig}
-if test -f /etc/redhat-release -o -f /etc/fedora-release; then
- install -m 755 doc/rc.lighttpd.redhat %{buildroot}%{_sysconfdir}/init.d/lighttpd
+if [ -f /etc/redhat-release -o -f /etc/fedora-release ]; then
+ install -m 755 doc/rc.lighttpd.redhat %{buildroot}%{_sysconfdir}/init.d/lighttpd
else
- install -m 755 doc/rc.lighttpd %{buildroot}%{_sysconfdir}/init.d/lighttpd
+ install -m 755 doc/rc.lighttpd %{buildroot}%{_sysconfdir}/init.d/lighttpd
fi
install -m 644 doc/sysconfig.lighttpd %{buildroot}%{_sysconfdir}/sysconfig/lighttpd
@@ -49,16 +46,16 @@ rm -rf %{buildroot}
%post
## read http://www.fedora.us/docs/spec.html next time :)
-if test "$1" = "1"; then
- # real install, not upgrade
- /sbin/chkconfig --add lighttpd
+if [ "$1" = "1" ]; then
+ # real install, not upgrade
+ /sbin/chkconfig --add lighttpd
fi
%preun
-if test "$1" = "0"; then
- # real uninstall, not upgrade
- %{_sysconfdir}/init.d/lighttpd stop
- /sbin/chkconfig --del lighttpd
+if [ "$1" = "0"]; then
+ # real uninstall, not upgrade
+ %{_sysconfdir}/init.d/lighttpd stop
+ /sbin/chkconfig --del lighttpd
fi
%files
diff --git a/lighttpd.spec.in b/lighttpd.spec.in
index 9436a83..2e41846 100644
--- a/lighttpd.spec.in
+++ b/lighttpd.spec.in
@@ -6,21 +6,19 @@ Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.
Packager: Jan Kneschke <jan@kneschke.de>
License: BSD
Group: Networking/Daemons
-URL: http://jan.kneschke.de/projects/lighttpd/
+URL: http://www.lighttpd.net/
Requires: pcre >= 3.1 zlib
-BuildPrereq: libtool zlib-devel
+BuildRequires: libtool zlib-devel
BuildRoot: %{_tmppath}/%{name}-root
-
%description
lighttpd is intented to be a frontend for ad-servers which have to deliver
small files concurrently to many connections.
-Available rpmbuild rebuild options :
---with : ssl mysql lua memcache
+Available rpmbuild rebuild options:
+--with: ssl mysql lua memcache
%prep
-
%setup -q
%build
@@ -33,14 +31,13 @@ rm -rf %{buildroot}
make
%install
-
%makeinstall
mkdir -p %{buildroot}%{_sysconfdir}/{init.d,sysconfig}
-if test -f /etc/redhat-release -o -f /etc/fedora-release; then
- install -m 755 doc/rc.lighttpd.redhat %{buildroot}%{_sysconfdir}/init.d/lighttpd
+if [ -f /etc/redhat-release -o -f /etc/fedora-release ]; then
+ install -m 755 doc/rc.lighttpd.redhat %{buildroot}%{_sysconfdir}/init.d/lighttpd
else
- install -m 755 doc/rc.lighttpd %{buildroot}%{_sysconfdir}/init.d/lighttpd
+ install -m 755 doc/rc.lighttpd %{buildroot}%{_sysconfdir}/init.d/lighttpd
fi
install -m 644 doc/sysconfig.lighttpd %{buildroot}%{_sysconfdir}/sysconfig/lighttpd
@@ -49,16 +46,16 @@ rm -rf %{buildroot}
%post
## read http://www.fedora.us/docs/spec.html next time :)
-if test "$1" = "1"; then
- # real install, not upgrade
- /sbin/chkconfig --add lighttpd
+if [ "$1" = "1" ]; then
+ # real install, not upgrade
+ /sbin/chkconfig --add lighttpd
fi
%preun
-if test "$1" = "0"; then
- # real uninstall, not upgrade
- %{_sysconfdir}/init.d/lighttpd stop
- /sbin/chkconfig --del lighttpd
+if [ "$1" = "0"]; then
+ # real uninstall, not upgrade
+ %{_sysconfdir}/init.d/lighttpd stop
+ /sbin/chkconfig --del lighttpd
fi
%files
diff --git a/openwrt/control b/openwrt/control
index 7dee2c3..7aa3529 100644
--- a/openwrt/control
+++ b/openwrt/control
@@ -1,8 +1,8 @@
Package: lighttpd
-Version: 1.4.18
+Version: 1.4.19
Architecture: mipsel
Maintainer: Jan Kneschke <jan@kneschke.de>
-Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.18.tar.gz
+Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.19.tar.gz
Section: net
Priority: optional
Depends:
diff --git a/openwrt/lighttpd.mk b/openwrt/lighttpd.mk
index 71cf0c7..1474f75 100644
--- a/openwrt/lighttpd.mk
+++ b/openwrt/lighttpd.mk
@@ -10,7 +10,7 @@
# For this example we'll use a fairly simple package that compiles easily
# and has sources available for download at sourceforge
-LIGHTTPD=lighttpd-1.4.18
+LIGHTTPD=lighttpd-1.4.19
LIGHTTPD_TARGET=.built
LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
diff --git a/src/Makefile.am b/src/Makefile.am
index 24967c8..a112789 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,20 +16,20 @@ if CROSS_COMPILING
configparser.c configparser.h:
mod_ssi_exprparser.c mod_ssi_exprparser.h:
else
-configparser.y: lemon
-mod_ssi_exprparser.y: lemon
+$(srcdir)/configparser.y: lemon
+$(srcdir)/mod_ssi_exprparser.y: lemon
-configparser.c configparser.h: configparser.y
+configparser.c configparser.h: $(srcdir)/configparser.y
rm -f configparser.h
$(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
-mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
+mod_ssi_exprparser.c mod_ssi_exprparser.h: $(srcdir)/mod_ssi_exprparser.y
rm -f mod_ssi_exprparser.h
$(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
endif
-configfile.c: configparser.h
-mod_ssi_expr.c: mod_ssi_exprparser.h
+$(srcdir)/configfile.c: configparser.h
+$(srcdir)/mod_ssi_expr.c: mod_ssi_exprparser.h
common_src=buffer.c log.c \
keyvalue.c chunk.c \
@@ -281,4 +281,4 @@ proc_open_CPPFLAGS= -DDEBUG_PROC_OPEN
#ajp_SOURCES = ajp.c
noinst_HEADERS = $(hdr)
-EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
+EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c SConscript
diff --git a/src/Makefile.in b/src/Makefile.in
index 2952518..826af20 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -755,7 +755,7 @@ proc_open_CPPFLAGS = -DDEBUG_PROC_OPEN
#bench_SOURCES = buffer.c bench.c
#ajp_SOURCES = ajp.c
noinst_HEADERS = $(hdr)
-EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
+EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c SConscript
all: all-am
.SUFFIXES:
@@ -1669,19 +1669,19 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
@CROSS_COMPILING_TRUE@configparser.c configparser.h:
@CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h:
-@CROSS_COMPILING_FALSE@configparser.y: lemon
-@CROSS_COMPILING_FALSE@mod_ssi_exprparser.y: lemon
+@CROSS_COMPILING_FALSE@$(srcdir)/configparser.y: lemon
+@CROSS_COMPILING_FALSE@$(srcdir)/mod_ssi_exprparser.y: lemon
-@CROSS_COMPILING_FALSE@configparser.c configparser.h: configparser.y
+@CROSS_COMPILING_FALSE@configparser.c configparser.h: $(srcdir)/configparser.y
@CROSS_COMPILING_FALSE@ rm -f configparser.h
@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
-@CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
+@CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: $(srcdir)/mod_ssi_exprparser.y
@CROSS_COMPILING_FALSE@ rm -f mod_ssi_exprparser.h
@CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
-configfile.c: configparser.h
-mod_ssi_expr.c: mod_ssi_exprparser.h
+$(srcdir)/configfile.c: configparser.h
+$(srcdir)/mod_ssi_expr.c: mod_ssi_exprparser.h
# 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/src/SConscript b/src/SConscript
new file mode 100644
index 0000000..0ad2a4e
--- /dev/null
+++ b/src/SConscript
@@ -0,0 +1,195 @@
+import os
+import re
+import types
+
+Import('env')
+
+common_src = Split("buffer.c log.c \
+ keyvalue.c chunk.c \
+ http_chunk.c stream.c fdevent.c \
+ stat_cache.c plugin.c joblist.c etag.c array.c \
+ data_string.c data_count.c data_array.c \
+ data_integer.c md5.c data_fastcgi.c \
+ fdevent_select.c fdevent_linux_rtsig.c \
+ fdevent_poll.c fdevent_linux_sysepoll.c \
+ fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \
+ data_config.c bitset.c \
+ inet_ntop_cache.c crc32.c \
+ connections-glue.c \
+ configfile-glue.c \
+ http-header-glue.c \
+ splaytree.c network_writev.c \
+ network_write.c network_linux_sendfile.c \
+ network_freebsd_sendfile.c \
+ network_solaris_sendfilev.c network_openssl.c \
+ status_counter.c \
+")
+
+src = Split("server.c response.c connections.c network.c \
+ configfile.c configparser.c request.c proc_open.c")
+
+lemon = env.Program('lemon', 'lemon.c')
+
+configparser = env.Command(['configparser.c', 'configparser.h'], 'configparser.y', '(cd build; ../' + lemon[0].path + ' -q ../$SOURCE ../src/lempar.c; cd ..)')
+env.Depends(configparser, lemon)
+
+mod_ssi_exprparser = env.Command(['mod_ssi_exprparser.c', 'mod_ssi_exprparser.h'], 'mod_ssi_exprparser.y', '(cd build; ../' + lemon[0].path + ' -q ../$SOURCE ../src/lempar.c; cd ..)')
+env.Depends(mod_ssi_exprparser, lemon)
+
+## the modules and how they are built
+modules = {
+ 'mod_access' : { 'src' : [ 'mod_access.c' ] },
+ 'mod_alias' : { 'src' : [ 'mod_alias.c' ] },
+ 'mod_cgi' : { 'src' : [ 'mod_cgi.c' ] },
+ 'mod_fastcgi' : { 'src' : [ 'mod_fastcgi.c' ] },
+ 'mod_scgi' : { 'src' : [ 'mod_scgi.c' ] },
+ 'mod_staticfile' : { 'src' : [ 'mod_staticfile.c' ] },
+ 'mod_dirlisting' : { 'src' : [ 'mod_dirlisting.c' ], 'lib' : [ env['LIBPCRE'] ] },
+ 'mod_indexfile' : { 'src' : [ 'mod_indexfile.c' ] },
+ 'mod_setenv' : { 'src' : [ 'mod_setenv.c' ] },
+ 'mod_rrdtool' : { 'src' : [ 'mod_rrdtool.c' ] },
+ 'mod_usertrack' : { 'src' : [ 'mod_usertrack.c' ] },
+ 'mod_proxy' : { 'src' : [ 'mod_proxy.c' ] },
+ 'mod_userdir' : { 'src' : [ 'mod_userdir.c' ] },
+ 'mod_secdownload' : { 'src' : [ 'mod_secure_download.c' ] },
+ 'mod_accesslog' : { 'src' : [ 'mod_accesslog.c' ] },
+ 'mod_simple_vhost' : { 'src' : [ 'mod_simple_vhost.c' ] },
+ 'mod_evhost' : { 'src' : [ 'mod_evhost.c' ] },
+ 'mod_expire' : { 'src' : [ 'mod_expire.c' ] },
+ 'mod_status' : { 'src' : [ 'mod_status.c' ] },
+ 'mod_compress' : { 'src' : [ 'mod_compress.c' ], 'lib' : [ env['LIBZ'], env['LIBBZ2'] ] },
+ 'mod_redirect' : { 'src' : [ 'mod_redirect.c' ], 'lib' : [ env['LIBPCRE'] ] },
+ 'mod_rewrite' : { 'src' : [ 'mod_rewrite.c' ], 'lib' : [ env['LIBPCRE'] ] },
+ 'mod_auth' : {
+ 'src' : [ 'mod_auth.c', 'http_auth_digest.c', 'http_auth.c' ],
+ 'lib' : [ env['LIBCRYPT'], env['LIBLDAP'], env['LIBLBER'] ] },
+ 'mod_webdav' : { 'src' : [ 'mod_webdav.c' ], 'lib' : [ env['LIBXML2'], env['LIBSQLITE3'], env['LIBUUID'] ] },
+ 'mod_mysql_vhost' : { 'src' : [ 'mod_mysql_vhost.c' ], 'lib' : [ env['LIBMYSQL'] ] },
+ 'mod_trigger_b4_dl' : { 'src' : [ 'mod_trigger_b4_dl.c' ], 'lib' : [ env['LIBPCRE'] ] },
+ 'mod_cml' : {
+ 'src' : [ 'mod_cml_lua.c', 'mod_cml.c', 'mod_cml_funcs.c' ],
+ 'lib' : [ env['LIBPCRE'], env['LIBMEMCACHE'], env['LIBLUA'], env['LIBLUALIB'] ] },
+ 'mod_uploadprogress' : { 'src' : [ 'mod_uploadprogress.c' ] },
+ 'mod_evasive' : { 'src' : [ 'mod_evasive.c' ] },
+ 'mod_ssi' : { 'src' : [ 'mod_ssi_exprparser.c', 'mod_ssi_expr.c', 'mod_ssi.c' ], 'lib' : [ env['LIBPCRE'] ] },
+ 'mod_flv_streaming' : { 'src' : [ 'mod_flv_streaming.c' ] },
+ 'mod_magnet' : { 'src' : [ 'mod_magnet.c', 'mod_magnet_cache.c' ], 'lib' : [ env['LIBLUA'] ] },
+}
+
+staticenv = env.Copy(CPPFLAGS=[ env['CPPFLAGS'], '-DLIGHTTPD_STATIC', '-DOPENSSL_NO_KRB5'])
+
+## all the core-sources + the modules
+staticsrc = src + common_src
+
+staticlib = env['LIBS']
+staticinit = ''
+for module in modules.keys():
+ staticsrc += modules[module]['src']
+ staticinit += "PLUGIN_INIT(%s)\n"%module
+ if modules[module].has_key('lib'):
+ staticlib += modules[module]['lib']
+
+open('plugin-static.h', 'w+').write(staticinit)
+
+## turn all src-files into objects
+staticobj = []
+for cfile in staticsrc:
+ staticobj += [ staticenv.Object('static-' + cfile.replace('.c', ''), cfile) ]
+
+staticbin = staticenv.Program('lighttpd-semi-static',
+ staticobj,
+ LIBS = staticlib
+ )
+
+## you might have to adjust the list of libs and the order for your setup
+## this is tricky, be warned
+fullstaticlib = []
+
+## try to calculate the libs for fullstatic with ldd
+## 1. find the lib
+## 2. check the deps
+## 3. add them to the libs
+searchlibs = os.pathsep.join([ '/lib/', '/usr/lib/', '/usr/local/lib/' ])
+lddre = re.compile(r'^\s+lib([^=-]+)(?:-[\.0-9]+)?\.so\.[0-9]+ =>', re.MULTILINE)
+for libs in staticlib:
+ if type(libs) is types.StringType: libs = [ libs ]
+ for lib in libs:
+ fullstaticlib += [ lib ]
+ solibpath = env.WhereIs('lib' + lib + '.so', searchlibs)
+ fullstaticlib += [ lib ]
+ if solibpath is None:
+ continue
+
+ f = os.popen('ldd ' + solibpath, 'r')
+ for aword in lddre.findall(f.read()):
+ fullstaticlib += [ aword ]
+ f.close
+
+
+fullstaticbin = staticenv.Program('lighttpd-static',
+ staticobj,
+ LIBS = fullstaticlib,
+ LINKFLAGS= ['-static']
+ )
+
+Alias('static', staticbin)
+Alias('fullstatic', fullstaticbin)
+
+implib = 'lighttpd.exe.a'
+bin_targets = ['lighttpd']
+bin_linkflags = [ env['LINKFLAGS'] ]
+if env['COMMON_LIB'] == 'lib':
+ common_lib = env.SharedLibrary('liblighttpd', common_src, LINKFLAGS = [ env['LINKFLAGS'], '-Wl,--export-dynamic' ])
+else:
+ src += common_src
+ common_lib = []
+ if env['COMMON_LIB'] == 'bin':
+ bin_linkflags += [ '-Wl,--export-all-symbols', '-Wl,--out-implib=build/' + implib ]
+ bin_targets += [ implib ]
+ else:
+ bin_linkflags += [ '-Wl,--export-dynamic' ]
+
+instbin = env.Program(bin_targets, src, LINKFLAGS = bin_linkflags, LIBS= [ env['LIBS'], common_lib, env['LIBDL'] ])
+env.Depends(instbin, configparser)
+
+spawn_fcgi = env.Program("spawn-fcgi", "spawn-fcgi.c")
+
+if env['COMMON_LIB'] == 'bin':
+ common_lib = instbin[1]
+
+env['SHLIBPREFIX'] = ''
+instlib = []
+for module in modules.keys():
+ libs = [ common_lib ]
+ if modules[module].has_key('lib'):
+ libs += modules[module]['lib']
+ instlib += env.SharedLibrary(module, modules[module]['src'], LIBS= [ libs ])
+
+inst = []
+
+Default(spawn_fcgi)
+inst += env.Install('${bindir}', spawn_fcgi)
+
+if env['build_dynamic']:
+ Default(instbin[0], instlib)
+ inst += env.Install('${sbindir}', instbin[0])
+ inst += env.Install('${libdir}', instlib)
+ if env['COMMON_LIB'] == 'lib':
+ Default(common_lib)
+ inst += env.Install('${bindir}', common_lib)
+
+if env['build_static']:
+ Default(staticbin)
+ inst += env.Install('${sbindir}', staticbin)
+
+if env['build_fullstatic']:
+ Default(fullstaticbin)
+ inst += env.Install('${sbindir}', fullstaticbin)
+
+env.Alias('dynamic', instbin)
+# default all to be installed
+env.Alias('install', inst)
+
+pkgdir = '.'
+tarname = env['package'] + '-' + env['version']
+
diff --git a/src/array.h b/src/array.h
index b8a8345..9dacf10 100644
--- a/src/array.h
+++ b/src/array.h
@@ -86,10 +86,12 @@ typedef enum {
COMP_HTTP_URL,
COMP_HTTP_HOST,
COMP_HTTP_REFERER,
- COMP_HTTP_USERAGENT,
+ COMP_HTTP_USER_AGENT,
COMP_HTTP_COOKIE,
- COMP_HTTP_REMOTEIP,
- COMP_HTTP_QUERYSTRING,
+ COMP_HTTP_REMOTE_IP,
+ COMP_HTTP_QUERY_STRING,
+ COMP_HTTP_SCHEME,
+ COMP_HTTP_REQUEST_METHOD,
COMP_LAST_ELEMENT
} comp_key_t;
diff --git a/src/base.h b/src/base.h
index abedf79..acaf533 100644
--- a/src/base.h
+++ b/src/base.h
@@ -515,6 +515,7 @@ typedef struct {
#ifdef USE_OPENSSL
SSL_CTX *ssl_ctx;
#endif
+ unsigned short is_proxy_ssl;
} server_socket;
typedef struct {
diff --git a/src/configfile-glue.c b/src/configfile-glue.c
index f6ead92..66a596e 100644
--- a/src/configfile-glue.c
+++ b/src/configfile-glue.c
@@ -277,7 +277,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
}
break;
}
- case COMP_HTTP_REMOTEIP: {
+ case COMP_HTTP_REMOTE_IP: {
char *nm_slash;
/* handle remoteip limitations
*
@@ -341,11 +341,15 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
}
break;
}
+ case COMP_HTTP_SCHEME:
+ l = con->uri.scheme;
+ break;
+
case COMP_HTTP_URL:
l = con->uri.path;
break;
- case COMP_HTTP_QUERYSTRING:
+ case COMP_HTTP_QUERY_STRING:
l = con->uri.query;
break;
@@ -372,7 +376,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
}
break;
}
- case COMP_HTTP_USERAGENT: {
+ case COMP_HTTP_USER_AGENT: {
data_string *ds;
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
l = ds->value;
@@ -381,7 +385,17 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
}
break;
}
+ case COMP_HTTP_REQUEST_METHOD: {
+ const char *method = get_http_method_name(con->request.http_method);
+
+ /* we only have the request method as const char but we need a buffer for comparing */
+
+ buffer_copy_string(srv->tmp_buf, method);
+ l = srv->tmp_buf;
+
+ break;
+ }
default:
return COND_RESULT_FALSE;
}
diff --git a/src/configparser.c b/src/configparser.c
index 363b395..58a03fe 100644
--- a/src/configparser.c
+++ b/src/configparser.c
@@ -54,7 +54,7 @@ static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
return NULL;
}
-/* op1 is to be eat/return by this function, op1->key is not cared
+/* op1 is to be eat/return by this function if success, op1->key is not cared
op2 is left untouch, unreferenced
*/
data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
@@ -72,7 +72,6 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
return (data_unset *)ds;
} else {
fprintf(stderr, "data type mismatch, cannot be merge\n");
- op1->free(op1);
return NULL;
}
}
@@ -106,7 +105,7 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
}
-#line 110 "configparser.c"
+#line 109 "configparser.c"
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
@@ -515,42 +514,42 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
case 25:
#line 142 "./configparser.y"
{ buffer_free((yypminor->yy0)); }
-#line 518 "configparser.c"
+#line 517 "configparser.c"
break;
case 35:
#line 133 "./configparser.y"
{ (yypminor->yy41)->free((yypminor->yy41)); }
-#line 523 "configparser.c"
+#line 522 "configparser.c"
break;
case 36:
#line 134 "./configparser.y"
{ (yypminor->yy41)->free((yypminor->yy41)); }
-#line 528 "configparser.c"
+#line 527 "configparser.c"
break;
case 37:
#line 135 "./configparser.y"
{ (yypminor->yy41)->free((yypminor->yy41)); }
-#line 533 "configparser.c"
+#line 532 "configparser.c"
break;
case 39:
#line 136 "./configparser.y"
{ array_free((yypminor->yy40)); }
-#line 538 "configparser.c"
+#line 537 "configparser.c"
break;
case 40:
#line 137 "./configparser.y"
{ array_free((yypminor->yy40)); }
-#line 543 "configparser.c"
+#line 542 "configparser.c"
break;
case 41:
#line 138 "./configparser.y"
{ buffer_free((yypminor->yy43)); }
-#line 548 "configparser.c"
+#line 547 "configparser.c"
break;
case 42:
#line 139 "./configparser.y"
{ buffer_free((yypminor->yy43)); }
-#line 553 "configparser.c"
+#line 552 "configparser.c"
break;
default: break; /* If no destructor action specified: do nothing */
}
@@ -818,9 +817,9 @@ static void yy_reduce(
/* No destructor defined for global */
break;
case 5:
-#line 116 "./configparser.y"
+#line 115 "./configparser.y"
{ yymsp[-1].minor.yy78 = NULL; }
-#line 823 "configparser.c"
+#line 822 "configparser.c"
yy_destructor(1,&yymsp[0].minor);
break;
case 6:
@@ -835,31 +834,33 @@ static void yy_reduce(
case 9:
#line 144 "./configparser.y"
{
- buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
- if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
- fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
- ctx->current->context_ndx,
- ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
- ctx->ok = 0;
- } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
- array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
- yymsp[0].minor.yy41 = NULL;
- } else {
- fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
- ctx->current->context_ndx,
- ctx->current->key->ptr, yymsp[0].minor.yy41->key->ptr);
- ctx->ok = 0;
- yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
- yymsp[0].minor.yy41 = NULL;
+ if (ctx->ok) {
+ buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
+ if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
+ fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
+ ctx->current->context_ndx,
+ ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
+ ctx->ok = 0;
+ } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
+ array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
+ } else {
+ fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
+ ctx->current->context_ndx,
+ ctx->current->key->ptr, yymsp[0].minor.yy41->key->ptr);
+ ctx->ok = 0;
+ yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
+ yymsp[0].minor.yy41 = NULL;
+ }
}
buffer_free(yymsp[-2].minor.yy43);
yymsp[-2].minor.yy43 = NULL;
}
-#line 858 "configparser.c"
+#line 859 "configparser.c"
yy_destructor(2,&yymsp[-1].minor);
break;
case 10:
-#line 166 "./configparser.y"
+#line 168 "./configparser.y"
{
array *vars = ctx->current->value;
data_unset *du;
@@ -884,6 +885,7 @@ static void yy_reduce(
du = configparser_merge_data(du, yymsp[0].minor.yy41);
if (NULL == du) {
ctx->ok = 0;
+ du->free(du);
}
else {
buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
@@ -898,11 +900,11 @@ static void yy_reduce(
yymsp[-2].minor.yy43 = NULL;
yymsp[0].minor.yy41 = NULL;
}
-#line 901 "configparser.c"
+#line 903 "configparser.c"
yy_destructor(3,&yymsp[-1].minor);
break;
case 11:
-#line 205 "./configparser.y"
+#line 208 "./configparser.y"
{
if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
yygotominor.yy43 = buffer_init_string("var.");
@@ -914,10 +916,10 @@ static void yy_reduce(
yymsp[0].minor.yy0 = NULL;
}
}
-#line 917 "configparser.c"
+#line 919 "configparser.c"
break;
case 12:
-#line 217 "./configparser.y"
+#line 220 "./configparser.y"
{
yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
if (NULL == yygotominor.yy41) {
@@ -927,19 +929,19 @@ static void yy_reduce(
yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 930 "configparser.c"
+#line 932 "configparser.c"
yy_destructor(5,&yymsp[-1].minor);
break;
case 13:
-#line 227 "./configparser.y"
+#line 230 "./configparser.y"
{
yygotominor.yy41 = yymsp[0].minor.yy41;
yymsp[0].minor.yy41 = NULL;
}
-#line 939 "configparser.c"
+#line 941 "configparser.c"
break;
case 14:
-#line 232 "./configparser.y"
+#line 235 "./configparser.y"
{
yygotominor.yy41 = NULL;
if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
@@ -966,59 +968,59 @@ static void yy_reduce(
buffer_free(yymsp[0].minor.yy43);
yymsp[0].minor.yy43 = NULL;
}
-#line 969 "configparser.c"
+#line 971 "configparser.c"
break;
case 15:
-#line 259 "./configparser.y"
+#line 262 "./configparser.y"
{
yygotominor.yy41 = (data_unset *)data_string_init();
buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
buffer_free(yymsp[0].minor.yy0);
yymsp[0].minor.yy0 = NULL;
}
-#line 979 "configparser.c"
+#line 981 "configparser.c"
break;
case 16:
-#line 266 "./configparser.y"
+#line 269 "./configparser.y"
{
yygotominor.yy41 = (data_unset *)data_integer_init();
((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
buffer_free(yymsp[0].minor.yy0);
yymsp[0].minor.yy0 = NULL;
}
-#line 989 "configparser.c"
+#line 991 "configparser.c"
break;
case 17:
-#line 272 "./configparser.y"
+#line 275 "./configparser.y"
{
yygotominor.yy41 = (data_unset *)data_array_init();
array_free(((data_array *)(yygotominor.yy41))->value);
((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
yymsp[0].minor.yy40 = NULL;
}
-#line 999 "configparser.c"
+#line 1001 "configparser.c"
break;
case 18:
-#line 278 "./configparser.y"
+#line 281 "./configparser.y"
{
yygotominor.yy40 = array_init();
}
-#line 1006 "configparser.c"
+#line 1008 "configparser.c"
yy_destructor(8,&yymsp[-1].minor);
yy_destructor(9,&yymsp[0].minor);
break;
case 19:
-#line 281 "./configparser.y"
+#line 284 "./configparser.y"
{
yygotominor.yy40 = yymsp[-1].minor.yy40;
yymsp[-1].minor.yy40 = NULL;
}
-#line 1016 "configparser.c"
+#line 1018 "configparser.c"
yy_destructor(8,&yymsp[-2].minor);
yy_destructor(9,&yymsp[0].minor);
break;
case 20:
-#line 286 "./configparser.y"
+#line 289 "./configparser.y"
{
if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
@@ -1035,37 +1037,37 @@ static void yy_reduce(
yygotominor.yy40 = yymsp[-2].minor.yy40;
yymsp[-2].minor.yy40 = NULL;
}
-#line 1038 "configparser.c"
+#line 1040 "configparser.c"
yy_destructor(10,&yymsp[-1].minor);
break;
case 21:
-#line 303 "./configparser.y"
+#line 306 "./configparser.y"
{
yygotominor.yy40 = yymsp[-1].minor.yy40;
yymsp[-1].minor.yy40 = NULL;
}
-#line 1047 "configparser.c"
+#line 1049 "configparser.c"
yy_destructor(10,&yymsp[0].minor);
break;
case 22:
-#line 308 "./configparser.y"
+#line 311 "./configparser.y"
{
yygotominor.yy40 = array_init();
array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 1057 "configparser.c"
+#line 1059 "configparser.c"
break;
case 23:
-#line 314 "./configparser.y"
+#line 317 "./configparser.y"
{
yygotominor.yy41 = yymsp[0].minor.yy41;
yymsp[0].minor.yy41 = NULL;
}
-#line 1065 "configparser.c"
+#line 1067 "configparser.c"
break;
case 24:
-#line 318 "./configparser.y"
+#line 321 "./configparser.y"
{
buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
buffer_free(yymsp[-2].minor.yy43);
@@ -1074,7 +1076,7 @@ static void yy_reduce(
yygotominor.yy41 = yymsp[0].minor.yy41;
yymsp[0].minor.yy41 = NULL;
}
-#line 1077 "configparser.c"
+#line 1079 "configparser.c"
yy_destructor(11,&yymsp[-1].minor);
break;
case 25:
@@ -1083,18 +1085,18 @@ static void yy_reduce(
case 26:
break;
case 27:
-#line 330 "./configparser.y"
+#line 333 "./configparser.y"
{
data_config *dc;
dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
assert(dc);
configparser_push(ctx, dc, 0);
}
-#line 1093 "configparser.c"
+#line 1095 "configparser.c"
yy_destructor(12,&yymsp[0].minor);
break;
case 28:
-#line 337 "./configparser.y"
+#line 340 "./configparser.y"
{
data_config *cur;
@@ -1103,16 +1105,16 @@ static void yy_reduce(
assert(cur && ctx->current);
- yygotominor.yy0 = cur;
+ yygotominor.yy78 = cur;
}
-#line 1108 "configparser.c"
+#line 1110 "configparser.c"
/* No destructor defined for globalstart */
yy_destructor(13,&yymsp[-2].minor);
/* No destructor defined for metalines */
yy_destructor(14,&yymsp[0].minor);
break;
case 29:
-#line 348 "./configparser.y"
+#line 351 "./configparser.y"
{
assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
@@ -1121,20 +1123,20 @@ static void yy_reduce(
yymsp[-3].minor.yy78 = NULL;
yymsp[0].minor.yy78 = NULL;
}
-#line 1124 "configparser.c"
+#line 1126 "configparser.c"
/* No destructor defined for eols */
yy_destructor(15,&yymsp[-1].minor);
break;
case 30:
-#line 357 "./configparser.y"
+#line 360 "./configparser.y"
{
yygotominor.yy78 = yymsp[0].minor.yy78;
yymsp[0].minor.yy78 = NULL;
}
-#line 1134 "configparser.c"
+#line 1136 "configparser.c"
break;
case 31:
-#line 362 "./configparser.y"
+#line 365 "./configparser.y"
{
data_config *cur;
@@ -1145,14 +1147,14 @@ static void yy_reduce(
yygotominor.yy78 = cur;
}
-#line 1148 "configparser.c"
+#line 1150 "configparser.c"
/* No destructor defined for context */
yy_destructor(13,&yymsp[-2].minor);
/* No destructor defined for metalines */
yy_destructor(14,&yymsp[0].minor);
break;
case 32:
-#line 373 "./configparser.y"
+#line 376 "./configparser.y"
{
data_config *dc;
buffer *b, *rvalue, *op;
@@ -1201,10 +1203,15 @@ static void yy_reduce(
{ COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) },
{ COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) },
{ COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) },
- { COMP_HTTP_USERAGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
+ { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
+ { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"user-agent\"]" ) },
{ COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) },
- { COMP_HTTP_REMOTEIP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
- { COMP_HTTP_QUERYSTRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
+ { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
+ { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) },
+ { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
+ { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") },
+ { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") },
+ { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) },
{ COMP_UNSET, NULL, 0 },
};
size_t i;
@@ -1288,45 +1295,45 @@ static void yy_reduce(
yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 1291 "configparser.c"
+#line 1298 "configparser.c"
yy_destructor(16,&yymsp[-6].minor);
yy_destructor(18,&yymsp[-4].minor);
yy_destructor(19,&yymsp[-2].minor);
break;
case 33:
-#line 508 "./configparser.y"
+#line 516 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_EQ;
}
-#line 1301 "configparser.c"
+#line 1308 "configparser.c"
yy_destructor(20,&yymsp[0].minor);
break;
case 34:
-#line 511 "./configparser.y"
+#line 519 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_MATCH;
}
-#line 1309 "configparser.c"
+#line 1316 "configparser.c"
yy_destructor(21,&yymsp[0].minor);
break;
case 35:
-#line 514 "./configparser.y"
+#line 522 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_NE;
}
-#line 1317 "configparser.c"
+#line 1324 "configparser.c"
yy_destructor(22,&yymsp[0].minor);
break;
case 36:
-#line 517 "./configparser.y"
+#line 525 "./configparser.y"
{
yygotominor.yy27 = CONFIG_COND_NOMATCH;
}
-#line 1325 "configparser.c"
+#line 1332 "configparser.c"
yy_destructor(23,&yymsp[0].minor);
break;
case 37:
-#line 521 "./configparser.y"
+#line 529 "./configparser.y"
{
yygotominor.yy43 = NULL;
if (ctx->ok) {
@@ -1343,10 +1350,10 @@ static void yy_reduce(
yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
yymsp[0].minor.yy41 = NULL;
}
-#line 1346 "configparser.c"
+#line 1353 "configparser.c"
break;
case 38:
-#line 538 "./configparser.y"
+#line 546 "./configparser.y"
{
if (ctx->ok) {
if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
@@ -1356,11 +1363,11 @@ static void yy_reduce(
yymsp[0].minor.yy43 = NULL;
}
}
-#line 1359 "configparser.c"
+#line 1366 "configparser.c"
yy_destructor(24,&yymsp[-1].minor);
break;
case 39:
-#line 548 "./configparser.y"
+#line 556 "./configparser.y"
{
if (ctx->ok) {
if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
@@ -1370,7 +1377,7 @@ static void yy_reduce(
yymsp[0].minor.yy43 = NULL;
}
}
-#line 1373 "configparser.c"
+#line 1380 "configparser.c"
yy_destructor(25,&yymsp[-1].minor);
break;
};
@@ -1400,11 +1407,11 @@ static void yy_parse_failed(
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser fails */
-#line 107 "./configparser.y"
+#line 106 "./configparser.y"
ctx->ok = 0;
-#line 1407 "configparser.c"
+#line 1414 "configparser.c"
configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
diff --git a/src/configparser.y b/src/configparser.y
index 30f5fd9..57e2dc5 100644
--- a/src/configparser.y
+++ b/src/configparser.y
@@ -51,7 +51,7 @@ static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
return NULL;
}
-/* op1 is to be eat/return by this function, op1->key is not cared
+/* op1 is to be eat/return by this function if success, op1->key is not cared
op2 is left untouch, unreferenced
*/
data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
@@ -69,7 +69,6 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
return (data_unset *)ds;
} else {
fprintf(stderr, "data type mismatch, cannot be merge\n");
- op1->free(op1);
return NULL;
}
}
@@ -123,6 +122,7 @@ metaline ::= EOL.
%type aelement {data_unset *}
%type condline {data_config *}
%type condlines {data_config *}
+%type global {data_config *}
%type aelements {array *}
%type array {array *}
%type key {buffer *}
@@ -142,22 +142,24 @@ metaline ::= EOL.
%token_destructor { buffer_free($$); }
varline ::= key(A) ASSIGN expression(B). {
- buffer_copy_string_buffer(B->key, A);
- if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
- fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
- ctx->current->context_ndx,
- ctx->current->key->ptr, A->ptr);
- ctx->ok = 0;
- } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
- array_insert_unique(ctx->current->value, B);
- B = NULL;
- } else {
- fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
- ctx->current->context_ndx,
- ctx->current->key->ptr, B->key->ptr);
- ctx->ok = 0;
- B->free(B);
- B = NULL;
+ if (ctx->ok) {
+ buffer_copy_string_buffer(B->key, A);
+ if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
+ fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
+ ctx->current->context_ndx,
+ ctx->current->key->ptr, A->ptr);
+ ctx->ok = 0;
+ } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
+ array_insert_unique(ctx->current->value, B);
+ B = NULL;
+ } else {
+ fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
+ ctx->current->context_ndx,
+ ctx->current->key->ptr, B->key->ptr);
+ ctx->ok = 0;
+ B->free(B);
+ B = NULL;
+ }
}
buffer_free(A);
A = NULL;
@@ -187,6 +189,7 @@ varline ::= key(A) APPEND expression(B). {
du = configparser_merge_data(du, B);
if (NULL == du) {
ctx->ok = 0;
+ du->free(du);
}
else {
buffer_copy_string_buffer(du->key, A);
@@ -418,10 +421,15 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio
{ COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) },
{ COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) },
{ COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) },
- { COMP_HTTP_USERAGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
+ { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
+ { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"user-agent\"]" ) },
{ COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) },
- { COMP_HTTP_REMOTEIP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
- { COMP_HTTP_QUERYSTRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
+ { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
+ { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) },
+ { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
+ { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") },
+ { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") },
+ { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) },
{ COMP_UNSET, NULL, 0 },
};
size_t i;
diff --git a/src/connections.c b/src/connections.c
index 94d36b4..184ecb9 100644
--- a/src/connections.c
+++ b/src/connections.c
@@ -394,10 +394,13 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
* 403 is from the response handler when noone else catched it
*
* */
- if (con->uri.path->used &&
+ if ((!con->http_status || con->http_status == 200) && con->uri.path->used &&
con->uri.path->ptr[0] != '*') {
response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
+ con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
+ con->parsed_response &= ~HTTP_CONTENT_LENGTH;
+
con->http_status = 200;
con->file_finished = 1;
@@ -498,9 +501,11 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
case 207:
case 200: /* class: header + body */
case 201:
+ case 300:
case 301:
case 302:
case 303:
+ case 307:
break;
case 206: /* write_queue is already prepared */
@@ -511,13 +516,13 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
default:
/* disable chunked encoding again as we have no body */
con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
+ con->parsed_response &= ~HTTP_CONTENT_LENGTH;
chunkqueue_reset(con->write_queue);
con->file_finished = 1;
break;
}
-
if (con->file_finished) {
/* we have all the content and chunked encoding is not used, set a content-length */
@@ -536,12 +541,16 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
if ((con->http_status >= 100 && con->http_status < 200) ||
con->http_status == 204 ||
con->http_status == 304) {
+ data_string *ds;
/* no Content-Body, no Content-Length */
- } else if (qlen >= 0) {
+ if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Content-Length"))) {
+ buffer_reset(ds->value); // Headers with empty values are ignored for output
+ }
+ } else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) {
/* qlen = 0 is important for Redirects (301, ...) as they MAY have
* a content. Browsers are waiting for a Content otherwise
*/
- buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
+ buffer_copy_off_t(srv->tmp_buf, qlen);
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
}
@@ -582,6 +591,8 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
* a HEAD request has the same as a GET
* without the content
*/
+ con->file_finished = 1;
+
chunkqueue_reset(con->write_queue);
con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
}
@@ -834,14 +845,8 @@ int connection_reset(server *srv, connection *con) {
con->plugin_ctx[pd->id] = 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
+ /* The cond_cache gets reset in response.c */
+// config_cond_cache_reset(srv, con);
#ifdef USE_OPENSSL
if (con->ssl_error_want_reuse_buffer) {
diff --git a/src/etag.c b/src/etag.c
index c1146c3..630956f 100644
--- a/src/etag.c
+++ b/src/etag.c
@@ -1,5 +1,14 @@
#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined HAVE_STDINT_H
#include <stdint.h>
+#elif defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
#include "buffer.h"
#include "etag.h"
diff --git a/src/fdevent_solaris_devpoll.c b/src/fdevent_solaris_devpoll.c
index f77daef..76414a4 100644
--- a/src/fdevent_solaris_devpoll.c
+++ b/src/fdevent_solaris_devpoll.c
@@ -67,7 +67,7 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
int ret;
dopoll.dp_timeout = timeout_ms;
- dopoll.dp_nfds = ev->maxfds;
+ dopoll.dp_nfds = ev->maxfds - 1;
dopoll.dp_fds = ev->devpollfds;
ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
diff --git a/src/http_auth.c b/src/http_auth.c
index 1bfb460..89abde6 100644
--- a/src/http_auth.c
+++ b/src/http_auth.c
@@ -29,6 +29,7 @@
#include "log.h"
#include "http_auth.h"
#include "http_auth_digest.h"
+#include "inet_ntop_cache.h"
#include "stream.h"
#ifdef USE_OPENSSL
@@ -862,7 +863,7 @@ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p,
/* password doesn't match */
if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
- log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
+ log_error_write(srv, __FILE__, __LINE__, "sbbss", "password doesn't match for ", con->uri.path, username, ", IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
buffer_free(username);
buffer_free(password);
@@ -1130,7 +1131,7 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p
}
log_error_write(srv, __FILE__, __LINE__, "sss",
- "digest: auth failed for", username, "wrong password");
+ "digest: auth failed for ", username, ": wrong password, IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
buffer_free(b);
return 0;
diff --git a/src/mod_auth.c b/src/mod_auth.c
index 19ed387..7bd306d 100644
--- a/src/mod_auth.c
+++ b/src/mod_auth.c
@@ -238,13 +238,13 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
int auth_type_len = auth_realm - http_authorization;
if ((auth_type_len == 5) &&
- (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
+ (0 == strncasecmp(http_authorization, "Basic", auth_type_len))) {
if (0 == strcmp(method->value->ptr, "basic")) {
auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
}
} else if ((auth_type_len == 6) &&
- (0 == strncmp(http_authorization, "Digest", auth_type_len))) {
+ (0 == strncasecmp(http_authorization, "Digest", auth_type_len))) {
if (0 == strcmp(method->value->ptr, "digest")) {
if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
con->http_status = 400;
diff --git a/src/mod_cgi.c b/src/mod_cgi.c
index f5e5b3a..82ae78b 100644
--- a/src/mod_cgi.c
+++ b/src/mod_cgi.c
@@ -1004,6 +1004,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
case -1:
/* error */
log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
+ return -1;
break;
default: {
handler_ctx *hctx;
@@ -1227,8 +1228,14 @@ TRIGGER_FUNC(cgi_trigger) {
#if 0
log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", p->cgi_pid.ptr[ndx]);
#endif
+ } else if (WIFSIGNALED(status)) {
+ /* FIXME: what if we killed the CGI script with a kill(..., SIGTERM) ?
+ */
+ if (WTERMSIG(status) != SIGTERM) {
+ log_error_write(srv, __FILE__, __LINE__, "sd", "cleaning up CGI: process died with signal", WTERMSIG(status));
+ }
} else {
- log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
+ log_error_write(srv, __FILE__, __LINE__, "s", "cleaning up CGI: ended unexpectedly");
}
cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
diff --git a/src/mod_compress.c b/src/mod_compress.c
index 464945e..79f6e74 100644
--- a/src/mod_compress.c
+++ b/src/mod_compress.c
@@ -102,6 +102,50 @@ FREE_FUNC(mod_compress_free) {
return HANDLER_GO_ON;
}
+// 0 on success, -1 for error
+int mkdir_recursive(char *dir) {
+ char *p = dir;
+
+ if (!dir || !dir[0])
+ return 0;
+
+ while ((p = strchr(p + 1, '/')) != NULL) {
+
+ *p = '\0';
+ if ((mkdir(dir, 0700) != 0) && (errno != EEXIST)) {
+ *p = '/';
+ return -1;
+ }
+
+ *p++ = '/';
+ if (!*p) return 0; // Ignore trailing slash
+ }
+
+ return (mkdir(dir, 0700) != 0) && (errno != EEXIST) ? -1 : 0;
+}
+
+// 0 on success, -1 for error
+int mkdir_for_file(char *filename) {
+ char *p = filename;
+
+ if (!filename || !filename[0])
+ return -1;
+
+ while ((p = strchr(p + 1, '/')) != NULL) {
+
+ *p = '\0';
+ if ((mkdir(filename, 0700) != 0) && (errno != EEXIST)) {
+ *p = '/';
+ return -1;
+ }
+
+ *p++ = '/';
+ if (!*p) return -1; // Unexpected trailing slash in filename
+ }
+
+ return 0;
+}
+
SETDEFAULTS_FUNC(mod_compress_setdefaults) {
plugin_data *p = p_d;
size_t i = 0;
@@ -134,6 +178,8 @@ SETDEFAULTS_FUNC(mod_compress_setdefaults) {
}
if (!buffer_is_empty(s->compress_cache_dir)) {
+ mkdir_recursive(s->compress_cache_dir->ptr);
+
struct stat st;
if (0 != stat(s->compress_cache_dir->ptr, &st)) {
log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
@@ -342,27 +388,8 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
BUFFER_APPEND_SLASH(p->ofn);
if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
- size_t offset = p->ofn->used - 1;
- char *dir, *nextdir;
-
buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
-
buffer_copy_string_buffer(p->b, p->ofn);
-
- /* mkdir -p ... */
- for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
- *nextdir = '\0';
-
- if (-1 == mkdir(p->b->ptr, 0700)) {
- if (errno != EEXIST) {
- log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
-
- return -1;
- }
- }
-
- *nextdir = '/';
- }
} else {
buffer_append_string_buffer(p->ofn, con->uri.path);
}
@@ -384,6 +411,11 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
buffer_append_string_buffer(p->ofn, sce->etag);
+ if (-1 == mkdir_for_file(p->ofn->ptr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "couldn't create directory for file", p->ofn);
+ return -1;
+ }
+
if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
if (errno == EEXIST) {
/* cache-entry exists */
@@ -407,6 +439,11 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
close(ofd);
+ /* Remove the incomplete cache file, so that later hits aren't served from it */
+ if (-1 == unlink(p->ofn->ptr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
+ }
+
return -1;
}
@@ -416,6 +453,12 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
close(ofd);
close(ifd);
+
+ /* Remove the incomplete cache file, so that later hits aren't served from it */
+ if (-1 == unlink(p->ofn->ptr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
+ }
+
return -1;
}
@@ -438,22 +481,29 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
break;
}
- if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
- munmap(start, sce->st.st_size);
- close(ofd);
- close(ifd);
- return -1;
- }
-
- if ((size_t)r != p->b->used) {
-
+ if (ret == 0) {
+ r = write(ofd, p->b->ptr, p->b->used);
+ if (-1 == r) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "writing cachefile", p->ofn, "failed:", strerror(errno));
+ ret = -1;
+ } else if ((size_t)r != p->b->used) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs", "writing cachefile", p->ofn, "failed: not enough bytes written");
+ ret = -1;
+ }
}
munmap(start, sce->st.st_size);
close(ofd);
close(ifd);
- if (ret != 0) return -1;
+ if (ret != 0) {
+ /* Remove the incomplete cache file, so that later hits aren't served from it */
+ if (-1 == unlink(p->ofn->ptr)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
+ }
+
+ return -1;
+ }
buffer_copy_string_buffer(con->physical.path, p->ofn);
@@ -570,6 +620,8 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
off_t max_fsize;
stat_cache_entry *sce = NULL;
+ if (con->mode != DIRECT || con->http_status) return HANDLER_GO_ON;
+
/* only GET and POST can get compressed */
if (con->request.http_method != HTTP_METHOD_GET &&
con->request.http_method != HTTP_METHOD_POST) {
@@ -678,8 +730,16 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
}
} else if (0 == deflate_file_to_buffer(srv, con, p,
con->physical.path, sce, compression_type)) {
+ buffer *mtime;
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
+
+ mtime = strftime_cache_get(srv, sce->st.st_mtime);
+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
+
+ etag_mutate(con->physical.etag, sce->etag);
+ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
return HANDLER_FINISHED;
diff --git a/src/mod_extforward.c b/src/mod_extforward.c
index 8ed336d..be7dd0f 100644
--- a/src/mod_extforward.c
+++ b/src/mod_extforward.c
@@ -20,6 +20,7 @@
/**
* mod_extforward.c for lighttpd, by comman.kang <at> gmail <dot> com
* extended, modified by Lionel Elie Mamane (LEM), lionel <at> mamane <dot> lu
+ * support chained proxies by glen@delfi.ee, #1528
*
* Config example:
*
@@ -33,6 +34,10 @@
* Note that "all" has precedence over specific entries,
* so "all except" setups will not work.
*
+ * In case you have chained proxies, you can add all their IP's to the
+ * config. However "all" has effect only on connecting IP, as the
+ * X-Forwarded-For header can not be trusted.
+ *
* Note: The effect of this module is variable on $HTTP["remotip"] directives and
* other module's remote ip dependent actions.
* Things done by modules before we change the remoteip or after we reset it will match on the proxy's IP.
@@ -225,18 +230,16 @@ static array *extract_forward_array(buffer *pbuffer)
char *base, *curr;
/* state variable, 0 means not in string, 1 means in string */
int in_str = 0;
- for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++)
- {
+ for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++) {
if (in_str) {
- if ( (*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':' ) {
+ if ((*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':') {
/* found an separator , insert value into result array */
- put_string_into_array_len(result, base, curr-base);
+ put_string_into_array_len(result, base, curr - base);
/* change state to not in string */
in_str = 0;
}
} else {
- if (*curr >= '0' && *curr <= '9')
- {
+ if (*curr >= '0' && *curr <= '9') {
/* found leading char of an IP address, move base pointer and change state */
base = curr;
in_str = 1;
@@ -244,9 +247,8 @@ static array *extract_forward_array(buffer *pbuffer)
}
}
/* if breaking out while in str, we got to the end of string, so add it */
- if (in_str)
- {
- put_string_into_array_len(result, base, curr-base);
+ if (in_str) {
+ put_string_into_array_len(result, base, curr - base);
}
}
return result;
@@ -255,18 +257,40 @@ static array *extract_forward_array(buffer *pbuffer)
#define IP_TRUSTED 1
#define IP_UNTRUSTED 0
/*
- check whether ip is trusted, return 1 for trusted , 0 for untrusted
-*/
+ * check whether ip is trusted, return 1 for trusted , 0 for untrusted
+ */
static int is_proxy_trusted(const char *ipstr, plugin_data *p)
{
- data_string* allds = (data_string *) array_get_element(p->conf.forwarder,"all");
+ data_string* allds = (data_string *)array_get_element(p->conf.forwarder, "all");
+
if (allds) {
- if (strcasecmp(allds->value->ptr,"trust") == 0)
+ if (strcasecmp(allds->value->ptr, "trust") == 0) {
return IP_TRUSTED;
- else
+ } else {
return IP_UNTRUSTED;
+ }
}
- return (data_string *)array_get_element(p->conf.forwarder,ipstr) ? IP_TRUSTED : IP_UNTRUSTED ;
+
+ return (data_string *)array_get_element(p->conf.forwarder, ipstr) ? IP_TRUSTED : IP_UNTRUSTED;
+}
+
+/*
+ * Return char *ip of last address of proxy that is not trusted.
+ * Do not accept "all" keyword here.
+ */
+static const char *last_not_in_array(array *a, plugin_data *p)
+{
+ array *forwarder = p->conf.forwarder;
+
+ for (int i = a->used - 1; i >= 0; i--) {
+ data_string *ds = (data_string *)a->data[i];
+ const char *ip = ds->value->ptr;
+
+ if (!array_get_element(forwarder, ip)) {
+ return ip;
+ }
+ }
+ return NULL;
}
struct addrinfo *ipstr_to_sockaddr(const char *host)
@@ -305,7 +329,7 @@ struct addrinfo *ipstr_to_sockaddr(const char *host)
static void clean_cond_cache(server *srv, connection *con) {
- config_cond_cache_reset_item(srv, con, COMP_HTTP_REMOTEIP);
+ config_cond_cache_reset_item(srv, con, COMP_HTTP_REMOTE_IP);
}
URIHANDLER_FUNC(mod_extforward_uri_handler) {
@@ -316,9 +340,8 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
struct addrinfo *addrlist = NULL;
#endif
const char *dst_addr_str = NULL;
- int i;
array *forward_array = NULL;
- char *real_remote_addr = NULL;
+ const char *real_remote_addr = NULL;
#ifdef HAVE_IPV6
#endif
@@ -342,7 +365,6 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
return HANDLER_GO_ON;
}
- /* if the remote ip itself is not trusted , then do nothing */
#ifdef HAVE_IPV6
dst_addr_str = inet_ntop(con->dst_addr.plain.sa_family,
con->dst_addr.plain.sa_family == AF_INET6 ?
@@ -353,7 +375,9 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
#else
dst_addr_str = inet_ntoa(con->dst_addr.ipv4.sin_addr);
#endif
- if (IP_UNTRUSTED == is_proxy_trusted (dst_addr_str, p) ) {
+
+ /* if the remote ip itself is not trusted, then do nothing */
+ if (IP_UNTRUSTED == is_proxy_trusted(dst_addr_str, p)) {
if (con->conf.log_request_handling) {
log_error_write(srv, __FILE__, __LINE__, "s",
"remote address is NOT a trusted proxy, skipping");
@@ -362,40 +386,34 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
return HANDLER_GO_ON;
}
+ /* build forward_array from forwarded data_string */
forward_array = extract_forward_array(forwarded->value);
-
- /* Testing shows that multiple headers and multiple values in one header
- come in _reverse_ order. So the first one we get is the last one in the request. */
- for (i = forward_array->used - 1; i >= 0; i--) {
- data_string *ds = (data_string *) forward_array->data[i];
- if (ds) {
- real_remote_addr = ds->value->ptr;
- break;
- } else {
- /* bug ? bailing out here */
- break;
- }
- }
+ real_remote_addr = last_not_in_array(forward_array, p);
if (real_remote_addr != NULL) { /* parsed */
sock_addr sock;
-
struct addrinfo *addrs_left;
+ server_socket *srv_sock = con->srv_socket;
+ data_string *forwarded_proto = (data_string *)array_get_element(con->request.headers, "X-Forwarded-Proto");
+
+ if (forwarded_proto && !strcmp(forwarded_proto->value->ptr, "https")) {
+ srv_sock->is_proxy_ssl = 1;
+ } else {
+ srv_sock->is_proxy_ssl = 0;
+ }
if (con->conf.log_request_handling) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "using address:", real_remote_addr);
+ log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr);
}
#ifdef HAVE_IPV6
addrlist = ipstr_to_sockaddr(real_remote_addr);
sock.plain.sa_family = AF_UNSPEC;
- for (addrs_left = addrlist; addrs_left != NULL;
- addrs_left = addrs_left -> ai_next) {
+ for (addrs_left = addrlist; addrs_left != NULL; addrs_left = addrs_left -> ai_next) {
sock.plain.sa_family = addrs_left->ai_family;
- if ( sock.plain.sa_family == AF_INET ) {
+ if (sock.plain.sa_family == AF_INET) {
sock.ipv4.sin_addr = ((struct sockaddr_in*)addrs_left->ai_addr)->sin_addr;
break;
- } else if ( sock.plain.sa_family == AF_INET6 ) {
+ } else if (sock.plain.sa_family == AF_INET6) {
sock.ipv6.sin6_addr = ((struct sockaddr_in6*)addrs_left->ai_addr)->sin6_addr;
break;
}
@@ -430,7 +448,7 @@ URIHANDLER_FUNC(mod_extforward_uri_handler) {
if (addrlist != NULL ) freeaddrinfo(addrlist);
#endif
}
- array_free(forward_array);
+ array_free(forward_array);
/* not found */
return HANDLER_GO_ON;
diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c
index 75b52ad..9ce9556 100644
--- a/src/mod_fastcgi.c
+++ b/src/mod_fastcgi.c
@@ -162,8 +162,8 @@ typedef struct {
* if host is one of the local IP adresses the
* whole connection is local
*
- * if tcp/ip should be used host AND port have
- * to be specified
+ * if port is not 0, and host is not specified,
+ * "localhost" (INADDR_LOOPBACK) is assumed.
*
*/
buffer *host;
@@ -823,12 +823,12 @@ static int fcgi_spawn_connection(server *srv,
fcgi_addr_in.sin_family = AF_INET;
if (buffer_is_empty(host->host)) {
- fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
} else {
struct hostent *he;
/* set a useful default */
- fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
+ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (NULL == (he = gethostbyname(host->host->ptr))) {
@@ -858,7 +858,11 @@ static int fcgi_spawn_connection(server *srv,
fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
buffer_copy_string(proc->connection_name, "tcp:");
- buffer_append_string_buffer(proc->connection_name, host->host);
+ if (!buffer_is_empty(host->host)) {
+ buffer_append_string_buffer(proc->connection_name, host->host);
+ } else {
+ buffer_append_string(proc->connection_name, "localhost");
+ }
buffer_append_string(proc->connection_name, ":");
buffer_append_long(proc->connection_name, proc->port);
}
@@ -1687,12 +1691,16 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h
#endif
} else {
fcgi_addr_in.sin_family = AF_INET;
- if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "converting IP address failed for", host->host,
- "\nBe sure to specify an IP address here");
-
- return -1;
+ if (!buffer_is_empty(host->host)) {
+ if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs",
+ "converting IP address failed for", host->host,
+ "\nBe sure to specify an IP address here");
+
+ return -1;
+ }
+ } else {
+ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
fcgi_addr_in.sin_port = htons(proc->port);
servlen = sizeof(fcgi_addr_in);
@@ -1702,7 +1710,11 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h
if (buffer_is_empty(proc->connection_name)) {
/* on remote spawing we have to set the connection-name now */
buffer_copy_string(proc->connection_name, "tcp:");
- buffer_append_string_buffer(proc->connection_name, host->host);
+ if (!buffer_is_empty(host->host)) {
+ buffer_append_string_buffer(proc->connection_name, host->host);
+ } else {
+ buffer_append_string(proc->connection_name, "localhost");
+ }
buffer_append_string(proc->connection_name, ":");
buffer_append_long(proc->connection_name, proc->port);
}
@@ -2045,12 +2057,9 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) {
s = get_http_version_name(con->request.http_version);
FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)),con)
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
+ if (srv_sock->is_ssl || srv_sock->is_proxy_ssl) {
FCGI_ENV_ADD_CHECK(fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")),con)
}
-#endif
-
FCGI_ENV_ADD_CHECK(fcgi_env_add_request_headers(srv, con, p), con);
@@ -2343,7 +2352,7 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p
/* no header */
buffer_free(packet->b);
- log_error_write(srv, __FILE__, __LINE__, "s", "FastCGI: header too small");
+ log_error_write(srv, __FILE__, __LINE__, "sdsds", "FastCGI: header too small:", packet->b->used, "bytes <", sizeof(FCGI_Header), "bytes");
return -1;
}
@@ -2530,15 +2539,28 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
}
if (host->allow_xsendfile &&
- NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
+ (NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))
+ || NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-Sendfile")))) {
stat_cache_entry *sce;
if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
+ data_string *dcls = data_string_init();
/* found */
-
http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
hctx->send_content_body = 0; /* ignore the content */
joblist_append(srv, con);
+
+ buffer_copy_string_len(dcls->key, "Content-Length", sizeof("Content-Length")-1);
+ buffer_copy_long(dcls->value, sce->st.st_size);
+ dcls = (data_string*) array_replace(con->response.headers, (data_unset *)dcls);
+ if (dcls) dcls->free((data_unset*)dcls);
+
+ con->parsed_response |= HTTP_CONTENT_LENGTH;
+ con->response.content_length = sce->st.st_size;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "send-file error: couldn't get stat_cache entry for:",
+ ds->value);
}
}
@@ -2719,9 +2741,14 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
int ret;
- /* sanity check */
+ /* sanity check:
+ * - host != NULL
+ * - either:
+ * - tcp socket (do not check host->host->uses, as it may be not set which means INADDR_LOOPBACK)
+ * - unix socket
+ */
if (!host ||
- ((!host->host->used || !host->port) && !host->unixsocket->used)) {
+ (!host->port && !host->unixsocket->used)) {
log_error_write(srv, __FILE__, __LINE__, "sxddd",
"write-req: error",
host,
@@ -3456,8 +3483,9 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
if (s_len < ct_len) continue;
/* check extension in the form "/fcgi_pattern" */
- if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
- break;
+ if (*(extension->key->ptr) == '/') {
+ if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0)
+ break;
} else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
/* check extension in the form ".fcg" */
break;
@@ -3473,7 +3501,7 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
for (k = 0; k < extension->used; k++) {
host = extension->hosts[k];
- /* we should have at least one proc that can do somthing */
+ /* we should have at least one proc that can do something */
if (host->active_procs == 0) {
host = NULL;
diff --git a/src/mod_proxy.c b/src/mod_proxy.c
index c4ac15f..4d8ecdd 100644
--- a/src/mod_proxy.c
+++ b/src/mod_proxy.c
@@ -1093,15 +1093,17 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p
if (s_len < ct_len) continue;
/* check extension in the form "/proxy_pattern" */
- if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
- if (s_len > ct_len + 1) {
- char *pi_offset;
+ if (*(extension->key->ptr) == '/') {
+ if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
+ if (s_len > ct_len + 1) {
+ char *pi_offset;
- if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
- path_info_offset = pi_offset - fn->ptr;
+ if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
+ path_info_offset = pi_offset - fn->ptr;
+ }
}
+ break;
}
- break;
} else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
/* check extension in the form ".fcg" */
break;
@@ -1203,7 +1205,7 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p
}
/* didn't found a higher id, wrap to the start */
- if (ndx != -1 && max_usage != INT_MAX) {
+ if (ndx == -1 && max_usage != INT_MAX) {
ndx = max_usage;
}
diff --git a/src/mod_scgi.c b/src/mod_scgi.c
index bc487c5..b7287ba 100644
--- a/src/mod_scgi.c
+++ b/src/mod_scgi.c
@@ -1057,6 +1057,9 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) {
/* a local socket + self spawning */
size_t pno;
+ /* HACK: just to make sure the adaptive spawing is disabled */
+ df->min_procs = df->max_procs;
+
if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
@@ -2694,8 +2697,9 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i
if (s_len < ct_len) continue;
/* check extension in the form "/scgi_pattern" */
- if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
- break;
+ if (*(extension->key->ptr) == '/') {
+ if (strncmp(fn->ptr, extension->key->ptr, ct_len) == 0)
+ break;
} else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
/* check extension in the form ".fcg" */
break;
diff --git a/src/mod_secure_download.c b/src/mod_secure_download.c
index 08a0554..57e407f 100644
--- a/src/mod_secure_download.c
+++ b/src/mod_secure_download.c
@@ -245,7 +245,8 @@ URIHANDLER_FUNC(mod_secdownload_uri_handler) {
/* timed-out */
if (srv->cur_ts - ts > p->conf.timeout ||
srv->cur_ts - ts < -p->conf.timeout) {
- con->http_status = 408;
+ /* "Gone" as the url will never be valid again instead of "408 - Timeout" where the request may be repeated */
+ con->http_status = 410;
return HANDLER_FINISHED;
}
diff --git a/src/mod_ssi.c b/src/mod_ssi.c
index e706e8f..d02d998 100644
--- a/src/mod_ssi.c
+++ b/src/mod_ssi.c
@@ -36,6 +36,11 @@
#include <sys/filio.h>
#endif
+#include "etag.h"
+
+/* The newest modified time of included files for include statement */
+static volatile time_t include_file_last_mtime = 0;
+
/* init the plugin data */
INIT_FUNC(mod_ssi_init) {
plugin_data *p;
@@ -575,6 +580,11 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
break;
case SSI_INCLUDE:
chunkqueue_append_file(con->write_queue, p->stat_fn, 0, st.st_size);
+
+ /* Keep the newest mtime of included files */
+ if (st.st_mtime > include_file_last_mtime)
+ include_file_last_mtime = st.st_mtime;
+
break;
}
} else {
@@ -718,50 +728,57 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
/* father */
int status;
ssize_t r;
+ int was_interrupted = 0;
close(from_exec_fds[1]);
/* wait for the client to end */
/*
- * FIXME: if we get interrupted by a SIGCHILD we count this as error
- *
- * for now it only happened on OpenBSD.
- *
- * that leads to zombies and missing output
+ * OpenBSD and Solaris send a EINTR on SIGCHILD even if we ignore it
*/
- if (-1 == waitpid(pid, &status, 0)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
- } else if (WIFEXITED(status)) {
- int toread;
- /* read everything from client and paste it into the output */
-
- while(1) {
- if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "unexpected end-of-file (perhaps the ssi-exec process died)");
- return -1;
+ do {
+ if (-1 == waitpid(pid, &status, 0)) {
+ if (errno == EINTR) {
+ was_interrupted++;
+ } else {
+ was_interrupted = 0;
+ log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
}
-
- if (toread > 0) {
- b = chunkqueue_get_append_buffer(con->write_queue);
-
- buffer_prepare_copy(b, toread + 1);
-
- if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
- /* read failed */
- break;
+ } else if (WIFEXITED(status)) {
+ int toread;
+ /* read everything from client and paste it into the output */
+ was_interrupted = 0;
+
+ while(1) {
+ if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "unexpected end-of-file (perhaps the ssi-exec process died)");
+ return -1;
+ }
+
+ if (toread > 0) {
+ b = chunkqueue_get_append_buffer(con->write_queue);
+
+ buffer_prepare_copy(b, toread + 1);
+
+ if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
+ /* read failed */
+ break;
+ } else {
+ b->used = r;
+ b->ptr[b->used++] = '\0';
+ }
} else {
- b->used = r;
- b->ptr[b->used++] = '\0';
+ break;
}
- } else {
- break;
}
+ } else {
+ was_interrupted = 0;
+ log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
}
- } else {
- log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
- }
+ } while (was_interrupted > 0 && was_interrupted < 4); /* if waitpid() gets interrupted, retry, but max 4 times */
+
close(from_exec_fds[0]);
break;
@@ -912,6 +929,9 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p)
build_ssi_cgi_vars(srv, con, p);
p->if_is_false = 0;
+ /* Reset the modified time of included files */
+ include_file_last_mtime = 0;
+
if (-1 == stream_open(&s, con->physical.path)) {
log_error_write(srv, __FILE__, __LINE__, "sb",
"stream-open: ", con->physical.path);
@@ -1010,6 +1030,30 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p)
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+ {
+ /* Generate "ETag" & "Last-Modified" headers */
+
+ stat_cache_entry *sce = NULL;
+ time_t lm_time = 0;
+ buffer *mtime = NULL;
+
+ stat_cache_get_entry(srv, con, con->physical.path, &sce);
+
+ etag_mutate(con->physical.etag, sce->etag);
+ response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+
+ if (sce->st.st_mtime > include_file_last_mtime)
+ lm_time = sce->st.st_mtime;
+ else
+ lm_time = include_file_last_mtime;
+
+ mtime = strftime_cache_get(srv, lm_time);
+ response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
+ }
+
+ /* Reset the modified time of included files */
+ include_file_last_mtime = 0;
+
/* reset physical.path */
buffer_reset(con->physical.path);
diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c
index 59fafee..0ffa901 100644
--- a/src/mod_staticfile.c
+++ b/src/mod_staticfile.c
@@ -352,7 +352,7 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
size_t k;
int s_len;
stat_cache_entry *sce = NULL;
- buffer *mtime;
+ buffer *mtime = NULL;
data_string *ds;
int allow_caching = 1;
@@ -450,7 +450,9 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
}
}
- response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
+ if (con->conf.range_requests) {
+ response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
+ }
if (allow_caching) {
if (p->conf.etags_used && con->etag_flags != 0 && !buffer_is_empty(sce->etag)) {
@@ -483,7 +485,23 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
/* if the value is the same as our ETag, we do a Range-request,
* otherwise a full 200 */
- if (!buffer_is_equal(ds->value, con->physical.etag)) {
+ if (ds->value->ptr[0] == '"') {
+ /**
+ * client wants a ETag
+ */
+ if (!con->physical.etag) {
+ do_range_request = 0;
+ } else if (!buffer_is_equal(ds->value, con->physical.etag)) {
+ do_range_request = 0;
+ }
+ } else if (!mtime) {
+ /**
+ * we don't have a Last-Modified and can match the If-Range:
+ *
+ * sending all
+ */
+ do_range_request = 0;
+ } else if (!buffer_is_equal(ds->value, mtime)) {
do_range_request = 0;
}
}
diff --git a/src/mod_status.c b/src/mod_status.c
index 80c0040..028cbc7 100644
--- a/src/mod_status.c
+++ b/src/mod_status.c
@@ -560,6 +560,8 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c
double avg;
time_t ts;
char buf[32];
+ unsigned int k;
+ unsigned int l;
b = chunkqueue_get_append_buffer(con->write_queue);
@@ -588,6 +590,22 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c
buffer_append_long(b, srv->conns->used);
BUFFER_APPEND_STRING_CONST(b, "\n");
+ BUFFER_APPEND_STRING_CONST(b, "IdleServers: ");
+ buffer_append_long(b, srv->conns->size - srv->conns->used);
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+
+ /* output scoreboard */
+ BUFFER_APPEND_STRING_CONST(b, "Scoreboard: ");
+ for (k = 0; k < srv->conns->used; k++) {
+ connection *c = srv->conns->ptr[k];
+ const char *state = connection_get_short_state(c->state);
+ buffer_append_string_len(b, state, 1);
+ }
+ for (l = 0; l < srv->conns->size - srv->conns->used; l++) {
+ BUFFER_APPEND_STRING_CONST(b, "_");
+ }
+ BUFFER_APPEND_STRING_CONST(b, "\n");
+
/* set text/plain output */
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
diff --git a/src/mod_userdir.c b/src/mod_userdir.c
index 2fef0f2..e664bf2 100644
--- a/src/mod_userdir.c
+++ b/src/mod_userdir.c
@@ -21,6 +21,7 @@ typedef struct {
array *include_user;
buffer *path;
buffer *basepath;
+ unsigned short letterhomes;
} plugin_config;
typedef struct {
@@ -87,6 +88,7 @@ SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
{ "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
{ "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+ { "userdir.letterhomes", NULL, T_CONFIG_BOOLEAN,T_CONFIG_SCOPE_CONNECTION }, /* 4 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -102,11 +104,13 @@ SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
s->include_user = array_init();
s->path = buffer_init();
s->basepath = buffer_init();
+ s->letterhomes = 0;
cv[0].destination = s->path;
cv[1].destination = s->exclude_user;
cv[2].destination = s->include_user;
cv[3].destination = s->basepath;
+ cv[4].destination = &(s->letterhomes);
p->config_storage[i] = s;
@@ -128,6 +132,7 @@ static int mod_userdir_patch_connection(server *srv, connection *con, plugin_dat
PATCH(exclude_user);
PATCH(include_user);
PATCH(basepath);
+ PATCH(letterhomes);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -149,6 +154,8 @@ static int mod_userdir_patch_connection(server *srv, connection *con, plugin_dat
PATCH(include_user);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
PATCH(basepath);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.letterhomes"))) {
+ PATCH(letterhomes);
}
}
}
@@ -170,6 +177,11 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
mod_userdir_patch_connection(srv, con, p);
+ /* enforce the userdir.path to be set in the config, ugly fix for #1587;
+ * should be replaced with a clean .enabled option in 1.5
+ */
+ if (p->conf.path->used == 0) return HANDLER_GO_ON;
+
uri_len = con->uri.path->used - 1;
/* /~user/foo.html -> /home/user/public_html/foo.html */
@@ -253,6 +265,10 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) {
buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
BUFFER_APPEND_SLASH(p->temp_path);
+ if (p->conf.letterhomes) {
+ buffer_append_string_len(p->temp_path, p->username->ptr, 1);
+ BUFFER_APPEND_SLASH(p->temp_path);
+ }
buffer_append_string_buffer(p->temp_path, p->username);
}
BUFFER_APPEND_SLASH(p->temp_path);
diff --git a/src/network_linux_sendfile.c b/src/network_linux_sendfile.c
index 6586efb..5f01812 100644
--- a/src/network_linux_sendfile.c
+++ b/src/network_linux_sendfile.c
@@ -162,6 +162,7 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd,
switch (errno) {
case EAGAIN:
case EINTR:
+ /* ok, we can't send more, let's try later again */
r = 0;
break;
case EPIPE:
@@ -172,9 +173,7 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd,
"sendfile failed:", strerror(errno), fd);
return -1;
}
- }
-
- if (r == 0) {
+ } else if (r == 0) {
int oerrno = errno;
/* We got an event to write but we wrote nothing
*
diff --git a/src/network_openssl.c b/src/network_openssl.c
index e6df35e..ff9fb97 100644
--- a/src/network_openssl.c
+++ b/src/network_openssl.c
@@ -58,31 +58,6 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
}
- /* evil hack for opera 9.01 and 8.54 and earlier
- *
- * opera hangs if the trainling 0\r\n\r\n is in a seperate SSL-packet
- *
- * we try to move the packet into the previous mem-chunk if possible
- */
- if ((cq == con->write_queue) &&
- (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) &&
- (con->file_finished)) {
- /* merge the last chunk into the previous chunk */
-
- for(c = cq->first; c && c->next && c->next->next; c = c->next);
-
- if (c &&
- c->type == MEM_CHUNK &&
- c->next &&
- c->next->type == MEM_CHUNK &&
- c->next->mem->used == sizeof("0\r\n\r\n") &&
- 0 == strcmp(c->next->mem->ptr, "0\r\n\r\n")) {
- buffer_append_string_buffer(c->mem, c->next->mem);
-
- c->next->mem->used = 0;
- }
- }
-
for(c = cq->first; c; c = c->next) {
int chunk_finished = 0;
@@ -128,6 +103,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
/* no, but we have errno */
switch(errno) {
case EPIPE:
+ case ECONNRESET:
return -2;
default:
log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
@@ -230,6 +206,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu
/* no, but we have errno */
switch(errno) {
case EPIPE:
+ case ECONNRESET:
return -2;
default:
log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
diff --git a/src/response.c b/src/response.c
index b8775f0..bc2bdd1 100644
--- a/src/response.c
+++ b/src/response.c
@@ -19,6 +19,7 @@
#include "stat_cache.h"
#include "chunk.h"
+#include "configfile.h"
#include "connections.h"
#include "plugin.h"
@@ -59,7 +60,8 @@ int http_response_write_header(server *srv, connection *con) {
ds = (data_string *)con->response.headers->data[i];
if (ds->value->used && ds->key->used &&
- 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
+ 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
+ 0 != strncmp(ds->key->ptr, "X-Sendfile", sizeof("X-Sendfile") - 1)) {
if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
@@ -149,6 +151,9 @@ handler_t http_response_prepare(server *srv, connection *con) {
*
* */
+ config_cond_cache_reset(srv, con);
+ config_setup_connection(srv, con); // Perhaps this could be removed at other places.
+
if (con->conf.log_condition_handling) {
log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
}
@@ -180,11 +185,13 @@ handler_t http_response_prepare(server *srv, connection *con) {
buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
buffer_to_lower(con->uri.authority);
+ config_patch_connection(srv, con, COMP_HTTP_SCHEME); /* Scheme: */
config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
- config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
+ config_patch_connection(srv, con, COMP_HTTP_REMOTE_IP); /* Client-IP */
config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
- config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
+ config_patch_connection(srv, con, COMP_HTTP_USER_AGENT);/* User-Agent: */
config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
+ config_patch_connection(srv, con, COMP_HTTP_REQUEST_METHOD); /* REQUEST_METHOD */
/** their might be a fragment which has to be cut away */
if (NULL != (qstr = strchr(con->request.uri->ptr, '#'))) {
@@ -270,7 +277,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
*/
config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
- config_patch_connection(srv, con, COMP_HTTP_QUERYSTRING); /* HTTPqs */
+ config_patch_connection(srv, con, COMP_HTTP_QUERY_STRING); /* HTTPqs */
/* do we have to downgrade to 1.0 ? */
if (!con->conf.allow_http11) {
@@ -547,17 +554,14 @@ handler_t http_response_prepare(server *srv, connection *con) {
buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
do {
- struct stat st;
-
if (slash) {
buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
} else {
buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
}
- if (0 == stat(con->physical.path->ptr, &(st)) &&
- S_ISREG(st.st_mode)) {
- found = 1;
+ if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+ found = S_ISREG(sce->st.st_mode);
break;
}
@@ -589,6 +593,20 @@ handler_t http_response_prepare(server *srv, connection *con) {
return HANDLER_FINISHED;
}
+#ifdef HAVE_LSTAT
+ if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
+ con->http_status = 403;
+
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction");
+ log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
+ }
+
+ buffer_reset(con->physical.path);
+ return HANDLER_FINISHED;
+ };
+#endif
+
/* we have a PATHINFO */
if (pathinfo) {
buffer_copy_string(con->request.pathinfo, pathinfo);
@@ -631,8 +649,14 @@ handler_t http_response_prepare(server *srv, connection *con) {
/* if we are still here, no one wanted the file, status 403 is ok I think */
- if (con->mode == DIRECT) {
- con->http_status = 403;
+ if (con->mode == DIRECT && con->http_status == 0) {
+ switch (con->request.http_method) {
+ case HTTP_METHOD_OPTIONS:
+ con->http_status = 200;
+ break;
+ default:
+ con->http_status = 403;
+ }
return HANDLER_FINISHED;
}
diff --git a/src/server.c b/src/server.c
index 132eb32..585a973 100644
--- a/src/server.c
+++ b/src/server.c
@@ -697,9 +697,6 @@ int main (int argc, char **argv) {
}
}
- /* #372: solaris need some fds extra for devpoll */
- if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
-
if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
} else {
@@ -759,6 +756,19 @@ int main (int argc, char **argv) {
return -1;
}
+#ifdef HAVE_PWD_H
+ /*
+ * Change group before chroot, when we have access
+ * to /etc/group
+ * */
+ if (srv->srvconf.groupname->used) {
+ setgid(grp->gr_gid);
+ setgroups(0, NULL);
+ if (srv->srvconf.username->used) {
+ initgroups(srv->srvconf.username->ptr, grp->gr_gid);
+ }
+ }
+#endif
#ifdef HAVE_CHROOT
if (srv->srvconf.changeroot->used) {
tzset();
@@ -775,15 +785,7 @@ int main (int argc, char **argv) {
#endif
#ifdef HAVE_PWD_H
/* drop root privs */
- if (srv->srvconf.groupname->used) {
- setgid(grp->gr_gid);
- setgroups(0, NULL);
- }
-
if (srv->srvconf.username->used) {
- if (srv->srvconf.groupname->used) {
- initgroups(srv->srvconf.username->ptr, grp->gr_gid);
- }
setuid(pwd->pw_uid);
}
#endif
@@ -891,6 +893,17 @@ int main (int argc, char **argv) {
pid_fd = -1;
}
+ // Close stderr ASAP in the child process to make sure that nothing
+ // is being written to that fd which may not be valid anymore.
+ if (-1 == log_error_open(srv)) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "Opening errorlog failed. Going down.");
+
+ plugins_free(srv);
+ network_close(srv);
+ server_free(srv);
+ return -1;
+ }
+
if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
@@ -941,15 +954,7 @@ int main (int argc, char **argv) {
return -1;
}
- if (-1 == log_error_open(srv)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "opening errorlog failed, dying");
- plugins_free(srv);
- network_close(srv);
- server_free(srv);
- return -1;
- }
#ifdef HAVE_SIGACTION
diff --git a/src/spawn-fcgi.c b/src/spawn-fcgi.c
index 8237e79..60e02bd 100644
--- a/src/spawn-fcgi.c
+++ b/src/spawn-fcgi.c
@@ -37,7 +37,7 @@ typedef int socklen_t;
#endif
#ifdef HAVE_SYS_UN_H
-int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const char *unixsocket, int child_count, int pid_fd, int nofork) {
+int fcgi_spawn_connection(char *appPath, char **appArgv, char *addr, unsigned short port, const char *unixsocket, int child_count, int pid_fd, int nofork) {
int fcgi_fd;
int socket_type, status;
struct timeval tv = { 0, 100 * 1000 };
@@ -48,6 +48,9 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const
socklen_t servlen;
+ pid_t child;
+ int val;
+
if (child_count < 2) {
child_count = 5;
}
@@ -71,6 +74,25 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const
#endif
socket_type = AF_UNIX;
fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
+
+ /* check if some backend is listening on the socket
+ * as if we delete the socket-file and rebind there will be no "socket already in use" error
+ */
+ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
+ fprintf(stderr, "%s.%d\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ if (-1 != connect(fcgi_fd, fcgi_addr, servlen)) {
+ fprintf(stderr, "%s.%d: socket is already used, can't spawn\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
+
+ /* cleanup previous socket if it exists */
+ unlink(unixsocket);
+ close(fcgi_fd);
} else {
fcgi_addr_in.sin_family = AF_INET;
if (addr != NULL) {
@@ -85,144 +107,128 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const
fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
}
+ /* open socket */
if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
fprintf(stderr, "%s.%d\n",
__FILE__, __LINE__);
return -1;
}
- if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
- /* server is not up, spawn in */
- pid_t child;
- int val;
+ val = 1;
+ if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
+ fprintf(stderr, "%s.%d\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
- if (unixsocket) unlink(unixsocket);
+ /* create socket */
+ if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
+ fprintf(stderr, "%s.%d: bind failed: %s\n",
+ __FILE__, __LINE__,
+ strerror(errno));
+ return -1;
+ }
- close(fcgi_fd);
+ if (-1 == listen(fcgi_fd, 1024)) {
+ fprintf(stderr, "%s.%d: fd = -1\n",
+ __FILE__, __LINE__);
+ return -1;
+ }
- /* reopen socket */
- if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
- fprintf(stderr, "%s.%d\n",
- __FILE__, __LINE__);
- return -1;
- }
+ if (!nofork) {
+ child = fork();
+ } else {
+ child = 0;
+ }
- val = 1;
- if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
- fprintf(stderr, "%s.%d\n",
- __FILE__, __LINE__);
- return -1;
- }
+ switch (child) {
+ case 0: {
+ char cgi_childs[64];
- /* create socket */
- if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
- fprintf(stderr, "%s.%d: bind failed: %s\n",
- __FILE__, __LINE__,
- strerror(errno));
- return -1;
- }
+ int i = 0;
- if (-1 == listen(fcgi_fd, 1024)) {
- fprintf(stderr, "%s.%d: fd = -1\n",
- __FILE__, __LINE__);
- return -1;
- }
+ /* is safe as we limit to 256 childs */
+ sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
- if (!nofork) {
- child = fork();
- } else {
- child = 0;
+ if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
+ close(FCGI_LISTENSOCK_FILENO);
+ dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
+ close(fcgi_fd);
}
- switch (child) {
- case 0: {
- char cgi_childs[64];
- char *b;
-
- int i = 0;
-
- /* is save as we limit to 256 childs */
- sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
+ /* we don't need the client socket */
+ for (i = 3; i < 256; i++) {
+ close(i);
+ }
- if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
- close(FCGI_LISTENSOCK_FILENO);
- dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
- close(fcgi_fd);
- }
+ /* create environment */
- /* we don't need the client socket */
- for (i = 3; i < 256; i++) {
- close(i);
- }
+ putenv(cgi_childs);
- /* create environment */
+ /* fork and replace shell */
+ if (appArgv) {
+ execv(appArgv[0], appArgv);
- putenv(cgi_childs);
-
- /* fork and replace shell */
- b = malloc(strlen("exec ") + strlen(appPath) + 1);
+ } else {
+ char *b = malloc(strlen("exec ") + strlen(appPath) + 1);
strcpy(b, "exec ");
strcat(b, appPath);
/* exec the cgi */
execl("/bin/sh", "sh", "-c", b, (char *)NULL);
+ }
- exit(errno);
+ exit(errno);
+
+ break;
+ }
+ case -1:
+ /* error */
+ break;
+ default:
+ /* father */
+
+ /* wait */
+ select(0, NULL, NULL, NULL, &tv);
+
+ switch (waitpid(child, &status, WNOHANG)) {
+ case 0:
+ fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
+ __FILE__, __LINE__,
+ child);
+
+ /* write pid file */
+ if (pid_fd != -1) {
+ /* assume a 32bit pid_t */
+ char pidbuf[12];
+
+ snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
+
+ write(pid_fd, pidbuf, strlen(pidbuf));
+ close(pid_fd);
+ pid_fd = -1;
+ }
break;
- }
case -1:
- /* error */
break;
default:
- /* father */
-
- /* wait */
- select(0, NULL, NULL, NULL, &tv);
-
- switch (waitpid(child, &status, WNOHANG)) {
- case 0:
- fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
+ if (WIFEXITED(status)) {
+ fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
+ __FILE__, __LINE__,
+ WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
+ } else if (WIFSIGNALED(status)) {
+ fprintf(stderr, "%s.%d: child signaled: %d\n",
+ __FILE__, __LINE__,
+ WTERMSIG(status));
+ } else {
+ fprintf(stderr, "%s.%d: child died somehow: %d\n",
__FILE__, __LINE__,
- child);
-
- /* write pid file */
- if (pid_fd != -1) {
- /* assume a 32bit pid_t */
- char pidbuf[12];
-
- snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
-
- write(pid_fd, pidbuf, strlen(pidbuf));
- close(pid_fd);
- pid_fd = -1;
- }
-
- break;
- case -1:
- break;
- default:
- if (WIFEXITED(status)) {
- fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
- __FILE__, __LINE__,
- WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
- } else if (WIFSIGNALED(status)) {
- fprintf(stderr, "%s.%d: child signaled: %d\n",
- __FILE__, __LINE__,
- WTERMSIG(status));
- } else {
- fprintf(stderr, "%s.%d: child died somehow: %d\n",
- __FILE__, __LINE__,
- status);
- }
+ status);
}
-
- break;
}
- } else {
- fprintf(stderr, "%s.%d: socket is already used, can't spawn\n",
- __FILE__, __LINE__);
- return -1;
+
+ break;
}
close(fcgi_fd);
@@ -239,9 +245,12 @@ void show_version () {
}
void show_help () {
- char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
-" - spawns fastcgi processes\n" \
-"usage:\n" \
+ char *b = \
+"Usage: spawn-fcgi [options] -- <fcgiapp> [fcgi app arguments]\n" \
+"\n" \
+"spawn-fcgi v" PACKAGE_VERSION " - spawns fastcgi processes\n" \
+"\n" \
+"Options:\n" \
" -f <fcgiapp> filename of the fcgi-application\n" \
" -a <addr> bind to ip address\n" \
" -p <port> bind to tcp-port\n" \
@@ -264,6 +273,7 @@ int main(int argc, char **argv) {
char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
*groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
*addr = NULL;
+ char **fcgi_app_argv = { NULL };
unsigned short port = 0;
int child_count = 5;
int i_am_root, o;
@@ -274,10 +284,10 @@ int main(int argc, char **argv) {
i_am_root = (getuid() == 0);
- while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
+ while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
switch(o) {
case 'f': fcgi_app = optarg; break;
- case 'a': addr = optarg;/* ip addr */ break;
+ case 'a': addr = optarg;/* ip addr */ break;
case 'p': port = strtol(optarg, NULL, 10);/* port */ break;
case 'C': child_count = strtol(optarg, NULL, 10);/* */ break;
case 's': unixsocket = optarg; /* unix-domain socket */ break;
@@ -294,7 +304,11 @@ int main(int argc, char **argv) {
}
}
- if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
+ if (optind < argc) {
+ fcgi_app_argv = &argv[optind];
+ }
+
+ if ((fcgi_app == NULL && fcgi_app_argv == NULL) || (port == 0 && unixsocket == NULL)) {
show_help();
return -1;
}
@@ -404,6 +418,18 @@ int main(int argc, char **argv) {
}
}
+ /*
+ * Change group before chroot, when we have access
+ * to /etc/group
+ */
+ if (groupname) {
+ setgid(grp->gr_gid);
+ setgroups(0, NULL);
+ if (username) {
+ initgroups(username, grp->gr_gid);
+ }
+ }
+
if (changeroot) {
if (-1 == chroot(changeroot)) {
fprintf(stderr, "%s.%d: %s %s\n",
@@ -420,18 +446,12 @@ int main(int argc, char **argv) {
}
/* drop root privs */
- if (groupname) {
- setgid(grp->gr_gid);
- }
if (username) {
- if (groupname) {
- initgroups(username, grp->gr_gid);
- }
setuid(pwd->pw_uid);
}
}
- return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
+ return fcgi_spawn_connection(fcgi_app, fcgi_app_argv, addr, port, unixsocket, child_count, pid_fd, nofork);
}
#else
int main() {
diff --git a/src/stream.c b/src/stream.c
index aac6cf7..d249647 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -64,6 +64,7 @@ int stream_open(stream *f, buffer *fn) {
NULL);
if (!mh) {
+/*
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
@@ -73,7 +74,7 @@ int stream_open(stream *f, buffer *fn) {
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
-
+*/
return -1;
}
diff --git a/tests/LightyTest.pm b/tests/LightyTest.pm
index 33eca61..6e3f5c2 100755
--- a/tests/LightyTest.pm
+++ b/tests/LightyTest.pm
@@ -72,7 +72,7 @@ sub stop_proc {
if (defined $pid) {
kill('TERM',$pid) or return -1;
- select(undef, undef, undef, 0.01);
+ select(undef, undef, undef, 0.1);
}
return 0;
@@ -92,6 +92,8 @@ sub start_proc {
unlink($self->{LIGHTTPD_PIDFILE});
if (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'strace') {
system("strace -tt -s 512 -o strace ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
+ } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'truss') {
+ system("/usr/dtrctkit/bin/dtruss -d -e ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." 2> strace &");
} elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'valgrind') {
system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --log-file=valgrind ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
} else {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dfdf06b..c353730 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -31,14 +31,20 @@ CONFS=fastcgi-10.conf \
core-response.t \
core-keepalive.t \
core.t \
+ mod-proxy.t \
+ proxy.conf \
+ mod-secdownload.t \
mod-access.t \
mod-auth.t \
mod-cgi.t \
mod-compress.t \
mod-fastcgi.t \
mod-redirect.t \
- mod-userdir.t \
mod-rewrite.t \
+ mod-userdir.t \
+ env-variables.t \
+ env-variables.conf \
+ symlink.t \
request.t \
mod-ssi.t \
LightyTest.pm \
@@ -49,12 +55,12 @@ CONFS=fastcgi-10.conf \
core-404-handler.t \
404-handler.conf
-
TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
EXTRA_DIST=wrapper.sh lighttpd.conf \
lighttpd.user \
lighttpd.htpasswd \
+ SConscript \
$(CONFS) \
$(TESTS)
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 429efd1..4a792b1 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -244,14 +244,20 @@ CONFS = fastcgi-10.conf \
core-response.t \
core-keepalive.t \
core.t \
+ mod-proxy.t \
+ proxy.conf \
+ mod-secdownload.t \
mod-access.t \
mod-auth.t \
mod-cgi.t \
mod-compress.t \
mod-fastcgi.t \
mod-redirect.t \
- mod-userdir.t \
mod-rewrite.t \
+ mod-userdir.t \
+ env-variables.t \
+ env-variables.conf \
+ symlink.t \
request.t \
mod-ssi.t \
LightyTest.pm \
@@ -266,6 +272,7 @@ TESTS_ENVIRONMENT = $(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
EXTRA_DIST = wrapper.sh lighttpd.conf \
lighttpd.user \
lighttpd.htpasswd \
+ SConscript \
$(CONFS) \
$(TESTS)
diff --git a/tests/SConscript b/tests/SConscript
new file mode 100644
index 0000000..07c76c9
--- /dev/null
+++ b/tests/SConscript
@@ -0,0 +1,45 @@
+Import('env')
+
+tests = Split('prepare.sh \
+ run-tests.pl \
+ cleanup.sh')
+
+extra_dist = Split('fastcgi-10.conf \
+ fastcgi-auth.conf \
+ fastcgi-responder.conf \
+ fastcgi-13.conf \
+ bug-06.conf \
+ bug-12.conf \
+ core-var-include.t \
+ var-include.conf \
+ var-include-sub.conf \
+ condition.conf \
+ core-condition.t \
+ core-request.t \
+ core-response.t \
+ core-keepalive.t \
+ core.t \
+ mod-access.t \
+ mod-auth.t \
+ mod-cgi.t \
+ mod-compress.t \
+ mod-fastcgi.t \
+ mod-redirect.t \
+ mod-userdir.t \
+ mod-rewrite.t \
+ request.t \
+ mod-ssi.t \
+ LightyTest.pm \
+ mod-setenv.t')
+
+t = env.Command('foo1', 'prepare.sh', '(cd ./tests/; ./prepare.sh; cd ..)')
+t += env.Command('foo2', 'run-tests.pl', '( cd ./tests/; SHELL=/bin/sh ./run-tests.pl; cd ..)')
+t += env.Command('foo3', 'cleanup.sh', '(cd ./tests/; ./cleanup.sh; cd ..)')
+
+if env['LIBFCGI']:
+ fcgis = []
+ fcgis += env.Program("fcgi-auth", "fcgi-auth.c", LIBS=env['LIBFCGI'])
+ fcgis += env.Program("fcgi-responder", "fcgi-responder.c", LIBS=env['LIBFCGI'])
+ env.Depends(t, fcgis)
+
+env.Alias('check', t )
diff --git a/tests/cachable.t b/tests/cachable.t
index 0d1e1b4..605a68f 100755
--- a/tests/cachable.t
+++ b/tests/cachable.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core-404-handler.t b/tests/core-404-handler.t
index b9c5df1..599ade2 100644
--- a/tests/core-404-handler.t
+++ b/tests/core-404-handler.t
@@ -10,10 +10,10 @@
# returning no status -> 200
#
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core-condition.t b/tests/core-condition.t
index 96b05d8..53919a1 100755
--- a/tests/core-condition.t
+++ b/tests/core-condition.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core-keepalive.t b/tests/core-keepalive.t
index 8d91b4c..b4f51f9 100755
--- a/tests/core-keepalive.t
+++ b/tests/core-keepalive.t
@@ -1,10 +1,9 @@
#!/usr/bin/env perl
-
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core-request.t b/tests/core-request.t
index fc6e25f..a24777f 100755
--- a/tests/core-request.t
+++ b/tests/core-request.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core-response.t b/tests/core-response.t
index c7a158c..ff2cf1d 100755
--- a/tests/core-response.t
+++ b/tests/core-response.t
@@ -1,10 +1,9 @@
#!/usr/bin/env perl
-
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core-var-include.t b/tests/core-var-include.t
index b26790f..8161751 100755
--- a/tests/core-var-include.t
+++ b/tests/core-var-include.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/core.t b/tests/core.t
index 6de933c..b196666 100755
--- a/tests/core.t
+++ b/tests/core.t
@@ -1,10 +1,9 @@
#!/usr/bin/env perl
-
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/env-variables.conf b/tests/env-variables.conf
new file mode 100644
index 0000000..043e788
--- /dev/null
+++ b/tests/env-variables.conf
@@ -0,0 +1 @@
+server.document-root = env.CWD
diff --git a/tests/env-variables.t b/tests/env-variables.t
new file mode 100644
index 0000000..ee48ee9
--- /dev/null
+++ b/tests/env-variables.t
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+BEGIN {
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
+}
+
+use strict;
+use IO::Socket;
+use Test::More tests => 2;
+use LightyTest;
+
+my $tf = LightyTest->new();
+$tf->{CONFIGFILE} = 'env-variables.conf';
+
+TODO: {
+ local $TODO = 'we still crash on undefined environment variables';
+ ok($tf->start_proc == 0, "Starting lighttpd");
+ ok($tf->stop_proc == 0, "Stopping lighttpd");
+};
diff --git a/tests/fcgi-auth.c b/tests/fcgi-auth.c
index bb7ae69..26bbd0f 100644
--- a/tests/fcgi-auth.c
+++ b/tests/fcgi-auth.c
@@ -1,4 +1,6 @@
+#ifdef HAVE_CONFIG_H
#include "config.h"
+#endif
#ifdef HAVE_FASTCGI_FASTCGI_H
#include <fastcgi/fcgi_stdio.h>
#else
diff --git a/tests/fcgi-responder.c b/tests/fcgi-responder.c
index 9270295..721c2ce 100644
--- a/tests/fcgi-responder.c
+++ b/tests/fcgi-responder.c
@@ -1,4 +1,6 @@
+#ifdef HAVE_CONFIG_H
#include "config.h"
+#endif
#ifdef HAVE_FASTCGI_FASTCGI_H
#include <fastcgi/fcgi_stdio.h>
#else
diff --git a/tests/lowercase.t b/tests/lowercase.t
index b9ee8e8..f6f6f2c 100755
--- a/tests/lowercase.t
+++ b/tests/lowercase.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-access.t b/tests/mod-access.t
index 82275df..58c01ac 100755
--- a/tests/mod-access.t
+++ b/tests/mod-access.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-auth.t b/tests/mod-auth.t
index cfeb042..475a5f6 100755
--- a/tests/mod-auth.t
+++ b/tests/mod-auth.t
@@ -1,14 +1,14 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
use IO::Socket;
-use Test::More tests => 13;
+use Test::More tests => 14;
use LightyTest;
my $tf = LightyTest->new();
@@ -48,6 +48,16 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des)');
+$t->{REQUEST} = ( <<EOF
+GET /server-config HTTP/1.0
+Host: auth-htpasswd.example.org
+Authorization: basic ZGVzOmRlcw==
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des) (lowercase)');
+
+
SKIP: {
skip "no md5 for crypt under cygwin", 1 if $^O eq 'cygwin';
$t->{REQUEST} = ( <<EOF
diff --git a/tests/mod-cgi.t b/tests/mod-cgi.t
index b89a1af..24777ca 100755
--- a/tests/mod-cgi.t
+++ b/tests/mod-cgi.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-compress.t b/tests/mod-compress.t
index f243832..4fa66db 100755
--- a/tests/mod-compress.t
+++ b/tests/mod-compress.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-fastcgi.t b/tests/mod-fastcgi.t
index 2c1dedb..44b4b03 100755
--- a/tests/mod-fastcgi.t
+++ b/tests/mod-fastcgi.t
@@ -1,13 +1,13 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
-use Test::More tests => 46;
+use Test::More tests => 47;
use LightyTest;
my $tf = LightyTest->new();
@@ -223,7 +223,7 @@ EOF
}
SKIP: {
- skip "no php found", 4 unless -x "/usr/bin/php-cgi";
+ skip "no php found", 5 unless -x "/usr/bin/php-cgi";
$tf->{CONFIGFILE} = 'fastcgi-13.conf';
ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
$t->{REQUEST} = ( <<EOF
@@ -234,6 +234,15 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'FastCGI + local spawning');
+ $t->{REQUEST} = ( <<EOF
+HEAD /indexfile/index.php HTTP/1.0
+Host: www.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-Content-Length' => '0' } ];
+ # Of course a valid content-length != 0 would be ok, but we assume for now that such one is not generated.
+ ok($tf->handle_http($t) == 0, 'Check for buggy content length with HEAD');
+
$t->{REQUEST} = ( <<EOF
GET /get-env.php?env=MAIL HTTP/1.0
Host: www.example.org
diff --git a/tests/mod-proxy.t b/tests/mod-proxy.t
new file mode 100755
index 0000000..b43c465
--- /dev/null
+++ b/tests/mod-proxy.t
@@ -0,0 +1,53 @@
+#!/usr/bin/env perl
+BEGIN {
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
+}
+
+use strict;
+use IO::Socket;
+use Test::More tests => 6;
+use LightyTest;
+
+my $tf_real = LightyTest->new();
+my $tf_proxy = LightyTest->new();
+
+my $t;
+
+## we need two procs
+## 1. the real webserver
+## 2. the proxy server
+
+$tf_real->{PORT} = 2048;
+$tf_real->{CONFIGFILE} = 'lighttpd.conf';
+$tf_real->{LIGHTTPD_PIDFILE} = $tf_real->{TESTDIR}.'/tmp/lighttpd/lighttpd.pid';
+
+$tf_proxy->{PORT} = 2050;
+$tf_proxy->{CONFIGFILE} = 'proxy.conf';
+$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{TESTDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
+
+ok($tf_real->start_proc == 0, "Starting lighttpd") or die();
+
+ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
+
+$t->{REQUEST} = ( <<EOF
+GET /index.html HTTP/1.0
+Host: www.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ok($tf_proxy->handle_http($t) == 0, 'valid request');
+
+$t->{REQUEST} = ( <<EOF
+GET /index.html HTTP/1.0
+Host: www.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'Apache 1.3.29' } ];
+ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
+
+ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
+
+ok($tf_real->stop_proc == 0, "Stopping lighttpd");
diff --git a/tests/mod-redirect.t b/tests/mod-redirect.t
index 076a4b3..14669d9 100755
--- a/tests/mod-redirect.t
+++ b/tests/mod-redirect.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-rewrite.t b/tests/mod-rewrite.t
index a1e2193..4de8c10 100755
--- a/tests/mod-rewrite.t
+++ b/tests/mod-rewrite.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-secdownload.t b/tests/mod-secdownload.t
new file mode 100755
index 0000000..c8cad38
--- /dev/null
+++ b/tests/mod-secdownload.t
@@ -0,0 +1,79 @@
+#!/usr/bin/env perl
+BEGIN {
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
+}
+
+use strict;
+use IO::Socket;
+use Test::More tests => 7;
+use LightyTest;
+use Digest::MD5 qw(md5_hex);
+
+my $tf = LightyTest->new();
+my $t;
+
+ok($tf->start_proc == 0, "Starting lighttpd") or die();
+
+my $secret = "verysecret";
+my $f = "/index.html";
+my $thex = sprintf("%08x", time);
+my $m = md5_hex($secret.$f.$thex);
+
+$t->{REQUEST} = ( <<EOF
+GET /sec/$m/$thex$f HTTP/1.0
+Host: vvv.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+
+ok($tf->handle_http($t) == 0, 'secdownload');
+
+$thex = sprintf("%08x", time - 1800);
+$m = md5_hex($secret.$f.$thex);
+
+$t->{REQUEST} = ( <<EOF
+GET /sec/$m/$thex$f HTTP/1.0
+Host: vvv.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 410 } ];
+
+ok($tf->handle_http($t) == 0, 'secdownload - gone (timeout)');
+
+$t->{REQUEST} = ( <<EOF
+GET /sec$f HTTP/1.0
+Host: vvv.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
+
+ok($tf->handle_http($t) == 0, 'secdownload - direct access');
+
+$t->{REQUEST} = ( <<EOF
+GET $f HTTP/1.0
+Host: www.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+
+ok($tf->handle_http($t) == 0, 'secdownload - conditional access');
+
+
+$f = "/noexists";
+$thex = sprintf("%08x", time);
+$m = md5_hex($secret.$f.$thex);
+
+$t->{REQUEST} = ( <<EOF
+GET /sec/$m/$thex$f HTTP/1.0
+Host: vvv.example.org
+EOF
+ );
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
+
+ok($tf->handle_http($t) == 0, 'secdownload - timeout');
+
+ok($tf->stop_proc == 0, "Stopping lighttpd");
+
diff --git a/tests/mod-setenv.t b/tests/mod-setenv.t
index a5c2b7e..1e56301 100755
--- a/tests/mod-setenv.t
+++ b/tests/mod-setenv.t
@@ -1,10 +1,9 @@
#!/usr/bin/env perl
-
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-ssi.t b/tests/mod-ssi.t
index a6b021b..d5d69db 100755
--- a/tests/mod-ssi.t
+++ b/tests/mod-ssi.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/mod-userdir.t b/tests/mod-userdir.t
index 13a8e1b..40f55ef 100755
--- a/tests/mod-userdir.t
+++ b/tests/mod-userdir.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/proxy.conf b/tests/proxy.conf
new file mode 100644
index 0000000..2d1ab0d
--- /dev/null
+++ b/tests/proxy.conf
@@ -0,0 +1,156 @@
+server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
+server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
+
+## bind to port (default: 80)
+server.port = 2050
+
+## bind to localhost (default: all interfaces)
+server.bind = "localhost"
+server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
+server.name = "www.example.org"
+server.tag = "Proxy"
+
+server.dir-listing = "enable"
+
+#server.event-handler = "linux-sysepoll"
+#server.event-handler = "linux-rtsig"
+
+#server.modules.path = ""
+server.modules = (
+ "mod_rewrite",
+ "mod_setenv",
+ "mod_access",
+ "mod_auth",
+# "mod_httptls",
+ "mod_status",
+ "mod_expire",
+ "mod_simple_vhost",
+ "mod_redirect",
+# "mod_evhost",
+# "mod_localizer",
+ "mod_fastcgi",
+ "mod_proxy",
+ "mod_cgi",
+ "mod_compress",
+ "mod_userdir",
+ "mod_accesslog" )
+
+server.indexfiles = ( "index.php", "index.html",
+ "index.htm", "default.htm" )
+
+
+######################## MODULE CONFIG ############################
+
+
+accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
+
+mimetype.assign = ( ".png" => "image/png",
+ ".jpg" => "image/jpeg",
+ ".jpeg" => "image/jpeg",
+ ".gif" => "image/gif",
+ ".html" => "text/html",
+ ".htm" => "text/html",
+ ".pdf" => "application/pdf",
+ ".swf" => "application/x-shockwave-flash",
+ ".spl" => "application/futuresplash",
+ ".txt" => "text/plain",
+ ".tar.gz" => "application/x-tgz",
+ ".tgz" => "application/x-tgz",
+ ".gz" => "application/x-gzip",
+ ".c" => "text/plain",
+ ".conf" => "text/plain" )
+
+compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
+compress.filetype = ("text/plain", "text/html")
+
+setenv.add-environment = ( "TRAC_ENV" => "foo")
+setenv.add-request-header = ( "FOO" => "foo")
+setenv.add-response-header = ( "BAR" => "foo")
+
+proxy.debug = 1
+proxy.server = ( "" => (
+ "grisu" => (
+ "host" => "127.0.0.1",
+ "port" => 2048,
+ )
+ )
+ )
+
+
+cgi.assign = ( ".pl" => "/usr/bin/perl",
+ ".cgi" => "/usr/bin/perl",
+ ".py" => "/usr/bin/python" )
+
+userdir.include-user = ( "jan" )
+userdir.path = "/"
+
+ssl.engine = "disable"
+ssl.pemfile = "server.pem"
+
+auth.backend = "plain"
+auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
+auth.backend.plain.groupfile = "lighttpd.group"
+
+auth.backend.ldap.hostname = "localhost"
+auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
+auth.backend.ldap.filter = "(uid=$)"
+
+auth.require = ( "/server-status" =>
+ (
+ "method" => "digest",
+ "realm" => "download archiv",
+# "require" => ("group=www", "user=jan", "host=192.168.2.10")
+ "require" => "group=www|user=jan|host=192.168.2.10"
+ ),
+ "/auth.php" =>
+ (
+ "method" => "basic",
+ "realm" => "download archiv",
+# "require" => ("group=www", "user=jan", "host=192.168.2.10")
+ "require" => "user=jan"
+ ),
+ "/server-config" =>
+ (
+ "method" => "basic",
+ "realm" => "download archiv",
+# "require" => ("group=www", "user=jan", "user=weigon", "host=192.168.2.10")
+ "require" => "group=www|user=jan|host=192.168.2.10"
+ )
+ )
+
+url.access-deny = ( "~", ".inc")
+
+url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
+
+url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
+ "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
+
+expire.url = ( "/expire/access" => "access 2 hours",
+ "/expire/modification" => "access plus 1 seconds 2 minutes")
+
+#cache.cache-dir = "/home/weigon/wwwroot/cache/"
+
+#### status module
+status.status-url = "/server-status"
+status.config-url = "/server-config"
+
+$HTTP["host"] == "vvv.example.org" {
+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
+}
+
+$HTTP["host"] == "zzz.example.org" {
+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
+ server.name = "zzz.example.org"
+}
+
+$HTTP["host"] == "no-simple.example.org" {
+ server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
+ server.name = "zzz.example.org"
+}
+
+$HTTP["host"] !~ "(no-simple\.example\.org)" {
+ simple-vhost.document-root = "pages"
+ simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
+ simple-vhost.default-host = "www.example.org"
+}
+
diff --git a/tests/request.t b/tests/request.t
index c153b21..d2c8819 100755
--- a/tests/request.t
+++ b/tests/request.t
@@ -1,9 +1,9 @@
#!/usr/bin/env perl
BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s#/[^/]+$#/#;
- unshift @INC, $srcdir;
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
}
use strict;
diff --git a/tests/run-tests.pl b/tests/run-tests.pl
index 6dae9a8..818f1c2 100755
--- a/tests/run-tests.pl
+++ b/tests/run-tests.pl
@@ -3,7 +3,7 @@
use strict;
use Test::Harness qw(&runtests $verbose);
-$verbose=0;
+$verbose = (defined $ENV{'VERBOSE'} ? $ENV{'VERBOSE'} : 0);;
my $srcdir = (defined $ENV{'srcdir'} ? $ENV{'srcdir'} : '.');
diff --git a/tests/symlink.t b/tests/symlink.t
new file mode 100644
index 0000000..9b275bd
--- /dev/null
+++ b/tests/symlink.t
@@ -0,0 +1,115 @@
+#!/usr/bin/env perl
+BEGIN {
+ # add current source dir to the include-path
+ # we need this for make distcheck
+ (my $srcdir = $0) =~ s,/[^/]+$,/,;
+ unshift @INC, $srcdir;
+}
+
+use strict;
+use IO::Socket;
+use Test::More tests => 10;
+use LightyTest;
+
+my $tf = LightyTest->new();
+my $t;
+my $docroot = $tf->{'TESTDIR'}."/tmp/lighttpd/servers/www.example.org/pages";
+
+sub init_testbed {
+ return 0 unless eval { symlink("",""); 1 };
+ my $f = "$docroot/index.html";
+ my $l = "$docroot/index.xhtml";
+ my $rc = undef;
+ unless (-l $l) {
+ return 0 unless symlink($f,$l);
+ };
+ $f = "$docroot/expire";
+ $l = "$docroot/symlinked";
+ $rc = undef;
+ unless (-l $l) {
+ return 0 unless symlink($f,$l);
+ }
+ return 1;
+};
+
+SKIP: {
+ skip "perl does not support symlinking or setting up the symlinks failed.", 10 unless init_testbed;
+ ok($tf->start_proc == 0, "Starting lighttpd") or die();
+
+# allow case
+# simple file
+ $t->{REQUEST} = ( <<EOF
+GET /index.html HTTP/1.0
+Host: symlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ ok($tf->handle_http($t) == 0, 'allow: simple file');
+
+# symlinked file
+ $t->{REQUEST} = ( <<EOF
+GET /index.xhtml HTTP/1.0
+Host: symlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ ok($tf->handle_http($t) == 0, 'allow: symlinked file');
+
+# directly symlinked dir
+ $t->{REQUEST} = ( <<EOF
+GET /symlinked/ HTTP/1.0
+Host: symlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ ok($tf->handle_http($t) == 0, 'allow: directly symlinked dir');
+
+# symlinked dir in path
+ $t->{REQUEST} = ( <<EOF
+GET /symlinked/access.txt HTTP/1.0
+Host: symlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ ok($tf->handle_http($t) == 0, 'allow: symlinked dir in path');
+
+# deny case
+# simple file
+ $t->{REQUEST} = ( <<EOF
+GET /index.html HTTP/1.0
+Host: nosymlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
+ ok($tf->handle_http($t) == 0, 'deny: simple file');
+
+# symlinked file
+ $t->{REQUEST} = ( <<EOF
+GET /index.xhtml HTTP/1.0
+Host: nosymlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
+ ok($tf->handle_http($t) == 0, 'deny: symlinked file');
+
+# directly symlinked dir
+ $t->{REQUEST} = ( <<EOF
+GET /symlinked/ HTTP/1.0
+Host: nosymlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
+ ok($tf->handle_http($t) == 0, 'deny: directly symlinked dir');
+
+# symlinked dir in path
+ $t->{REQUEST} = ( <<EOF
+GET /symlinked/access.txt HTTP/1.0
+Host: nosymlink.example.org
+EOF
+ );
+ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
+ ok($tf->handle_http($t) == 0, 'deny: symlinked dir in path');
+
+# cleanup
+ ok($tf->stop_proc == 0, "Stopping lighttpd");
+};