summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore15
-rw-r--r--AUTHORS6
-rw-r--r--CMakeLists.txt27
-rw-r--r--COPYING31
-rw-r--r--ChangeLog4031
-rw-r--r--INSTALL32
-rw-r--r--INSTALL.svn67
-rw-r--r--Makefile.am1
-rw-r--r--NEWS204
-rw-r--r--README157
-rwxr-xr-xautogen.sh103
-rw-r--r--cmake/LighttpdMacros.cmake46
-rw-r--r--cmake/UsePkgConfig.cmake54
-rw-r--r--configure.ac797
-rw-r--r--distribute.sh.in85
-rw-r--r--doc/.cvsignore4
-rw-r--r--doc/CMakeLists.txt39
-rw-r--r--doc/Makefile.am86
-rw-r--r--doc/access.txt41
-rw-r--r--doc/accesslog.txt126
-rw-r--r--doc/alias.txt36
-rw-r--r--doc/authentication.txt211
-rw-r--r--doc/build-win32.txt67
-rw-r--r--doc/cgi.txt50
-rw-r--r--doc/compress.txt192
-rw-r--r--doc/configuration.txt520
-rw-r--r--doc/dirlisting.txt82
-rw-r--r--doc/evhost.txt46
-rw-r--r--doc/expire.txt42
-rw-r--r--doc/features.txt116
-rw-r--r--doc/lighttpd.874
-rw-r--r--doc/lighttpd.conf310
-rw-r--r--doc/lighttpd.user1
-rw-r--r--doc/newstyle.css49
-rw-r--r--doc/oldstyle.css25
-rw-r--r--doc/performance.txt241
-rw-r--r--doc/plugins.txt260
-rwxr-xr-xdoc/rc.lighttpd155
-rw-r--r--doc/rc.lighttpd.redhat87
-rw-r--r--doc/redirect.txt41
-rw-r--r--doc/rewrite.txt71
-rw-r--r--doc/rrdtool-graph.sh38
-rw-r--r--doc/rrdtool.txt111
-rw-r--r--doc/secdownload.txt147
-rw-r--r--doc/security.txt60
-rw-r--r--doc/setenv.txt37
-rw-r--r--doc/simple-vhost.txt109
-rw-r--r--doc/skeleton.txt29
-rwxr-xr-xdoc/spawn-php.sh54
-rw-r--r--doc/ssi.txt76
-rw-r--r--doc/ssl.txt62
-rw-r--r--doc/state.dot18
-rw-r--r--doc/state.txt170
-rw-r--r--doc/status.txt111
-rw-r--r--doc/sysconfig.lighttpd1
-rw-r--r--doc/traffic-shaping.txt55
-rw-r--r--doc/trigger_b4_dl.txt57
-rw-r--r--doc/userdir.txt72
-rw-r--r--doc/webdav.txt64
-rwxr-xr-xmake.example23
-rw-r--r--src/.cvsignore17
-rw-r--r--src/CMakeLists.txt678
-rw-r--r--src/Makefile.am365
-rw-r--r--src/XGetopt.h23
-rw-r--r--src/ajp13.h136
-rw-r--r--src/array-static.h38
-rw-r--r--src/array.c398
-rw-r--r--src/array.h160
-rw-r--r--src/base.h731
-rw-r--r--src/bitset.c69
-rw-r--r--src/bitset.h21
-rw-r--r--src/buffer.c1169
-rw-r--r--src/buffer.h166
-rw-r--r--src/chunk.c718
-rw-r--r--src/chunk.h94
-rw-r--r--src/config.h.cmake153
-rw-r--r--src/configfile-glue.c675
-rw-r--r--src/configfile.c1376
-rw-r--r--src/configfile.h30
-rw-r--r--src/configparser.y571
-rw-r--r--src/connections-glue.c51
-rw-r--r--src/connections.c1599
-rw-r--r--src/connections.h20
-rw-r--r--src/crc32.c82
-rw-r--r--src/crc32.h25
-rw-r--r--src/data_array.c65
-rw-r--r--src/data_config.c136
-rw-r--r--src/data_count.c68
-rw-r--r--src/data_integer.c65
-rw-r--r--src/data_string.c121
-rw-r--r--src/etag.c53
-rw-r--r--src/etag.h16
-rw-r--r--src/fastcgi.h136
-rw-r--r--src/fcgi-stat-accel.c118
-rw-r--r--src/fdevent.c390
-rw-r--r--src/fdevent.h280
-rw-r--r--src/fdevent_freebsd_kqueue.c221
-rw-r--r--src/fdevent_linux_rtsig.c235
-rw-r--r--src/fdevent_linux_sysepoll.c147
-rw-r--r--src/fdevent_poll.c153
-rw-r--r--src/fdevent_select.c166
-rw-r--r--src/fdevent_solaris_devpoll.c181
-rw-r--r--src/filter.c182
-rw-r--r--src/filter.h42
-rw-r--r--src/http-header-glue.c384
-rw-r--r--src/http_auth.c1252
-rw-r--r--src/http_auth.h81
-rw-r--r--src/http_auth_digest.c25
-rw-r--r--src/http_auth_digest.h24
-rw-r--r--src/http_parser.h11
-rw-r--r--src/http_req.c323
-rw-r--r--src/http_req.h37
-rw-r--r--src/http_req_parser.y160
-rw-r--r--src/http_req_range.c188
-rw-r--r--src/http_req_range.h37
-rw-r--r--src/http_req_range_parser.y76
-rw-r--r--src/http_req_range_test.c72
-rw-r--r--src/http_req_test.c141
-rw-r--r--src/http_resp.c303
-rw-r--r--src/http_resp.h40
-rw-r--r--src/http_resp_parser.y143
-rw-r--r--src/http_resp_test.c141
-rw-r--r--src/inet_ntop_cache.c53
-rw-r--r--src/inet_ntop_cache.h7
-rw-r--r--src/iosocket.c44
-rw-r--r--src/iosocket.h50
-rw-r--r--src/joblist.c77
-rw-r--r--src/joblist.h19
-rw-r--r--src/keyvalue.c390
-rw-r--r--src/keyvalue.h112
-rw-r--r--src/lemon.c4400
-rw-r--r--src/lempar.c693
-rw-r--r--src/log.c457
-rw-r--r--src/log.h43
-rw-r--r--src/md5.c355
-rw-r--r--src/md5.h57
-rw-r--r--src/mod_access.c230
-rw-r--r--src/mod_accesslog.c911
-rw-r--r--src/mod_alias.c204
-rw-r--r--src/mod_auth.c672
-rw-r--r--src/mod_auth.h0
-rw-r--r--src/mod_cgi.c1312
-rw-r--r--src/mod_chunked.c381
-rw-r--r--src/mod_compress.c848
-rw-r--r--src/mod_deflate.c1408
-rw-r--r--src/mod_dirlisting.c957
-rw-r--r--src/mod_evasive.c200
-rw-r--r--src/mod_evhost.c347
-rw-r--r--src/mod_expire.c375
-rw-r--r--src/mod_flv_streaming.c322
-rw-r--r--src/mod_indexfile.c254
-rw-r--r--src/mod_magnet.c984
-rw-r--r--src/mod_magnet_cache.c137
-rw-r--r--src/mod_magnet_cache.h33
-rw-r--r--src/mod_mysql_vhost.c309
-rw-r--r--src/mod_postgresql_vhost.c371
-rw-r--r--src/mod_proxy_backend_ajp13.c836
-rw-r--r--src/mod_proxy_backend_fastcgi.c819
-rw-r--r--src/mod_proxy_backend_http.c423
-rw-r--r--src/mod_proxy_backend_scgi.c475
-rw-r--r--src/mod_proxy_core.c2624
-rw-r--r--src/mod_proxy_core.h122
-rw-r--r--src/mod_proxy_core_address.c210
-rw-r--r--src/mod_proxy_core_address.h36
-rw-r--r--src/mod_proxy_core_backend.c50
-rw-r--r--src/mod_proxy_core_backend.h74
-rw-r--r--src/mod_proxy_core_backlog.c109
-rw-r--r--src/mod_proxy_core_backlog.h61
-rw-r--r--src/mod_proxy_core_pool.c141
-rw-r--r--src/mod_proxy_core_pool.h68
-rw-r--r--src/mod_proxy_core_protocol.c66
-rw-r--r--src/mod_proxy_core_protocol.h40
-rw-r--r--src/mod_proxy_core_rewrites.c127
-rw-r--r--src/mod_proxy_core_rewrites.h40
-rw-r--r--src/mod_redirect.c229
-rw-r--r--src/mod_rewrite.c337
-rw-r--r--src/mod_rrdtool.c501
-rw-r--r--src/mod_secure_download.c351
-rw-r--r--src/mod_setenv.c254
-rw-r--r--src/mod_simple_vhost.c282
-rw-r--r--src/mod_skeleton.c207
-rw-r--r--src/mod_sql_vhost_core.c384
-rw-r--r--src/mod_sql_vhost_core.h60
-rw-r--r--src/mod_ssi.c1095
-rw-r--r--src/mod_ssi.h44
-rw-r--r--src/mod_ssi_expr.c325
-rw-r--r--src/mod_ssi_expr.h31
-rw-r--r--src/mod_ssi_exprparser.y122
-rw-r--r--src/mod_staticfile.c552
-rw-r--r--src/mod_status.c893
-rw-r--r--src/mod_trigger_b4_dl.c589
-rw-r--r--src/mod_uploadprogress.c638
-rw-r--r--src/mod_userdir.c325
-rw-r--r--src/mod_usertrack.c277
-rw-r--r--src/mod_webdav.c2688
-rw-r--r--src/network.c891
-rw-r--r--src/network.h16
-rw-r--r--src/network_backends.h59
-rw-r--r--src/network_freebsd_sendfile.c157
-rw-r--r--src/network_gthread_aio.c481
-rw-r--r--src/network_gthread_freebsd_sendfile.c265
-rw-r--r--src/network_gthread_sendfile.c272
-rw-r--r--src/network_linux_aio.c382
-rw-r--r--src/network_linux_sendfile.c192
-rw-r--r--src/network_openssl.c402
-rw-r--r--src/network_posix_aio.c467
-rw-r--r--src/network_solaris_sendfilev.c149
-rw-r--r--src/network_win32_send.c265
-rw-r--r--src/network_write.c227
-rw-r--r--src/network_writev.c356
-rw-r--r--src/plugin.c592
-rw-r--r--src/plugin.h114
-rw-r--r--src/proc_open.c395
-rw-r--r--src/proc_open.h25
-rw-r--r--src/request.c599
-rw-r--r--src/request.h9
-rw-r--r--src/response.c794
-rw-r--r--src/response.h22
-rw-r--r--src/server.c1792
-rw-r--r--src/server.h20
-rw-r--r--src/settings.h183
-rw-r--r--src/splaytree.c210
-rw-r--r--src/splaytree.h24
-rw-r--r--src/stat_cache.c563
-rw-r--r--src/stat_cache.h14
-rw-r--r--src/status_counter.c75
-rw-r--r--src/status_counter.h20
-rw-r--r--src/stream.c107
-rw-r--r--src/stream.h14
-rw-r--r--src/sys-files.c66
-rw-r--r--src/sys-files.h87
-rw-r--r--src/sys-mmap.h26
-rw-r--r--src/sys-process.h17
-rw-r--r--src/sys-socket.c76
-rw-r--r--src/sys-socket.h73
-rw-r--r--src/sys-strings.h46
-rw-r--r--src/timing.c11
-rw-r--r--src/timing.h12
-rw-r--r--src/valgrind/Makefile.am1
-rw-r--r--src/valgrind/valgrind.h469
-rw-r--r--src/xgetopt.c222
-rw-r--r--tests/.cvsignore6
-rw-r--r--tests/CMakeLists.txt30
-rwxr-xr-xtests/LightyTest.pm373
-rw-r--r--tests/Makefile.am70
-rw-r--r--tests/bug-06.conf152
-rw-r--r--tests/bug-12.conf154
-rwxr-xr-xtests/cachable.t112
-rwxr-xr-xtests/cleanup.sh14
-rw-r--r--tests/condition.conf59
-rwxr-xr-xtests/core-condition.t139
-rwxr-xr-xtests/core-keepalive.t91
-rwxr-xr-xtests/core-request.t278
-rwxr-xr-xtests/core-response.t108
-rwxr-xr-xtests/core-var-include.t61
-rwxr-xr-xtests/core.t166
-rw-r--r--tests/default.conf113
-rw-r--r--tests/docroot/123/12345.html1
-rw-r--r--tests/docroot/123/12345.txt1
-rw-r--r--tests/docroot/123/Makefile.am1
-rw-r--r--tests/docroot/123/dummyfile.bla1
-rw-r--r--tests/docroot/123/phpinfo.php1
-rw-r--r--tests/docroot/Makefile.am1
-rw-r--r--tests/docroot/www/Makefile.am5
-rw-r--r--tests/docroot/www/cgi-pathinfo.pl7
-rw-r--r--tests/docroot/www/cgi.php9
-rw-r--r--tests/docroot/www/cgi.pl7
-rw-r--r--tests/docroot/www/exec-date.shtml1
-rw-r--r--tests/docroot/www/expire/Makefile.am1
-rw-r--r--tests/docroot/www/expire/access.txt0
-rw-r--r--tests/docroot/www/expire/modification.txt0
-rw-r--r--tests/docroot/www/get-env.php4
-rw-r--r--tests/docroot/www/get-header.pl8
-rw-r--r--tests/docroot/www/get-post-len.pl15
-rw-r--r--tests/docroot/www/get-post-md5.php3
-rw-r--r--tests/docroot/www/get-server-env.php3
-rw-r--r--tests/docroot/www/go/Makefile.am1
-rw-r--r--tests/docroot/www/go/cgi.php9
-rw-r--r--tests/docroot/www/index.html113
-rw-r--r--tests/docroot/www/index.txt113
-rw-r--r--tests/docroot/www/indexfile/Makefile.am1
-rw-r--r--tests/docroot/www/indexfile/index.php1
-rw-r--r--tests/docroot/www/indexfile/return-404.php5
-rw-r--r--tests/docroot/www/indexfile/rewrite.php3
-rw-r--r--tests/docroot/www/nph-status.pl14
-rw-r--r--tests/docroot/www/phpinfo.php1
-rw-r--r--tests/docroot/www/prefix.fcgi3
-rw-r--r--tests/docroot/www/redirect.php4
-rw-r--r--tests/docroot/www/ssi.shtml1
-rw-r--r--tests/fastcgi-10.conf129
-rwxr-xr-xtests/fastcgi.t233
-rw-r--r--tests/fcgi-auth.c31
-rw-r--r--tests/fcgi-responder.c63
-rw-r--r--tests/lighttpd.conf127
-rw-r--r--tests/lighttpd.htpasswd2
-rw-r--r--tests/lighttpd.user1
-rw-r--r--tests/lowercase.conf70
-rwxr-xr-xtests/lowercase.t94
-rwxr-xr-xtests/mod-access.t27
-rwxr-xr-xtests/mod-auth.t144
-rwxr-xr-xtests/mod-cgi.t152
-rw-r--r--tests/mod-compress.conf32
-rwxr-xr-xtests/mod-compress.t106
-rw-r--r--tests/mod-proxy.t.deprecated175
-rwxr-xr-xtests/mod-redirect.t51
-rwxr-xr-xtests/mod-rewrite.t70
-rwxr-xr-xtests/mod-secdownload.t79
-rwxr-xr-xtests/mod-setenv.t51
-rwxr-xr-xtests/mod-ssi.t39
-rwxr-xr-xtests/mod-userdir.t44
-rwxr-xr-xtests/prepare.sh50
-rw-r--r--tests/proxy-backend-1.conf7
-rw-r--r--tests/proxy-backend-2.conf7
-rw-r--r--tests/proxy.conf26
-rwxr-xr-xtests/request.t418
-rwxr-xr-xtests/run-tests.pl20
-rwxr-xr-xtests/symlink.t115
-rw-r--r--tests/var-include-sub.conf34
-rw-r--r--tests/var-include.conf41
-rwxr-xr-xtests/wrapper.sh9
320 files changed, 5 insertions, 74982 deletions
diff --git a/.cvsignore b/.cvsignore
deleted file mode 100644
index cb2e0c23..00000000
--- a/.cvsignore
+++ /dev/null
@@ -1,15 +0,0 @@
-Makefile
-Makefile.in
-configure
-depcomp
-config.*
-mkinstalldirs
-distribute.sh
-autom4te.cache
-libtool
-missing
-aclocal.m4
-install-sh
-compile
-ltmain.sh
-stamp-h1
diff --git a/AUTHORS b/AUTHORS
deleted file mode 100644
index 590be9df..00000000
--- a/AUTHORS
+++ /dev/null
@@ -1,6 +0,0 @@
-Jan Kneschke <jan@kneschke.de>
-Elan Ruusamäe <glen@delfi.ee>
-Marcus Rückert <darix@opensu.se>
-mOo <moo.lighttpd@gmail.com>
-Robert Jakabosky <bobby@neoawareness.com>
-Stefan Bühler <stbuehler@web.de>
diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index e175b50b..00000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-PROJECT(lighttpd C)
-
-CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0 FATAL_ERROR)
-
-SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
-
-INCLUDE(CTest)
-
-ENABLE_TESTING()
-
-SET(CPACK_PACKAGE_VERSION_MAJOR 1)
-SET(CPACK_PACKAGE_VERSION_MINOR 5)
-SET(CPACK_PACKAGE_VERSION_PATCH 0)
-
-SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
-SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README")
-SET(CPACK_PACKAGE_VENDOR "jan@kneschke.de")
-
-SET(CPACK_SOURCE_GENERATOR "TGZ")
-SET(CPACK_SOURCE_IGNORE_FILES "/\\\\.;~$;/_;build/;CMakeFiles/;CMakeCache;gz$;Makefile\\\\.;trace;Testing/;foo;autom4te;cmake_install;CPack;\\\\.pem;ltmain.sh;configure;libtool;/config\\\\.;missing;autogen.sh;install-sh;Dart;aclocal;log$;Makefile$")
-
-SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
-
-ADD_SUBDIRECTORY(src build)
-ADD_SUBDIRECTORY(doc)
-ADD_SUBDIRECTORY(tests)
-
diff --git a/COPYING b/COPYING
deleted file mode 100644
index 3f699760..00000000
--- a/COPYING
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-Copyright (c) 2004, Jan Kneschke, incremental
- All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-- Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-- Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-- Neither the name of the 'incremental' nor the names of its contributors may
- be used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index 8853a4de..00000000
--- a/ChangeLog
+++ /dev/null
@@ -1,4031 +0,0 @@
-CVS-Version: $Id: ChangeLog,v 1.18 2004/04/09 22:08:19 weigon Exp $
-
-** NOTE **
-
-This file is abondend in favour of the NEWS file
-
-** NOTE **
-
-
-15.06.2005 20:10 - 1.3.15
-- mod_cml, mod_trigger_b4_dl
-
- added both plugins
-
- check http://trac.lighttpd.net/trac/log/branches/lighttpd-1.3.x/ for the
- rest
-
-15.06.2005 13:59 - 1.3.14
-- documentation
-
- more fix-ups for mod_fastcgi, configuration and mysql-vhost
-
-- tests
-
- unified test-scripts to use the same framework
-
-14.06.2005 23:38
-- documentation
-
- updated docs for mod_proxy and mod_scgi
-
-12.06.2005 12:55 - pre-release
-- mod_fastcgi
-
- fixed event handling after delayed connect
-
- make retry timeout configurable
-
- removed unused events if we switch to FCGI_STATE_READ
-
- disabled adaptive spawning
-
-- mod_proxy
-
- added hash-based and round-robin balancing
-
- use port 80 is default
-
- fixed errorhandling on connection refused
-
- fixed usage of dead hosts [285]
-
-- mod_cgi
-
- send 500 if the CGI died before we received any data
-
- redirect the stderr of CGI to our errorlog
-
- cleanup cgi-env after we finished our request
-
-- uri-handling
-
- don't replace + to space before the ?query part
-
- accept characters > 127 again
-
-- mod_auth
-
- fixed segfault if debugging is enabled [371]
-
-- mod_scgi
-
- added SCGI support for python + WSGI [381], [382]
-
-- mod_setenv
-
- fixed conditionals for setenv.add-environment [109]
-
-- generic
-
- report an error on duplicate config-keys in configfile [267]
-
- call initgroups to join the groups of the users [239]
-
- fixed automatic redirects if SSL is used
-
- fixed compilation on Solaris [283]
-
- disable accept-filtering on FreeBSD if ssl is used [320]
-
- fixed handling of range-request larger than 2Gb
-
- fixed comparisions of mime-types to case-insensitive [266]
-
- added quotation of ETags [376], [378]
-
-06.03.2005 12:22 - 1.3.13
-- mod_accesslog
-
- fixed NULL dereference on logfile cycling if accesslog is not set
-
-05.03.2005 17:30
-- mod_proxy
-
- handle delayed connect in the same way as mod_fastcgi
-
-03.03.2005 19:00
-- freebsd
-
- handle remote-close gracefully
-
-- ssl
-
- handle remote-close gracefully
-
-- dir-listing
-
- added dir-listing.hide-dotfiles and added an option to set css files
-
-02.03.2005 19:41
-- fastcgi
-
- fixed path-info for prefix-patterns
-
- fixed path-info for PHP
-
-02.03.2005 14:47 - 1.3.12
-- mod_fastcgi
-
- fixed handling of dead fastcgi process which sent their SIGCLD to
- initd and not to lighttpd. Moving the daemonize before starting
- the fastcgi procs fixes this.
-
-01.03.2005 23:59
-- irix
-
- fixed minor compile issues with MIPSpro
-
-01.03.2005 11:57
-- request-handling
-
- handle most duplicate headers as 400, Bug #25
-
-- mod_fastcgi
-
- added more checks
-
-28.02.2005 18:26
-- mod_expire
-
- don't ignore 'modification' any more, Bug #39
- only handles static files
-
-- last-modified
-
- really compare timestamps, Bug #34
-
-28.02.2005 11:54
-- buffer
-
- rewrote int2buffer functions
-
- simplified path_simplify
-
-- pid-file
-
- ignore EACCESS on unlink
-
-28.02.2005 10:35
-- mod_fastcgi
-
- accept \n\n, Bug #32
-
-- cygwin
-
- moved functions used by plugin and main-program to *-glue.c
-
-- lemon
-
- removed warnings about shadowed variables
-
-28.02.2005 01:00
-- ssl
-
- added ssl.ca-file, Bug #19
-
- improved error-messages
-
-27.02.2005 23:48
-- test cases
-
- rewrote to test-framework to use Perl + Test::More
- ported more test-cases
-
-22.02.2005 01:20
-- mod_fastcgi
-
- replaced inet_addr by inet_aton
-
-- request-handling
-
- fixed segfault if host is empty
-
-20.02.2005 20:05
-- cgi
-
- fixed cgi.assign for empty handlers again
-
-20.02.2005 16:54 - 1.3.11
-- request handling
-
- ignore \r\n before request-line in keep-alive requests (Bug #13)
-
-- cgi, fastcgi
-
- added REMOTE_PORT and SERVER_ADDR
-
- fixed check for broken status-code in nph-scripts (Bug #14)
-
-- fastcgi
-
- fixed passing cmdline options the spawned binary (Bug #16)
-
- fixed failed reconnects (Bug #9)
-
-- macos x
-
- fixed build on max
-
-- mod_secdownload
-
- parse conditional secure-download.secret (Bug #8)
-
-- mod_userdir
-
- redirect if username is not followed by / (Bug #15)
-
-13.02.2005 17:33
-- mod_auth
-
- fix crash if require, realm or method are empty (Bug #5)
-
-13.02.2005 14:52
-- network
-
- handle EPIPE and ECONNRESET as 'client has closed connection' in writev()
- (Bug #1)
-
-- macosx
-
- compile error on MacOS X due to missing environ (patch by Johan Sörensen)
- (Bug #2)
-
-- indexfiles
-
- append the detected indexfile only once to uri.path (reported by Thomas
- Seifert)
- (Bug #3)
-
-06.02.2005 15:16 - 1.3.10
-- fastcgi
-
- display a error-message if a hostname if specified in fastcgi.server->host
- we need an IP here
-
-- debug
-
- added debug.log-state-handling
-
-- spawn-fcgi
-
- accept a full commandline for spawning
-
-06.02.2005 12:50
-- fastcgi
-
- fixed openssl handling
-
-- network_freebsd_sendfilev
-
- gracefull handling of connections closed on client-side
- removed debug-message
-
-06.02.2005 01:44 - 1.3.9
-- documentation
-
- added docs for SSL setup and mod_status
-
-- fastcgi
-
- fixed config handling on PowerPC for local-spawning
-
-05.02.2005 15:14
-- fastcgi
-
- added bin-environment to setup the environment of the spawned process
-
- added bin-copy-environment to copy only the specified set of options
- from the old environment
-
- added handling of cmd-line options to bin-path
-
-- setenv
-
- fixed crashed in setenv.add-response-header
-
-04.02.2005 18:09
-- configure
-
- fixed docs for --with-mysql
-
-- fastcgi
-
- improved performance of building the header (drop strlen())
-
-04.02.2005 01:59
-- cgi
-
- don't send file on error
-
- check if cgi-handler exists before executing it
-
- added support for nph-...
-
-02.02.2005 21:18 - pre-release
-- request parsing
-
- handle invalid characters in URI
-
-02.02.2005 15:12
-- makefiles
-
- dropped unused header files from the distribution
-
-02.02.2005 14:18
-- fastcgi
-
- delete sockets on shutdown
-
-- http/1.1
-
- adding option to disable http/1.1
-
-01.02.2005 12:03
-- cygwin
-
- fixed plugins_load to use the right extensions again
- removed mmap check
- added ssl support
-
-01.02.2005 01:49
-- configure
-
- make check for valgrind.h covered by --with-valgrind
-
-- mod_localizer, mod_maps
-
- remove both plugins from the distribution
-
-- file-not-found
-
- handle file not found again
-
-30.01.2005 16:44
-- HEAD requests
-
- don't send content on dynamic HEAD requests with status 200
-
-30.01.2005 15:16 - 1.3.8
-- network-handler
-
- remove debug output on writev() if the remote side closed the connection
-
-- directory index
-
- handle EACCES correctly
-
-29.01.2005 15:16 - pre-release
-- mod_alias
-
- fixed mod_alias + pathinfo handling
-
-- mod_accesslog
-
- added access-log to syslog patch from allan
-
-28.01.2005 17:30
-- directory redirect without Host-header
-
- use server-ip instead of client-ip for the Location:
-
-- fastcgi + pathinfo
-
- if fastcgi-auth redirects to a directory which doesn't exist handle it
- correctly (bug introduced in 1.3.8)
-
-- requesting directories
-
- clean physical.path if directory is requested and dir-listing is disabled
- send 403 again (buf introduced in 1.3.8)
-
-28.01.2005 12:08
-- fastcgi
-
- ignore FDEVENT_HUP for unix-sockets as a simple read + timeout will do
- the job anyway
-
-22.01.2005 20:28 - pre-release
-- fastcgi
-
- send content and headers if authorizer mode is used
-
- use a new connection if connection is died to fastcgi
- and we have not used it yet
-
-18.01.2005 21:21 - pre-release
-- plugins
-
- added version-id to plugins to detect plugins which are not up-to-date
-
-16.01.2005 23:11
-- fastcgi
-
- fixed write-failed after crash of fastcgi-child
-
-16.01.2005 20:43
-- setenv
-
- fixed setenv.add-environment
-
-- fastcgi
-
- fixed authorizer + added testcases
-
-16.01.2005 17:40 - pre-release
-- mod_status
-
- beautified mod_status
-
-- mod_setenv
-
- added setenv.add-environment
-
-- timeouts
-
- add timeout to read-post
-
-15.01.2005 12:57
-- debug
-
- added debug options to log
- - missing files
- - request header
- - response header
- - request handling
-
- added a more usefull error message for the status-code changes in the
- request parser
-
-- server announcement
-
- set Server: header for dynamic content too
-
-- fastcgi
-
- fixed double free
-
- don't crash on FDEVENT_ERR
-
- added a comment for EAGAIN on connect()
-
-08.01.2005 17:45
-- ssl
-
- report an error if ssl.engine is enable but no ssl support compiled in
-
-08.01.2005 12:23
-- mod_status
-
- added request time to the output
-
- (late changelog) added host and filename to the output (fobax)
- (late changelog) HTMLalized the output (fobax)
-
-06.01.2005 19:51 - pre-release
-- error-handler
-
- let the error-handler handle 403 requests too
-
- make the error-handler setable by a module
-
-- error-pages
-
- reworked the error-page handling
-
-05.01.2005 13:10
-- keep-alive handling
-
- made sure that keep-alive is really handled correctly
-
-04.01.2005 17:02
-- mod_setenv
-
- added a module to added request and response headers on the fly
-
-- error-log
-
- send error log to syslog() if no errorlogfile is specified (again)
-
-02.01.2005 22:44 - pre-release
-- response handling
-
- cut of body for status 301, 304 and 205
-
-- buffer
-
- optimized all _hex functions (Silvan Minghetti)
-
-02.01.2005 20:32
-- fastcgi
-
- if bin-path is not specified, don't die (bug introduced in the last pre-rel)
-
-- auth
-
- if userfile is empty don't auth.
-
-02.01.2005 19:06
-- mod_compress
-
- fixed off by one if cache-dir is not set
-
-02.01.2005 16:10
-- conditional config
-
- fixed !~ and !=
-
-- buffer
-
- copy empty buffers correctly
-
-31.12.2004 17:45
-- ipv6 + pidfile
-
- don't complain if we can't remove the pidfile (Silvan Minghetti)
-
- remove ipv6 option from the commandline of lighttpd doesn't support
- ipv6 (Silvan Minghetti)
-
-31.12.2004 15:41 - pre-release
-- kqueue
-
- simplified event handling (adam)
-
-- fastcgi
-
- fixed div-by-zero bugs in the adaptive process spawning
-
-- mysql-vhost
-
- added mysql-vhost (Christer Holgersson)
-
-30.12.2004 19:09
-- fastcgi
-
- added adaptive spawning of FastCGI processes
-
-- traffic shaping
-
- added traffic shaping per virtual server
-
-28.12.2004 23:26
-- traffic shaping
-
- added traffic shaping per connection
-
-25.12.2004 22:58
-- mod_status
-
- fixed status.url again (Timo)
-
-21.12.2004 11:29
-- configure
-
- added check for signal and select (compile fix for netbsd 1.4 and 1.5)
-
-11.12.2004 12:38 - 1.3.7
-- fastcgi + php
-
- retry to connect to another PHP child if one of them dies after
- connect
-
-- cgi + multipart
-
- don't transform CONTENT_TYPE to HTTP_CONTENT_TYPE
-
-- debian
-
- more cleanup, updated changelog, added more deps and suggests
- (Chris Brown)
-
-10.12.2004 22:33
-- event handler
-
- fixed crashes in kqueue
-
-10.12.2004 13:57 - pre-release
-- mod_status
-
- fixed wraparound in total requests and total traffic
-
-- debian
-
- updated licence and packaging
-
-- security
-
- call setgroups() to get rid of all groups
-
-- ssl
-
- handle SSL_shutdown() == 0 correctly
-
- fixed openssl detection in configure
-
- fixed handling of chunked encoding
-
-- request handling
-
- handle Connection: keep-alive correctly (case as not ignored)
-
-21.11.2004 02:39
-- windows
-
- merged basic native windows port (compiles with mingw)
-
-20.11.2004 18:43
-- conditional
-
- ported
- - cgi
- - secdownload
- - expire
- - localizer
- - usertrack
- - status
- - proxy
-
-- server-tag
-
- Server: ... can now be specified by server.tag = "..."
-
-- spawn-fcgi
-
- fixed typo in usage text
-
-- ssl
-
- fixed detection of libs and headers
-
-05.11.2004 16:01
-- fastcgi
-
- added more usefull error messages
-
-04.11.2004 23:01
-- ssi
-
- added support for ${...}
-
-03.11.2004 14:51 - 1.3.6
-- fastcgi
-
- added spawn-fcgi to the distribution
- added spawn-local-fastcgi yourself ( bin-path )
-
-03.11.2004 11:22
-- accesslog
-
- don't cycle accesslogs of external processes are used
-
-02.11.2004 15:34
-- fastcgi
-
- handle END-OF-REQUEST correctly if chunk-encoding is not used
-
-02.11.2004 10:53
-- internal redirects
-
- fixed handling of query strings in internal redirects for directories
-
-02.11.2004 09:54 - pre-release
-- cgi
-
- add REMOTE_USER, suppress AUTHORIZATION
- handle payloads > 4k
-
-- mod_alias
-
- fixed url checking
-
-- follow-symlink
-
- fixed config
-
-31.10.2004 11:30 - 1.3.5
-- writev
-
- fixed seg-fault in debug-message if write() fails and LFS is enabled
- handle EINTR
-
-- sendfile linux
-
- handle EINTR
-
-31.10.2004 09:09
-- freebsd
-
- added missing header in joblist.c
- fixed test-scripts for zsh
-
-30.10.2004 22:26
-- modules
-
- added mod_userdir and mod_alias
- added docs for the new modules
-
-30.10.2004 19:52
-- porting
-
- added defines for MAP_FAILED for NetBSD 1.3.x
-
-30.10.2004 18:54 - pre-release
-- pipelining
-
- fixed offset calculations
-
-- ipv6
-
- IPv6 might be disabled at compile-time
-
-- rewrite
-
- close mem-leak
-
-- auth
-
- forgot to reset the global-config handler
-
-- symlink
-
- add option to disable follow-symlink
-
-- ssi
-
- added support for exec-cmd
-
-23.10.2004 - 1.3.4
-- max-fds
-
- set the upper limit of fds only if server.max-fds is set
-
-23.10.2004 13:49
-- accesslog
-
- use a shell to handle accesslog-pipes
-
-22.10.2004 17:00
-- accesslog
-
- added logging of user-supplied data via %{...}o and
- X-LIGHTTPD-* header
-
-22.10.2004 14:57 - pre-release
-- openwrt
-
- fixed configure-checks and Makefile.am's to build cleanly with a
- cross-compiler
-
- builds cleanly for openwrt
-
-22.10.2004 13:03
-- out-of-fd
-
- improved the out-of-fd handler
-
-- cgi, fastcgi
-
- set SERVER_NAME to server.name or the value submitted by Host:
-
-- error-handler
-
- only set old status code if it wasn't set by a handler
-
-21.10.2004 22:36 - pre-release
-- fastcgi
-
- don't crash on out-of-fd condition
-
-- out-of-fd
-
- try handle the out-of-fd condition in a sane way
-
-21.10.2004 15:03
-- mod_auth
-
- seperated auth.backend.*.userfile for plain, htpasswd and htdigest
-
- added 'digest-auth' against 'plain-backend'
-
- added auth.debug for debugging
-
-16.10.2004 10:18 - 1.3.3
-- mod_simple_vhost, mod_evhost
-
- conditional-ized
-
-- mod_rrdtool
-
- maintain the request-counter for each conditional-config (adam)
-
-14.10.2004 11:30
-- accesslogs
-
- cycle all access-logs
-
-- mod_rewrite
-
- tell the user to install pcre.h if he wants to use mod_rewrite
-
-10.10.2004 10:11 - pre-release
-- error-handler
-
- added a error-handler for status 404 (server.error-handler-404)
-
-09.10.2004 16:28 - pre-release
-- cgi
-
- added support for \n in headers
-
-- mod_auth
-
- added conditional auth
-
-01.10.2004 09:28
-- plugins
-
- fixed off by one error in plugin initialization (Mike)
- related into a segfault on AMD64
-
-30.09.2004 21:44 - 1.3.2
-- file-cache
-
- disabled the file-cache it was taken the wrong files from the cache
-
-30.09.2004 08:39 - 1.3.1
-- file-cache
-
- drop a unused file-cache entry after 10 seconds
- reuse unused entries
-
-- request-parser
-
- accept IPv6 adresses in Host header
-
-- tests
-
- modified the scripts to work with zsh (check on Linux, Irix and FreeBSD)
-
-26.09.2004 12:28
-- comparission function
-
- file-cache has delivering the wrong entry if only the last character of
- the filename differed and the filesize was the same.
-
-- cgi + cygwin
-
- cgi need s SYSTEMROOT environment
-
-
-22.09.2004 08:55
-- network
-
- detect of file has been shrinked while we are sending it out and terminate
- the connection if would run over the edge
-
-22.09.2004 07:56
-- mod rewrite, fastcgi, ...
-
- keep REQUEST_URI after rewrite
-
-21.09.2004 22:49
-- fastcgi authorizer
-
- fixed cleanup code (matt)
-
-21.09.2004 20:08
-- rrdtool
-
- rrdtool.db-name is now conditional
-
- fixed check if write() failed (adam)
-
-17.09.2004 17:50 - 1.3.0
-- rewrite
-
- added url.rewrite-final = ...
-
-17.09.2004 15:55
-- code cleanup
-
- integrated the fixes from cygwin into the main tree
-
-- kqueue
-
- init kqueue after daemonizing (broken since 12.09.2004 14:02)
-
-16.09.2004 21:00
-- cygwin + macosx
-
- finished the cygwin port
- this port seems to fix the problems on macosx too
-
-12.09.2004 14:02
-- socket handling
-
- added support to handle more than one server socket
-
-11.09.2004 12:23 - 1.2.8
-- EINTR
-
- handle EINTR for linux-sendfile
-
-- configfile
-
- ignore an extra comma at the end of the array declaration
-
-11.09.2004 09:46
-- mod_proxy
-
- pass remote-addr as X-Forwarded-For to the real server behind the proxy
-
-- code cleanup
-
- moved all cut'n'paste versions of the inet_ntop cache to inet_ntop_cache.c
-
-- fcgi
-
- don't overwrite the fd in fcgi_establish connection if connect fails. this
- results in various problem in other places.
-
-05.09.2004 09:46
-- file-cache
-
- cache the mimetype
-
-- last-modified
-
- don't complain if the If-Modified-Since contains a valid comment/option
- like <timestamp>; length = ...
-
-05.09.2004 09:13
-- expires
-
- overwrite the Expire if it is set by a previous plugin
-
-- conditional config
-
- conditional config as disabled in 1.2.7 by accident
-
-04.09.2004 10:02 - 1.2.7
-- mod-proxy
-
- remove the \0 before the post content
-
-- cgi
-
- fixed hanging process if cgi-crash terminates to fast (before we read its
- response)
-
-- extented attributes
-
- added xattr support, submitted by Ari
-
-29.08.2004 16:00
-- rrdtool
-
- moved the rrdtool support from mod_status into its own module mod_rrdtool
-
- rrdtool.binary = "/usr/bin/rrdtool"
- rrdtool.db-name = "/var/www/lighttpd.rrd"
-
-29.08.2004 11:00 - pre-release
-- timeouts
-
- server.max-keep-alive-requests = 0 replaces
- server.use-keep-alive = "disable"
-
- added
- server.max-keep-alive-idle
- server.max-read-idle
- server.max-write-idle
-
-- docs
-
- added a entry for each config-value into configuration.txt
- added simple docs for
- rewrite
- redirect
- compress
- cgi
- simple-vhost
-
-29.08.2004 10:05
-- config options
-
- complain if no configfile is specified
-
-- fastcgi
-
- removed stupid allocation bug which might cause a problem in really rare
- cases
-
-26.08.2004 22:06 - 1.2.6
-- optimize
-
- use array_strcasecmp() in favour of strcasecmp() as it is slightly
- faster.
-
- apply the case-insentive conversion also on the last character. (adam)
-
- sort the checked elements in request.c and filter apply the logic to
- compare some less fields, if the header is not used.
-
- improved the config-patch function to use our internal buffer-compare
- functions instead of strcmp
-
-22.08.2004 16:09 - pre-release
-- cgi
-
- added missing cleanup code
-
-- fastcgi
-
- remove double-free
- added handling of EINTR in some places
-
-- leaks
-
- fixed some leaks in the new config code
-
-- array_strcasecmp
-
- fixed alignment in the improved array_strcasecmp function (adam)
-
-20.08.2004 14:46 - pre-release
-- performance
-
- optimized a few useless strlen() away as we either know the length from
- buffer->used - 1 or by sizeof(str) - 1 if it is constant.
-
- optimized the 'find the \r\n\r\n' function.
-
- improved the array_strcasecmp() based on another idea from (ralf)
-
-- accesslog
-
- enabled the strftime cache again
-
-15.08.2004 23:41
-- accesslog
-
- added apache-like CustomLog handling in accesslog.format
-
- accesslog.format = "..."
-
-15.08.2004 21:08
-- test-cases
-
- remove testdir
-
-- configfiles
-
- handle escaping of " in strings properly
-
-13.08.2004 12:07
-- array
-
- improved inner-loop of array_strcasecmp() (ralf)
-
-11.08.2004 14:14
-- fcgi socket
-
- use SUN_LEN if available
-
-- keep-alive
-
- disable keep-alive on request
-
- server.use-keep-alive = "disable"
-
-10.08.2004 15:59 - 1.2.5
-- conditional config
-
- mod_fastcgi
- mod_rewrite
- mod_redirect
- mod_access
- mod_compress
- mod_accesslog
-
- are ported
-
-10.08.2004 13:05
-- pipelining
-
- fixed very stupid pipelining bug
-
-09.08.2004 22:07 - pre-release
-- conditional config
-
- first code for conditional config
-
-09.08.2004 14:21
-- fcgi
-
- fixed access to free()'d memory (doesn't create any harm)
-
-- isdigit, warings
-
- signed -> unsigned for 2 more isdigit() calls (adam)
- removed some unused var's if pcre is not available (adam)
-
-08.08.2004 20:57 - pre-release
-- debian
-
- added a chmod to /var/log/lighttpd/ (allan)
-
-08.08.2004 12:05
-- kqueue
-
- use EV_SET() instead of setting the ev-struct by hand (adam)
-
-- fcgi
-
- fixed the EINPROGRESS handling to use getsockopt (er)
- fixed a leak of server is disabled (er)
-
-- solaris 10 port-api
-
- added a skeleton for the sol10 port api
-
-06.08.2004 10:18
-- mod_ssi
-
- fix DATE_LOCAL so it displays the correct time zone (Jeremy Hinegardner)
-
-04.08.2004 11:43
-- openbsd fixes
-
- dropped usage of MAX() in buffer.c
- added prober includes for md5.h if openssl is enabled (brad)
-
-- memory usage
-
- documented the way how lighttpd caches memory blocks
- reset the buffers after they have been written by the network-layer
-
-- kqueue
-
- modify fd-bitmask only if kevent succeeded (adam)
-
-
-03.08.2004 15:09
-- mod_compress
-
- compress even if you have no cachedir set
-
-03.08.2004 13:26 - pre-release
-- Makefile
-
- fixed dependencies for parallel build in mod_ssi_expr.c
-
-- combo patch
-
- * Tinker with kqueue(). Add a reset method so that the kqueue file
- descriptor can be re-enabled after a fork(). Emulate the devpoll driver
- in that adds and deletes are sent to the notification mechanism im-
- mediately, which should cut down on phantom events. Use
- ev->kq_results as a sliding window.
-
- * Change F_SETFD calls to use the preferred FD_CLOEXEC instead of 1.
-
- * Remove unnecessary fdevent fcntl handlers. It appears that the only
- driver that needs one is Linux RT signals.
-
- * Quiet compiler warning about unused parameter.
-
- * Set the close-on-exec flag for the /dev/poll and epoll_create() file
- descriptors.
-
- * Return failure if /dev/poll could not be opened instead of logging
- and continuing.
-
- * Detect EAGAIN after writev() failures. FreeBSD sendfile() doesn't need
- protection, as the man page says:
-
- When using a socket marked for non-blocking I/O, sendfile() may send
- fewer bytes than requested. In this case, the number of bytes success-
- fully written is returned in *sbytes (if specified), and the error
- EAGAIN is returned.
-
- (adam, georg, matt)
-
-
-02.08.2004 18:08
-- mod_ssi
-
- check for pcre before compiling the module
-
-- fdevents
-
- dropped fdevent_fcntl added by the last patch (adam)
- kqueue: events == FDEVENT_IN -> events & FDEVENT_IN (adam)
-
-31.07.2004 22:07 - 1.2.4
-- fdevents
-
- * Test at configure time for kqueue() and <sys/event.h>
- * Remove various hard-coded constants from event handlers
- * Move maxfds into the event structure, and out of the
- fdevent_*_init handlers. Event handlers can use the maxfds
- member to size arrays.
- * Various event structure renames to discourage clashes
- * Remove extra (ignored) call to fdevent_event_next_fdndx() in
- the main server loop.
- * Wrestle with kqueue(). The implementation has to deal with
- phantom events (for fds which have been deleted/closed), similar
- to the Linux RT signals code. Like the RT code, it maintains a
- bitmask of active fds. After a successful call to kevent(), the
- code will compress/overwrite dead events. The other annoyance is
- that the handler must track the event filter for each fd, even
- though you cannot support both read and write filters for the same
- fd in one kqueue. The handler maintains a separate bitmask for fd
- filters (1 == EVFILT_IN, 0 == EVFILT_OUT).
- (adam)
-
-- server side includes
-
- added native server-side includes based on the docs from apache:
- http://httpd.apache.org/docs/mod/mod_include.html
-
- not supported are:
- - exec
- - nested virtual
- - config.errmsg
- - echo.encoding
-
-24.07.2004
-- fdevents
-
- added a bitset to figure out if we received a event for an unregistered fd
- in rt-signal (adam)
-
-- kqueue
-
- added kqueue support (Matt Levine)
-
-13.07.2004 08:58
-- configfile
-
- parse keys correctly that contain a digit (Geoff Adams)
-
-- fcgi
-
- fixed large post uploads (Geoff Adams)
- fixed uri if docroot is set (Geoff Adams)
-
-03.07.2004 22:50 - 1.2.3
-- index-files
-
- rewrite uri.path to the index-file instead of keeping it at .../
- this fixes index-file handling in FastCGI/CGI docroot is used
-
-- close-on-exec
-
- enable close-on-exec handling to simplify FD handling in CGI code
-
-- cgi
-
- keep error-log-fd open to catch the error handling for execve()
-
- report error if cgi-exec file doesn't exist
-
-- proxy
-
- pass page-content on error to the user (E.R.)
- code cleanup (E.R.)
-
-- ssi
-
- first skeleton of a plugin for ServerSideIncludes
-
-- security
-
- limit the headerlength again to 64k max
-
-03.07.2004 14:23
-- configure
-
- fixed compile-check for libpcre if pcre-config doesn't point to /usr/lib
-
-02.07.2004 18:17
-- buffers
-
- always allocate a multiply of 64bytes. this should reduce the number of
- realloc()s and still doesn't has a too high overhead.
-
-02.07.2004 11:07
-- fds
-
- connect stdin, stdout and stderr to /dev/null instead of just closing it
- use dup2() instead of dup()
-
-- accesslog
-
- if accesslog.filename starts with a | spawn a process which will get data
- in one chunk once in a while
-
-01.07.2004 11:00
-- sample config
-
- added text/css and text/javascript mimetypes
-
-28.06.2004 12:18
-- proxy module
-
- added a proxy module (based on the fastcgi module) and added some
- documentation
-
-25.06.2004 21:41
-- last-modified handling
-
- replaced %Z by GMT. otherwise the last-modified check will most often fail.
-
-24.06.2004 20:20
-- relax http-parser
-
- don't reply 400 in case of an empty header-field, just ignore it
-
-23.06.2004 22:10
-- file-cache
-
- don't cache mmap() for files larger than 64k as we run out of RAM otherwise
- too fast (check with some 200mb files)
-
-- 64bit fixes
-
- fixed buffer_equal on sparc64
-
-15.06.2004 19:09 - 1.2.2
-- mmap cache
-
- fixed mmap-caching in network_write.c and network_writev.c after a direct
- hint by E.Rodichev
-
-- sendfile + linux
-
- check at config-time if sendfile() works on Linux
-
-11.06.2004 15:09
-- fcgi + unix sockets
-
- added support for unix domain sockets (spawn-fcgi 1.2.0 required)
-
-10.06.2004 11:49
-- configure
-
- use pcre-config to determine the position of the pcre headers
-
-05.06.2004 22:06
-- filehandle-cache
-
- remove mmap-segment if filecache gets invalidated
-
-30.05.2004 14:13 - lighttpd 1.2.1
-- response headers
-
- request headers that appear twice are grouped together like expected by
- the CGI spec (concat with a ", ")
- response headers behaved the same way but are not grouped anymore. They
- stay seperated. Actually they are concated by \r\n<key>: <value> which is
- the same in the end.
-
-- file uploads
-
- the handling of longer post requests is fixed now.
-
-28.05.2004 09:13
-- cgi
-
- added support for direct calls to cgi-binary
-
-22.05.2004 21:58
-- pipeling
-
- the code cleanup is finished successfully. Now all cases of pipelining are
- handle the right way. POST pipelining was still not working up to now.
-
-22.05.2004 12:55
-- code cleanup
-
- use the well-tested code from the write-queue as the base for the
- read-queues and simplify the pipeline handling alot that way.
-
-20.05.2004 15:08
-- network backends
-
- enabled sendfile support again (__FreeBSD__ instead of __freebsd__)
-
- added a mmap cache as part of the filedescriptor cache
-
- added AIX specific send_file() support (untested)
-
-20.05.2004 10:40
-- segfaults
-
- fixed some minor segfaults on startup when no config file is used.
-
-17.05.2004 10:58 - lighttpd 1.2.0
-- documentation
-
- reformated the documentation the doc/ directory
-
-15.05.2004 14:45
-- localizer
-
- fixed build of localizer extension
-
-15.05.2004 12:35
-- POST requests
-
- there is no need to die if we spot a simple POST request on a static file
-
-- pipelining
-
- fixed HTTP/1.1 pipelining which caused the problems with opera
-
-- array handling
-
- how did that bug survive such a long time ? a wrong compare function was
- used in one case, but not the other.
-
-15.05.2004 03:20
-- secure and fast downloads
-
- added a module which allows secure and fast downloading of files:
- 1. the application (.php, ...) controls the access to the files
- 2. the webserver is handling the transfer (and check the app generated
- tokens)
-
- the token is based on
- - a secret
- - a timestamp
- - the filename
- this means even if the token is is distributed by the user it will get
- invalid after a given timeout (default 60 seconds)
-
-- errorfiles
-
- check for errorfiles before using them
-
-- code cleanup
-
- applied cleanup fixes from adam
-
-14.05.2004 18:47
-- fdevent handling
-
- added a more generic callback interface to the fdevent structures which
- simplifies the writing of plugins. this might destabilize lighttpd for a
- while
-
-- cgi
-
- fixed header parsing of the header is sent in chunks and the terminator is
- sent in a single chunk
-
-- EINTR
-
- fixed some occurences of EINTR which read()
-
-03.05.2004 23:55
-- portability
-
- E.R.:
- * portability fixes for Solaris 2.5
-
-02.05.2004 10:15
-- Expect: Handling
-
- added incomplete support for Expect: 100-continue (RFC 2616 8.2.3) by
- sending always 417 for every Expect-request (see 14.20)
-
- we have been blamed for not supporting it:
- http://lists.w3.org/Archives/Public/ietf-http-wg/2004JanMar/0059.html
-
-29.04.2004 23:07 - 1.1.9
-- usertracking
-
- added a very basic usertracking cookie handler
-
-29.04.2004 19:37
-- network-writev
-
- Adam:
- * call munmap() on error in write()
-
-- docs
-
- E.R:
- * documented 'check-local'
-
-- test-env
-
- made the shell scripts more portable (checked with zsh, bash and ksh)
-
- fixed compilation on NetBSD
-
-28.04.2004 22:22
-- FastCGI
-
- E.Rodichev:
- * added "Authorizer" mode for FastCGI
-
-27.04.2004 18:08
-- ssl
-
- Alexey Slynko:
- * handle SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE in SSL_write the
- right way.
-
-- FastCGI
-
- add 'check-local' instead of the implicit 'if-docroot-is-set' handling
- implemented at 24.04.2004 14:34
-
- E.Rodichev:
- * remove useless extra-/ in before uri.path
- * add 'prefix' notation for FastCGI processes
-
-26.04.2004 16:52
-- code cleanup
-
- patches from Alexey Slynko:
- * remove the pidfile if lighttpd terminates the normal way (if not in chroot)
- * init SSL before getting daemonized
-
-25.04.2004 19.15
-- mem-leak
-
- fixed mem-leak on broken HTTP-headers
-
-- FastCGI
-
- patches from E.Rodichev:
-
- 1. CONTENT_LENGTH
- "If no data are attached, then this metavariable is either NULL or not
- defined".
-
- 2. QUERY_STRING
- If the Script-URI does not include a query component, the QUERY_STRING
- metavariable MUST be defined as an empty string ("").
-
- 3. Doubling of REMOTE_ADDR removed.
-
- patches from adam:
- * fixed bug in the sizeof() patches from yesterday.
- * some more *_long to *_off_t
-
-24.04.2004 14:34
-- FastCGI
-
- don't check for localfile if 'docroot' for a FastCGI host is specified.
-
-24.04.2004 12:13
-- POST
-
- fixed POST request handling
-
-- chunk-encoding
-
- the generated HEX strings where broken since the 1.1.8
- (this effected all HTTP/1.1 requests without Content-Length like FastCGI-PHP)
-
-- code cleanup
-
- patches from adam:
- * malloc + memset -> calloc
- * sizeof(int) -> sizeof(<variable>)
- * assign fd_set instead of memcpy()
- * init fd -> connection fd pointers to -1
-
-16.04.2004 08:48 - 1.1.8
-- code cleanup
-
- don't reuse buffer > 64k (see settings.h)
-
- added server.max-request-size to limit the maximum request-body size
- (in kBytes)
-
- don't accept HTTP-request headers larger then 32kBytes (see settings.h)
-
- minor speed improvements in the request-parser
-
- More cleanup patches from adam:
-
- * change pre-ANSI C/valid C++ syntax for function declarations/definitions
- from using () to (void). Ex: int foo(); --> int foo(void);
- * use static linkage as much as possible, to limit possible symbol
- collisions
- * whack more unneeded variables
- * try and prevent any errno clobbering by storing the old errno value before
- any subsequent system calls, and restoring before function exit.
- * change printf syntax for unsigned variables from %d to %u
-
-15.04.2004 18:41
-- code cleanup
-
- handle all int != size_t cases in fcgi.c correctly
-
- check headerfields to have a value
-
- handle both EINVAL cases of writev() before the can occur
-
- limit content-length to SSIZE_MAX
- disallow negative content-length
-
- the usage of ltostr() has been reduced to the minimum in favour of
- buffer_/append|copy)_(long|off_t)
-
- dropped ultostr() and ultohex() in favour of buffer_*
-
-15.04.2004 16:35
-- portablity
-
- more patches from adam:
-
- * remove warnings for unused parameters and variables
- * remove warnings for mismatched pointer assignments
- * change "gtime_r" to "gmtime_r"
-
-13.04.2004 20:48
-- test-cases
-
- made the 'make check' target self-contained
-
- In our case we have to call the targets in the following order:
-
- $ ./configure ...
- $ make
- $ make install
- $ make check
-
- because the path to the plugins is hardcoded in the binary itself
-
- using
-
- $ ./configure --prefix=/tmp/lighttpd-1.1.x/
- ...
-
- will help if you don't really want to install before testing.
-
-13.04.2004 00:05
-- portability
-
- adam sent another patchset:
-
- * Wrap PCRE-specific data member access with an #ifdef
- * Add const to pointer using return value from dlerror()
- * Explicitly initialize pointer in the lemon parser to 0,
- in order to catch missing else { } clause
- * Use a time_t rather than an int for gmtime() call. On some
- systems (including 32- and 64-bit SPARC) time_t is a long.
-
-12.04.2004 17:00 - 1.1.7
-- fastcgi
-
- strip WS after HTTP-response headers coming from the FastCGI process
-
- added REMOTE_USER to the Server->FastCGI headers
- removed HTTP_AUTHORIZATION from the Server->FastCGI headers
-
-12.04.2004 10:24
-- cgi
-
- if we don't get a partial HTTP-response-header send the content out as soon
- as the cgi script is finished
-
-12.04.2004 01:23
-- compression
-
- added bzip2 compression (supported by w3m)
-
-12.04.2004 00:12
-- configfile
-
- add some usefull error messages if the tokenizer or the parser fail to
- read the configfile
-
-11.04.2004 22:04
-- configure
-
- added --with-ldap and --disable-lfs to the configure options
-
-11.04.2004 20:28
-- 64bit offset size
-
- disable linux-sendfile support for linux 2.4.x for now as it don't
- support 64bit transfers
-
- fixed all assignments on the path from the stat() to the Content-Length
- HTTP-header
-
-- head requests
- set content-length in HEAD requests
-
-- accesslog
-
- write accesslog entry on network error
-
- write the correct amount of byte written to the accesslog
-
-11.04.2004 11:48
-- code cleanup
-
- moved the config for the cgi-plugin from config.c to the plugin.
-
- moved some buffers which were only used by a one or two plugin from
- the server-structure to the plugins
-
- keeping the plugins independent from the server-core is a 'good thing'
-
-10.04.2004 19:06
-- configfile parser
-
- removed the leaks from the configfile parser
-
-09.04.2004 23:15 - 1.1.6
-- stricter http-parser
-
- added line-folding although noone really seems to use it.
-
-09.04.2004 18:42
-- configfile parser
-
- the hand-written configfile parser has been replaced by a LALR(1) one.
- 'lemon' from the sqlite guys has been used to generate the parser.
-
-- by-host, by-url, by-file, by ...
-
- $HTTP["url"] =~ "~$" {
- access.deny = "all"
- }
-
- $HTTP["host"] =~ "." {
- simple-vhost.server-root = "/home/weigon/wwwroot/servers/"
- simple-vhost.default-host = "grisu.home.kneschke.de"
- simple-vhost.document-root = "pages"
- }
-
- $HTTP["host"] == "incremental.home.kneschke.de" {
- server.docroot = "/hasdasd"
- }
-
- at least the parser can handle it now. Currently there is no real support
- for this context-based config-option. But the syntax and the parser are
- done.
-
-09.04.2004 10:58
-- ssl support
-
- enable ssl support again
-
-- mmap
-
- enabled mmap+write again
-
-08.04.2004 12:34
-- stricter http-parser
-
- based on a thread at
-
- http://lists.w3.org/Archives/Public/ietf-http-wg/2004JanMar/0050.html
-
- the HTTP-parser has been adjusted to be more correct when it comes to
- request-header fieldnames
-
- the whitespace handling around the ':' has been relaxed as requested
-
-07.04.2004 17:06
-- sigaction
-
- use sigaction instead of signal if possible
-
-07.04.2004 13:55
-- accesslog
-
- use localtime-timestamps in accesslogs if struct tm has a tm_gmtoff field
-
-07.04.2004 10:41 - 1.1.5
-- -D_REENTRANT
-
- solaris + localtime_r() needs it
-
-07.04.2004 02:54
-- mod_auth + ldap
-
- added a ldap backend to the auth plugin.
-
-06.04.2004 13:37
-- pidfile
-
- fixed the permissions of the pidfile (Matthijs van der Klip)
-
-- specfile
-
- merge the RedHat and SuSE specfile with Matthijs
-
-- 64bit file-offsets
-
- moved the FILE_OFFSET_BITS settings from the config.h the Makefile to enable
- 64bit offsets the right way
-
-06.04.2004 12:32
-- mod_expire
-
- added an apache compatible mod_expire which adds Expires: headers to the
- request
-
- expire.url = ( "/buggy/" => "access 2 hours" )
-
-05.04.2004 22:34
-- solaris devpoll
-
- forgot to provide the infrastructure to actually enable the devpoll event
- handler. the same has been done for the freebsd-kqueue handler (which
- doesn't work yet)
-
- fixed the devpoll support while testing it on a real solaris box
-
-05.04.2004 09:49
-- debian
-
- added debian packaging support written by Vincent Wagelaar
-
-- solaris
-
- Another set of patches for Solaris from Adam
- * Detect <sys/devpoll.h>
- * Detect and include <sys/filio.h> for definition of FIONREAD
- * Detect and link against the library exporting hstrerror
- * Correct typo in SENDFILE_LIB
- * Use__sun instead of __solaris__ for detecting operating system.
- Please see http://predef.sourceforge.net/preos.html for more
- detail
- * Explicitly cast arguments to isalpha() and toupper() to unsigned
- char. The man page says that the functions support the range of
- an unsigned char, and EOF.
- * Include <limits.h> and define UIO_MAXIOV as IOV_MAX for Solaris.
-
-04.04.2004 18:05 - 1.1.4
-- pidfile
-
- added pidfile writing after deamonizing
-
-04.04.2004 01:05
-- fdevent
-
- added framework for freebsd_kqueue and solaris_devpoll
-
- the solaris_devpoll one might event work (untested)
-
-03.04.2004 16:41
-- network
-
- added framework for filebased chunks
- - read-write + mmap-write
- - linux-sendfile
- - freebsd-sendfile
- - solaris-sendfilev (untested)
-
- and memorybased chunks
- - write
- - writev
-
- made TCP_CORK a 'global' flag around the write_chunkqueue-calls
-
- the writev() support should improve the performance for all non-static
- pages.
-
- 170 req/s against 158 req/s for the following script if writev() is used
- instead of write()
-
- <?php
-
- for ($i = 0; $i < 1000; $i++) {
- print $i."<br />\n";
- flush();
- }
-
- ?>
-
-28.03.2004 13:42
-- cleanup
-
- applied some cleanup patches submitted by Adam:
- * variables modified in signal handlers should be sig_atomic_t
- * assert statements should not have side effects
- * STD{IN,OUT,ERR}_FILENO preferred instead of {0,1,2}
- * dieing --> dying
- * SEGFAULT calls abort directly, instead of derefencing a NULL pointer
-
-- mod_accesslog
-
- modified the accesslog format to be CLF compatible
- set locale for LC_TIME to C
-
-26.03.2004 16:13
-- path info
-
- enabled the pathinfo code again
-
-
-25.03.2004 13:30 - 1.1.3
-- portability
-
- compiles fine now without any patches on IRIX
-
-- hostname detection
-
- reworked "get the hostname for HTTP/1.0 requests which don't specify a
- Host: ..." to only query the name in this single case for the server side
- of the connection
-
-- errorlog handling
-
- stderr is only used until the errorlog is init'ed
- if no error-log is specified, syslog() is used
- if cycling error-log fails, syslog() is used
-
-- accesslog cycling
-
- don't fall back to stdout anymore
-
-- event-handler
-
- use poll() as the default event-handler again
-
-24.03.2004 01:37 - 1.1.2a
-- error messages
-
- added some hints to the failing error-messages
-
-22.03.2004 01:58 - 1.1.2
-- configure
-
- some protability changes to get the 'inline' working with the MIPS CC
-
-21.03.2004 22:00
-- mod_rewrite, mod_redirect
-
- reading the config for those two plugins was not working
-
-- fdevents
-
- changed the compile time setting for the event handling into a run-time
- setting.
-
- server.event-handler = "select" # poll, linux-rtsig, linux-sysepoll
-
- added sys_epoll() for linux 2.6
-
- select - all systems
- poll - Linux 2.1.23+, all XPG4-UNIX
- sigio - linux 2.4.0+
- sysepoll - linux 2.5.66+
-
- 1000-4k-nok 1000-100k-nok
- select 1776.99 296.52
- poll 678.02 607.28
- sigio 3754.46 1411.23
- sysepoll 3817.67 1431.02
-
-21.03.2004 00:10
-- configure script
-
- rewrote large parts of the lib/header detection of the configure script
-
-20.03.2004 01:39
-- fastcgi
-
- as the docroot on external hosts might be different than the webserver
- docroot it can now be specified in the config:
-
- fastcgi.server = ( ".php" =>
- ( "grisu" =>
- (
- "host" => "192.168.2.41",
- "docroot" => "/home/jan/servers/",
- "port" => 1026
- )
- )
- )
-
- a huge internal cleanup in the config handling made the code more readable.
- some more warnings and error checking should track most of the config
- errors for the fastcgi plugin
-
-19.03.2004 12:34
-- external patches
-
- Matthijs van der Klip submitted three nice patches:
- - turn off writing in mod_status if status.rrd-reports is set to disable
- - fix for a debug message
- - get the hostname for HTTP/1.0 requests which don't specify a Host: ...
- - rc-script for RedHat
-
-- documentation
-
- added a documentation section about authentification
- - doc/authentification.txt
-
-19.03.2004 05:11
-- optimizations
-
- implemented special versions of
- - strcasecmp (array_strcasecmp)
- - isdigit, isalpha, isalnum (light_*)
-
- added a faster check for a finished header
-
- after disabling all modules it is still possible to get 20 kreq/s.
-
-15.03.2004 19:45 - 1.1.1
-- localizer server
-
- added the localizer-server module to the code
-
-- chunked-encoding
-
- Apple's Safari or HTTP-Handler doesn't handle chunked-extensions defined by
- RFC 2616 correctly and doesn't ignore them. Disabled the chunked-extension
- which were just used for debugging purposes.
-
-07.03.2004 12:20
-- optimization
-
- moved the checks if a plugins support a given function from the dispatcher
- (plugins_call) to plugins_call_init() to do the check only once.
-
- equalized the plugins functions to only two types:
- SERVER_FUNC()
- CONNECTION_FUNC()
-
- replaced all handwritten plugin_call-handlers with macros
-
- made all plugin-functions 'static'
-
- with all plugins loaded we are at 15kreq/s gain
- without any plugin loaded at 16kreq/s
-
- before the change we were at 13kreq/s
-
-06.03.2004 21:13
-- compilation fixes
-
- fixed some warnings on FreeBSD and NetBSD by adding
- #include <netinet/in.h>
-
- ifdef'ed a pcre-entry in base.h
-
- remove #define _XOPEN_SOURCE from http_auth.c for IRIX
- crypt() on Linux needs _XOPEN_SOURCE
-
-06.03.2004 19:18 - 1.1.0
-- authentification
-
- added htpasswd and htdigest backends to work against user-files generated
- by htpasswd and htdigest.
-
- for basic auth:
- - plain
- - htpasswd (crypt only)
- - htdigest
-
- for digest auth:
- - plain
- - htdigest
-
-06.03.2004 17:35
-- authentification
-
- check the method in the authorization header againt the configured method
-
-06.03.2004 14:54
-- hostname parsing
-
- added a RFC-2396 conforming "Host:" parser
- added 17 checks for the parser
-
-06.03.2004 10:25
-- configuration
-
- added a warning for unknown configuration variables.
-
- dropped the 'specific-for.url' ideas for now as it is not known yet how to
- implement it the right way
-
- renamed some config-variables to reflect there actual meaning
- - server.host -> server.bind
- - server.virtual-* -> simple-vhost.*
- - server.userid -> server.username
- - server.groupid -> server.groupname
- - server.docroot -> server.document-root
-
-
-05.03.2004 15:36
-- fastcgi
-
- internals: moved all mod_fastcgi settings from the global struct to the
- plugin itself
-
-- vhosting
-
- got a patch for enhanced virtualhosting from christian kruse -> mod_evhost
-
- moved the virtual hosting config (server.virtual-*) to it's own module
- called mod_simple_vhost
-
-23.02.2004 10:06
-- configfile
-
- rearragned the config-file structure again to be able to add settings for
- a given URL, Host, Filename, ...
- This change affects some config-options directly (access.deny,
- url.rewrite, url.redirect, virtual-hosting, ...)
-
- added 'specific-for.url' for url specific config settings
-
-- digest auth
-
- FIX: md5-sess type
-
- seperate the auth-backend stuff
-
-13.02.2004 22:23 - lighttpd 1.0.3
-- content-length + POST
-
- FIX: If header and content didn't fit into one single packet the rest of
- the content was not read correctly
-
-13.02.2004 01:07
-- content-length + POST
-
- the check for content-length on a POST request vanished somehow in one of
- the previous releases.
-
-- header search
-
- FIX: the search for header fields was up to now case-sensitive. Now it is
- like required by the standard case-in-sensitive.
-
-- browser bugs
-
- w3m 0.2.5 adds an additional \r\n at the end of the POST requests which is
- handled now
-
-10.02.2004 10:12
-- start script
-
- took the suse rc-skeleton which states to be LSB compliant and modified it
- for lighttpd needs
-
-09.02.2004 11:48
-- HEAD requests
-
- FIX: HEAD requests for static files delived the content from the GET
- request. (test case is added)
-
-08.02.2004 15:53
-- directory listings
-
- FIX: the pathname has not encoded at all before it was transfered to the
- browser. a proper url and html-encoding has been added.
-
- added modification-time and filesize to the output
-
- added a basic css for the virtual listings
-
-07.02.2004 22:15 - lighttpd 1.0.2
-- sample configfile
-
- rearranged the config-file to have all the important options at the top
-
-- docs
-
- added a mod-rewrite options
-
-- mod_accesslog
-
- stdout is no longer used a default for the accesslog
-
-- error-messages
-
- the 404 is now reported in the error-log
-
-07.02.2004 17:30
-- configfile handling
-
- if a key is used twice like
-
- url.rewrite = ( "url1" => "url")
- url.rewrite = ( "url2" => "url")
-
- you get an error now. You have to write:
-
- url.rewrite = ( "url1" => "url",
- "url2" => "url")
-
-31.01.2004 12:22 - lighttpd 1.0.1
-- log cycling
-
- added a sighup-handler to the plugin interface and fixed the log-cycling
- for access-logs
-
-- portability
-
- disabled the interval-time optimization on IRIX
-
-- documentation
-
- added a lot of new documentation to README
-
-31.01.2004 10:59
-- status module
-
- added two new options rrd-dir and rrd-reports:
-
- rrd-reports = (boolean) # enables RRD-reports
- rrd-dir = (string) # path for the daily status-files
-
- fixed the "status-files in /"-bug this way
-
-
-22.01.2004 13:38 - lighttpd 1.0.0
-- simple docroot
-
- fixed handling of docroots if virtual-host is disabled
-
-27.12.2003 11:12
-- license handling
-
- added the first interface to license handling.
-
-25.12.2003 23:48
-- protability
-
- Verified again that the code compiles and runs cleanly on Linux, FreeBSD,
- NetBSD and IRIX
-
- compiling with gcc and the option -pedantic works fine
- compiling with mipspro cc works fine, too
-
-- tests
-
- added some more tests: 39 tests
-
-25.12.2003 16:01
-- protability
-
- some compile fixes for FreeBSD have been applied and a new switch has been
- added to choose between IPv4 and IPv6 on FreeBSD.
- (cmdline: -6, configfile: server.use-ipv6)
-
-- packaging
-
- cleaned up the specfile for building RPMs
-
-21.12.2003 01:00
-- authorization
-
- brought basic and digest auth back to life. this module as the last one
- which had to be updated after the config-file changes
-
-- test harness framework
-
- add 3 tests for basic auth
-
-20.12.2003 22:10
-- compression
-
- added gzip compression (gzip-header + deflate + crc)
-
-- test harness framework
-
- added a 22 tests to verify the correct behaviour of lighttpd
-
-- request parsing
-
- GET http://www.yahoo.com/ HTTP/1.0
-
- is handled now as
-
- GET / HTTP/1.0
-
-- plugins
-
- moved FastCGI and CGI handling into modules which can be loaded at run-time
-
-17.12.2003 13:18
-- compression
-
- the directory structure is now build automaticly
-
-15.12.2003 01:00
-- compression
-
- added a compression cache to the compression module (mod_compress)
-
- Vary: Accept-Encoding is set now as it influences to delivered stream of
- bytes. This is important for caches.
-
-10.12.2003 00:24
-- config files
-
- a new config-file format is ready for the final release of lighttpd.
-
- it supports:
-
- server.docroot = "string"
- server.host = integer
- server.modules = ( "string", "string" )
- server.mimetypes = ( "key" => "value" )
- server.complex = ( "key" => ( "string", integer ),
- "string",
- integer )
-
- the syntax should look familar to all who worked with Perl or PHP.
-
- config-file handling has been seperated into a parser and a lexer. Both
- are currently written by hand and will propably be rewritten into bison
- flex if time permits. But that would be a cosmetical change.
-
-05.12.2003 03:07
-- status-page
-
- improved the status page to display
- - the current connection-stati
- - average throughput over 5 seconds
- (requests/s and output-bound traffic)
-
- now you can see what is going on in the server
-
-- access-log
-
- the accesslog is now a module and can be disabled by just removing the
- plugin from the list of loaded plugins
-
-04.12.2003 16:18
-- chroot-ing
-
- how-to: using chroot
-
- - chroot to /home/www/
- - docroot at /servers/<hostname>/pages/
- - defaulthost www.example.org
-
- e.g. (external view)
- /home/www/servers/www.example.org/pages/index.html
-
- (in chroot)
- /servers/www.example.org/pages/index.html
-
- config:
-
- chroot /home/www/
- userid wwwrun
- groupid nogroup
-
- virtual-server-root /servers/
- virtual-server-default-host www.example.org
- virtual-server-docroot /pages/
-
- The FastCGI process is living outside this chroot definition as it is
- started seperatly.
-
-01.12.2003 02:06
-- cleanup
-
- in preparation for the first stable release some internals had to be
- cleaned up. Basicly it was a cleanup of workflow of the creation of the
- response-header. All modules can use a clean interface for this purpose
- now. This is espacially usefull for all modules which have to pass some
- HTTP-headers to the client.
-
-29.11.2003 22:22
-- modules
-
- finally moved the modules to shared libraries and cleaned up some code
- path to become more readable.
-
- So far we have:
-
- mod_rewrite
- mod_redirect
- mod_access
- mod_auth
- mod_cache
- mod_chat
- mod_status
- mod_maps
-
-28.11.2003 18:16
-- redirects
-
- as lighttpd supports url-rewriting redirection was a few lines of new code.
-
- redirect ^/wishlist/(.+) http://jan.kneschke.de/wishlist/$1
-
- rewrite ^/wishlist/(.+) /new/wishlist/$1
-
-28.11.2003 17:00
-- signal stuff
-
- setitimer is used to send a event every second to call time() only once a
- second. another system call which has been remove from the main-loop.
-
- sending HUP to lighttpd will close and re-open the logfiles. this is used
- for cycling logfiles.
-
-#! /bin/sh
-
-###
-#
-# a simple logfile rotator for lighttpd
-#
-
-DATE=`date +"%Y%m%d-%H%M"`
-LPID=`pidof lighttpd`
-mv access.log access.log.${DATE}
-kill -HUP ${LPID}
-gzip access.log.${DATE}
-
-27.11.2003 01:07
-- native win32 port
-
- a first attempt for a native win32 has been done. For now mingw is the
- base for the development as it provides a basic unix-like framework for
- building native win32 applications.
-
- the most internal files have been ported and the over all progress is
- going well. At the end this will just be a prove of concept.
-
-26.11.2003 01:17
-- access denied
-
- added a access-deny filter to block specific urls like
-
- access-deny ~
- access-deny .inc
-
-17.11.2003 01:06
-- bug fixing
-
- a fstat() on a opened fd which has changed reports wrong the file-info.
- Using stat() again helps to solve this problem.
-
- the sig-io version doesn't suffer from this problem.
-
- the etags are now used for verifing file-cache-entries.
-
-- chat
-
- enabled the internal login mechanism again
-
- added support transfering session-infos over MySQL.
-
-15.11.2003 00:19
-- optimizing
-
- added a buffer_equal_reverse function which is optimized version of strcmp
- which is going backwards as pathnames are often the same for in the first
- bytes.
-
- wrote a one-pass parser for the request-header. The combination of
- strstr(..., "\r\n") to seperate lines and strchr(..., ':') to seperate
- keys from values more or less touched every byte twice.
-
- we are still at 18.000 req/s for 4kb keep-alive requests even with etags
- and handling all header fields.
-
-14.11.2003 17:26
-- fcgi
-
- Content-Type wasn't passed correctly to the FastCGI app. HTTP_CONTENT_TYPE
- was sent instead.
-
-- cache
-
- provided access to the Session-ID
-
-- error-log
-
- the timestamp is now written in a human readable form
-
-22.10.2003 00:06
-- fcgi, cgi
-
- added a special set of array-functions which are optimised for the "insert
- only once" case.
-
- this provides access to the headers which are now forwarded to the external
- interfaces. Before this change only a limited set of request-headers were
- forwarded.
-
-21.10.2003 11:58
-- modules
-
- added a new module-hook after the basic-init of the module for handling
- config-settings and prepare the overall operartion (like building
- db-connections, compiling regexes, ...)
-
-- cache
-
- use turckmm-cache 2.4.3 to get some numbers for the php-latency:
-
- /usr/sbin/ab -n 10000 -c 10 http://alba.home.kneschke.de:1025/index.php
-
- handling the cache-decision and the cache-hit in php:
-
- cache-miss: 100% (-&gt; $version = 0)
-
- plain : 108.13 req/s
- turckmm-cache: 218.39 req/s
-
- cache-hit: 100% (-&gt; $version = 1)
-
- plain : 164.45 req/s
- turckmm-cache: 653.98 req/s
-
- handling the cache-decision and the cache-hit in the server:
-
- cache-hit: 100%, but using index.cml
-
- cml: 4918.84 req/s (no keep-alive)
- cml: 6901.31 req/s (keep-alive)
-
- cache-miss: 100%, but using index.cml
-
- plain : 108.39 req/s
- turckmm-cache: 217.84 req/s
-
- Conclusion:
- - there is no loss in the cache-miss case through the cml-handling
- - the cache-hit case can be improved dramaticly with lighttpd-cache
- - turckmm-cache improves the cache-miss case alot
-
-20.10.2003 00:40
-- cache
-
- the first 'real-life' test showed dramatic improvements in the req/s
- handling.
-
- The basic idea was to move the decision if a php-page can be taken from
- the cache from the php-code to the webserver.
-
- See here why this is a good thing:
-
- the quite common code which works for http://jan.kneschke.de/ is using
- templates and is quite static, but depends on 4 external files (the
- menu-structure, the template, the current content, the class-file).
-
- the index-file is always:
-
- include_once "jk.inc";
-
- $v = new view();
- print $v->get(array(array ("file" => "content.html")));
-
- It is more or less the same for all pages.
-
- This basic setup can deliver 100 requests/s.
-
- The next step has:
- - application bases caching
-
- as we know that each pages depends on those 4 files, you can check if they
- have been modified since the last request and deliver the content from the
- cache otherwise.
-
- this increased the throughput to 150 req/s. (cache-hit ratio 100%)
-
- The next logic step is to move the decision-making process out of the PHP
- code as PHP is to slow for the cache-hit path:
-
- a CML (Cache-Markup-Language) has been written which describes the whole
- decision process which has been written in PHP-code before:
-
-
-output.content-type text/html
-
-output.include _cache.html
-
-trigger.handler index.php
-
-trigger.if file.mtime("../lib/php/menu.csv") > file.mtime("_cache.html")
-trigger.if file.mtime("templates/jk.tmpl") > file.mtime("_cache.html")
-trigger.if file.mtime("content.html") > file.mtime("_cache.html")
-
- if one of the 'trigger.if' statements is true the 'trigger.handler' is
- called to generate the pages.
-
- if none of the them is trigger the files from 'output.include' are sent to
- the browser with content-type specified in the first line:
-
- The result was very 'promissing':
-
- 5900 req/s with keep-alive
- 3800 req/s without keep-alive
-
- (both for a cache-hit ratio of 100%)
-
- for keep-alive this is factor <b>59</b> against the plain un-cached
- version and still <b>39</b> againt the php-cache-version which is doing
- exactly the same.
-
- Time for party. :)
-
-19.10.2003 - 18:55
-- cache
-
- the handling of functions has been improved. they are now 'plugable'. just
- the dlopen() stuff is missing.
-
- a new datatype has been added: the string
-
- this makes it possible to evaluate something like:
-
-trigger.if unix.time.now() - file.mtime("head.html") > 30
-trigger.if mysql.query("SELECT count(*) " + \
- " FROM structure AS struc, session AS sess " + \
- " WHERE struct.user = sess.user" + \
- " AND sess.id = \"" + mysql.escape("ab\"c") + "\"")
-
- you see:
- - string operations (concat)
- - handing of escape-sequences
- - functions
- - comparisions
-
-18.10.2003 - 13:39
-- cvs
-
- imported everything into the cvs server which makes the whole revision
- handler a lot easier. The CVS server was up all the time but not used.
- Importing required 5 minutes of work which included merge the freebsd and
- the linux tree.
-
-- compilers + platforms
-
- on a regular various compilers and platform are check to compile with with
- the current code base:
-
- platform | os | compiler | state
- ---------+---------------------+--------------+---------
- ia32 | Linux 2.4.22 | gcc 2.95.3 | ok
- ia32 | FreeBSD 5.1-CURRENT | gcc 3.3.1 | ok
- mips64 | IRIX 6.5 | gcc 3.2.2 | ok
- misp64 | IRIX 6.5 | MIPSpro 7.41 | ok
-
- the mipspro compiler revealed some warning which resulted in a nice
- code-cleanup that made the code more readable.
-
-18.10.2003 - 03:00
-- e-tags and friends
-
- in preparation for the php-conference at the begin of november in
- frankfurt/main the server has the support some more caching/proxy tags
- like:
- - E-Tag (14.19) [done]
- - If-Match (14.24)
- - If-None-Match (14.26) [done]
- - If-Range (14.27)
-
- Section (13.3.3) binds them together. [RFC 2616]
-
- using lxr.kde.org and lxr.mozilla.org revealed that
- - konqui only uses if-none-match
- - mozilla uses if-none-match and if-range
-
- it looks like it isn't that easy to trigger the if-range case.
-
- As ulf suggested the etag is a hash of file-size, inode-number and mtime.
-
-- fd-caching
-
- ulf just phoned me ask proposed the free the cache more agressivly in case
- of fd-shortage. increasing the the fd-limit is the better idea. :)
-
-17.10.2003 12:45
-- chat
-
- finished the mysql-support for storing the sessions
-
-12.10.2003 20:56
-- valgrind
-
- used valgrind again to verify that the code a free of mem-leaks and found
- a 'leak generator' in the chunk-api.
-
- the last few leaks were just some missing free()'s at the end of the
- program run which would have been freed anyway.
-
- at the end valgrind couldn't find any missing free()'s.
-
-11.10.2003 12:09
-- FastCGI
-
- reduced the number of system calls for FastCGI to WebServer to 2 calls per
- fd-event. (ioctl() + read())
-
- this has no direct effect of the performance of the server, but improves
- the possible througput of the load-balancer.
-
-10.10.2003 21:09
-- FastCGI - load-balancing
-
- a brown paper bug has been fixed which caused to decreasing throughput if
- load-balancing was enabled.
-
-
- benchmarking the req/s with load-balancing shows really nice results:
-
-
- server : req/s comment
- ---------+--------------------------------------------------
- ulf : 764.06 (php)
- lappi : 800.06 (php)
-
- ulf+lappi: 1526.95 (2 * php)
-
- grisu : 1265.66 (php + ab + lighttpd)
-
-
- all : 1647.72 (3 * php + ab + lighttpd)
- all(nice): 1904.40 (same as all, but the local php on grisu
- has been 'nice -20'd)
-
-
- if a php is run on the load-balancer it has to get a lower priority than
- the load-balancer itself as to handle the work of (here) 3 php-servers.
-
-
-10.10.2003 15:11
-- java ?
-
- http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jk2/common/AJPv13.html
-
-08.10.2003 21:08
-- gigE
-
- Last week 3 RTL8169S gigE cards arrived and were installed in the
- test-framework.
-
- They are very cheap (20 Euros) and are a good start for a low-level
- benchmark network.
-
- First result show us:
-
- 48 Mb/s with ab.
-
- The webserver and the test-server are equipped with a 2000+ AMD CPU. The
- system load 95%, user load is 3%, the rest is idle on both plattforms.
-
- After some calculations at gets clear that there are various bottlenecks:
-
- 1. The PCI-Bus (32bit/33Mhz) can only transfer 133Mb/s
- - 48 Mb/s TCP-Traffic results in 55Mb/s Ethernet-Traffic (verified with
- slurm) [outgoing]
- - there is about 10Mb/s incomming traffic at the PCI bus which the
- requests
- - the rest of the devices at the PCI bus are eating the last few mb/s
- 2. IRQ-Handling
- - There are reasons why the RTL8169S cards are so cheap
- - they can't send jumbo-frames
- - only 8k/64k buffers which results in a interrupt every 3 packets
- - they are at least handling checksum offloading for ip, udp and tcp
-
- In the end there is a need for new hardware to limit the throughput by the
- Ethernet again.
- - PCI-X, 64bit-PCI, ...
- - 'real' gigE-Network cards
- - ...
-
-
- BTW: 2.4.22 + the r8139 driver are very flacky and resulted in 3 lock-ups
- for today.
-
- In another test the dual-PPro-FreeBSD 5.1-CURRENT machine has been used as
- server with a gigE interface (re0) at has shown that the CPU is the limit
- for this combination. The maximum thoughput was 7Mb/s.
-
- Another small benchmark:
- $ ab -n 1000 -c 10 http://192.168.2.41:&lt;port&gt;/lighttpd-20030925.tar
-
- port | server | CPU Idle
- ------+-------­---------+-----------
- 1025 | lighttpd | 75%
- 1026 | thttpd 2.23b1 | 75%
- 1027 | boa-0.94.14rc17 | 69% *
- 1028 | apache 1.3.x | 77%
-
-
- In all 4 cases the thoughput was 8600 kbytes/s.
-
- * boa had 9 failed transfers.
-
-- FreeBSD
-
- The problems with FreeBSD 5.0-RELEASE vanished after updating to
- 5.1-CURRENT.
-
-26.09.2003 18:22
-- FreeBSD
-
- A SMP-machine has been added to the test-farm. It is running FreeBSD
- 5.1-RELEASE and will help to the improve the scalability.
-
- fixed sendfile() handling.
-
-- FreeBSD problems
-
- FreeBSD-5.1-RELEASE-SMP
- 2 * Pentium Pro 200 MHz
- 192.168.2.38 (doubleheart)
- (webserver [lighttpd at port 1025, thttpd at port 1027])
-
- Linux 2.4.20
- 1 * AMD 2000+
- 192.168.2.10 (grisu)
- (ab)
-
- Problem:
- Connections are reset by the kernel without any application intervention.
-
- Calling 'ab' (apachebench) at grisu with the following paramters:
-
- /usr/sbin/ab -n 10000 -c 10 http://192.168.2.38:1025/index.html
-
- results in the following output:
-
- ...
- Time taken for tests: 40.610 seconds
- Complete requests: 10000
- Failed requests: 5980
- (Connect: 0, Length: 5980, Exceptions: 0)
- ...
-
-
- This is reproducable and the number of failed requests is always
- 5980 +/- 50 requests. In other words: after 4000 requests tcpdump shows
- the following output:
-
- tcpdump shows:
-
- 00:53:48.923029 192.168.2.10.39774 &gt; 192.168.2.38.1025: S [tcp sum ok]
- 1013737315:1013737315(0) win 5840 &lt;mss 1460,sackOK,timestamp 5208461
- 0,nop,wscale0&gt; (DF) (ttl 64, id 7918, len 60)
-0x0000 4500 003c 1eee 4000 4006 964d c0a8 020a E..&lt;..@.@..M....
-0x0010 c0a8 0226 9b5e 0401 3c6c 6763 0000 0000 ...&amp;.^..&lt;lgc....
-0x0020 a002 16d0 eeaa 0000 0204 05b4 0402 080a ................
-0x0030 004f 798d 0000 0000 0103 0300 .Oy.........
-
- 00:53:48.923330 192.168.2.38.1025 &gt; 192.168.2.10.39774: S [tcp sum ok]
- 1803860672:1803860672(0) ack 1013737316 win 65535 &lt;mss 1460,nop,wscale
- 1,nop,nop,timestamp 4459794 5208461&gt; (DF) (ttl 64, id 6821, len 60)
-0x0000 4500 003c 1aa5 4000 4006 9a96 c0a8 0226 E..&lt;..@.@......&amp;
-0x0010 c0a8 020a 0401 9b5e 6b84 bac0 3c6c 6764 .......^k...&lt;lgd
-0x0020 a012 ffff d4ce 0000 0204 05b4 0103 0301 ................
-0x0030 0101 080a 0044 0d12 004f 798d .....D...Oy.
-
- 00:53:48.924009 192.168.2.10.39774 &gt; 192.168.2.38.1025: . [tcp sum ok] ack 1
- win 5840 &lt;nop,nop,timestamp 5208461 4459794&gt; (DF)
- (ttl 64, id 7919, len 52)
-0x0000 4500 0034 1eef 4000 4006 9654 c0a8 020a E..4..@.@..T....
-0x0010 c0a8 0226 9b5e 0401 3c6c 6764 6b84 bac1 ...&amp;.^..&lt;lgdk...
-0x0020 8010 16d0 e9c3 0000 0101 080a 004f 798d .............Oy.
-0x0030 0044 0d12
-
- 00:53:48.924150 192.168.2.10.39774 &gt; 192.168.2.38.1025: P [tcp sum ok]
- 1:29(28) ack 1 win 5840 &lt;nop,nop,timestamp 5208461 4459794&gt; (DF)
- (ttl 64, id 7920, len 80)
- 0x0000 4500 0050 1ef0 4000 4006 9637 c0a8 020a E..P..@.@..7....
- 0x0010 c0a8 0226 9b5e 0401 3c6c 6764 6b84 bac1 ...&amp;.^..&lt;lgdk...
- 0x0020 8018 16d0 27e4 0000 0101 080a 004f 798d ....'........Oy.
- 0x0030 0044 0d12 4745 5420 2f69 6e64 6578 2e68 .D..GET./index.h
- 0x0040 746d 6c20 4854 5450 2f31 2e30 0d0a 0d0a tml.HTTP/1.0....
-
- 00:53:48.924728 192.168.2.38.1025 &gt; 192.168.2.10.39774: R [tcp sum ok]
- 1803860673:1803860673(0) win 0 (ttl 64, id 6831, len 40)
-0x0000 4500 0028 1aaf 0000 4006 daa0 c0a8 0226 E..(....@......&amp;
-0x0010 c0a8 020a 0401 9b5e 6b84 bac1 0000 0000 .......^k.......
-0x0020 5004 0000 64ba 0000
-
- SYN, SYN+ACK, ACK, DATA, RST
-
- strace shows that no connection attempt has been reported to the
- application which is poll()'ing the server socket.
-
- /* the common loop without any block attempts */
-
- accept(3, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, [0]) = 5
- fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
- read(5, "GET /index.html HTTP/1.0\r\n\r\n", 4095) = 28
- stat("/home/jan/lighttpd-0.1.0/servers/", {st_mode=S_IFDIR|0755, st_size=512, ...}) = 0
- fstat(6, {st_mode=S_IFREG|0644, st_size=4348, ...}) = 0
- write(5, "HTTP/1.0 200 OK\r\nConnection: clo"..., 235) = 235
- write(2, "1064875136: (network.c.210) 235 "..., 33) = 33
- syscall_393(0x6, 0x5, 0, 0, 0x10fc, 0, 0xbfbff2c0, 0) = 0
- close(5) = 0
-
- /* no futher waiting connections */
-
- accept(3, 0xbfbff700, [1852702730]) = -1 EAGAIN (Resource temporarily unavailable)
-
- /* enter the main-loop */
-
- gettimeofday({1769235301, 1663069807}, NULL) = 0
- poll([{fd=3, events=POLLIN}], 1, 1000) = 0
- gettimeofday({4294967295, 65537}, NULL) = 0
- poll([{fd=3, events=POLLIN}], 1, 1000) = 0
- gettimeofday({4294967295, 65537}, NULL) = 0
- poll([{fd=3, events=POLLIN}], 1, 1000) = 0
- ...
-
- (strace is broken for accept() and gettimeofday(), syscall_393() is sendfile())
-
- after entering the main-loop the webserver doesn't receive any new POLLIN
- events at all for the next 10-15 seconds. Any connection-attempt within
- the period is, as you can see in the tcpdump output, accepted by the
- kernel and the received data is thrown away as the kernel sends a RST.
- After those 10-15 seconds the application gets a POLLIN event for the
- server socket and the normal data-transfer taken place for the next 4000
- requests.
-
- This behaviour is reproducable with thttpd 2.20c and the current lighttpd.
-
-
-26.09.2003 11:42
-- localizer
-
- ported the localizer-server application into a module for lighttpd. After
- 30 minutes the code was ported and funtional. This modules provides access
- to the localizer-db by a HTTP-Interface and generates the response as
- HTML, CSV and plain-text.
-
- So far, the module-interface looks good and flexible enough.
-
- 7000 req/s is good enough too. Generating the HTML and querying the DB
- needs some time.
-
-22.09.2003 08:40
-- modules
-
- introduced a simple module interface which allow to hook into the process
- of handling the requests. Basicly it allows to move the url-rewriter, the
- auth-sub-system and the cache out of the main-code. The module-interface
- will be extended to allow the cgi and the fastcgi sub-processes to be
- moved into a module.
-
-15.09.2003 09:36
-- error-handling
-
- fastcgi and cgi connections are now closed correctly if the corresponding
- client-connection has died.
-
-14.09.2003 10:40
-- cgi
-
- finally streaming works with CGI, too
-
- this enable support for cgiirc.sf.net and friends which use streaming as
- there transport mechanism.
-
- streaming has been verified with cgiirc-0.5.2.
-
-- fdevents
-
- there where some reports that sigio didn't work as expected. It just
- reported no events at all. Looks like a known bug in the glibc on
- those platforms.
-
- Using poll() instead solve the problems.
-
-27.08.2003 22:12
-- rewrite
-
- a pcre based rewrite engine has been integrated
-
-- cgi
-
- the file-based cgi interface has been replace by two pipes.
-
-23.07.2003 13:29
-- fdevents
-
- the whole fd-event handling has been reworked and several smaller bugs
- and design-errors have fixed.
-
- sigio, poll() and select() are working fine again.
-
- On IRIX 6.5 SIGIO could be used, but without further testing poll() is used.
-
-- cgi
- CGI-support is still broken.
-
-21.07.2003 18:46
-- dnotify
-
- using the F_NOTIFY feautre of the Linux 2.4.x kernel gives anothre nice
- performance boost as lighttpd can cache the stat()'s the right way, now.
-
- 23009.66 @ 5-4k-k which means +10% against 30.06.2003 14:03
-
- for 1000-4k-nok the performace nearly doubles: 3730.23 goes up to 6144.39
-
-17.07.2003 13:21
-- FreeBSD
-
- a small patch (#include &lt;&gt;) to compile lighttpd on FreeBSD again.
-
-08.07.2003 10:48
-- fileinfo-cache
-
- A reallife test showed that the cache wasn't perfect at all as it made
- lighttpd crash. This is fixed now.
-
-30.06.2003 17:40
-- lighttpd-bench
-
- After some problems with other benchmarking tools for webservers the first
- version of lighttpd-bench has been written.
-
- It a revealed a nasty strange behaviour which was fixed by increasing the
- listen-backlog from 5 to 1024.
-
-30.06.2003 14:03
-- fileinfo-cache
-
- the fileinfo-cache has been relaxed a little bit and there are always 2
- fstat()'s per file-request now. This isn't that dramatic:
-
- 21800.74 req/s is still a very good result (7-4k-k).
-
-29.06.2003 03:29
-- fileinfo-cache
-
- a fileinfo cache has been added to reduce the number of system-calls to
- stat and open a file.
-
- in the releases before the same file was stat'ed at least 2 times plus a
- stat on the docroot for each request. Now the stat()'s and the
- corresponding open() + close() calls are cached and the number of system
- calls has been reduced to the minimum:
-
- $ strace -eopen,stat64,read,write,sendfile,accept,shutdown,close \
- -p `pidof lighttpd`
-
-/* first connection */
-accept(3, {sin_family=AF_INET6, sin6_port=htons(56211),
- inet_pton(AF_INET6, "::ffff:192.168.2.10", &amp;sin6_addr), sin6_flowinfo=0,
- sin6_scope_id=0}, [28]) = 5
-accept(3, 0xbffff470, [28]) = -1 EAGAIN
-read(5, "GET /index.html HTTP/1.0\r\nUser-A"..., 4095) = 91
-stat64("/home/weigon/projects/lighttpd/servers/grisu.home.kneschke.de:1025/pages/",
- {st_mode=S_IFDIR|0755, st_size=3656, ...}) = 0
-stat64("/home/weigon/projects/lighttpd/servers/grisu.home.kneschke.de:1025/pages//index.html",
- {st_mode=S_IFREG|0644, st_size=4348, ...}) = 0
-open("/home/weigon/projects/lighttpd/servers/grisu.home.kneschke.de:1025/pages//index.html",
- O_RDONLY) = 6
-write(5, "HTTP/1.0 200 OK\r\nConnection: clo"..., 235) = 235
-sendfile(5, 6, [0], 4348) = 4348
-shutdown(5, 1 /* send */) = 0
-close(5) = 0
-
-/* second connection */
-accept(3, {sin_family=AF_INET6, sin6_port=htons(56212), inet_pton(AF_INET6,
- "::ffff:192.168.2.10", &amp;sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28])
- = 5
-accept(3, 0xbffff470, [28]) = -1 EAGAIN
-read(5, "GET /index.html HTTP/1.0\r\nUser-A"..., 4095) = 91
-write(5, "HTTP/1.0 200 OK\r\nConnection: clo"..., 235) = 235
-sendfile(5, 6, [0], 4348) = 4348
-shutdown(5, 1 /* send */) = 0
-close(5) = 0
-
-
- In the end we have a new speed record:
-
- (ab -c 8 -n 100000 http://192.168.2.10:1025/index.html with poll())
- Requests per second: 23435.67 [#/sec] (mean)
-
- This is a speed increasement of 20-30% against the last internal benchmark.
-
-
-28.06.2003 02:30
-- caching framework
-
- the trigger.if directive is working fine. the basic algebra is done ( +,
- -, *, / and comperations =, &lt;=, &gt;=, &gt;, &lt; and the boolean logic
- &amp;&amp; and || including braces)
-
- two basic function are available:
- - unix.time.now
- - file.mtime(...)
-
-25.06.2003 17:33
-- caching framework
-
- added output.include, output.content-type for a cache-hit and
- trigger.handler for a cache-miss.
-
- the actual decision is made be trigger.if which will be added tomorrow.
-
-15.06.2003 15:33
-- sig-io
-
- After several other smaller optimisations lighttpd performs better with
- sig-io under high load:
-
- sigio+poll poll
- c1000-4k-nok : 2635.95 1643.39
- c1000-4k-k : 7335.68 6788.87
- c1000-100k-nok: 2353.49 1217.73
- c1000-100k-k : 3097.89 2080.73
-
-
- The user-space part has been optimized a lot. Now it is time to optimized
- the number of context-switches between user and kernel-mode.
-
- user 0m0.180s
- sys 0m1.160s
-
- a fileinfo-cache is the way to go.
-
- struct {
- buffer *name;
- struct stat st;
- int handler;
- ...
-
- int fd;
- void *mmap_p;
- }
-
-11.06.2003 14:57
-- sig-io is back again
-
- and it works fine.
-
- sigio (Realtime-Signals under Linux 2.4.x) sends one signal per event and
- buffers the rest of the events in a kernel queue. If the is full a SIGIO
- is sent and poll() gets all events at once for further processing.
-
-
- Currently the behaviour is a little bit strange:
- - sig-io + poll() is good for non-keep-alive connections
- - poll() for keep-alive connections
-
- c1000-4k-nok: (1000 concurrent request, 4k filesize, no keepalive)
- poll : 1521.38
- sigio+poll: 2124.00
-
- c1000-4k-k: (1000 concurrent request, 4k filesize, keepalive)
- poll : 5882.35
- sigio+poll: 1239.46
-
- Very strange for now.
-
-09.06.2003 23:59
-- code-cleanup
-
- the event-handling code has been rewritten to handle single events better
- as they are expected from sig-io.
-
- the fallback-mode of sig-io is broken now, but the normal poll() mode got
- a 10% increasement in speed. This means the we are back the speed level of
- 20030308-0155 are as fast as zeus again.
-
- Especially under higher load the current lighttpd performes better.
-
-09.06.2003 11:51
-- sig-io benchmark
-
- 20030609-1151 20030608-2110 20030308-0155
--c 10 sigio select() poll() poll()
-4k : 7870.92 7937.77 8035.36 9443.76
-4k (keep-alive) : 14098.41 14590.02 14275.52 17985.61
-100k : 3366.32 3382.03 3261.15 3722.32
-100k (keep-alive) : 5544.77 5576.00 5573.20 5975.86
--c 100
-4k : 6144.77 5821.40 5714.29 6724.95
-4k (keep-alive) : 9097.53 9213.19 8979.08 10833.06
-100k : 2549.33 2495.94 2318.95 2607.36
-100k (keep-alive) : 4267.67 4283.94 4094.17 4314.06
-
-
-For -c 100 4k and 100k sig-io gives a small increasment.
-
-09.06.2003 01:00
-- sig-io
-
- writing large files works now as expected. After removing the limit for
- the chunks of sendfile the write-buffer-is-empty-again signal is
- generated. that was missing.
-
- 321 of 10000 connections still have the wrong length. After that is fixed
- it is time to start some benchmarks again.
-
-08.06.2003 21:10
-- sig-io
-
- first attempts in getting SIGIO support running which were not very
- successfull yet.
-
-- poll()/select() benchmark
-
- 20030608-2110 20030525-1623 20030308-0155
--c 10 select() poll() poll() poll()
-4k : 7937.77 8035.36 8166.60 9443.76
-4k (keep-alive) : 14590.02 14275.52 14781.97 17985.61
-100k : 3382.03 3261.15 3176.42 3722.32
-100k (keep-alive) : 5576.00 5573.20 5809.56 5975.86
--c 100
-4k : 5821.40 5714.29 5669.26 6724.95
-4k (keep-alive) : 9213.19 8979.08 8418.22 10833.06
-100k : 2495.94 2318.95 2314.28 2607.36
-100k (keep-alive) : 4283.94 4094.17 4456.92 4314.06
-
-
- as the overall processing cycle has been rearranged the overall figures
- changed in minor ranges. c100-4k-k increased, *-100k-k decreased.
-
- At least it still works.
-
-08.06.2003 12:45
-- select()/poll()
-
- implementate an abstration layer for fd-events (like eevry other webserver).
- currently we support poll() and select().
-
- This should bring us support for Mac OS X and propably Windows.
-
-04.06.2003 18:35
-- configure
-
- lighttpd can now be build without ssl-support even if openssl is installed
-
-- protability
-
- - on IRIX IPv6 is supported now out of the box
- - for FreeBSD some missing haeders have been added
-
-04.06.2003 14:34
-- pipelining
-
- adding support for pipeling introduces a problem if the request-header
- was broken. this has been fixed now.
-
-- unneccesary slashes
-
- when building pathes from different portions of a string (e.g. docroot
- virt-server-docroot + request-uri) slashes where added for security and
- simplicity. This resulted in up to 5 adjacent slashes which caused no harm
- but looked strange. (fixed)
-
-04.06.2003 09:57
-- start/stop messages
-
- the error-log contains the start and end-times of the lighttpd process,
- now.
-
-- configfile
-
- the config-file parser has been relaxed to accepts tabs instead of spaces.
-
-- better error-handling
-
- fixed a <a
- href="http://bugs.php.net/?id=24009">bug in the FastCGI-SAPI of PHP</a>
-
- if the fastcgi process dies or closes the connection unexpectedly we
- return 500 now instead of closing the connection to the client.
-
-- Location
-
- the CGI/1.1-rev-03 specification requires us to send Status 302 if a
- Location-header is sent by the client and a Status-header is missing.
-
-- PATH_TRANSLATED
-
- if PHP is compiled without --discard-path PATH_TRANSLATED has to be
- provided.
-
-27.05.2003 15:54
-- directory listings
-
- if a directory is requested and the directory doesn't contain a index-file
- a directory-listing can be displayed. You have to enable directory-listings
- in the config-file (directory-listings on)
-
-- url-decoding
-
- up to know urls where not decoded at all (%26 -> . and so on). This has
- been added. Unicode isn't supported as we use 8-bit chars internally.
-
-26.05.2003 00:44
-- pipelining
-
- as Sascha required pipelining for his benchmarking tool it has been
- implemented.
-
- pipelining allows sending a bunch of requests at once without waiting for
- the actual responses. This reduces the network-overhead and the
- round-trip-time.
-
-- non-free()d memory
-
- dmalloc helped to close some non-free()d memory. For the normal operation
- this isn't important as only memory chunks which had to be free()d at the
- end of the live-time of the lighttpd-process were not de-allocated.
-
-- partly-initialized variables
-
- lighttpd wasn't initializing the main-structure which resulted in strange
- behaviour in rare circumstances.
-
-
-25.05.2003 16:23
-- benchmarks
-
- after removing some useless internal copies we are more or less at the old
- speed levels.
-
- after adding virtual-hosts 10% of the performance were lost. Using less
- memcpy() operations might add several other boosts.
-
- I've just checked how lighttpd compares to Zeus.
-
- lighttpd (current) (old)
--c 10 20030525-1623 20030308-0155 Zeus 4_2
-4k : 8166.60 9443.76 7278.55
-4k (keep-alive) : 14781.97 17985.61 16496.21
-100k : 3176.42 3722.32 3156.37
-100k (keep-alive) : 5809.56 5975.86 5460.30
--c 100
-4k : 5669.26 6724.95 5134.26
-4k (keep-alive) : 8418.22 10833.06 8010.25
-100k : 2314.28 2607.36 2688.32
-100k (keep-alive) : 4456.92 4314.06 4240.70
-
-23.05.2003 14:38
-- cgi-variables
-
- HTTP_HOST was missing for the cgi-module while the fcgi-module passed it
- through to the handler. Fixed that.
-
-- fcgi-errors
-
- the connection to the fcgi was dropped and poll() reported an error, the
- error wasn't reported to the client the right way.
-
-22.05.2003 23:02
-- authorization
-
- the first password-storage has been added:
-
- [auth]
- backend plan
- plain-userfile &lt;filename&gt;
-
- require /download/ user=jan|user=anom
- http-auth /download/ "download archiv" digest
-
- groups are prepared but not implemented. basic and digest are working fine.
-
-20.05.2003 17:53
-- authentification
-
- The auth-methods from RFC 2617 have been added.
- - auth basic
- - auth digest
-
- The only source for accounts is currently only the config-file.
-
- auth-digest needs the plain-text passwort. Are there any source which
- provide a plain-text password ?
-
-12.05.2003 14:33
-- virtual hosts
-
- added very basic virtual-host support
-
- virtual-server-root /home/weigon/projects/lighttpd/servers/
- virtual-server-default-host grisu.home.kneschke.de:1025
- virtual-server-docroot /pages/
-
- docroot is
-
- - if http-host exists
- &lt;virtual-server-root&gt; + &lt;http-host&gt; + &lt;virtual-server-docroot&gt;
-
- - otherwise
- &lt;virtual-server-root&gt; + &lt;virtual-server-default-host&gt; +
- &lt;virtual-server-docroot&gt;
-
- - if even virtual-server-default-host does not exist, 500 is sent
-
-
-12.05.2003 13:02
-- code cleanup
-
- After two month of development it was time clean-up the internal
- structures. It looks like every went fine as lighttpd works es expected
- like before.
-
-- deflate
- the on-the-fly compression has been verified to work fine with opera,
- konqui, mozilla and the IE.
-
-12.05.2003 02:10
-- on-the-fly compression: deflate
-
- Why the hell are the defining a "deflate" encoding in the form of
-
- _deflate_ The "zlib" format defined in RFC 1950 [31] in combination
- with the "deflate" compression mechanism described in RFC 1951 [29].
- (RFC 2616)
-
- and noone implements it that way ? Konqui and Mozilla expect a plain
- deflate() package without the zlib-header.
-
- Konqui is using "inflate2(..., -MAX_WBITS); " which is noted in the zlib
- source as
-
- /* handle undocumented nowrap option (no zlib header or check) */
-
- Funny. Very, very funny.
-
-
- Anyway. We have mimetype-depended compression support now.
-
-11.05.2003 21:56
-- logging
- re-arranged the logfile structure to write CLF + useragent + referrer.
-
-11.05.2003 10:23
-- POST file-upload
- added the missing functionality to send more than a single packet to the
- FCGI-Server (or Client ? ... the PHP).
-
- This gives us the file-upload thing for eg. PHP and large user-forms
- (&gt;16kb).
-
-05.05.2003 15:21
-- PATH_INFO
-
- added support for PATH_INFO. PHP is a little strange and doesn't trust the
- passed PATH_INFO setting. Works fine now.
-
-30.04.2003 15:25
-- bug-fixing day
-
- While testing the FastCGI interface with the MSIE Björn Schotte discovered
- that sometimes the output repeats itself from the start in an endless loop.
- This bug has been fixed.
-
- The read-write-fallback for ancient systems seeked the wrong FDs.
-
- The FastCGI handler is now separting the HTTP-Header from the
- response-body what results in a cleaner interface. The "header too long
- for caching" message is gone now.
-
-28.04.2003 18:18
-- chunked transfer-encoding
-
- The FastCGI part is now using Chunked-Transfer-Encoding if HTTP/1.1 is
- used and no content-length is specified.
-
-27.04.2003 23:10
-- chunked transfer-encoding
- added "Transfer-Encoding: chunked" which is currently used in the web-chat
- for the endless stream. Perhaps it helps some browsers.
-
- The FastCGI interface will get a the chunked-support too, as it will
- enable keep-alive even if no content-length is returned from the FastCGI
- process. We know the size of the chunks and will report it to the browser.
-
-16.04.2003 12:02
-- gigE deatchmatch
-
- sascha compared the current lighttpd to his premium thttpd in his
- gigabit-Ethernet-Network.
-
- <a
-href="http://schumann.cx/gbit_deathmatch.txt">http://schumann.cx/gbit_deathmatch.txt</a>
-
- small comment:
- lighttpd provides the same performance (req/s and thoughput), but uses more
- CPU-Time.
-
-10.04.2003 17:22
-- works on IRIX
-
- Jörg Behrens provided me login to his SGI Origin and after fixing two small
- typos it worked fine on IRIX. (#if define HAVE... was missing a 'd' and
- getopt returns a 'int' and not a 'char')
-
- IPv6 support is currently disabled for IRIX a gethostbyname2() isn't
- available.
-
-10.04.2003 15:56
-- another bug-fixing day
- The upper limit of open connections was enforced and a caused a seg-fault.
- The current limit is set to 4096 parallel connections.
-
- As sascha benchmarked lighttpd and his premium thttpd I tried to reproduce
- his reported results and had to fix 2 flaws in the async-io handling of
- httpd_load which was used for the testing.
-
- If sascha starts another benchmark session I'll put a link to it here.
-
-09.04.2003 00:08
-- bug-fixing time
- Date: and Last-Modified: where sending a timezone != GMT what was invalid.
- The timestamp itself was correct, just the timezone use the wrong
- characters.
-
- the fcgi-code had an buffer-overflow for larger POST-Requests.
-
- The fcgi-code still has problems with POST-Request larger than 16kb as the
- the write buffer is full. Currently we don't handle this case except from
- reporting it in the error-log.
-
-02.04.2003 01:17
-- cgi is back
-
- The CGI Interface wasn't tested for a longer time. It don't really
- survived the introduction of the config-file handling and the internal
- changes that were part of it.
-
- A small test with
-
-#! /usr/bin/perl
-print "Content-Type: text/html\r\n\r\n";
-print time()."\n";
-0;
-
- produced 219 req/s.
-
- Calling PHP via the CGI interface results in 100 req/s. Same script, same
- parameters for 'ab' and same PHP result in 1400 req/s if we use the
- FastCGI interface.
-
- <b>Don't forget</b>: these benchmarks only represent figures for scenarios which
- are not very realistic. They are just usefull for comparisions of the
- internals. We don't want to benchmark applications.
-
-01.04.2003 23:04
-- new benchmarks
-
- This time we wanted to see if we can get the fastcgi-Interface a little bit
- faster. We use this small script for the testing the interface.
-
-&lt;?php
-
-ob_start(/*"ob_gzhandler"*/);
-print "12345&lt;br /&gt;\n";
-header("Content-Length: ".ob_get_length());
-ob_end_flush();
-
-?&gt;
-
- It generate a small network load and is the best case for benchmarking the
- overhead of the call to the fastcgi-php.
-
- Using the chunk-API instead auf tmp-files increase the req/s vom 1200req/s
- to 1600 req/s and the IO-load went down as expected. Waiting for the
- filesystem and creating 1200 files per second required some time. The
- CGI-Interface is still using tempfiles.
-
-01.04.2003 19:28 (no april fools joke)
-- added SSL support
- I took -lssl and -lcrypto and added SSLv2/SSLv3/TLS support to lighttpd.
-
- After some reading I realisized that libcrypto contained some of my code.
- They have a similar buffer-struct with similar functions and they use the
- same MD5-code from the RFC. :)
-
- Adding basic SSL-support was quite esay: replacing all write/read-calls by
- SSL_write/read, initializing the ssl-context the right way and telling
- openssl where to get the data from (SSL_set_fd). It fits really well into
- lighttpd.
-
-- sidenote
- sooner or later the con->filename handler will vanish in favour of the
- direct interface to the chunk-API which will simplifiy the design a little
- bit.
-
-31.03.2003 20:50
-- added a web-chat module
- 1400 lines of C-code are neccesary to add a web-chat to lighttpd.
-
- Features:
- - bb-code for text-layouting
- - auto-highlight for URLs and Email-adresses
- - unlimited number of channels
- - max. 32.000 users per channel
- - fast as it is directly integrated into the web-server
- - easy to install (as easy as lighttpd)
- - IRC-like (/msg, /kick, /me, ...)
- - works with MS IE, Mozilla, Konqueror, ...
- - uses as little JavaScript as possible to stay compatible with all browsers
- - flood-protection (2 Levels: ignore and kick)
- - uses CSS for customized look-and-feel
-
-25.03.2003 00:36
-- finished the config-file support
- now we have config-sections
-
- [fastcgi]
- fastcgi .php 192.168.2.76 1025
-
- The only this missing is -HUP handling to re-read the config. But that
- will follow when I'm up again.
-
-20.03.2003 01:04
-- adding config-file support
- the most boring part of the writing programs after writing documentation.
- The format is quite simple and good enough for lighttpd.
-
-19.03.2003 03:05
-- more on sendfile support
- added support for freebsd's version of sendfile().
-
- Linux:
- ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
-
- FreeBSD:
- int sendfile(int fd, int s, off_t offset, size_t nbytes,
- struct sf_hdtr *hdtr, off_t *sbytes, int flags);
-
- the first 2 params are swap, the next 2 are the same and the last 3 are
- set to NULL or 0.
-
- Solaris 9 is providing a direct interface to the chunk-API with the
- sendfilev() system call:
-
- ssize_t sendfilev(int fildes,
- const struct sendfilevec *vec, int sfvcnt, size_t *xferred);
-
- recovering from a failure is a little bit more complex, but it should be
- fast. I just need a system to test it. Anyone ?
-
-18.03.2003 17:32
-- in the news
- what a surprise: lighttpd is announced in entwickler.com.
-
- <a href="http://www.entwickler.com/itr/news/psecom,id,9483,nodeid,82.html">http://www.entwickler.com/itr/news/psecom,id,9483,nodeid,82.html</a>
-
- this was not planned.
-
-
-- implemented the chunked-API
- rather writing the content of multi-range'd requests to a temp-file we
- just register the parts in a chunk-queue.
-
- chunk 1 [mem] - part-header
- chunk 2 [file] - source-file (offset, len)
- chunk 3 [mem] - part-header
- chunk 4 [file] - source-file (offset, len)
- chunk 5 [mem] - part-footer
-
- If everything is prepared, the content-length is calculated and the
- http-header is generated and prepended to the chunk-queue.
-
- the handle_write() function which handles the write-process just sends the
- chunks to the network without only further modifications.
-
- the chunk-api even simplifies the
- 'my-fastcgi-process-needs-some-time-to-create-the-response-
- and-sends-the-data-in-chunks' case. Just add the chunk to the queue if it
- is received.
-
-13.03.2003 10:49
-- another set of real-life benchmarks
-
- the chairman was benchmarked a little bit. Chairman is full-flegded WCMS.
- As every CMS it needs some time to generate pages. To speed the page
- generating the static-parts of the page can be cached internally.
-
- without caching with caching
-apache + mod_php : 2.50 10.64 req/s
-lighttpd + fcgi-php: 2.50 22.74 req/s
-
- Looks like lighttpd is the way to go :)
-
- Please, don't compare these numbers with the other benchmarks:
- We used a different test-machine which is a little bit under-powered
- for this test-case.
-
-12.03.2003 13:43
-- another large application works with lighttpd
-
- <a
-href="http://www.thinkphp.de/content/content2.php?CatID=44&amp;NewsID=95">Chairman</a> from <a href="http://www.thinkphp.de/">thinkphp</a> has been verified to work with lighttpd.
-
- Three things are worth to note:
-
- 1. ALWAYS use log_error in the php.ini if you use FastCGI
- otherwise it will put the errormessages directly into fastcgi-socket
- without any FastCGI Header. This will result in strange errors.
- (its a PHP bug)
- 2. DOCUMENT_ROOT has been added to the environment variables
- 3. a small bug for sending larger output from a fastcgi client has been
- fixed.
-
-11.03.2003 11:52
-- added two neccesary features
- - redirect _dir_ to _dir_/
- - append index-file to _dir_/ if they exist
-
-11.03.2003 00:13
-- another target
- after adding some headers lighttpd compiles without any warnings
- under cygwin on Windows.
-
- A native windows port will take some time as I have to figure out the
- changes on the winsock.h to the unix headers.
-
-10.03.2003 11:52
-- added Solaris 8 and 9
- lighttpd has been confirmed to compile and work on
-
- - linux
- - FreeBSD, NetBSD
- - Solaris 8, 9
-
- Perhaps I can get lcc to compile it on windows.
-
-10.03.2003 01:30
-- another platform was confirmed
- lighttpd works on NetBSD
-
-- another webserver benchmark
- mathopd (http://www.mathopd.org/)
-
- Mathopd/1.4
--c 10
-4k : 6329.11 [#/sec]
-4k (keep-alive) : 10235.41 [#/sec]
-100k : 1168.50 [#/sec]
-100k (keep-alive) : 268.82 [#/sec] (99% idle)
--c 100
-4k : ---- (connections dropped)
-4k (keep-alive) : ----
-100k : ----
-100k (keep-alive) : ----
-
-Very good values for small files, but the rest ?
-
-10.03.2003 00:06
-- added more write-handlers
- 1. sendfile (linux only)
- 2. mmap + write
- 3. read + write
-
- This means that lighttpd runs on some more systems. It has been verified
- to compile and work on linux 2.4.x and FreeBSD.
-
-
--c 100
- sendfile mmap read
-4k 6476.68 5698.01 5363.08 [#/sec]
-100k 2312.35 841.54 783.09 [#/sec]
-
- The mmap() numbers could be better with a fd+mmap-cache. The zero-copy thing
- is good for our performance.
-
-- tested another small httpd - BOA
- just to get a better view about the performance of lighttpd i've tested
- another httpd: Boa/0.94.14rc16 (http://www.boa.org/)
-
- Boa/0.94.14rc16
--c 10
-4k : 5659.63 [#/sec]
-4k (keep-alive) : 250.23 [#/sec]
-100k : 1104.29 [#/sec]
-100k (keep-alive) : 1363.14 [#/sec]
--c 100
-4k : 4319.65 [#/sec]
-4k (keep-alive) : 2490.66 [#/sec]
-100k : 815.93 [#/sec]
-100k (keep-alive) : 1007.05 [#/sec]
-
- The results are a little bit strange. Keep-Alive for small files seems to be
- broken.
-
- It looks like lighttpd has enough power for now. Time the port and add more
- features.
-
-09.03.2003 13:26
-- load-balancing works great
-
- I used the framework from http://framework.netuse.de/ as a
- real-life example again to test the load-balancer.
-
- setup:
- - grisu
- - AMD athlon XP 2000+
- - runs lighttpd + ab + a 'nice -15'ed FastCGI-PHP
- - generates 153 req/s alone
-
- - laptop
- - Intel PIII 850
- - runs a FastCGI-PHP
- - generates 88 req/s
-
- using the internal load-balancer of lighttpd which balances the
- php-requests over grisu and laptop generate:
- 221 req/s
-
- An apache with mod_php running on grisu gives 117.04 req/s only.
-
-09.03.2003 12:46
-- building the connect connection to the fcgi-php is not non-blocking
- socket() -> connect() -> fcntl(non-blocking) resulted in some problems as
- the connect() call blocked sometimes for 1 seconds.
-
- socket() -> fcntl(non-blocking) -> connect() solves this problem, but
- addes more overhead. The first connect-attempt seems always to
- return EINPROGRESS.
-
-08.03.2003 15:06
-- the first 'real-life' PHP test showed 2 bugs in the POST handling.
- 1. the Content-Type header was not forwarded via fastcgi
- 2. the internal content_length handler wasn't reset after the request
-
- now lighttpd + php work with
-
- http://framework.netuse.de/
-
- the basic application gives us 145 req/s
-
-08.03.2003 11:06
-- use diet to 'test' your code
- diet gives some use full warnings which should be followed. I took the
- chance and removed the last few fprintf() and sprintf() from the code.
- now, we don't need stdio.h anymore.
-
- a staticly linked, stripped lighttpd is 42884 bytes large.
-
-08.03.2003 01:55
-- buffer_strcat() uses strlen() to get the length of the 'to-be-catted-string'
- if the string is constant or has a known length you can pass that function
- which gives use buffer_strcat_len() which passes the string length as a
- parameter.
-
-- using a ramdisk as the base for the tempfiles generated mkstemp() is a
- very cood idea
- it reduces the io-load on the system and gives as more cpu-time for
- load-balancing the php-requests.
-
-- cache the output of strftime(), gmtime() and localtime
- we generate more then 10.000 req/s which results in using the same
- timestamp over and over again. It is sufficient to generate the timestamp
- once a second and give us a bunch of CPU-cycles for sending files.
-
- the same applies for other timestamps like Last-modified which sends a
- string version of st.st_mtime. Cache it.
-
-- don't try to overoptimize for code for the sake of clean code
- the range support require some hack in the first versions like setting the
- write_offset to the start of the range and keeping the rest of the
- "code 200" send code as usual. Only a few lines added this first range
- feature. fast, but a hack. It made things more complicated then neccesary
- to add multi-range support in this scenario.
-
- removing the hack doing small clean preprocessing helps to clean up the
- whole 'write a chunk on the wire' code. At the end we use less code and
- have a cleaner design.
-
- Sascha proposed a chunked layer which just takes the chunks (http-header,
- part-header, part-message, ... and the last boundary) and passes them to
- the write-to-the-wire-code. This is far more elegant and will perhaps same
- us from other problems, too. Currently I think that it is not necessary.
- First we have to fix some protability issues.
-
-Ok, today benches:
-
- today last
--c 10
-4k : 9443.76 7739.94 + 22%
-4k (keep-alive) : 17985.61 13885.03 + 29%
-100k : 3722.32 3349.97 + 11%
-100k (keep-alive) : 5975.86 4965.49 + 20%
--c 100
-4k : 6724.95 5918.56 + 13%
-4k (keep-alive) : 10833.06 8405.48 + 28%
-100k : 2607.36 2393.60 + 9%
-100k (keep-alive) : 4314.06 4035.35 + 7%
-
-Top Transfer Rate:
-
- 86365.77 [Kbytes/sec] received
-
-Too much for a GigE-link ?
-
-
-so far:
-
-- use state-engines
-
- a non-forking webserver like described in
-
- http://www.kegel.com/c10k.html
-
-- don't use fprintf() for logging.
- writing one line to log file takes more time that sending responsing the a
- HTTP-request
-
-- take care of your memory
-
- typedef struct {
- char *ptr;
- size_t used;
- size_t size;
- } buffer;
-
- buffer* buffer_init();
- void buffer_free(buffer *b);
- int buffer_prepare_copy(buffer *b, size_t size);
- int buffer_prepare_append(buffer *b, size_t size);
- int buffer_strcpy(buffer *b, const char *s);
- int buffer_strcpy_len(buffer *b, const char *s, int s_len);
- int buffer_strcat(buffer *b, const char *s);
- int buffer_strcat_len(buffer *b, const char *s, int s_len);
-
- buffer_init() is only called once per buffer. If you don't need the
- buffer, set 'used' to zero and reused it afterward.
- buffer_strcpy() + buffer_strcat() check if the 'used' + the new strlen()
- fit in to the 'size' of the buffer. If not the realloc() the buffer.
- buffer_strcat() uses memcpy(ptr + used - 1, s, s_len + 1); which should
- be faster than the original strcat().
-
- Using those buffers keep the memory usage at 2Mb. malloc() and free() are
- only called at the beginnig of the programm and at the end.
-
-- don't used sprintf() to convert a integer into a string as like
- sprintf(buf, "%d", l);
-
- write your own ltostr function. sprintf() is to general for the case and
- is slow.
-
-
-Speed:
-------
-
-Let's assume that <a
-href="http://www.acme.com/software/thttpd/">thttpd</a> is (one of) the
-fastest webservers out there.
-
-all httpds were started with:
-
-$ ./thttpd -p 1026 -D \
- -d /home/weigon/projects/localizer/src/lighttpd/docroot/ \
- -l thttpd.access.log
-
-(lighttpd uses the same parameters).
-
-We used ApacheBench for testing the RPS (requests per second).
-
-$ /usr/sbin/ab -dS -c 10 -n 100000 http://192.168.2.10:80/dummy.out
-
- lighttpd thttpd/2.21b+php thttpd/2.20c thttpd/2.23b1
-(concurrency 10)
-4k : 7739.94 6040.84 5078.20 5888.24 [#/sec]
-4k (keep-alive): 13885.03 10349.82 5034.49 5853.09 [#/sec]
-100k : 3349.97 1176.29[1] 1188.74 1198.29 [#/sec]
-100k (keep-a.) : 4965.49 2513.38[2] 1100.65 1130.51 [#/sec]
-(concurrency 100)
-4k : 5918.56 4907.01 4987.53 4886.87 [#/sec]
-4k (keep-alive): 8405.48 6379.99 4938.76 4816.26 [#/sec]
-100k : 2393.60 972.73 958.27 961.09 [#/sec]
-100k (keep-a.) : 4035.35 893.51[3] 970.21 955.05 [#/sec]
-
-thttpd/2.21b+php has been patched with the keep-alive + php patches from PHP4
-sapi/thttpd/thttpd_patch.
-
-[1] ab reported:
-Failed requests: 1
- (Connect: 0, Length: 1, Exceptions: 0)
-[2] ab reported:
-Failed requests: 5
- (Connect: 0, Length: 5, Exceptions: 0)
-[3] ab reported:
-Failed requests: 24
- (Connect: 0, Length: 24, Exceptions: 0)
-
-Tunning the thttpd:
--------------------
-- disable symlink checking (chroot() or -nos)
-- log to /dev/shm/logfile, a ramdisk or disable logging
-
-
-$ ./thttpd -p 1026 -D \
- -d /home/weigon/projects/localizer/src/lighttpd/docroot/ \
- -l /dev/null
-
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index 1ecc9edb..00000000
--- a/INSTALL
+++ /dev/null
@@ -1,32 +0,0 @@
-
-============
-Installation
-============
-
-:author: Jan Kneschke
-:Date: $Date: $
-:Revision: $Revision: $
-
-Installation
-------------
-
-Get the source from
-
-http://www.lighttpd.net/download/
-
-unpack it by ::
-
- $ gzip -cd lighttpd-1.x.x.tar.gz | tar xf -
-
-compile and install it with ::
-
- $ cd lighttpd-1.x.x
- $ ./configure
- $ make
- $ su -
- # make install
- # exit
-
-take look at the configfile in ./doc/lighttpd.conf,
-make your own copy of that file and modify it for your needs.
-
diff --git a/INSTALL.svn b/INSTALL.svn
deleted file mode 100644
index 696106d5..00000000
--- a/INSTALL.svn
+++ /dev/null
@@ -1,67 +0,0 @@
-
-============
-Installation from svn repo
-============
-
-:author: mOo
-:Date: $Date: $
-:Revision: $Revision: $
-
-Prerequirement
-------------
-subversion (required, for svn co, svn up)
-perl (optional, for check)
-php (optional, for check)
-
-Choose one of the build systems:
-1. build with autotools
-autotools (required for autogen.sh)
-
-2. build with cmake
-see make.example
-
-Check out the source
-------------
-Review which source you want to checkout at:
-http://trac.lighttpd.net/trac/browser
-http://trac.lighttpd.net/trac/browser/tags
-
-the current latest version is trunk:
-http://trac.lighttpd.net/trac/browser/trunk
-
-and check it out by ::
-
- svn checkout svn://svn.lighttpd.net/lighttpd/trunk/
-
-
-Build, Test and Install
-------------
-
-with autoconf
-------------
-
- $ cd trunk
- $ ./autogen.sh
-if you have problem with autogen.sh, check aclocal autoconf automake version
-
-check configure options
- $ ./configure --help
- $ ./configure --prefix=/usr/local/lighttpd/ --enable-...
- $ make clean
- $ make check
- $ src/lighttpd -Df your_test.conf
- (Ctrl+C once or twice to terminate lighttpd)
- $ su -
- # make install
- # exit
-
-take look at the configfile in ./doc/lighttpd.conf,
-make your own copy of that file before modify it for your needs.
-
-Keep up to date with lastest svn repo
-------------
-simply do:
- $ svn up
-and follow the instructions in "Build and Install".
-
-Do not make a non-released version on production server, you have been warned.
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index b2f3c513..00000000
--- a/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS=src doc tests
diff --git a/NEWS b/NEWS
deleted file mode 100644
index ae5e0058..00000000
--- a/NEWS
+++ /dev/null
@@ -1,204 +0,0 @@
-
-====
-NEWS
-====
-
-- 1.5.0 -
- * fixed decoding of common headers in AJP13 (#1399)
- * disable experimental linux-aio and posix-aio support, use gthread-aio instead
- * fixed several crashes in log-request-handling with %s being NULL on solaris
- * fixed network-backend-solaris-sendfilev (EINVAL in writev())
- * fixed initgroups() called after chroot (#1384)
- * execute fcgi app without /bin/sh if used as argument to spawn-fcgi (#1428)
- * fix bug that rrdtool reports "0" for incoming data (#1514)
- * ssl.cipher-list and ssl.use-sslv2 ported from 1.4.x (#1422)
- * add IdleServers and Scoreboard directives in ?auto mode for mod_status (#1507)
- * support letterhomes in mod_userdir (#1473)
- * mod_auth ldap rework, most important change is being able to startup if ldap server is down (#1535)
- * Add possibility to disable methods in mod_compress (#1773)
- * fixed ECONNRESET handling in network-openssl
- * fixed log_write() for log-files > 4kbyte
- * fix sending source of cgi script instead of 500 error if fork fails
- * fix min-procs handling in mod_scgi.c, just set to max-procs (patch from #623)
- * mod_cgi: add a event-handler for STDERR_FILENO and log it with ERROR()
- * fixed building/testing outside of the src dir
- * fix many (64-bit) format warnings and unsigned/signed compare warnings
- * fixed out of range access in fd array (#1562, #372, #1603) (CVE-2008-0983)
- * fix auth-ldap configuration in tests
- * fcgi-stat-accel: Fix unused var / indentation
- * fix mod_compress bug (#1027)
- * fix ssl error queue handling (#285) (CVE-2008-1531)
- * fix dependencies of the parser files in the Makefile
- * fix server.kbytes-per-second (#1102)
- * let spawn-fcgi propagate exit code from spawned fcgi application
- * fix in/out statistics for connections
- * close connection after redirect in trigger_b4_dl
- * remove scons build system
- * fix memory leak on windows (#1371)
- * do not add Accept-Ranges header if range-request is disabled (#1449)
- * mod_compress: match mime-type additionaly against the part before ";" (i.e. without encoding)
- * fix bug with IPv6 in mod_evasive (#1579)
- * fix mod_magnet: enable "request.method" and "request.protocol" in lighty.env (#1308)
- * mod_magnet: set con->mode if content was generated so lighty doesn't append error messages.
- * fix #1574: check for symlinks after successful pathinfo matching
- * fix #1396: req-method OPTIONS: do not insert default response if request was denied
- * fix server.max-keep-alive-requests handling
- * reset physical.path after mod_magnet request restart
- * fix mod-proxy-backend-http waiting for http body for 304 and 205 (#1178)
- * fixed sock_addr reading in mod_cgi.c (#1672)
- * fixed postgresql-vhost module to use all options (#1694)
- * fixed #1565: mod_compress should check if the request is already handled, e.g. by fastcgi
- * merged from @1874: add ETag configuration (#1442)
- * case insensitive match for secdownload md5 token (#1710)
- * handle only HEAD, GET and POST in mod_dirlisting (same as in staticfile) (#1687)
- * fixed mod_webdav, litmus now passes everything except locks (#1738)
- * fixed #1555: HTTP Request/Response only accept complete headers, i.e. ended with double CRLF
- * fixed url encoding to encode more characters (#266)
- * fixed dropping last character of evhost pattern (#161)
- * Match headers case insensitive in response (removing of X-{Sendfile,LIGHTTPD-*}, catching Date/Server)
- * fixed mem leak in ssi expression parser (#1753), thx Take5k
- * decode url before matching in mod_rewrite (#1720)
- * fixed bug with case-insensitive filenames in mod_userdir (#1589), spotted by "anders1"
- * use decoded url for matching in mod_redirect (#1720)
- * don't return HANDLER_ERROR from proxy-core content handling, produce 500 instead
- * do not modify content-length in mod_chunked.c for HEAD requests (produced false Content-Length: 0 headers)
- * fix sending content-length for static HEAD requests
- * removed distribution specific stuff (was outdated anyway)
- * use pipe-io instead of SIGUSR1 to wakeup main thread (fixes #1517)
- * Fix ajp13 response header handling (fixes #1628)
- * Enhance mod_uploadprogress to show uploaded size after upload is done (closes #1632) by icy
- * Fix memory leak in stat-cache (closes #1693), patch by peto
- * Fix shutdown leaks (fixes #1811), patch by peto
- * Fix bogus send->bytes_in counter (problems with mod-deflate)
- * Reformat log output (add timestamp to new log functions)
- * Use void as return type for connection state machine - may fix some bugs
- * Fix select() fdevent backend
- * Fix DoS due to unhandled requests (results in hanging connections); return 403 instead of 200
- without mod_deflate/compressed requests they will eventually time out
- * Fix wrong format strings (fixes #1900, thx stepancheg)
- * Port some mod_rrdtool fixes from 1.4.x (#604, #419 and more)
- * New lighttpd man page (moved it to section 8) (fixes #1875)
- * Fix leaving zombie process with include_shell (#1777)
- * Finally removed spawn-fcgi
- * Allow xattr to overwrite mime type (fixes #1929)
- * Fix endless loop in ajp (fixes #1897)
- * Fix segfault in mod_proxy_backend_http (fixes #1154)
- * merge: Fix base64 decoding in mod_auth (#1757)
- * merge: Compare address family in inet_ntop_cache
- * Revert CVE-2008-4359 (#1720) fix "encoding+simplifying urls for rewrite/redirect": too many regressions.
- * merge: Fix wrong malloc sizes in mod_accesslog (probably nothing bad happened...) (#1855, thx ycheng)
- * merge: Some small buffer.c fixes (#1837)
- * merge: Disable SSLv2 by default
- * merge: Use/enforce sane max-connection values (#1803)
- * merge: Fix max-connection limit handling/100% cpu usage (#1436)
- * merge: Fix segfault if siginfo_t* is NULL in sigaction handler (#1926)
- * merge: Create rrd file for empty rrdfile in mod_rrdtool (#1788)
- * merge: Strip trailing dot from "Host:" header
- * merge: Remove the optional port info from SERVER_NAME (thx Mr_Bond)
- * merge: Rename configure.in to configure.ac, with small cleanups (#1932)
- * merge: Add proper SUID bit detection (#416)
- * merge: Check for regular file in mod_cgi, so we don't try to start directories
- * merge: Include mmap.h from chunk.h to fix some problems with #define mmap mmap64 (#1923)
- * merge: Fix segfault for appending matched parts if there was no regex matching (just give empty strings) (#1601)
- * merge: fixed wrong result of buffer_caseless_compare("a", "ab") (#1287)
- * Fix many warnings
- * Fix SERVER_NAME port stripping (fixes #1968)
- * Fix mod_cgi environment keys mangling (fixes #1969)
- * Fix max-age value in mod_expire for 'modification' (fixes #1978)
- * Allow using pcre with cross-compiling (pcre-config got fixed; fixes #1986)
- * Fix segfault with openssl (DoS, fixes #2003)
- * Improve chunkqueue cleanup (remove empty chunks after ssl failures)
- * Add "lighty.req_env" table to mod_magnet for setting/getting environment values for cgi (fixes #1967, thx presbrey)
- * Fix segfault in mod_expire after failed config parsing (fixes #1992)
- * Add ssi.content-type option (default text/html, fixes #615)
- * Fix distbuild (add mod-compress.conf to dist files)
- * Add support for "real" entropy from /dev/[u]random (fixes #1977)
- * Adding support for additional chars in LDAP usernames (fixes #1941)
- * Ignore multiple "If-None-Match" headers (only use first one, fixes #753)
- * Fix 100% cpu usage if time() < 0 (thx to gaspa and cate, fixes #1964)
- * Free wakeup_iosocket (thx peto, fixes #1808)
- * Free ssl cipher list (thx peto, fixes #1809)
- * Add gthread-freebsd-sendfile (thx peto, fixes #1795)
- * Send gthread dummy pointers to wake them up for faster exit (thx peto, fixes #1812)
- * Fix race condition with joblist thread condition/mutex (thx peto, fixes #1823)
- * Fix segfault if there is no mimetype for the error documents
- * Use unsigned int for secdownload.timeout (fixes #1966)
- * Add server.breakagelog, a "special" stderr (fixes #1863)
- * Silenced the annoying "request timed out" warning, enable with the "debug.log-timeouts" option (fixes #2018)
- * Hide some ssl errors per default, enable them with debug.log-ssl-noise (#397)
- * Add "cgi.execute-x-only" to mod_cgi, requires +x for cgi scripts (fixes #2013)
- * Fixed gthread-freebsd-sendfile (#1795)
- * cmake: check for strtoll
- * Fix FD_SETSIZE comparision warnings
- * Add "lua-5.1" to searched pkg-config names for lua
- * Set FD_CLOEXEC for bound sockets before pipe-logger forks (fixes #2026)
- * Report non-fatal ssl errors as "connection close"
- * Add '%_' pattern for complete hostname in mod_evhost (fixes #1737)
- * Allow digits in hostnames in more places (fixes #1148)
- * Allow all comparisons for $SERVER["socket"] - only bind for "=="
- * Fix mod_deflate bzip2 compression level (thx peto, fixes #2035)
- * Add proxy-core.disable-time (used for all disable-times), default value 1 sec (fixes #1038)
- * Add proxy-core.max-backlog-size (set to 0 to disable backlog, thx e-razor)
- * Enable linux-aio-sendfile for testing in cmake again, fix a small bug in it
- * Set tm.tm_isdst = 0 before mktime() (fixes #2047)
- * Allow chunkqueue_skip to skip all types of chunks
- * Use linux-epoll by default if available (fixes #2021)
- * Add TLS servername indication (SNI) support (fixes #386, thx Peter Colberg <peter@colberg.org>)
- * Add SSL Client Certificate verification (#1288)
- * mod_accesslog: escape special characters (fixes #1551, thx icy)
- * Don't print ssl error if client didn't support TLS SNI
- * Reopen out stream in X-Rewrite (fixes #1678)
- * Remove joblist thread, don't use timed pops for async queues
- * Fix mod_cgi hang on "crash-before-header-sent" bug
- * Set content-length in mod_compress (fixes #2089, thx liming)
- * Mark recv-queue closed if backend connection got closed in mod_proxy_core (fixes #2090, thx liming)
- * mod_magnet: add traceback for printing lua errors
- * export some SSL_CLIENT_* vars for client cert validation (fixes #1288, thx presbrey)
- * reset tlsext_server_name in connection_reset - fixes random hostnames in the $HTTP["host"] conditional
- * Accept ":" in the reason-phrase of a status-line
- * mod_accesslog: support %e (fixes #2113, thx presbrey)
- * Require at least glib 2.10.0 for g_atomic_int_set (fixes #2127)
- * Fix select() backend under high load (off-by-one, noticed by Manuel Scharf in a forum thread)
- * Append to previous buffer in con read (fixes #2147, found by liming, CVE-2010-0295)
- * Fix handling return value of SSL_CTX_set_options (fixes #2157, thx mlcreech)
- * Print double quotes properly when dumping config file (fixes #1806)
- * Include IP addresses on error log on password failures (fixes #2191)
- * Combine Cache-Control header value in mod_expire to existing HTTP header if header already added by other modules (fixes #2068)
- * Fix conditional interpretation of core options
- * proxy-backend-http: fix chunked encoding parser
- * more strict check for server.stat-cache-engine
- * Read hostname from absolute https:// uris in the request line (patch by Adrian Schröter <adrian@suse.de>)
- * [ssl/md5] prefix our own md5 implementation with li_ so it doesn't conflict with the openssl one (fixes #2269)
- * Enable linux-aio-sendfile for testing in autotools too
- * [mod_auth] Fix signedness error in http_auth (fixes #2370, CVE-2011-4362)
- * buffer_caseless_compare: always convert letters to lowercase to get transitive results, fixing array lookups (fixes #2405)
- * fix :port handling in $HTTP["host"] checks (fixes #2135. thx liming)
- * fix memleak in mod_auth (fixes #2457, thx brarcher)
- * fix ipv6 disabling (fixes #2292, thx bert)
-
-- 1.5.0-r19.. -
- * -F option added for spawn-fcgi
- * replaced mod_fastcgi, mod_scgi, mod_proxy with mod_proxy_core + backends
- * added query-string parsing for mod_uploadprogress
- * added threaded stat()
- * added threaded disk-read() support
- * added dir-listing.set-footer in mod_dirlisting (#1277)
- * added logging of the PID and UID of the sending process for SIGTERM and SIGINT
- * added support for AJP13 to mod_proxy_core
- * fixed the out-of-fd support
- * fixed crash in mod_expire if 'modification' is used and stat() failed (#1063)
- * fixed hardcoded font-sizes in mod_dirlisting (#1267)
- * fixed different ETag length on 32/64 platforms (#1279)
- * fixed conditional dir-listing.exclude (#930)
- * fixed CONTENT_LENGTH = -1 in mod_cgi (#1276)
- * fixed typecast of NULL on execl() (#1235)
- * fixed extra Content-Length header on 1xx, 204 and 304 (#1002)
- * fixed mysql server reconnects (#518)
- * fixed prctl() usage (#1310, #1333)
- * fixed FastCGI header overrun in mod_fastcgi (reported by mattias@secweb.se)
- * fixed mem-leak in mod_auth (reported by Stefan Esser)
- * fixed crash with md5-sess and cnonce not set in mod_auth (reported by Stefan Esser)
- * fixed missing check for base64 encoded string in mod_auth and Basic auth
- (reported by Stefan Esser)
- * fixed possible crash in Auth-Digest header parser on trailing WS in
- mod_auth (reported by Stefan Esser)
diff --git a/README b/README
index 5a701554..72a32171 100644
--- a/README
+++ b/README
@@ -1,156 +1,9 @@
+The stable series lives in the branch lighttpd-1.4.x, check it out:
-========
-lighttpd
-========
+ svn checkout svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x
--------------
-a light httpd
--------------
-
-:author: Jan Kneschke
-:Date: $Date: 2004/11/03 22:25:54 $
-:Revision: $Revision: 1.8 $
-
-:abstract:
- lighttpd a secure, fast, compliant and very flexible web-server
- which has been optimized for high-performance environments. It has a very
- low memory footprint compared to other webservers and takes care of cpu-load.
- Its advanced feature-set (FastCGI, CGI, Auth, Output-Compression,
- URL-Rewriting and many more) make lighttpd the perfect webserver-software
- for every server that is suffering load problems.
-
-the naming
-----------
-
-lighttpd is a __httpd__ which is
-
-- fast as __light__ning and
-- __light__ when it comes to memory consumption and system requirements
-
-Features
---------
-
-Network
-```````
-
-- IPv4, IPv6
-
-Protocols
-`````````
-
-- HTTP/1.0 (http://www.ietf.org/rfc/rfc1945.txt)
-- HTTP/1.1 (http://www.ietf.org/rfc/rfc2616.txt)
-- HTTPS (provided by openssl)
-- CGI/1.1 (http://CGI-Spec.Golux.Com/)
-- FastCGI (http://www.fastcgi.com/devkit/doc/fcgi-spec.html)
-
-Advanced Features
-`````````````````
-
-- load-balanced FastCGI
- (one webserver distributes requests to multiple PHP-servers via FastCGI)
-- custom error pages (for Response-Code 400-599)
-- virtual hosts
-- directory listings
-- streaming CGI and FastCGI
-- URL-Rewriting
-- HTTP-Redirection
-- output-compression with transparent caching
-
-FastCGI-Support
-```````````````
-
-- parses the Response-header and completes the HTTP-header accordingly
-- Keep-Alive handling based on Content-Length header
-
-PHP-Support
-```````````
-
-- same speed as or faster than apache + mod_php4
-- handles various PHP bugs in the FastCGI SAPI
-- includes a utility to spawn FastCGI processes (necessary for PHP 4.3.x)
-
-Security features
-`````````````````
-
-- chroot(), set UID, set GID
-- protecting docroot
-
-HTTP/1.1 features
-`````````````````
-
-- Ranges (start-end, start-, -end, multiple ranges)
-- HTTP/1.0 Keep-Alive + HTTP/1.1 persistent Connections
-- methods: GET, HEAD, POST
-- Last-Modified + If-Modified handling
-- sends Content-Length if possible
-- sends Transfer-Encoding: chunk, if Content-Length is not possible
-- sends Content-Type
-- on-the-fly output compression (deflate, gzip)
-- authentication: basic and digest
- (http://www.ietf.org/rfc/rfc2617.txt)
-
-HTTP/1.1 compliance
-```````````````````
-
-- Sends 206 for Range Requests
-- Sends 304 for If-Modified Requests
-- Sends 400 for missing Host on HTTP/1.1 requests
-- Sends 400 for broken Request-Line
-- Sends 411 for missing Content-Length on POST requests
-- Sends 416 for "out-of-range" on Range: Header
-- Sends 501 for request-method != (GET|POST|HEAD)
-- Sends 505 for protocol != HTTP/1.0 or HTTP/1.1
-- Sends Date: on every requests
-
-Intended Audience
------------------
-
-- Ad-Server Front-Ends ("Banner-Schleuder")
- - delivering small files rapidly
-- php-servers under high load
- (load-balancing the php-request over multiple PHP-servers)
-
-Works with
-----------
-
-It has been tested to work with
-
-- IE 6.0
-- Mozilla 1.x
-- Konqueror 3.1
- (for Keep-Alive/Persistent Connections, Accept-Encoding for PHP + gzip)
-- wget
- (for Resuming)
-- acrobat plugin
- (for multiple ranges)
-
-
-Works on
---------
-
-lighttpd has been verified to compile and work on
-
-- Linux
-- FreeBSD
-- NetBSD
-- Solaris 8 + 9
-- SGI IRIX 6.5
-
-missing for HTTP/1.1 compliance
--------------------------------
-- parsing chunked POST request
-
------------------
-Starting lighttpd
------------------
-
-As daemon in the background: ::
-
- $ lighttpd -f <configfile>
-
-or without detaching from the console: ::
-
- $ lighttpd -D -f <configfile>
+The current development version is lighttpd2 at http://git.lighttpd.net/lighttpd/lighttpd2.git, clone it:
+ git clone git://git.lighttpd.net/lighttpd/lighttpd2.git
+The previous trunk (aka "1.5") has been dead for some time, and is archived as svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.5-dead
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index b0fcff58..00000000
--- a/autogen.sh
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/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
-ARGS="$@"
-
-
-run() {
- echo "$ARGV0: running \`$@' $ARGS"
- $@ $ARGS
-}
-
-if test x`which which 2>/dev/null` = x; then
- echo "which program not found, exiting"; exit 1
-fi
-
-if test x`which pkg-config 2>/dev/null` = x; then
- echo "pkg-config not found, exiting"; exit 1
-fi
-
-## jump out if one of the programs returns 'false'
-set -e
-
-## on macosx glibtoolize, others have libtool
-if test x$LIBTOOLIZE = x; then
- if test \! x`which glibtoolize 2> /dev/null` = x; then
- LIBTOOLIZE=glibtoolize
- elif test \! x`which libtoolize-1.5 2> /dev/null` = x; then
- LIBTOOLIZE=libtoolize-1.5
- elif test \! x`which libtoolize 2> /dev/null` = x; then
- LIBTOOLIZE=libtoolize
- else
- echo "libtoolize 1.5.x wasn't found, exiting"; exit 1
- fi
-fi
-
-## suse has aclocal and aclocal-1.9
-if test x$ACLOCAL = x; then
- if test \! x`which aclocal-1.9 2> /dev/null` = x; then
- ACLOCAL=aclocal-1.9
- elif test \! x`which aclocal19 2> /dev/null` = x; then
- ACLOCAL=aclocal19
- elif test \! x`which aclocal 2> /dev/null` = x; then
- ACLOCAL=aclocal
- else
- echo "automake 1.9.x (aclocal) wasn't found, exiting"; exit 1
- fi
-fi
-
-if test x$AUTOMAKE = x; then
- if test \! x`which automake-1.9 2> /dev/null` = x; then
- AUTOMAKE=automake-1.9
- elif test \! x`which automake19 2> /dev/null` = x; then
- AUTOMAKE=automake19
- elif test \! x`which automake 2> /dev/null` = x; then
- AUTOMAKE=automake
- else
- echo "automake 1.9.x wasn't found, exiting"; exit 1
- fi
-fi
-
-
-## macosx has autoconf-2.59 and autoconf-2.60
-if test x$AUTOCONF = x; then
- if test \! x`which autoconf-2.59 2> /dev/null` = x; then
- AUTOCONF=autoconf-2.59
- elif test \! x`which autoconf259 2> /dev/null` = x; then
- AUTOCONF=autoconf259
- elif test \! x`which autoconf 2> /dev/null` = x; then
- AUTOCONF=autoconf
- else
- echo "autoconf 2.59+ wasn't found, exiting"; exit 1
- fi
-fi
-
-if test x$AUTOHEADER = x; then
- if test \! x`which autoheader-2.59 2> /dev/null` = x; then
- AUTOHEADER=autoheader-2.59
- elif test \! x`which autoheader259 2> /dev/null` = x; then
- AUTOHEADER=autoheader259
- elif test \! x`which autoheader 2> /dev/null` = x; then
- AUTOHEADER=autoheader
- else
- echo "autoconf 2.59+ (autoheader) wasn't found, exiting"; exit 1
- fi
-fi
-
-
-run $LIBTOOLIZE $LIBTOOLIZE_FLAGS
-run $ACLOCAL $ACLOCAL_FLAGS
-run $AUTOHEADER
-run $AUTOMAKE $AUTOMAKE_FLAGS
-run $AUTOCONF
-test "$ARGS" = "" && echo "Now type './configure ...' and 'make' to compile."
-
diff --git a/cmake/LighttpdMacros.cmake b/cmake/LighttpdMacros.cmake
deleted file mode 100644
index 1a7b9877..00000000
--- a/cmake/LighttpdMacros.cmake
+++ /dev/null
@@ -1,46 +0,0 @@
-## our modules are without the "lib" prefix
-
-MACRO(ADD_AND_INSTALL_LIBRARY LIBNAME SRCFILES)
- IF(BUILD_STATIC)
- ADD_LIBRARY(${LIBNAME} STATIC ${SRCFILES})
- TARGET_LINK_LIBRARIES(lighttpd ${LIBNAME})
- ELSE(BUILD_STATIC)
- ADD_LIBRARY(${LIBNAME} SHARED ${SRCFILES})
- SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} ${LIBNAME})
- ## Windows likes to link it this way back to app!
- IF(WIN32)
- SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES LINK_FLAGS lighttpd.lib)
- ENDIF(WIN32)
-
- IF(APPLE)
- SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES LINK_FLAGS "-flat_namespace -undefined suppress")
- ENDIF(APPLE)
- ENDIF(BUILD_STATIC)
-ENDMACRO(ADD_AND_INSTALL_LIBRARY)
-
-MACRO(LEMON_PARSER SRCFILE)
- GET_FILENAME_COMPONENT(SRCBASE ${SRCFILE} NAME_WE)
- ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${SRCBASE}.c ${CMAKE_CURRENT_BINARY_DIR}/${SRCBASE}.h
- COMMAND ${CMAKE_BINARY_DIR}/build/lemon
- ARGS -q ${CMAKE_CURRENT_SOURCE_DIR}/${SRCFILE} ${CMAKE_SOURCE_DIR}/src/lempar.c
- DEPENDS ${CMAKE_BINARY_DIR}/build/lemon ${CMAKE_CURRENT_SOURCE_DIR}/${SRCFILE} ${CMAKE_SOURCE_DIR}/src/lempar.c
- COMMENT "Generating ${SRCBASE}.c from ${SRCFILE}"
-)
-ENDMACRO(LEMON_PARSER)
-
-MACRO(ADD_TARGET_PROPERTIES _target _name _properties)
- SET(_properties ${ARGV})
- LIST(REMOVE_AT _properties 0)
- LIST(REMOVE_AT _properties 0)
- IF(${_name} STREQUAL LINK_FLAGS)
- TARGET_LINK_LIBRARIES(${_target} "${_properties}")
- ELSE()
- GET_TARGET_PROPERTY(_old_properties ${_target} ${_name})
- MESSAGE("adding property to ${_target} ${_name}: ${_properties}")
- IF(NOT _old_properties)
- # in case it's NOTFOUND
- SET(_old_properties)
- ENDIF(NOT _old_properties)
- SET_TARGET_PROPERTIES(${_target} PROPERTIES ${_name} "${_old_properties} ${_properties}")
- ENDIF()
-ENDMACRO(ADD_TARGET_PROPERTIES)
diff --git a/cmake/UsePkgConfig.cmake b/cmake/UsePkgConfig.cmake
deleted file mode 100644
index a8cd9072..00000000
--- a/cmake/UsePkgConfig.cmake
+++ /dev/null
@@ -1,54 +0,0 @@
-# - pkg-config module for CMake
-#
-# Defines the following macros:
-#
-# PKGCONFIG(package includedir libdir linkflags cflags)
-#
-# Calling PKGCONFIG will fill the desired information into the 4 given arguments,
-# e.g. PKGCONFIG(libart-2.0 LIBART_INCLUDE_DIR LIBART_LINK_DIR LIBART_LINK_FLAGS LIBART_CFLAGS)
-# if pkg-config was NOT found or the specified software package doesn't exist, the
-# variable will be empty when the function returns, otherwise they will contain the respective information
-#
-
-
-
-FIND_PROGRAM(PKGCONFIG_EXECUTABLE NAMES pkg-config PATHS /usr/local/bin )
-
-MACRO(PKGCONFIG _package _include_DIR _link_DIR _link_FLAGS _cflags)
-# reset the variables at the beginning
- SET(${_include_DIR})
- SET(${_link_DIR})
- SET(${_link_FLAGS})
- SET(${_cflags})
- IF(MSVC)
- SET(_msvc_mode --msvc-syntax)
- ELSE(MSVC)
- SET(_msvc_mode)
- ENDIF(MSVC)
- # if pkg-config has been found
- IF(PKGCONFIG_EXECUTABLE)
-
- EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_package} --exists RETURN_VALUE _return_VALUE OUTPUT_VARIABLE _pkgconfigDevNull )
-
- # and if the package of interest also exists for pkg-config, then get the information
- IF(NOT _return_VALUE)
-
- EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_msvc_mode} ${_package} --variable=includedir OUTPUT_VARIABLE __include_DIR)
- STRING(REPLACE "\n" "" ${_include_DIR} ${__include_DIR})
-
- EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_msvc_mode} ${_package} --variable=libdir OUTPUT_VARIABLE __link_DIR)
- STRING(REPLACE "\n" "" ${_link_DIR} ${__link_DIR})
-
- EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_msvc_mode} ${_package} --libs OUTPUT_VARIABLE __link_FLAGS)
- STRING(REPLACE "\n" "" ${_link_FLAGS} ${__link_FLAGS})
-
- EXEC_PROGRAM(${PKGCONFIG_EXECUTABLE} ARGS ${_msvc_mode} ${_package} --cflags OUTPUT_VARIABLE __cflags)
- STRING(REPLACE "\n" "" ${_cflags} ${__cflags})
-
- ENDIF(NOT _return_VALUE)
-
- ENDIF(PKGCONFIG_EXECUTABLE)
-
-ENDMACRO(PKGCONFIG _include_DIR _link_DIR _link_FLAGS _cflags)
-
-MARK_AS_ADVANCED(PKGCONFIG_EXECUTABLE)
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 01ba9bd4..00000000
--- a/configure.ac
+++ /dev/null
@@ -1,797 +0,0 @@
-# -*- Autoconf -*-
-# Process this file with autoconf to produce a configure script.
-AC_PREREQ(2.57)
-AC_INIT([lighttpd], [1.5.0], [contact@lighttpd.net])
-AC_CONFIG_SRCDIR([src/server.c])
-AC_CONFIG_HEADER([config.h])
-
-AC_CANONICAL_TARGET
-
-AM_INIT_AUTOMAKE
-
-# Checks for programs.
-AC_PROG_CC
-AM_PROG_CC_C_O
-AC_PROG_LD
-AC_PROG_INSTALL
-AC_PROG_AWK
-AC_PROG_CPP
-dnl AC_PROG_CXX
-AC_PROG_LN_S
-AC_PROG_MAKE_SET
-
-dnl AM_PROG_AR is needed for some linker stuff
-dnl AC_USE_SYSTEM_EXTENSIONS requires autoconf 2.60
-m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], [AC_USE_SYSTEM_EXTENSIONS])
-dnl AM_PROG_AR requires automake 1.11 (and uses AC_COMPILE_IFELSE which wants AC_USE_SYSTEM_EXTENSIONS)
-m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
-
-dnl check environment
-AC_AIX
-AC_ISC_POSIX
-AC_MINIX
-
-dnl AC_CANONICAL_HOST
-case $host_os in
- *darwin*|*cygwin*|*aix*|*mingw* ) NO_RDYNAMIC=yes;;
- * ) NO_RDYNAMIC=no;;
-esac
-AM_CONDITIONAL(NO_RDYNAMIC, test x$NO_RDYNAMIC = xyes)
-
-AC_EXEEXT
-
-dnl libtool
-AC_DISABLE_STATIC
-AC_ENABLE_SHARED
-
-AC_LIBTOOL_DLOPEN
-AC_PROG_LIBTOOL
-
-dnl for solaris
-CPPFLAGS="${CPPFLAGS} -D_REENTRANT -D__EXTENSIONS__"
-
-# Checks for header files.
-AC_HEADER_STDC
-AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h netinet/in.h stdlib.h string.h \
-sys/socket.h sys/time.h unistd.h sys/sendfile.h sys/uio.h \
-getopt.h sys/epoll.h sys/select.h poll.h sys/poll.h sys/devpoll.h sys/filio.h \
-sys/mman.h sys/event.h sys/port.h pwd.h sys/syslimits.h \
-sys/resource.h sys/un.h syslog.h sys/prctl.h pthread.h])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_C_INLINE
-AC_C_CHAR_UNSIGNED
-AC_TYPE_OFF_T
-AC_TYPE_PID_T
-AC_TYPE_SIZE_T
-
-AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
-AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
-AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
-#include <sys/socket.h>])
-
-# Checks for library functions.
-AC_FUNC_FORK
-dnl AC_FUNC_MALLOC
-#AC_FUNC_MMAP
-dnl AC_FUNC_REALLOC
-AC_TYPE_SIGNAL
-AC_FUNC_STAT
-AC_FUNC_STRFTIME
-AC_CHECK_FUNCS([issetugid])
-
-dnl Checks for database.
-MYSQL_INCLUDE=""
-MYSQL_LIBS=""
-
-AC_MSG_CHECKING(for MySQL support)
-AC_ARG_WITH(mysql,
- AC_HELP_STRING([--with-mysql@<:@=PATH@:>@],[Include MySQL support. PATH is the path to 'mysql_config']),
- [WITH_MYSQL=$withval],[WITH_MYSQL=no])
-
-if test "$WITH_MYSQL" != "no"; then
- AC_MSG_RESULT(yes)
- if test "$WITH_MYSQL" = "yes"; then
- AC_PATH_PROG(MYSQL_CONFIG, mysql_config)
- else
- MYSQL_CONFIG=$WITH_MYSQL
- fi
-
- if test "$MYSQL_CONFIG" = ""; then
- AC_MSG_ERROR(mysql_config is not found)
- fi
- if test \! -x $MYSQL_CONFIG; then
- AC_MSG_ERROR(mysql_config not exists or not executable, use --with-mysql=path-to-mysql_config)
- fi
-
- if $MYSQL_CONFIG | grep -- '--include' > /dev/null ; then
- MYSQL_INCLUDE="`$MYSQL_CONFIG --include | sed s/\'//g`"
- else
- MYSQL_INCLUDE="`$MYSQL_CONFIG --cflags | sed s/\'//g`"
- fi
- MYSQL_LIBS="`$MYSQL_CONFIG --libs | sed s/\'//g`"
-
- AC_MSG_CHECKING(for MySQL includes at)
- AC_MSG_RESULT($MYSQL_INCLUDE)
-
- AC_MSG_CHECKING(for MySQL libraries at)
- AC_MSG_RESULT($MYSQL_LIBS)
-dnl check for errmsg.h, which isn't installed by some versions of 3.21
- old_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $MYSQL_INCLUDE"
- AC_CHECK_HEADERS(errmsg.h mysql.h)
- CPPFLAGS="$old_CPPFLAGS"
-
- AC_DEFINE([HAVE_MYSQL], [1], [mysql support])
-else
- AC_MSG_RESULT(no)
-fi
-
-AC_SUBST(MYSQL_LIBS)
-AC_SUBST(MYSQL_INCLUDE)
-
-POSTGRESQL_INCLUDE=""
-POSTGRESQL_LIBS=""
-
-AC_MSG_CHECKING(for PostgreSQL support)
-AC_ARG_WITH(postgresql,
- AC_HELP_STRING([--with-postgresql@<:@=PATH@:>@],[Include PostgreSQL support. PATH is the path to 'pg_config']),
- [WITH_POSTGRESQL=$withval],[WITH_POSTGRESQL=no])
-
-if test "$WITH_POSTGRESQL" != "no"; then
- AC_MSG_RESULT($WITH_POSTGRESQL)
- if test "$WITH_POSTGRESQL" = "yes"; then
- AC_PATH_PROG(POSTGRESQL_CONFIG, pg_config)
- else
- POSTGRESQL_CONFIG=$WITH_POSTGRESQL
- fi
-
- if test "$POSTGRESQL_CONFIG" = ""; then
- AC_MSG_ERROR(pg_config is not found)
- fi
- if test \! -x $POSTGRESQL_CONFIG; then
- AC_MSG_ERROR($POSTGRESQL_CONFIG not exists or not executable, use --with-postgresql=path-to-pg_config)
- fi
-
- AC_MSG_CHECKING(for PostgreSQL includes at)
- if $POSTGRESQL_CONFIG --help | grep -- '--includedir' > /dev/null ; then
- POSTGRESQL_INCLUDE="-I`$POSTGRESQL_CONFIG --includedir | sed s/\'//g`"
- else
- POSTGRESQL_INCLUDE="`$POSTGRESQL_CONFIG --cflags | sed s/\'//g`"
- fi
- AC_MSG_RESULT($POSTGRESQL_INCLUDE)
-
- AC_MSG_CHECKING(for PostgreSQL libraries at)
- if test x"`$POSTGRESQL_CONFIG --libdir`" != "x"; then
- POSTGRESQL_LIBS="-L`$POSTGRESQL_CONFIG --libdir`"
- fi
- POSTGRESQL_LIBS="$POSTGRESQL_LIBS -lpgport -lpq -lrt"
- AC_MSG_RESULT($POSTGRESQL_LIBS)
-
- old_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $POSTGRESQL_INCLUDE"
- AC_CHECK_HEADERS(libpq-fe.h)
- CPPFLAGS="$old_CPPFLAGS"
-
- AC_DEFINE([HAVE_POSTGRESQL], [1], [postgresql support])
-else
- AC_MSG_RESULT(no)
-fi
-
-AC_SUBST(POSTGRESQL_LIBS)
-AC_SUBST(POSTGRESQL_INCLUDE)
-
-dnl Check for LDAP
-AC_MSG_CHECKING(for LDAP support)
-AC_ARG_WITH(ldap, AC_HELP_STRING([--with-ldap],[enable LDAP support]),
-[WITH_LDAP=$withval], [WITH_LDAP=no])
-AC_MSG_RESULT([$withval])
-if test "$WITH_LDAP" != "no"; then
- AC_CHECK_LIB(ldap, ldap_bind, [
- AC_CHECK_HEADERS([ldap.h],[
- LDAP_LIB=-lldap
- AC_DEFINE([HAVE_LIBLDAP], [1], [libldap])
- AC_DEFINE([HAVE_LDAP_H], [1])
- ])
- ])
- AC_SUBST(LDAP_LIB)
- AC_CHECK_LIB(lber, ber_printf, [
- AC_CHECK_HEADERS([lber.h],[
- LBER_LIB=-llber
- AC_DEFINE([HAVE_LIBLBER], [1], [liblber])
- AC_DEFINE([HAVE_LBER_H], [1])
- ])
- ])
- AC_SUBST(LBER_LIB)
-fi
-
-dnl Check for xattr
-AC_MSG_CHECKING(for extended attributes support)
-AC_ARG_WITH(attr, AC_HELP_STRING([--with-attr],[enable extended attribute support]),
-[WITH_ATTR=$withval],[WITH_ATTR=no])
-AC_MSG_RESULT($withval)
-if test "$WITH_ATTR" != "no"; then
- AC_CHECK_LIB(attr, attr_get, [
- AC_CHECK_HEADERS([attr/attributes.h],[
- ATTR_LIB=-lattr
- AC_DEFINE([HAVE_XATTR], [1], [libattr])
- AC_DEFINE([HAVE_ATTR_ATTRIBUTES_H], [1])
- ])
- ])
- AC_SUBST(ATTR_LIB)
-fi
-
-## openssl on solaris needs -lsocket -lnsl
-AC_SEARCH_LIBS(socket,socket)
-AC_SEARCH_LIBS(gethostbyname,nsl socket)
-AC_SEARCH_LIBS(hstrerror,resolv)
-
-save_LIBS=$LIBS
-AC_SEARCH_LIBS(dlopen,dl,[
- AC_CHECK_HEADERS([dlfcn.h],[
- if test "$ac_cv_search_dlopen" != no; then
- test "$ac_cv_search_dlopen" = "none required" || DL_LIB="$ac_cv_search_dlopen"
- fi
-
- AC_DEFINE([HAVE_LIBDL], [1], [libdl])
- AC_DEFINE([HAVE_DLFCN_H], [1])
- ])
-])
-LIBS=$save_LIBS
-AC_SUBST(DL_LIB)
-
-dnl Check for valgrind
-AC_MSG_CHECKING(for valgrind)
-AC_ARG_WITH(valgrind, AC_HELP_STRING([--with-valgrind],[enable internal support for valgrind]),
-[WITH_VALGRIND=$withval],[WITH_VALGRIND=no])
-AC_MSG_RESULT([$WITH_VALGRIND])
-if test "$WITH_VALGRIND" != "no"; then
- AC_CHECK_HEADERS([valgrind/valgrind.h])
-fi
-
-dnl Check for openssl
-AC_MSG_CHECKING(for OpenSSL)
-AC_ARG_WITH(openssl,
- AC_HELP_STRING([--with-openssl@<:@=DIR@:>@],[Include openssl support (default no)]),
- [WITH_OPENSSL=$withval],[WITH_OPENSSL=no])
-
-if test "$WITH_OPENSSL" != "no"; then
- use_openssl=yes
- if test "$WITH_OPENSSL" != "yes"; then
- CPPFLAGS="$CPPFLAGS -I$WITH_OPENSSL/include"
- LDFLAGS="$LDFLAGS -L$WITH_OPENSSL/lib"
- fi
-else
- use_openssl=no
-fi
-AC_MSG_RESULT([$use_openssl])
-
-AC_ARG_WITH(openssl-includes,
- AC_HELP_STRING([--with-openssl-includes=DIR],[OpenSSL includes]),
- [ use_openssl=yes CPPFLAGS="$CPPFLAGS -I$withval" ]
-)
-
-AC_ARG_WITH(openssl-libs,
- AC_HELP_STRING([--with-openssl-libs=DIR],[OpenSSL libraries]),
- [ use_openssl=yes LDFLAGS="$LDFLAGS -L$withval" ]
-)
-
-AC_ARG_WITH(kerberos5,
- AC_HELP_STRING([--with-kerberos5],[use Kerberos5 support with OpenSSL]),
- [ use_kerberos=yes ], [use_kerberos=no]
-)
-
-if test "x$use_openssl" = "xyes"; then
- if test "x$use_kerberos" != "xyes"; then
- CPPFLAGS="$CPPFLAGS -DOPENSSL_NO_KRB5"
- fi
-
- AC_CHECK_HEADERS([openssl/ssl.h])
- OLDLIBS="$LIBS"
- AC_CHECK_LIB(crypto, BIO_f_base64, [
- AC_CHECK_LIB(ssl, SSL_new, [ SSL_LIB="-lssl -lcrypto"
- AC_DEFINE(HAVE_LIBSSL, [], [Have libssl]) ], [], [ -lcrypto "$DL_LIB" ])
- ], [], [])
- LIBS="$OLDLIBS"
- AC_SUBST(SSL_LIB)
-fi
-
-AC_MSG_CHECKING(for perl regular expressions support)
-AC_ARG_WITH(pcre, AC_HELP_STRING([--with-pcre],[Enable pcre support (default yes)]),
- [WITH_PCRE=$withval],[WITH_PCRE=yes])
-AC_MSG_RESULT([$WITH_PCRE])
-
-if test "$WITH_PCRE" != "no"; then
- AC_PATH_PROG(PCRECONFIG, pcre-config)
-
- if test x"$PCRECONFIG" != x; then
- PCRE_LIB=`$PCRECONFIG --libs`
- CPPFLAGS="$CPPFLAGS `$PCRECONFIG --cflags`"
- OLDLIBS="$LIBS"
- LIBS="$LIBS $PCRE_LIB"
- AC_CHECK_LIB(pcre, pcre_compile, [
- AC_CHECK_HEADERS([pcre.h], [
- AC_DEFINE([HAVE_LIBPCRE], [1], [libpcre])
- AC_DEFINE([HAVE_PCRE_H], [1])
- ])
- ])
- LIBS="$OLDLIBS"
- else
- AC_MSG_ERROR([pcre-config wasn't found. Either install pcre and its headers or re-run 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_SUBST(Z_LIB)
-
-AC_MSG_CHECKING(for bzip2 support)
-AC_ARG_WITH(bzip2, AC_HELP_STRING([--with-bzip2],[Enable bzip2 support for mod_compress]),
- [WITH_BZIP2=$withval],[WITH_BZIP2=yes])
-AC_MSG_RESULT([$WITH_BZIP2])
-
-if test "$WITH_BZIP2" != "no"; then
- AC_CHECK_LIB(bz2, BZ2_bzCompress, [
- AC_CHECK_HEADERS([bzlib.h],[
- BZ_LIB=-lbz2
- AC_DEFINE([HAVE_LIBBZ2], [1], [libbz2])
- AC_DEFINE([HAVE_BZLIB_H], [1])
- ])
- ])
-fi
-AC_SUBST(BZ_LIB)
-
-if test -z "$PKG_CONFIG"; then
- AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
-fi
-
-AC_MSG_CHECKING(for properties in mod_webdav)
-AC_ARG_WITH(webdav-props, AC_HELP_STRING([--with-webdav-props],[properties in mod_webdav]),
-[WITH_WEBDAV_PROPS=$withval],[WITH_WEBDAV_PROPS=no])
-AC_MSG_RESULT([$WITH_WEBDAV_PROPS])
-
-if test "$WITH_WEBDAV_PROPS" != "no"; then
- PKG_CHECK_MODULES(XML, libxml-2.0, [
- AC_DEFINE([HAVE_LIBXML2], [1], [libxml2])
- AC_DEFINE([HAVE_LIBXML_H], [1], [libxml.h])
- ])
- PKG_CHECK_MODULES(SQLITE, sqlite3, [
- AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
- AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
- ])
-
- AC_MSG_CHECKING(for locks in mod_webdav)
- AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
- [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
- AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
-
- if test "$WITH_WEBDAV_LOCKS" != "no"; then
- AC_CHECK_LIB(uuid, uuid_unparse, [
- AC_CHECK_HEADERS([uuid/uuid.h],[
- UUID_LIB=-luuid
- AC_DEFINE([HAVE_UUID], [1], [libuuid])
- AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
- ])
- ])
- AC_SUBST(UUID_LIB)
- fi
-fi
-
-dnl Check for gdbm
-AC_MSG_CHECKING(for gdbm)
-AC_ARG_WITH(gdbm, AC_HELP_STRING([--with-gdbm],[gdbm storage for mod_trigger_b4_dl]),
-[WITH_GDBM=$withval],[WITH_GDBM=no])
-AC_MSG_RESULT([$WITH_GDBM])
-
-if test "$WITH_GDBM" != "no"; then
- AC_CHECK_LIB(gdbm, gdbm_open, [
- AC_CHECK_HEADERS([gdbm.h],[
- GDBM_LIB=-lgdbm
- AC_DEFINE([HAVE_GDBM], [1], [libgdbm])
- AC_DEFINE([HAVE_GDBM_H], [1])
- ])
- ])
- AC_SUBST(GDBM_LIB)
-fi
-
-dnl Check for memcache
-AC_MSG_CHECKING(for memcache)
-AC_ARG_WITH(memcache, AC_HELP_STRING([--with-memcache],[memcached storage for mod_trigger_b4_dl]),
-[WITH_MEMCACHE=$withval],[WITH_MEMCACHE=no])
-AC_MSG_RESULT([$WITH_MEMCACHE])
-if test "$WITH_MEMCACHE" != "no"; then
- AC_CHECK_LIB(memcache, mc_new, [
- AC_CHECK_HEADERS([memcache.h],[
- MEMCACHE_LIB=-lmemcache
- AC_DEFINE([HAVE_MEMCACHE], [1], [libmemcache])
- AC_DEFINE([HAVE_MEMCACHE_H], [1], [memcache.h])
- ])
- ])
- AC_SUBST(MEMCACHE_LIB)
-fi
-
-dnl Check for lua
-AC_MSG_CHECKING(for lua)
-AC_ARG_WITH(lua, AC_HELP_STRING([--with-lua],[lua engine for mod_magnet]),
-[WITH_LUA=$withval],[WITH_LUA=no])
-
-AC_MSG_RESULT($WITH_LUA)
-if test "$WITH_LUA" != "no"; then
- # try pkgconfig
- if test "$WITH_LUA" = "yes"; then
- LUAPC=lua
- else
- LUAPC=$WITH_LUA
- fi
-
- PKG_CHECK_MODULES(LUA, $LUAPC >= 5.1, [
- AC_DEFINE([HAVE_LUA], [1], [liblua])
- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
- ],[
- # for debian based systems
- PKG_CHECK_MODULES(LUA, lua5.1 >= 5.1, [
- AC_DEFINE([HAVE_LUA], [1], [liblua])
- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
- ],[
- # for freebsd
- PKG_CHECK_MODULES(LUA, lua-5.1 >= 5.1, [
- AC_DEFINE([HAVE_LUA], [1], [liblua])
- AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
- ])
- ])
- ])
-
- AC_SUBST(LUA_CFLAGS)
- AC_SUBST(LUA_LIBS)
-fi
-
-dnl need 2.10.0 for g_atomic_int_set
-PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.10.0, [
- AC_DEFINE([HAVE_GTHREAD], [1], [libglib])
- AC_DEFINE([HAVE_GLIB_H], [1], [glib.h])
-])
-
-save_LIBS=$LIBS
-AC_SEARCH_LIBS(crypt,crypt,[
- AC_CHECK_HEADERS([crypt.h],[
- AC_DEFINE([HAVE_CRYPT_H], [1])
- ])
-
- AC_DEFINE([HAVE_LIBCRYPT], [1], [libcrypt])
- if test "$ac_cv_search_crypt" != no; then
- test "$ac_cv_search_crypt" = "none required" || CRYPT_LIB="$ac_cv_search_crypt"
- fi
-])
-LIBS=$save_LIBS
-AC_SUBST(CRYPT_LIB)
-
-save_LIBS=$LIBS
-AC_SEARCH_LIBS(sendfilev,sendfile,[
- if test "$ac_cv_search_sendfilev" != no; then
- test "$ac_cv_search_sendfilev" = "none required" || SENDFILE_LIB="$ac_cv_search_sendfilev"
- AC_DEFINE([HAVE_SENDFILEV], [1], [solaris sendfilev])
- fi
-])
-LIBS=$save_LIBS
-AC_SUBST(SENDFILE_LIB)
-
-case $host_os in
- *mingw* ) LIBS="$LIBS -lwsock32";;
- * ) ;;
-esac
-
-AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
- strdup strerror strstr strtol strtoll sendfile getopt socket lstat \
- gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot strptime \
- getuid select signal pathconf madvise posix_fadvise posix_madvise \
- writev sigaction sendfile64 send_file kqueue port_create localtime_r gmtime_r])
-
-AC_MSG_CHECKING(for Large File System support)
-AC_ARG_ENABLE(lfs,
- AC_HELP_STRING([--enable-lfs],[Turn on Large File System (default)]),
- [case "${enableval}" in
- yes) CPPFLAGS="${CPPFLAGS} -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES" ;;
- no) ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-lfs) ;;
- esac],[CPPFLAGS="${CPPFLAGS} -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES"
- enable_lfs=yes])
-AC_MSG_RESULT($enableval)
-
-AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(off_t)
-
-if test "x$ac_cv_func_sendfile" = xyes; then
- # check if sendfile works
- AC_MSG_CHECKING(if sendfile works)
- if test "x$cross_compiling" = xno; then
- AC_TRY_RUN([
- #ifdef HAVE_SYS_SENDFILE_H
- #include <sys/sendfile.h>
- #endif /* HAVE_SYS_SENDFILE_H */
- #include <errno.h>
- int main() {
- int o = 0;
- if (-1 == sendfile(-1, 0, &o, 0) && errno == ENOSYS) return -1;
- return 0;
- } ],
- AC_MSG_RESULT(yes),
- [ AC_MSG_RESULT(no)
- AC_DEFINE([HAVE_SENDFILE_BROKEN], [1], [broken sendfile]) ] )
- else
- AC_MSG_RESULT(no, cross-compiling)
- AC_DEFINE([HAVE_SENDFILE_BROKEN], [1], [broken sendfile])
- fi
-fi
-
-dnl Check for IPv6 support
-
-AC_ARG_ENABLE(ipv6,
- AC_HELP_STRING([--disable-ipv6],[disable IPv6 support]),
- [case "${enableval}" in
- yes) ipv6=true ;;
- no) ipv6=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
- esac],[ipv6=true])
-
-if test x$ipv6 = xtrue; then
- AC_CACHE_CHECK([for IPv6 support], ac_cv_ipv6_support,
- [AC_TRY_LINK([ #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>], [struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0; ],
- [ac_cv_ipv6_support=yes], [ac_cv_ipv6_support=no])])
-
- if test "$ac_cv_ipv6_support" = yes; then
- AC_DEFINE(HAVE_IPV6,1,[Whether to enable IPv6 support])
- fi
-fi
-
-dnl Check for libaio
-AC_MSG_CHECKING(for libaio)
-AC_ARG_WITH(libaio, AC_HELP_STRING([--with-libaio],[enable libaio network write handlers]),
-[WITH_LIBAIO=$withval],[WITH_LIBAIO=no])
-AC_MSG_RESULT([$WITH_LIBAIO])
-if test "$WITH_LIBAIO" != "no"; then
- AC_CHECK_LIB(aio, io_getevents, [
- AC_CHECK_HEADERS([libaio.h],[
- AIO_LIB=-laio
- AC_DEFINE([HAVE_LIBAIO], [1], [libaio])
- AC_DEFINE([HAVE_LIBAIO_H], [1], [libaio.h])
- ])
- ])
- AC_SUBST(AIO_LIB)
-fi
-
-AM_CONDITIONAL(CROSS_COMPILING, test "x$cross_compiling" = xyes)
-
-dnl check for fastcgi lib, for the tests only
-fastcgi_found=no
-AC_CHECK_LIB(fcgi, FCGI_Accept, [
- AC_CHECK_HEADERS([fastcgi.h],[
- fastcgi_found=yes
- AC_DEFINE(HAVE_FASTCGI_H, 1, [ fastcgi.h ])
- ],[
- AC_CHECK_HEADERS([fastcgi/fastcgi.h],[
- fastcgi_found=yes
- AC_DEFINE(HAVE_FASTCGI_FASTCGI_H, 1, [fastcgi/fastcgi.h])
- ])
- ])
-])
-
-AM_CONDITIONAL(CHECK_WITH_FASTCGI, [test "x$fastcgi_found" = xyes])
-
-# check for extra compiler options (warning options)
-if test "${GCC}" = "yes"; then
- CFLAGS="${CFLAGS} -Wall -W -Wshadow -pedantic -std=gnu99"
-fi
-
-AC_ARG_ENABLE(extra-warnings,
- AC_HELP_STRING([--enable-extra-warnings],[enable extra warnings (gcc specific)]),
- [case "${enableval}" in
- yes) extrawarnings=true ;;
- no) extrawarnings=false ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-extra-warnings) ;;
- esac],[extrawarnings=false])
-
-if test x$extrawarnings = xtrue; then
- CFLAGS="${CFLAGS} -g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wno-pointer-sign -Wcast-align -Winline -Wsign-compare -Wnested-externs -Wpointer-arith -Wl,--as-needed -Wformat-security"
-fi
-
-dnl build version-id
-LIGHTTPD_VERSION_ID=`echo $PACKAGE_VERSION | $AWK -F '.' '{print "(" $1 " << 16 | " $2 " << 8 | " $3 ")"}'`
-AC_DEFINE_UNQUOTED([LIGHTTPD_VERSION_ID], [$LIGHTTPD_VERSION_ID], [lighttpd-version-id])
-
-AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile tests/Makefile \
- tests/docroot/Makefile \
- tests/docroot/123/Makefile \
- tests/docroot/www/Makefile \
- tests/docroot/www/go/Makefile \
- tests/docroot/www/indexfile/Makefile \
- tests/docroot/www/expire/Makefile \
- src/valgrind/Makefile \
- distribute.sh])
-AC_OUTPUT
-
-
-do_build="\
- mod_access \
- mod_accesslog \
- mod_alias \
- mod_auth \
- mod_cgi \
- mod_chunked \
- mod_compress \
- mod_deflate \
- mod_dirlisting \
- mod_evhost \
- mod_evasive \
- mod_expire \
- mod_flv_streaming\
- mod_indexfile \
- mod_proxy_core \
- mod_proxy_backend_http \
- mod_proxy_backend_fastcgi \
- mod_proxy_backend_scgi \
- mod_proxy_backend_ajp13 \
- mod_rrdtool \
- mod_secdownload \
- mod_setenv \
- mod_simple_vhost \
- mod_sql_vhost_core \
- mod_ssi \
- mod_staticfile \
- mod_status \
- mod_uploadprogress \
- mod_userdir \
- mod_usertrack \
- mod_webdav \
- "
-
-plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
-features="regex-conditionals"
-if test ! "x$PCRE_LIB" = x; then
- do_build="$do_build $plugins"
- enable_feature="$features"
-else
- no_build="$no_build $plugins"
- disable_feature="$features"
-fi
-
-plugins="mod_mysql_vhost"
-if test ! "x$MYSQL_LIBS" = x; then
- do_build="$do_build $plugins"
-else
- no_build="$no_build $plugins"
-fi
-
-plugins="mod_postgresql_vhost"
-if test ! "x$POSTGRESQL_LIBS" = x; then
- do_build="$do_build $plugins"
-else
- no_build="$no_build $plugins"
-fi
-
-plugins="mod_magnet"
-if test ! "x$LUA_LIBS" = x; then
- do_build="$do_build $plugins"
-else
- no_build="$no_build $plugins"
-fi
-
-features="storage-gdbm"
-if test ! "x$GDBM_LIB" = x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="storage-memcache"
-if test ! "x$MEMCACHE_LIB" = x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="compress-gzip compress-deflate"
-if test ! "x$Z_LIB" = x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="compress-bzip2"
-if test ! "x$BZ_LIB" = x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="auth-ldap"
-if test ! "x$LDAP_LIB" = x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="network-openssl"
-if test ! "x$SSL_LIB" = x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-# no crypt call
-features="auth-crypt"
-if test "$ac_cv_search_crypt" = no; then
- disable_feature="$disable_feature $features"
-else
- enable_feature="$enable_feature $features"
-fi
-
-features="network-ipv6"
-if test "$ac_cv_ipv6_support" = yes; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="large-files"
-if test "$enable_lfs" = yes; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="webdav-properties"
-if test "x$XML_LIBS" \!= x -a "x$SQLITE_LIBS" \!= x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-features="webdav-locks"
-if test "x$UUID_LIB" \!= x; then
- enable_feature="$enable_feature $features"
-else
- disable_feature="$disable_feature $features"
-fi
-
-## output
-
-$ECHO
-$ECHO "Plugins:"
-$ECHO
-
-$ECHO "enabled: "
-for p in $do_build; do
- $ECHO " $p"
-done | sort
-
-$ECHO "disabled: "
-for p in $no_build; do
- $ECHO " $p"
-done | sort
-
-$ECHO
-$ECHO "Features:"
-$ECHO
-
-$ECHO "enabled: "
-for p in $enable_feature; do
- $ECHO " $p"
-done | sort
-
-$ECHO "disabled: "
-for p in $disable_feature; do
- $ECHO " $p"
-done | sort
-
-$ECHO
diff --git a/distribute.sh.in b/distribute.sh.in
deleted file mode 100644
index e0b63a35..00000000
--- a/distribute.sh.in
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/bin/sh
-PACKAGE=@PACKAGE_TARNAME@
-VERSION=@VERSION@
-NAME=@PACKAGE_TARNAME@-@VERSION@
-
-DISTDIR="/home/jan/wwwroot/servers/www.lighttpd.net/pages/download/"
-RPMS="/home/jan/rpmbuild/RPMS/i386/${NAME}-1.i386.rpm \
- /home/jan/rpmbuild/SRPMS/${NAME}-1.src.rpm"
-FILES="${RPMS} ${NAME}.tar.gz \
- NEWS.html \
- ChangeLog \
- release-news.${VERSION}.txt \
- ${NAME}.tar.gz.sig"
-DLURL="http://www.lighttpd.net/download"
-pack=0
-echo $1
-case "$1" in
- --pack) pack=1;;
-esac
-
-echo ${nopack}
-
-if test x${pack} = x1; then
- make distcheck && rpmbuild -ta --nodeps ${NAME}.tar.gz
- gpg --detach-sign ${NAME}.tar.gz
- rpm --addsign ${RPMS}
-fi
-
-MD5RPM=`md5sum /home/jan/rpmbuild/RPMS/i386/${NAME}-1.i386.rpm| cut -b 1-32`
-MD5SRPM=`md5sum /home/jan/rpmbuild/SRPMS/${NAME}-1.src.rpm| cut -b 1-32`
-MD5TGZ=`md5sum ${NAME}.tar.gz| cut -b 1-32`
-DATE=`date +'%Y-%m-%d %H:%M'`
-NEWS=`cat NEWS | sed "/^- ${VERSION}/,/^-/p;d" | sed "/^- /d;/^$/d"`
-DLNAME="${DLURL}/${NAME}"
-
-cat > release-news.${VERSION}-mail.txt <<EOF
-${PACKAGE} ${VERSION} - ${DATE}
-
-Changes
--------
-${NEWS}
-
-Download
-- ${NAME}-1.i386.rpm [built on Fedora Core 4]
- ${DLNAME}-1.i386.rpm
- MD5: ${MD5RPM}
-- ${NAME}-1.src.rpm
- ${DLNAME}-1.src.rpm
- MD5: ${MD5SRPM}
-- ${NAME}.tar.gz
- ${DLNAME}.tar.gz
- MD5: ${MD5TGZ}
- Signature: ${DLNAME}.tar.gz.sig
-
-EOF
-
-cat > release-news.${VERSION}.txt <<EOF
-${PACKAGE} ${VERSION} - ${DATE}
-
-Changes
--------
-${NEWS}
-
-Checksums
-- ${NAME}-1.i386.rpm [built on Fedora Core 4]
- MD5: ${MD5RPM}
-- ${NAME}-1.src.rpm
- MD5: ${MD5SRPM}
-- ${NAME}.tar.gz
- MD5: ${MD5TGZ}
-
-EOF
-
-rst2html NEWS > NEWS.html
-
-for i in ${DISTDIR}; do
- cp -u ${FILES} $i
-done
-
-curdir=`pwd`
-cd ~/wwwroot/servers/www.lighttpd.net/
-make put
-cd ${curdir}
-
-
diff --git a/doc/.cvsignore b/doc/.cvsignore
deleted file mode 100644
index 0d1de1e9..00000000
--- a/doc/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile.in
-Makefile
-*.html
-*.ps.gz
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
deleted file mode 100644
index f42521ba..00000000
--- a/doc/CMakeLists.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-IF(NOT DOCDIR)
- SET(DOCDIR "share/doc/lighttpd")
-ENDIF(NOT DOCDIR)
-
-SET(L_DOCS
- accesslog.txt
- access.txt
- alias.txt
- authentication.txt
- cgi.txt
- CMakeLists.txt
- compress.txt
- configuration.txt
- dirlisting.txt
- evhost.txt
- expire.txt
- features.txt
- performance.txt
- plugins.txt
- redirect.txt
- rewrite.txt
- rrdtool.txt
- secdownload.txt
- security.txt
- setenv.txt
- simple-vhost.txt
- skeleton.txt
- ssi.txt
- ssl.txt
- state.txt
- status.txt
- traffic-shaping.txt
- trigger_b4_dl.txt
- userdir.txt
- webdav.txt
-)
-
-INSTALL(FILES ${L_DOCS}
- DESTINATION ${DOCDIR})
diff --git a/doc/Makefile.am b/doc/Makefile.am
deleted file mode 100644
index b9298c31..00000000
--- a/doc/Makefile.am
+++ /dev/null
@@ -1,86 +0,0 @@
-dist_man8_MANS=lighttpd.8
-
-DOCS=accesslog.txt \
-authentication.txt \
-cgi.txt \
-compress.txt \
-configuration.txt \
-features.txt \
-performance.txt \
-plugins.txt \
-redirect.txt \
-rewrite.txt \
-secdownload.txt \
-security.txt \
-simple-vhost.txt \
-skeleton.txt \
-ssi.txt \
-ssl.txt \
-state.txt \
-rrdtool.txt \
-alias.txt \
-userdir.txt \
-access.txt \
-traffic-shaping.txt \
-setenv.txt \
-status.txt \
-trigger_b4_dl.txt \
-webdav.txt \
-expire.txt \
-dirlisting.txt \
-evhost.txt
-
-HTMLDOCS=accesslog.html \
- authentication.html \
- cgi.html \
- compress.html \
- configuration.html \
- features.html \
- performance.html \
- plugins.html \
- proxy.html \
- redirect.html \
- rewrite.html \
- secdownload.html \
- security.html \
- simple-vhost.html \
- skeleton.html \
- ssi.html \
- ssl.html \
- state.html \
- rrdtool.html \
- alias.html \
- userdir.html \
- access.html \
- traffic-shaping.html \
- setenv.html \
- status.html \
- trigger_b4_dl.html \
- webdav.html \
- expire.html \
- dirlisting.html \
- evhost.html
-
-EXTRA_DIST=lighttpd.conf lighttpd.user \
- rc.lighttpd rc.lighttpd.redhat sysconfig.lighttpd \
- rrdtool-graph.sh \
- state.dot \
- spawn-php.sh \
- newstyle.css \
- oldstyle.css \
- $(DOCS)
-
-.txt.html:
- rst2html $^ > $@
-
-
-html: $(HTMLDOCS)
-
-#%.ps.gz: %.ps
-# gzip $^
-
-#%.ps: %.dot
-# dot -Tps -o $@ $^
-
-clean-local:
- rm -f *.html
diff --git a/doc/access.txt b/doc/access.txt
deleted file mode 100644
index ad8d6b06..00000000
--- a/doc/access.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-======
-Access
-======
-
-------------------
-Module: mod_access
-------------------
-
-:Author: Allan Wind
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The access module is used to deny access to files with given trailing path names.
-
-.. meta::
- :keywords: lighttpd, trailing path access control
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-The access module is used to deny access to files with given trailing path names.
-
-Options
-=======
-
-url.access-deny
- Denies access to all files with any of given trailing path names.
-
- Default: empty
-
- Example: ::
-
- url.access-deny = ( "~", ".inc")
-
- will deny access to all files ended with a diacritical mark (~) or .inc
- such as example~ or example.inc. A trailing diacritical mark is often
- used by editors for backup files. And the .inc extension is often used
- for include files with code.
diff --git a/doc/accesslog.txt b/doc/accesslog.txt
deleted file mode 100644
index 38701762..00000000
--- a/doc/accesslog.txt
+++ /dev/null
@@ -1,126 +0,0 @@
-=========
-Accesslog
-=========
-
----------------------
-Module: mod_accesslog
----------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The accesslog module ...
-
-.. meta::
- :keywords: lighttpd, accesslog, CLF
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-CLF like by default, flexible like apache
-
-Options
-=======
-
-accesslog.use-syslog
- send the accesslog to syslog
-
- Default: disabled
-
-accesslog.filename
- name of the file where the accesslog should be written too if syslog
- is not used.
-
- if the name starts with a '|' the rest of the name is taken
- as the name of a process which will be spawn and will get the
- output
-
- e.g.: ::
-
- accesslog.filename = "/var/log/lighttpd.log"
-
- $HTTP["host"] == "mail.example.org" {
- accesslog.filename = "|/usr/bin/cronolog"
- }
-
- Default: disabled
-
-accesslog.format
- the format of the logfile
-
- ====== ================================
- Option Description
- ====== ================================
- %% a percent sign
- %h name or address of remote-host
- %l ident name (not supported)
- %u authenticated user
- %t timestamp for the request-start
- %r request-line
- %s status code
- %b bytes sent for the body
- %i HTTP-header field
- %a remote address
- %A local address
- %B same as %b
- %C cookie field (not supported)
- %D time used in ms (not supported)
- %e environment (not supported)
- %f phyiscal filename
- %H request protocol (HTTP/1.0, ...)
- %m request method (GET, POST, ...)
- %n (not supported)
- %o `response header`_
- %p server port
- %P (not supported)
- %q query string
- %T time used in seconds
- %U request URL
- %v server-name
- %V (not supported)
- %X connection status
- %I bytes incomming
- %O bytes outgoing
- ====== ================================
-
- If %s is written %>s or %<s the < and the > are ignored. They are support
- for compat with apache.
-
- %i and %o expect the name of the field which should be written in curly brackets.
-
- e.g.: ::
-
- accesslog.format = "%h %l %u %t \"%r\" %b %>s \"%{User-Agent}i\" \"%{Referer}i\""
-
- Default: CLF compatible output
-
-Response Header
----------------
-
-The accesslog module provides a special way to log content from the
-application in a accesslog file. It can be used to log the session id into a
-logfile.
-
-If you want to log it into the accesslog just specify the field-name within
-a %{...}o like ::
-
- accesslog.format = "%h %l %u %t \"%r\" %b %>s \"%{User-Agent}i\" \"%{Referer}i\" \"%{X-LIGHTTPD-SID}o\""
-
-The prefix ``X-LIGHTTPD-`` is special as every response header starting with
-this prefix is assumed to be special for lighttpd and won't be sent out
-to the client.
-
-An example the use this functionality is provided below: ::
-
- <?php
-
- session_start();
-
- header("X-LIGHTTPD-SID: ".session_id());
-
- ?>
-
diff --git a/doc/alias.txt b/doc/alias.txt
deleted file mode 100644
index 95624755..00000000
--- a/doc/alias.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-=====
-Alias
-=====
-
------------------
-Module: mod_alias
------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The alias module ...
-
-.. meta::
- :keywords: lighttpd, alias
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-The alias module is used to specify a special document-root for a given url-subset.
-
-Options
-=======
-
-alias.url
- rewrites the document-root for a URL-subset
-
- Default: empty
-
- Example: ::
-
- alias.url = ( "/cgi-bin/" => "/var/www/servers/www.example.org/cgi-bin/" )
diff --git a/doc/authentication.txt b/doc/authentication.txt
deleted file mode 100644
index c550fb66..00000000
--- a/doc/authentication.txt
+++ /dev/null
@@ -1,211 +0,0 @@
-====================
-Using Authentication
-====================
-
-----------------
-Module: mod_auth
-----------------
-
-:Author: Jan Kneschke
-:Date: $Date$
-:Revision: $Revision$
-
-:abstract:
- The auth module provides ...
-
-.. meta::
- :keywords: lighttpd, authentication
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Supported Methods
------------------
-
-lighttpd supportes both authentication method described by
-RFC 2617:
-
-basic
-`````
-
-The Basic method transfers the username and the password in
-cleartext over the network (base64 encoded) and might result
-in security problems if not used in conjunction with a crypted
-channel between client and server.
-
-digest
-``````
-
-The Digest method only transfers a hashed value over the
-network which performs a lot of work to harden the
-authentication process in insecure networks.
-
-Backends
---------
-
-Depending on the method lighttpd provides various way to store
-the credentials used for the authentication.
-
-for basic auth:
-
-- plain_
-- htpasswd_
-- htdigest_
-- ldap_
-
-for digest auth:
-
-- plain_
-- htdigest_
-
-
-plain
-`````
-
-A file which contains username and the cleartext password
-seperated by a colon. Each entry is terminated by a single
-newline.::
-
- e.g.:
- agent007:secret
-
-
-htpasswd
-````````
-
-A file which contains username and the crypt()'ed password
-seperated by a colon. Each entry is terminated by a single
-newline. ::
-
- e.g.:
- agent007:XWY5JwrAVBXsQ
-
-You can use htpasswd from the apache distribution to manage
-those files. ::
-
- $ htpasswd lighttpd.user.htpasswd agent007
-
-
-htdigest
-````````
-
-A file which contains username, realm and the md5()'ed
-password seperated by a colon. Each entry is terminated
-by a single newline. ::
-
- e.g.:
- agent007:download area:8364d0044ef57b3defcfa141e8f77b65
-
-You can use htdigest from the apache distribution to manage
-those files. ::
-
- $ htdigest lighttpd.user.htdigest 'download area' agent007
-
-Using md5sum can also generate the password-hash: ::
-
- #!/bin/sh
- user=$1
- realm=$2
- pass=$3
-
- hash=`echo -n "$user:$realm:$pass" | md5sum | cut -b -32`
-
- echo "$user:$realm:$hash"
-
-To use it:
-
- $ htdigest.sh 'agent007' 'download area' 'secret'
- agent007:download area:8364d0044ef57b3defcfa141e8f77b65
-
-
-
-ldap
-````
-
-the ldap backend is basically performing the following steps
-to authenticate a user
-
-1. connect anonymously (at plugin init)
-2. get DN for filter = username
-3. auth against ldap server
-4. disconnect
-
-if all 4 steps are performed without any error the user is
-authenticated
-
-Configuration
-=============
-
-::
-
- ## debugging
- # 0 for off, 1 for 'auth-ok' messages, 2 for verbose debugging
- auth.debug = 0
-
- ## type of backend
- # plain, htpasswd, ldap or htdigest
- auth.backend = "htpasswd"
-
- # filename of the password storage for
- # plain
- auth.backend.plain.userfile = "lighttpd-plain.user"
-
- ## for htpasswd
- auth.backend.htpasswd.userfile = "lighttpd-htpasswd.user"
-
- ## for htdigest
- auth.backend.htdigest.userfile = "lighttpd-htdigest.user"
-
- ## for ldap
- # the $ in auth.backend.ldap.filter is replaced by the
- # 'username' from the login dialog
- auth.backend.ldap.hostname = "localhost"
- auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
- auth.backend.ldap.filter = "(uid=$)"
- # if enabled, startTLS needs a valid (base64-encoded) CA
- # certificate
- auth.backend.ldap.starttls = "enable"
- auth.backend.ldap.ca-file = "/etc/CAcertificate.pem"
- # if server performs client certificates validation we can
- # connect using user defined client certificates
- auth.backend.ldap.cert = "/etc/cert.pem"
- auth.backend.ldap.key = "/etc/req.pem"
-
- ## restrictions
- # set restrictions:
- #
- # ( <left-part-of-the-url> =>
- # ( "method" => "digest"/"basic",
- # "realm" => <realm>,
- # "require" => "user=<username>" )
- # )
- #
- # <realm> is a string to display in the dialog
- # presented to the user and is also used for the
- # digest-algorithm and has to match the realm in the
- # htdigest file (if used)
- #
-
- auth.require = ( "/download/" =>
- (
- "method" => "digest",
- "realm" => "download archiv",
- "require" => "user=agent007|user=agent008"
- ),
- "/server-info" =>
- (
- "method" => "digest",
- "realm" => "download archiv",
- "require" => "valid-user"
- )
- )
-
-Limitations
-============
-
-- The implementation of digest method is currently not
- completely compliant with the standard as it still allows
- a replay attack.
-
diff --git a/doc/build-win32.txt b/doc/build-win32.txt
deleted file mode 100644
index e343c7d3..00000000
--- a/doc/build-win32.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-Big thanks for Ben Harper (rogojin at gmail.com) for initial work and little help to get first setups.
-
-
-Prerequisities:
-
-First you need build environment. I recommend to get Visual Studio Express C++ from Microsoft.
-Then you need Platform SDK for Windows.
-
-CMake is used to build (http://www.cmake.org)
-
-And then you need few libraries to make Lighty work well:
-pkg-config (prebuilt can be found at: http://www.gimp.org/~tml/gimp/win32/pkg-config-0.20.zip)
-
-libg-2.0 library (prebuilt can be found at: http://ftp.gtk.org/pub/glib/2.12/win32/)
-Don't forget to download dependencies also!
-
-PCRE library (Psyon provides prebuilt: http://www.psyon.org/projects/pcre-win32/index.php)
-
-ZLib (You can get one from http://www.zlib.net/ )
-
-Current build doesn't support this yet, but good to know:
-
-OpenSSL (Shining Light Productions provides nice prebuilt set: http://www.slproweb.com/products/Win32OpenSSL.html)
-
-Install all libraries under same root, for example c:\sys\ - you need to separate PCRE .lib in "lib" dir, includes in "include" dir and
-
-Setting up environment:
-
-After installing you need few environments to setup. I recommend to make following batch files.
-Update paths as propriate:
-
-----------------------------------------------------------------------------------------------------
-
-cmakeenv.bat:
-
-@echo off
-
-set PATH=C:\sys\bin\;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin;%PATH%
-set INCLUDE=C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include;%INCLUDE%
-set LIB=C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib;%LIB%
-set PKG_CONFIG_PATH=c:\sys\lib\pkgconfig
-
- if not exist "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat" goto missing
- echo call "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
- call "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
- goto :eof
-
- :missing
- echo Missing file
- echo "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
- goto :eof
-
-----------------------------------------------------------------------------------------------------
-
-configure.bat:
-
-SET CMAKE_INCLUDE_PATH=c:\sys\include
-SET CMAKE_LIBRARY_PATH=c:\sys\lib
-
-----------------------------------------------------------------------------------------------------
-
-Run from commandline:
-
-cmake -G"NMake Makefiles" .
-
-or run cmakesetup to use GUI...
-
diff --git a/doc/cgi.txt b/doc/cgi.txt
deleted file mode 100644
index 898d57f4..00000000
--- a/doc/cgi.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-===
-CGI
-===
-
----------------
-Module: mod_cgi
----------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The cgi module provides a CGI-conforming interface.
-
-.. meta::
- :keywords: lighttpd, cgi
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-CGI programs allow you to enhance the functionality of the server in a very
-straight and simple way..
-
-Options
-=======
-
-cgi.assign
-
- file-extensions that are handled by a CGI program
-
- e.g.: ::
-
- cgi.assign = ( ".pl" => "/usr/bin/perl",
- ".cgi" => "/usr/bin/perl" )
-
-Examples
-========
-
-To setup a executable which doesn't need the help of a external program you
-just don't specify a handler for the extension. ::
-
- cgi.assign = ( ".sh" => "" )
-
-If the file has no extension keep in mind that lighttpd matches not the
-extension itself but the right part of the URL: ::
-
- cgi.assign = ( "/testfile" => "" )
diff --git a/doc/compress.txt b/doc/compress.txt
deleted file mode 100644
index 14fbc2dc..00000000
--- a/doc/compress.txt
+++ /dev/null
@@ -1,192 +0,0 @@
-==================
-Output Compression
-==================
-
---------------------
-Module: mod_compress
---------------------
-
-
-.. meta::
- :keywords: lighttpd, compress
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Output compression reduces the network load and can improve the overall
-throughput of the webserver. All major http-clients support compression by
-announcing it in the Accept-Encoding header. This is used to negotiate the
-most suitable compression method. We support deflate, gzip and bzip2.
-
-deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2
-depends on libbzip2. bzip2 is only supported by lynx and some other console
-text-browsers.
-
-We currently limit to compression support to static files.
-
-Caching
--------
-
-mod_compress can store compressed files on disk to optimize the compression
-on a second request away. As soon as compress.cache-dir is set the files are
-compressed.
-
-(You will need to create the cache directory if it doesn't already exist. The web server will not do this for you. The directory will also need the proper ownership. For Debian/Ubuntu the user and group ids should both be www-data.)
-
-The names of the cache files are made of the filename, the compression method
-and the etag associated to the file.
-
-Cleaning the cache is left to the user. A cron job deleting files older than
-10 days could do it: ::
-
- find /var/www/cache -type f -mtime +10 | xargs -r rm
-
-Limitations
------------
-
-The module limits the compression of files to files smaller than 128 MByte and
-larger than 128 Byte.
-
-The lower limit is set as small files tend to become larger by compressing due
-to the compression headers, the upper limit is set to work sensibly with
-memory and cpu-time.
-
-Directories containing a tilde ('~') are not created automatically (See ticket
-#113). To enable compression for user dirs you have to create the directories
-by hand in the cache directory.
-
-Options
-=======
-
-compress.allowed-encodings
- override default set of allowed encodings
-
- e.g.: ::
-
- compress.allowed-encodings = ("bzip2", "gzip", "deflate")
-
-compress.cache-dir
- name of the directory where compressed content will be cached
-
- e.g.: ::
-
- compress.cache-dir = "/var/www/cache/"
-
- # even better with virt-hosting
- $HTTP["host"] == "docs.example.org" {
- compress.cache-dir = "/var/www/cache/docs.example.org/"
- }
-
- Default: not set, compress the file for every request
-
-compress.filetype
- mimetypes which might get compressed
-
- e.g.: ::
-
- compress.filetype = ("text/plain", "text/html")
-
- Keep in mind that compressed JavaScript and CSS files are broken in some
- browsers. Not setting any filetypes will result in no files being compressed.
-
- NOTE: You have to specify the full mime-type! If you also define a charset, for example, you have to use "text/plain; charset=utf-8" instead of just "text/plain".
-
- Default: not set
-
-compress.max-filesize
- maximum size of the original file to be compressed kBytes.
-
- This is meant to protect the server against DoSing as compressing large
- (let's say 1Gbyte) takes a lot of time and would delay the whole operation
- of the server.
-
- There is a hard upper limit of 128Mbyte.
-
- Default: unlimited (== hard-limit of 128MByte)
-
-Display compressed files
-========================
-
-If you enable mod_compress, and you want to force clients to uncompress and display compressed text files, please force mimetype to nothing.
-Exemple :
-If you want to add headers for uncompress and display diff.gz files , add this section in your conf : ::
-
- $HTTP["url"] =~ "\.diff\.gz" {
- setenv.add-response-header = ( "Content-Encoding" => "gzip" )
- mimetype.assign = ()
- }
-
-
-Compressing Dynamic Content
-===========================
-
-PHP
----
-
-To compress dynamic content with PHP please enable ::
-
- zlib.output_compression = 1
- zlib.output_handler = On
-
-in the php.ini as PHP provides compression support by itself.
-
-mod_compress of lighttpd 1.5 r1992 may not set correct Content-Encoding with php-fcgi. A solution to that problem would be:
-
-1.disable mod_compress when request a php file::
-
- $HTTP["url"] !~ "\.php$" {
- compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml")
- }
-
-2.enable mod_setenv of your lighttpd::
-
- server.modules += ( "mod_setenv" )
-
-3.manually set Content-Encoding::
-
- $HTTP["url"] =~ "\.php$" {
- setenv.add-response-header = ( "Content-Encoding" => "gzip")
- }
-
-
-TurboGears
-----------
-
-To compress dynamic content with TurboGears please enable ::
-
- [/]
- gzip_filter.on = True
- gzip_filter.mime_types = ["application/x-javascript", "text/javascript", "text/html", "text/css", "text/plain"]
-
-in the config/app.cfg file in your TurboGears application. The above lines should already be in the file. You just need to remove the comment symbol in front of the lines to make them active.
-
-Django
-------
-
-To compress dynamic content with Django please enable the GZipMiddleware ::
-
- MIDDLEWARE_CLASSES = (
- 'django.middleware.gzip.GZipMiddleware',
- ...
- )
-
-in the settings.py file in your Django project.
-
-Catalyst
---------
-
-To compress dynamic content with Perl/Catalyst, simply use the Catalyst::Plugin::Compress::Gzip module available on CPAN ::
-
- use Catalyst qw(
- Compress::Gzip
- ...
- );
-
-in your main package (MyApp.pm). Further configuration is not required.
-
-}}}
-
-
-
diff --git a/doc/configuration.txt b/doc/configuration.txt
deleted file mode 100644
index e03e32ea..00000000
--- a/doc/configuration.txt
+++ /dev/null
@@ -1,520 +0,0 @@
-==================
-Configuration File
-==================
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date$
-:Revision: $Revision$
-
-:abstract:
- the layout of the configuration file
-
-.. meta::
- :keywords: lighttpd, configuration
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Basic Syntax
-------------
-
-A BNF like notation: ::
-
- option : NAME = VALUE
- merge : NAME += VALUE
- NAME : modulename.key
- VALUE : ( <string> | <integer> | <boolean> | <array> | VALUE [ + VALUE ]*)
- <string> : "text"
- <integer>: digit*
- <boolean>: ( "enable" | "disable" )
- <array> : "(" [ <string> "=>" ] <value> [, [ <string> "=>" ] <value> ]* ")"
- INCLUDE : "include" VALUE
- INCLUDE_SHELL : "include_shell" STRING_VALUE
-
-Example
--------
-
-::
-
- # default document-root
- server.document-root = "/var/www/example.org/pages/"
-
- # TCP port
- server.port = 80
-
- # selecting modules
- server.modules = ( "mod_access", "mod_rewrite" )
-
- # variables, computed when config is read.
- var.mymodule = "foo"
- server.modules += ( "mod_" + var.mymodule )
- # var.PID is initialised to the pid of lighttpd before config is parsed
-
- # include, relative to dirname of main config file
- include "mime.types.conf"
-
- # read configuration from output of a command
- include_shell "/usr/local/bin/confmimetype /etc/mime.types"
-
-
-Conditional Configuration
-=========================
-
-Most options can be configured conditionally by using the following syntax
-(including nesting).
-
-::
-
- <field> <operator> <value> {
- ...
- <field> <operator> <value> {
- ... nesting: match only when parent match
- }
- }
- else <field> <operator> <value> {
- ... the "else if" block
- }
-
-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"]
- match on useragent
-$HTTP["referer"]
- match on referer
-$HTTP["url"]
- match on url
-$HTTP["remoteip"]
- match on the remote IP or a remote Network
-$SERVER["socket"]
- match on socket. Value must be on the format "ip:port" where ip is an IP
- address and port a port number. Only equal match (==) is supported.
- It also binds the daemon to this socket. Use this if you want to do IP/port-
- based virtual hosts.
-
-<operator> is one of:
-
-==
- string equal match
-!=
- string not equal match
-=~
- perl style regular expression match
-!~
- perl style regular expression not match
-
-and <value> is either a quoted ("") literal string or regular expression.
-
-
-Example
--------
-
-::
-
- # disable directory-listings for /download/*
- dir-listing.activate = "enable"
- $HTTP["url"] =~ "^/download/" {
- dir-listing.activate = "disable"
- }
-
- # handish virtual hosting
- # map all domains of a top-level-domain to a single document-root
- $HTTP["host"] =~ "(^|\.)example\.org$" {
- server.document-root = "/var/www/htdocs/example.org/pages/"
- }
-
- # multiple sockets
- $SERVER["socket"] == "127.0.0.1:81" {
- server.document-root = "..."
- }
-
- $SERVER["socket"] == "127.0.0.1:443" {
- ssl.pemfile = "/var/www/certs/localhost.pem"
- ssl.engine = "enable"
-
- server.document-root = "/var/www/htdocs/secure.example.org/pages/"
- }
-
- # deny access for all googlebot
- $HTTP["useragent"] =~ "Google" {
- url.access-deny = ( "" )
- }
-
- # deny access for all image stealers
- $HTTP["referer"] !~ "^($|http://www\.example\.org)" {
- url.access-deny = ( ".jpg", ".jpeg", ".png" )
- }
-
- # deny the access to www.example.org to all user which
- # are not in the 10.0.0.0/8 network
- $HTTP["host"] == "www.example.org" {
- $HTTP["remoteip"] != "10.0.0.0/8" {
- url.access-deny = ( "" )
- }
- }
-
-Using variables
-===============
-
-You can set your own variables in the configuration to simplify your config.
-::
-
- var.basedir = "/home/www/servers/"
- $HTTP["host"] == "www.example.org" {
- server.name = "www.example.org"
- include "incl-base.conf"
- }
-
- in incl-base.conf:
- server.document-root = basedir + server.name + "/pages/"
- accesslog.filename = basedir + server.name + "/logs/access.log"
-
-You can also use environement variables or the default variables var.PID and
-var.CWD: ::
-
- var.basedir = env.LIGHTTPDBASE
-
- $HTTP["host"] == "www.example.org" {
- server.name = "www.example.org"
- include "incl-base.conf"
- include "incl-fastcgi.conf"
- }
-
- in incl-fastcgi.conf:
- fastcgi.server = ( ... => ((
- "socket" => basedir + server.name + "/tmp/fastcgi-" + PID + ".sock"
- )) )
-
-Or like the lighttpd script for rails does:
-
- var.basedir = var.CWD
-
- server.document-root = basedir + "/public/"
-
-Global context
-==============
-
-::
-
- global {
- ...
- }
-
-You don't need it in the main configuration file. But you might have
-difficulty setting server wide configuration inside a included-file from
-conditionals.
-
-Example
--------
-
-::
-
- in lighttpd.conf:
- server.modules = ()
- $HTTP["host"] == "www.example.org" {
- include "incl-php.conf"
- }
-
- in incl-php.conf:
- global {
- server.modules += ("mod_fastcgi")
- static-file.exclude-extensions += (".php")
- }
- fastcgi.server = "..."
-
-Options
-=======
-
-server module
--------------
-
-main sections
-`````````````
-
-server.document-root
- document-root of the webserver
-
- This variable has the specified as it will be used for all requests
- without a Host: header and for all with a know hostname which you
- might have specified with one of the above conditionals.
-
- Default: no default, required
-
-server.bind
- IP address, hostname or absolute path to the unix-domain socket the server
- listen on.
-
- Default: bind to all interfaces
-
- Example: ::
-
- server.bind = "127.0.0.1"
- server.bind = "www.example.org"
- server.bind = "/tmp/lighttpd.socket"
-
-server.port
- tcp-port to bind the server to
-
-.. note:: port belows 1024 require root-permissions
-
- Default: 80 (443 if ssl is enabled)
-
-server.use-ipv6
- bind to the IPv6 socket
-
-server.tag
- set the string returned by the Server: response header
-
- Default: lighttpd <current-version>
-
-server.errorlog
- pathname of the error-log
-
- Default: either STDERR or ``server.errorlog-use-syslog``
-
-server.errorlog-use-syslog
- send errorlog to syslog
-
- Default: disabled
-
-server.chroot
- root-directory of the server
-
- NOTE: requires root-permissions
-
-server.username
- username used to run the server
-
- NOTE: requires root-permissions
-
-server.groupname
- groupname used to run the server
-
- NOTE: requires root-permissions
-
-server.follow-symlink
- allow to follow-symlinks
-
- Default: enabled
-
-index-file.names
- list of files to search for if a directory is requested
- e.g.: ::
-
- index-file.names = ( "index.php", "index.html",
- "index.htm", "default.htm" )
-
- if a name starts with slash this file will be used a index generator
- for all directories.
-
-server.modules
- modules to load
-
-.. note:: the order of the modules is important.
-
- The modules are executed in the order as they are specified. Loading
- mod_auth AFTER mod_fastcgi might disable authentication for fastcgi
- backends (if check-local is disabled).
-
- As auth should be done first, move it before all executing modules (like
- proxy, fastcgi, scgi and cgi).
-
- rewrites, redirects and access should be first, followed by auth and
- the docroot plugins.
-
- Afterwards the external handlers like fastcgi, cgi, scgi and proxy and
- at the bottom the post-processing plugins like mod_accesslog.
-
- e.g.: ::
-
- server.modules = ( "mod_rewrite",
- "mod_redirect",
- "mod_alias",
- "mod_access",
- "mod_auth",
- "mod_status",
- "mod_simple_vhost",
- "mod_evhost",
- "mod_userdir",
- "mod_secdownload",
- "mod_cgi",
- "mod_ssi",
- "mod_compress",
- "mod_usertrack",
- "mod_expire",
- "mod_rrdtool",
- "mod_accesslog" )
-
- Starting with lighttpd 1.4.0 three default modules are loaded automaticly:
-
- - mod_indexfile
- - mod_dirlisting
- - mod_staticfile
-
-server.event-handler
- set the event handler
-
- Default: "poll"
-
-server.pid-file
- set the name of the .pid-file where the PID of the server should be placed.
- This option is used in combination with a start-script and the daemon mode
-
- Default: not set
-
-server.max-request-size
- maximum size in kbytes of the request (header + body). Only applies to POST
- requests.
-
- Default: 2097152 (2GB)
-
-server.max-worker
- number of worker processes to spawn. This is usually only needed on servers
- which are fairly loaded and the network handler calls delay often (e.g. new
- requests are not handled instantaneously).
-
- Default: 0
-
-server.name
- name of the server/virtual server
-
- Default: hostname
-
-server.max-keep-alive-requests
- maximum number of request within a keep-alive session before the server
- terminates the connection
-
- Default: 128
-
-server.max-keep-alive-idle
- maximum number of seconds until a idling keep-alive connection is droped
-
- Default: 30
-
-server.max-read-idle
- maximum number of seconds until a waiting, non keep-alive read times out
- and closes the connection
-
- Default: 60
-
-server.max-write-idle
- maximum number of seconds until a waiting write call times out and closes
- the connection
-
- Default: 360
-
-server.error-handler-404
- uri to call if the requested file results in a 404
-
- Default: not set
-
- Example: ::
-
- server.error-handler-404 = "/error-404.php"
-
-server.protocol-http11
- defines if HTTP/1.1 is allowed or not.
-
- Default: enabled
-
-server.range-requests
- defines if range requests are allowed or not.
-
- Default: enabled
-
-
-SSL engine
-``````````
-
-ssl.pemfile
- path to the PEM file for SSL support
-
-debugging
-`````````
-
-debug.dump-unknown-headers
- enables listing of internally unhandled HTTP-headers
-
- e.g. ::
-
- debug.dump-unknown-headers = "enable"
-
-mimetypes
-`````````
-
-mimetype.assign
- list of known mimetype mappings
- NOTE: if no mapping is given "application/octet-stream" is used
-
- e.g.: ::
-
- mimetype.assign = ( ".png" => "image/png",
- ".jpg" => "image/jpeg",
- ".jpeg" => "image/jpeg",
- ".html" => "text/html",
- ".txt" => "text/plain" )
-
- The list is compared top down and the first match is taken. This is
- important if you have matches like: ::
-
- ".tar.gz" => "application/x-tgz",
- ".gz" => "application/x-gzip",
-
- If you want to set another default mimetype use: ::
-
- ...,
- "" => "text/plain" )
-
- as the last entry in the list.
-
-mimetype.use-xattr
- If available, use the XFS-style extended attribute interface to
- retrieve the "Content-Type" attribute on each file, and use that as the
- mime type. If it's not defined or not available, fall back to the
- mimetype.assign assignment.
-
- e.g.: ::
-
- mimetype.use-xattr = "enable"
-
- on shell use:
-
- $ attr -s Content-Type -V image/svg svgfile.svg
-
- or
-
- $ attr -s Content-Type -V text/html indexfile
-
-
-debugging
-`````````
-
-debug.log-request-header
- default: disabled
-
-debug.log-response-header
- default: disabled
-
-debug.log-file-not-found
- default: disabled
-
-debug.log-request-handling
- default: disabled
-
-debug.log-condition-handling
- default: disabled
-
-debug.log-condition-cache-handling
- for developers only
- default: disabled
diff --git a/doc/dirlisting.txt b/doc/dirlisting.txt
deleted file mode 100644
index ea65ba6f..00000000
--- a/doc/dirlisting.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-==================
-Directory Listings
-==================
-
-----------------------
-Module: mod_dirlisting
-----------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2004/11/03 22:26:05 $
-:Revision: $Revision: 1.2 $
-
-:abstract:
- mod_dirlisting generates HTML based directory listings with full CSS
- control
-
-.. meta::
- :keywords: lighttpd, directory listings, dirlisting
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-mod_dirlisting is one of the modules which is loaded by default and don't have to
-be specified on server.modules to work.
-
-A directory listing is generated if a directory is requested and no index-file
-was found in that directory.
-
-To enable directory listings globally: ::
-
- dir-listing.activate = "enable"
-
-If you need it only for a directory, use conditionals: ::
-
- $HTTP["url"] =~ "^/download($|/)" {
- dir-listing.activate = "enable"
- }
-
-You can also use a external generator for directory listings if you use
-mod_indexfile. ::
-
- index-file.names = ( "/dir-generator.php" )
-
-If a directory is requested the dir-generator.php is called instead which can
-take the REQUEST_URI to see which directory was requested.
-
-For large folders this is highly recommend.
-
-Options
-=======
-
-dir-listing.activate
- enables virtual directory listings if a directory is requested no
- index-file was found
-
- Default: disabled
-
-dir-listing.hide-dotfiles
- if enabled, does not list hidden files in directory listings generated
- by the dir-listing option.
-
- Default: enabled
-
-dir-listing.external-css
- path to an external css stylesheet for the directory listing
-
-dir-listing.exclude
- list of regular expressions. Files that match any of the specified regular
- expressions will be excluded from directory listings.
-
-dir-listing.encoding
- set a encoding for the generated directory listing
-
- If you file-system is not using ASCII you have to set the encoding of
- the filenames as they are put into the HTML listing AS IS (with XML
- encoding)
-
- Example: ::
-
- dir-listing.encoding = "utf-8"
diff --git a/doc/evhost.txt b/doc/evhost.txt
deleted file mode 100644
index f44bd932..00000000
--- a/doc/evhost.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-========================
-Enhanced Virtual-Hosting
-========================
-
-------------------
-Module: mod_evhost
-------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2004/08/29 09:43:49 $
-:Revision: $Revision: 1.1 $
-
-:abstract:
- virtual hosting
-
-.. meta::
- :keywords: lighttpd, virtual hosting
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-mod_evhost builds the document-root based on a pattern which contains
-wildcards. Those wildcards can represent parts if the submitted hostname
-
-
-::
-
- %% => % sign
- %0 => domain name + tld
- %1 => tld
- %2 => domain name without tld
- %3 => subdomain 1 name
- %4 => subdomain 2 name
- %_ => the complete hostname (without port info)
-
- evhost.path-pattern = "/home/www/servers/%3/pages/"
-
-Options
-=======
-
-evhost.path-pattern
- pattern with wildcards to be replace to build a documentroot
-
-
diff --git a/doc/expire.txt b/doc/expire.txt
deleted file mode 100644
index 2aee9381..00000000
--- a/doc/expire.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-===============================================
-Controlling the Expiration of Content in Caches
-===============================================
-
-------------------
-Module: mod_expire
-------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2004/11/03 22:26:05 $
-:Revision: $Revision: 1.2 $
-
-:abstract:
- mod_expire controls the setting of the the Expire Response header
-
-.. meta::
- :keywords: lighttpd, expire
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-mod_expire controls the Expire header in the Response Header of HTTP/1.0
-messages. It is usefull to set it for static files which should be cached
-aggressivly like images, stylesheets or similar.
-
-Options
-=======
-
-expire.url
- assignes a expiration to all files below the specified path. The
- specification of the time is made up of: ::
-
- <access|modification> <number> <years|months|days|hours|minutes|seconds>
-
- following the syntax used by mod_expire in Apache 1.3.x and later.
-
- Example: ::
-
- expire.url = ( "/images/" => "access 1 hour" )
-
diff --git a/doc/features.txt b/doc/features.txt
deleted file mode 100644
index cfccbb11..00000000
--- a/doc/features.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-===============
-progress report
-===============
-
-:Author: Jan Kneschke
-:Date: $Date: 2004/11/03 22:26:05 $
-:Revision: $Revision: 1.2 $
-
-:abstract:
- This document tries to track the requested features and
- the release when they have been implemented.
-
-.. meta::
- :keywords: lighttpd, features
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-The document was inspired by a mail from David Phillips:
-
-http://marc.theaimsgroup.com/?l=thttpd&m=108051453226692&w=2
-
-It is used to see what is still missing and what is already done. ::
-
- zell@zell.best.vwh.net writes:
- > Now that the author has made the source code available, I am
- > considering installing and testing the latest version. From a
- > quick glance, it seems to support most/all of the features of
- > Premium thttpd and Zeus.
-
- If you think it compares to Zeus, then you've obviously never used Zeus.
-
- lighttpd is currently the only non-blocking open source web server to
- support FastCGI responders and that's worthwhile.
-
- The documentation is lacking. Comments in the configuration file do not
- make up for a complete manual.
-
-Constantly improving. ::
-
- The configuration syntax is overly complex, like Apache. There is no .htaccess
- support.
-
-.htaccess support is not planed yet. ::
-
- There is only one server. You cannot have a separate configuration for each
- virtual server. This would seem to be especially problematic when doing
- SSL.
-
-Works since 1.3.0. ::
-
- There is no SSI support. Zeus has full recursive SSI support. Output from
- a FastCGI program can get run through the SSI interpreter. SSI can also do
- virtual includes recursively.
-
-SSI works since 1.2.4. ::
-
- Request logging is not configurable. Zeus supports fully configurable
- access logging, plus a binary version of CLF that save space.
-
-1.2.6 adds Apache-like logfile config. ::
-
- Access control only allows authentication via username and password. There
- is no way to allow or deny based in IP address.
-
-planed for 1.3.x ::
-
- The request rewriting appears to only allow regex substitutions. Zeus has a
- simple, yet powerful, request rewrite language.
-
-
-
- There is no support for FastCGI authorizers. These are very useful for high
- traffic sites that require complex authentication schemes or that store
- authorization information in a central database.
-
-since 1.1.9. ::
-
- There is no bandwidth throttling support. Zeus does bandwidth throttling
- correctly (i.e. unlike past versions of thttpd) and can throttle on a
- per-subserver (thttpd-style virtual hosts) basis.
-
-since 1.3.8. ::
-
- There is no ISAPI support. ISAPI is an elegant, open API that allows
- modification of web server behavior. While it isn't strictly necessary for
- an open source web server, it nice to have a documented, consistent API,
- rather than having to manually patch the server.
-
-If someone requests it it might be implemented. ::
-
- There is no web based interface. Zeus has a complete web based interface
- for everything, including a powerful feature of configuring multiple virtual
- servers at once.
-
-That is something that should be a special feature of Zeus. :) ::
-
- There is no support for mapping certain URLs to specific filesystem paths.
-
-since 1.2.6 ::
-
- There is no referring checking. This is incredibly important to prevent
- hotlinking of bandwidth intensive media types (images, movies, etc.).
-
-we have something better: mod_secdownload. And if someone wants referer
-checking we have a condition in the config for it since 1.2.9 ::
-
- Zeus has a lot of features that lighttpd doesn't have, but I only mentioned
- the ones I care about and use.
-
- --
- David Phillips <david@acz.org>
- http://david.acz.org/
-
diff --git a/doc/lighttpd.8 b/doc/lighttpd.8
deleted file mode 100644
index 80ad5c95..00000000
--- a/doc/lighttpd.8
+++ /dev/null
@@ -1,74 +0,0 @@
-.TH LIGHTTPD "8" "2009-03-07" "" ""
-.
-.SH NAME
-lighttpd \- a fast, secure and flexible web server
-.
-.SH SYNOPSIS
-\fBlighttpd\fP [\fB\-ptDIvVh\fP] \fB\-f\fP \fIconfigfile\fP [\fB\-m\fP \fImoduledir\fP]
-.
-.SH DESCRIPTION
-\fBlighttpd\fP (pronounced 'lighty') is an advanced HTTP daemon that aims
-to be secure, fast, compliant and very flexible. It has been optimized for
-high performance. Its feature set includes, but is not limited to, FastCGI,
-CGI, basic and digest HTTP authentication, output compression, URL rewriting.
-.PP
-This manual page only lists the command line arguments. For details
-on how to configure \fBlighttpd\fP and its modules see the files in the
-doc-directory.
-.
-.SH OPTIONS
-The following options are supported:
-.TP 8
-\fB\-f\ \fP \fIconfigfile\fP
-Load configuration file \fIconfigfile\fP.
-.TP 8
-\fB\-m\ \fP \fImoduledir\fP
-Use
-\fImoduledir\fP
-as the directory that contains modules, instead of the default.
-.TP 8
-\fB\-p\fP
-Print the parsed configuration file in its internal form and exit.
-.TP 8
-\fB\-t\fP
-Test the configuration file for syntax errors and exit.
-.TP 8
-\fB\-D\fP
-Do not daemonize (go into background). The default is to daemonize.
-.TP 8
-\fB\-I\fP
-Go to background on SIGINT (useful with -D).
-Has no effect when using kqueue or /dev/poll.
-.TP 8
-\fB\-v\fP
-Show version and exit.
-.TP 8
-\fB\-V\fP
-Show compile-time features and exit.
-.TP 8
-\fB\-h\fP
-Show a brief help message and exit.
-.
-.SH FILES
-.TP 8
-/etc/lighttpd/lighttpd.conf
-The standard location for the configuration file.
-.TP 8
-/var/run/lighttpd.pid
-The standard location for the PID of the running \fBlighttpd\fP process.
-.
-.SH SEE ALSO
-Online Documentation: http://wiki.lighttpd.net/
-.PP
-spawn-fcgi(1)
-.PP
-\fIHypertext Transfer Protocol -- HTTP/1.1\fP, RFC 2616.
-.PP
-\fIHTTP Authentication: Basic and Digest Access Authentication\fP, RFC 2617.
-.PP
-\fIThe Common Gateway Interface Version 1.1\fP, RFC 3875.
-.PP
-\fIThe FastCGI specification\fP.
-.
-.SH AUTHOR
-Jan Kneschke <jan@kneschke.de>
diff --git a/doc/lighttpd.conf b/doc/lighttpd.conf
deleted file mode 100644
index c3348936..00000000
--- a/doc/lighttpd.conf
+++ /dev/null
@@ -1,310 +0,0 @@
-# lighttpd configuration file
-#
-# use it as a base for lighttpd 1.0.0 and above
-#
-# $Id: lighttpd.conf,v 1.7 2004/11/03 22:26:05 weigon Exp $
-
-############ Options you really have to take care of ####################
-
-## modules to load
-# at least mod_access and mod_accesslog should be loaded
-# all other module should only be loaded if really neccesary
-# - saves some time
-# - saves memory
-server.modules = (
-# "mod_rewrite",
-# "mod_redirect",
-# "mod_alias",
- "mod_access",
-# "mod_trigger_b4_dl",
-# "mod_auth",
-# "mod_status",
-# "mod_setenv",
-# "mod_proxy_core",
-# "mod_proxy_backend_http",
-# "mod_proxy_backend_fastcgi",
-# "mod_proxy_backend_scgi",
-# "mod_proxy_backend_ajp13",
-# "mod_simple_vhost",
-# "mod_evhost",
-# "mod_userdir",
-# "mod_cgi",
-# "mod_compress",
-# "mod_ssi",
-# "mod_usertrack",
-# "mod_expire",
-# "mod_secdownload",
-# "mod_rrdtool",
- "mod_accesslog" )
-
-## A static document-root. For virtual hosting take a look at the
-## mod_simple_vhost module.
-server.document-root = "/www/pages/"
-
-## where to send error-messages to
-server.errorlog = "/www/logs/lighttpd.error.log"
-
-# files to check for if .../ is requested
-index-file.names = ( "index.php", "index.html",
- "index.htm", "default.htm" )
-
-## set the event-handler (read the performance section in the manual)
-# server.event-handler = "freebsd-kqueue" # needed on OS X
-
-# mimetype mapping
-mimetype.assign = (
- ".pdf" => "application/pdf",
- ".sig" => "application/pgp-signature",
- ".spl" => "application/futuresplash",
- ".class" => "application/octet-stream",
- ".ps" => "application/postscript",
- ".torrent" => "application/x-bittorrent",
- ".dvi" => "application/x-dvi",
- ".gz" => "application/x-gzip",
- ".pac" => "application/x-ns-proxy-autoconfig",
- ".swf" => "application/x-shockwave-flash",
- ".tar.gz" => "application/x-tgz",
- ".tgz" => "application/x-tgz",
- ".tar" => "application/x-tar",
- ".zip" => "application/zip",
- ".mp3" => "audio/mpeg",
- ".m3u" => "audio/x-mpegurl",
- ".wma" => "audio/x-ms-wma",
- ".wax" => "audio/x-ms-wax",
- ".ogg" => "application/ogg",
- ".wav" => "audio/x-wav",
- ".gif" => "image/gif",
- ".jar" => "application/x-java-archive",
- ".jpg" => "image/jpeg",
- ".jpeg" => "image/jpeg",
- ".png" => "image/png",
- ".xbm" => "image/x-xbitmap",
- ".xpm" => "image/x-xpixmap",
- ".xwd" => "image/x-xwindowdump",
- ".css" => "text/css",
- ".html" => "text/html",
- ".htm" => "text/html",
- ".js" => "text/javascript",
- ".asc" => "text/plain",
- ".c" => "text/plain",
- ".cpp" => "text/plain",
- ".log" => "text/plain",
- ".conf" => "text/plain",
- ".text" => "text/plain",
- ".txt" => "text/plain",
- ".dtd" => "text/xml",
- ".xml" => "text/xml",
- ".mpeg" => "video/mpeg",
- ".mpg" => "video/mpeg",
- ".mov" => "video/quicktime",
- ".qt" => "video/quicktime",
- ".avi" => "video/x-msvideo",
- ".asf" => "video/x-ms-asf",
- ".asx" => "video/x-ms-asf",
- ".wmv" => "video/x-ms-wmv",
- ".bz2" => "application/x-bzip",
- ".tbz" => "application/x-bzip-compressed-tar",
- ".tar.bz2" => "application/x-bzip-compressed-tar"
- )
-
-# Use the "Content-Type" extended attribute to obtain mime type if possible
-#mimetype.use-xattr = "enable"
-
-
-## send a different Server: header
-## be nice and keep it at lighttpd
-# server.tag = "lighttpd"
-
-#### accesslog module
-accesslog.filename = "/www/logs/access.log"
-
-## deny access the file-extensions
-#
-# ~ is for backupfiles from vi, emacs, joe, ...
-# .inc is often used for code includes which should in general not be part
-# of the document-root
-url.access-deny = ( "~", ".inc" )
-
-$HTTP["url"] =~ "\.pdf$" {
- server.range-requests = "disable"
-}
-
-##
-# which extensions should not be handle via static-file transfer
-#
-# .php, .pl, .fcgi are most often handled by mod_proxy_core or mod_cgi
-static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
-
-######### Options that are good to be but not neccesary to be changed #######
-
-## bind to port (default: 80)
-#server.port = 81
-
-## bind to localhost (default: all interfaces)
-#server.bind = "grisu.home.kneschke.de"
-
-## error-handler for status 404
-#server.error-handler-404 = "/error-handler.html"
-#server.error-handler-404 = "/error-handler.php"
-
-## to help the rc.scripts
-#server.pid-file = "/var/run/lighttpd.pid"
-
-
-###### virtual hosts
-##
-## If you want name-based virtual hosting add the next three settings and load
-## mod_simple_vhost
-##
-## document-root =
-## virtual-server-root + virtual-server-default-host + virtual-server-docroot
-## or
-## virtual-server-root + http-host + virtual-server-docroot
-##
-#simple-vhost.server-root = "/home/weigon/wwwroot/servers/"
-#simple-vhost.default-host = "grisu.home.kneschke.de"
-#simple-vhost.document-root = "/pages/"
-
-
-##
-## Format: <errorfile-prefix><status-code>.html
-## -> ..../status-404.html for 'File not found'
-#server.errorfile-prefix = "/home/weigon/projects/lighttpd/doc/status-"
-
-## virtual directory listings
-#dir-listing.activate = "enable"
-
-## enable debugging
-#debug.log-request-header = "enable"
-#debug.log-response-header = "enable"
-#debug.log-request-handling = "enable"
-#debug.log-file-not-found = "enable"
-#debug.log-condition-handling = "enable"
-
-### only root can use these options
-#
-# chroot() to directory (default: no chroot() )
-#server.chroot = "/"
-
-## change uid to <uid> (default: don't care)
-#server.username = "wwwrun"
-
-## change uid to <uid> (default: don't care)
-#server.groupname = "wwwrun"
-
-#### compress module
-#compress.cache-dir = "/tmp/lighttpd/cache/compress/"
-#compress.filetype = ("text/plain", "text/html")
-
-#### mod-proxy-core module
-## read mod-proxy-core.txt for more info
-## for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
-#$PHYSICAL["existing-path"] =~ "\.php$" {
-# proxy-core.balancer = "round-robin"
-# proxy-core.allow-x-sendfile = "enable"
-# proxy-core.protocol = "fastcgi"
-# proxy-core.backends = ( "unix:/tmp/php-fastcgi.sock" )
-# proxy-core.max-pool-size = 16
-#}
-
-
-#### CGI module
-#cgi.assign = ( ".pl" => "/usr/bin/perl",
-# ".cgi" => "/usr/bin/perl" )
-#
-
-#### SSL engine
-#ssl.engine = "enable"
-#ssl.pemfile = "server.pem"
-
-#### status module
-#status.status-url = "/server-status"
-#status.config-url = "/server-config"
-
-#### auth module
-## read authentication.txt for more info
-#auth.backend = "plain"
-#auth.backend.plain.userfile = "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" => "user=jan"
-# ),
-# "/server-config" =>
-# (
-# "method" => "digest",
-# "realm" => "download archiv",
-# "require" => "valid-user"
-# )
-# )
-
-#### url handling modules (rewrite, redirect, access)
-#url.rewrite = ( "^/$" => "/server-status" )
-#url.redirect = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
-#### both rewrite/redirect support back reference to regex conditional using %n
-#$HTTP["host"] =~ "^www\.(.*)" {
-# url.redirect = ( "^/(.*)" => "http://%1/$1" )
-#}
-
-#
-# define a pattern for the host url finding
-# %% => % sign
-# %0 => domain name + tld
-# %1 => tld
-# %2 => domain name without tld
-# %3 => subdomain 1 name
-# %4 => subdomain 2 name
-#
-#evhost.path-pattern = "/home/storage/dev/www/%3/htdocs/"
-
-#### expire module
-#expire.url = ( "/buggy/" => "access 2 hours", "/asdhas/" => "access plus 1 seconds 2 minutes")
-
-#### ssi
-#ssi.extension = ( ".shtml" )
-
-#### rrdtool
-#rrdtool.binary = "/usr/bin/rrdtool"
-#rrdtool.db-name = "/var/www/lighttpd.rrd"
-
-#### setenv
-#setenv.add-request-header = ( "TRAV_ENV" => "mysql://user@host/db" )
-#setenv.add-response-header = ( "X-Secret-Message" => "42" )
-
-## for mod_trigger_b4_dl
-# trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
-# trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
-# trigger-before-download.trigger-url = "^/trigger/"
-# trigger-before-download.download-url = "^/download/"
-# trigger-before-download.deny-url = "http://127.0.0.1/index.html"
-# trigger-before-download.trigger-timeout = 10
-
-#### variable usage:
-## variable name without "." is auto prefixed by "var." and becomes "var.bar"
-#bar = 1
-#var.mystring = "foo"
-
-## integer add
-#bar += 1
-## string concat, with integer cast as string, result: "www.foo1.com"
-#server.name = "www." + mystring + var.bar + ".com"
-## array merge
-#index-file.names = (foo + ".php") + index-file.names
-#index-file.names += (foo + ".php")
-
-#### include
-#include /etc/lighttpd/lighttpd-inc.conf
-## same as above if you run: "lighttpd -f /etc/lighttpd/lighttpd.conf"
-#include "lighttpd-inc.conf"
-
-#### include_shell
-#include_shell "echo var.a=1"
-## the above is same as:
-#var.a=1
diff --git a/doc/lighttpd.user b/doc/lighttpd.user
deleted file mode 100644
index 727e9c33..00000000
--- a/doc/lighttpd.user
+++ /dev/null
@@ -1 +0,0 @@
-dummy:test123
diff --git a/doc/newstyle.css b/doc/newstyle.css
deleted file mode 100644
index 26f91d37..00000000
--- a/doc/newstyle.css
+++ /dev/null
@@ -1,49 +0,0 @@
-body {
- background-color: #F5F5F5;
-}
-a, a:active {
- text-decoration: none;
- color: blue;
-}
-a:visited {
- color: #48468F;
-}
-a:hover, a:focus {
- text-decoration: underline;
- color: red;
-}
-h2 {
- margin-bottom: 12px;
-}
-table {
- margin-left: 12px;
-}
-th, td {
- font-family: "Courier New", Courier, monospace;
- font-size: 10pt;
- text-align: left;
-}
-th {
- font-weight: bold;
- padding-right: 14px;
- padding-bottom: 3px;
-}
-td {
- padding-right: 14px;
-}
-td.s, th.s {
- text-align: right;
-}
-div.list {
- background-color: white;
- border-top: 1px solid #646464;
- border-bottom: 1px solid #646464;
- padding-top: 10px;
- padding-bottom: 14px;
-}
-div.foot {
- font-family: "Courier New", Courier, monospace;
- font-size: 10pt;
- color: #787878;
- padding-top: 4px;
-}
diff --git a/doc/oldstyle.css b/doc/oldstyle.css
deleted file mode 100644
index f3e26db3..00000000
--- a/doc/oldstyle.css
+++ /dev/null
@@ -1,25 +0,0 @@
-table {
- border: 1px solid black;
- padding: 1px;
-}
-th {
- background-color: black;
- border: 1px solid white;
- color: white;
- padding-right: 2px;
- padding-left: 2px;
-}
-td {
- background-color: #f0f0f0;
- border: 1px solid white;
- padding-right: 2px;
- padding-left: 2px;
-}
-td.s {
- background-color: #f0f0f0;
- text-align: right;
- padding-left: 14px;
-}
-div.foot {
- margin-top: 4px;
-}
diff --git a/doc/performance.txt b/doc/performance.txt
deleted file mode 100644
index c3e46f56..00000000
--- a/doc/performance.txt
+++ /dev/null
@@ -1,241 +0,0 @@
-========================
-Performance Improvements
-========================
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- handling performance issues in lighttpd
-
-.. meta::
- :keywords: lighttpd, performance
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Performance Issues
-------------------
-
-lighttpd is optimized into varying directions. The most important direction is
-performance. The operation system has two major facilities to help lighttpd
-a deliver its best performance.
-
-HTTP Keep-Alive
----------------
-
-Disabling keep-alive might help your server if you suffer from a large
-number of open file descriptors.
-
-The defaults for the server are: ::
-
- server.max-keep-alive-requests = 128
- server.max-keep-alive-idle = 30
- server.max-read-idle = 60
- server.max-write-idle = 360
-
-handling 128 keep-alive requests in a row on a single connection, waiting 30 seconds
-before an unused keep-alive connection gets dropped by lighttpd.
-
-If you handle several connections at once under a high load (let's assume 500 connections
-in parallel for 24h) you might run into the out-of-fd problem described below. ::
-
- server.max-keep-alive-requests = 4
- server.max-keep-alive-idle = 4
-
-would release the connections earlier and would free file descriptors without a
-detrimental performance loss.
-
-Disabling keep-alive completely is the last resort if you are still short on file descriptors: ::
-
- server.max-keep-alive-requests = 0
-
-Event Handlers
---------------
-
-The first one is the Event Handler which takes care of notifying the server
-that one of the connections is ready to send or receive. As you can see,
-every OS has at least the select() call which has some limitations.
-
-============ ========== ===============
-OS Method Config Value
-============ ========== ===============
-all select select
-Unix poll poll
-Linux 2.4+ rt-signals linux-rtsig
-Linux 2.6+ epoll linux-sysepoll
-Solaris /dev/poll solaris-devpoll
-FreeBSD, ... kqueue freebsd-kqueue
-============ ========== ===============
-
-
-For more information on this topic take a look at http://www.kegel.com/c10k.html
-
-Configuration
-`````````````
-
-The event handler can be set by specifying the 'Config Value' from above
-in the ``server.event-handler`` variable
-
-e.g.: ::
-
- server.event-handler = "linux-sysepoll"
-
-Network Handlers
-----------------
-
-The basic network interface for all platforms at the syscalls read() and
-write(). Every modern OS provides its own syscall to help network servers
-transfer files as fast as possible.
-
-If you want to send out a file from the webserver, it doesn't make any sense
-to copy the file into the webserver just to write() it back into a socket
-in the next step.
-
-sendfile() minimizes the work in the application and pushes a file directly
-into the network card (ideally).
-
-lighttpd supports all major platform-specific calls:
-
-========== ==========
-OS Method
-========== ==========
-all write
-Unix writev
-Linux 2.4+ sendfile
-Linux 2.6+ sendfile64
-Solaris sendfilev
-FreeBSD sendfile
-========== ==========
-
-The best backend is selected at compile time. In case you want to use
-another backend set: ::
-
- server.network-backend = "writev"
-
-You can find more information about network backend in:
-
- http://blog.lighttpd.net/articles/2005/11/11/optimizing-lighty-for-high-concurrent-large-file-downloads
-
-
-Max Connections
----------------
-
-As lighttpd is a single-threaded server, its main resource limit is the
-number of file descriptors, which is set to 1024 by default (on most systems).
-
-If you are running a high-traffic site you might want to increase this limit
-by setting ::
-
- server.max-fds = 2048
-
-This only works if lighttpd is started as root.
-
-Out-of-fd condition
--------------------
-
-Since file descriptors are used for TCP/IP sockets, files and directories,
-a simple request for a PHP page might result in using 3 file descriptors:
-
-1. the TCP/IP socket to the client
-2. the TCP/IP and Unix domain socket to the FastCGI process
-3. the filehandle to the file in the document root to check if it exists
-
-If lighttpd runs out of file descriptors, it will stop accepting new
-connections for awhile to use the existing file descriptors to handle the
-currently-running requests.
-
-If more than 90% of the file descriptors are used then the handling of new
-connections is disabled. If it drops below 80% again new connections will
-be accepted again.
-
-Under some circumstances you will see ::
-
- ... accept() failed: Too many open files
-
-in the error log. This tells you there were too many new requests at once
-and lighttpd could not disable the incoming connections soon enough. The
-connection was dropped and the client received an error message like 'connection
-failed'. This is very rare and might only occur in test setups.
-
-Increasing the ``server.max-fds`` limit will reduce the probability of this
-problem.
-
-stat() cache
-============
-
-A stat(2) can be expensive; caching it saves time and context switches.
-
-Instead of using stat() every time to check for the existence of a file
-you can stat() it once and monitor the directory the file is in for
-modifications. As long as the directory doesn't change, the files in it
-must all still be the same.
-
-With the help of FAM or gamin you can use kernel events to assure that
-your stat cache is up to date. ::
-
- server.stat-cache-engine = "fam" # either fam, simple or disabled
-
-See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
-See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
-
-Platform-Specific Notes
-=======================
-
-Linux
------
-
-For Linux 2.4.x you should think about compiling lighttpd with the option
-``--disable-lfs`` to disable the support for files larger than 2GB. lighttpd will
-fall back to the ``writev() + mmap()`` network calls which is ok, but not as
-fast as possible but support files larger than 2GB.
-
-Disabling the TCP options reduces the overhead of each TCP packet and might
-help to get the last few percent of performance out of the server. Be aware that
-disabling these options most likely decreases performance for high-latency and lossy
-links.
-
-- net.ipv4.tcp_sack = 0
-- net.ipv4.tcp_timestamps = 0
-
-Increasing the TCP send and receive buffers will increase the performance a
-lot if (and only if) you have a lot of large files to send.
-
-- net.ipv4.tcp_wmem = 4096 65536 524288
-- net.core.wmem_max = 1048576
-
-If you have a lot of large file uploads, increasing the receive buffers will help.
-
-- net.ipv4.tcp_rmem = 4096 87380 524288
-- net.core.rmem_max = 1048576
-
-Keep in mind that every TCP connection uses the configured amount of memory for socket
-buffers. If you've got many connections this can quickly drain the available memory.
-
-See http://www.acc.umu.se/~maswan/linux-netperf.txt for more information on these parameters.
-
-FreeBSD
--------
-
-On FreeBSD you might gain some performance by enabling accept filters. Just
-compile your kernel with: ::
-
- options ACCEPT_FILTER_HTTP
-
-For more ideas about tuning FreeBSD read: tuning(7)
-
-Reducing the recvspace should always be ok if the server only handles HTTP
-requests without large uploads. Increasing the sendspace would reduce the
-system load if you have a lot of large files to be sent, but keep in mind that
-you have to provide the memory in the kernel for each connection. 1024 * 64KB
-would mean 64MB of kernel RAM. Keep this in mind.
-
-- net.inet.tcp.recvspace = 4096
-
diff --git a/doc/plugins.txt b/doc/plugins.txt
deleted file mode 100644
index a7d707db..00000000
--- a/doc/plugins.txt
+++ /dev/null
@@ -1,260 +0,0 @@
-================
-Plugin Interface
-================
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The plugin interface is an integral part of lighttpd which
- provides a flexible way to add specific functionality to lighttpd.
-
-.. meta::
- :keywords: lighttpd, plugins
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Plugins allow you to enhance the functionality of lighttpd without
-changing the core of the webserver. They can be loaded at startup time
-and can change virtually any aspect of the behaviour of the webserver.
-
-Plugin Entry Points
--------------------
-
-lighttpd has 16 hooks which are used in different states of the
-execution of the request:
-
-Serverwide hooks
-````````````````
-
-:init_:
- called when the plugin is loaded
-:cleanup_:
- called when the plugin is unloaded
-:set_defaults_:
- called when the configuration has to be processed
-:handle_trigger_:
- called once a second
-:handle_sighup_:
- called when the server received a SIGHUP
-
-Connectionwide hooks
-````````````````````
-
-Most of these hooks are called in ``http_response_prepare()`` after some
-fields in the connection structure are set.
-
-:handle_uri_raw_:
- called after uri.path_raw, uri.authority and uri.scheme are set
-:handle_uri_clean_:
- called after uri.path (a clean URI without .. and %20) is set
-:handle_docroot_:
- called at the end of the logical path handle to get a docroot
-:handle_subrequest_start_:
- called if the physical path is set up and checked
-:handle_subrequest_:
- called at the end of ``http_response_prepare()``
-:handle_physical_path_:
- called after the physical path is created and no other handler is
- found for this request
-:handle_request_done_:
- called when the request is done
-:handle_connection_close_:
- called if the connection has to be closed
-:handle_joblist_:
- called after the connection_state_engine is left again and plugin
- internal handles have to be called
-:connection_reset_:
- called if the connection structure has to be cleaned up
-
-
-Plugin Interface
-----------------
-
-\*_plugin_init
-``````````````
-
-Every plugin has a uniquely-named function which is called after the
-plugin is loaded. It is used to set up the ``plugin`` structure with
-some useful data:
-
-- name of the plugin ``name``
-- all hooks
-
-The field ``data`` and ``lib`` should not be touched in the init function.
-``lib`` is the library handler from dlopen and ``data`` will be the storage
-of the internal plugin data.
-
-:returns:
- 0 (not handled)
-
-init
-````
-
-The first real call of a plugin function is the init hook which is used
-to set up the internal plugin data. The internal plugin is assigned the
-``data`` field mentioned in the \*_plugin_init description.
-
-:returns:
- a pointer to the internal plugin data.
-
-cleanup
-```````
-
-The cleanup hook is called just before the plugin is unloaded. It is meant
-to free all buffers allocated in ``init`` or somewhere else in the plugin
-which are still not freed and to close all handles which were opened and
-are not closed yet.
-
-:returns:
- HANDLER_GO_ON if ok (not handled)
-
-set_defaults
-````````````
-
-set_defaults is your entry point into the configfile parsing. It should
-pass a list of options to ``config_insert_values`` and check if
-the plugin configuration is valid. If it is not valid yet, it should
-set useful defaults or return with HANDLER_ERROR and an error message.
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR will terminate lighttpd
-
-connection_reset
-````````````````
-
-called at the end of each request
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR on error
-
-handle_trigger
-``````````````
-
-called once a second
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR on error
-
-handle_sighup
-`````````````
-
-called if a SIGHUP is received (cycling logfiles, ...)
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR on error
-
-handle_uri_raw
-``````````````
-
-called after uri_raw is set
-
-:returns:
- HANDLER_GO_ON if ok
- HANDLER_FINISHED if the final output is prepared
-
- HANDLER_ERROR on error
-
-handle_uri_clean
-````````````````
-
-called after uri.path is set
-
-:returns:
- HANDLER_GO_ON if ok
- HANDLER_FINISHED if the final output is prepared
-
- HANDLER_ERROR on error
-
-handle_docroot
-``````````````
-
-called when a docroot is needed
-
-:returns:
- HANDLER_GO_ON if ok
- HANDLER_FINISHED if the final output is prepared
-
- HANDLER_ERROR on error
-
-handle_subrequest_start
-```````````````````````
-
-called after physical.path is set
-
-:returns:
- HANDLER_GO_ON if ok
- HANDLER_FINISHED if the final output is prepared
-
- HANDLER_ERROR on error
-
-handle_subrequest
-`````````````````
-
-called if subrequest_start requested a COMEBACK or a WAIT_FOR_EVENT
-
-:returns:
- HANDLER_GO_ON if ok
- HANDLER_FINISHED if the final output is prepared
-
- HANDLER_ERROR on error
-
-handle_physical_path
-````````````````````
-
-called after physical.path is set
-
-:returns:
- HANDLER_GO_ON if ok
- HANDLER_FINISHED if the final output is prepared
-
- HANDLER_ERROR on error
-
-
-handle_request_done
-```````````````````
-
-called at the end of the request (logging, statistics, ...)
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR on error
-
-handle_connection_close
-```````````````````````
-
-called if the connection is terminated
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR on error
-
-handle_joblist
-``````````````
-
-called if the state of the connection has changed
-
-:returns:
- HANDLER_GO_ON if ok
-
- HANDLER_ERROR on error
-
-
diff --git a/doc/rc.lighttpd b/doc/rc.lighttpd
deleted file mode 100755
index 4dd2a1e5..00000000
--- a/doc/rc.lighttpd
+++ /dev/null
@@ -1,155 +0,0 @@
-#! /bin/sh
-# Copyright (c) 1995-2002 SuSE Linux AG, Nuernberg, Germany.
-# All rights reserved.
-#
-# Author: Kurt Garloff <feedback@suse.de>
-#
-# /etc/init.d/FOO
-#
-# and symbolic its link
-#
-# /(usr/)sbin/rcFOO
-#
-# LSB compliant service control script; see http://www.linuxbase.org/spec/
-#
-# System startup script for some example service or daemon FOO (template)
-#
-### BEGIN INIT INFO
-# Provides: FOO
-# Required-Start: $remote_fs $syslog
-# Required-Stop: $remote_fs $syslog
-# Default-Start: 3 5
-# Default-Stop: 0 1 2 6
-# Description: Start FOO to allow XY and provide YZ
-# continued on second line by '#<TAB>'
-### END INIT INFO
-#
-# Note on Required-Start: It does specify the init script ordering,
-# not real dependencies. Depencies have to be handled by admin
-# resp. the configuration tools (s)he uses.
-
-# Source SuSE config (if still necessary, most info has been moved)
-test -r /etc/rc.config && . /etc/rc.config
-
-# Check for missing binaries (stale symlinks should not happen)
-LIGHTTPD_BIN=/usr/sbin/lighttpd
-test -x $LIGHTTPD_BIN || exit 5
-
-# Check for existence of needed config file and read it
-LIGHTTPD_CONFIG=/etc/sysconfig/lighttpd
-test -r $LIGHTTPD_CONFIG || exit 6
-. $LIGHTTPD_CONFIG
-
-# Shell functions sourced from /etc/rc.status:
-# rc_check check and set local and overall rc status
-# rc_status check and set local and overall rc status
-# rc_status -v ditto but be verbose in local rc status
-# rc_status -v -r ditto and clear the local rc status
-# rc_failed set local and overall rc status to failed
-# rc_failed <num> set local and overall rc status to <num><num>
-# rc_reset clear local rc status (overall remains)
-# rc_exit exit appropriate to overall rc status
-# rc_active checks whether a service is activated by symlinks
-. /etc/rc.status
-
-# First reset status of this service
-rc_reset
-
-# Return values acc. to LSB for all commands but status:
-# 0 - success
-# 1 - generic or unspecified error
-# 2 - invalid or excess argument(s)
-# 3 - unimplemented feature (e.g. "reload")
-# 4 - insufficient privilege
-# 5 - program is not installed
-# 6 - program is not configured
-# 7 - program is not running
-#
-# Note that starting an already running service, stopping
-# or restarting a not-running service as well as the restart
-# with force-reload (in case signalling is not supported) are
-# considered a success.
-
-case "$1" in
- start)
- echo -n "Starting lighttpd"
- ## Start daemon with startproc(8). If this fails
- ## the echo return value is set appropriate.
-
- # NOTE: startproc returns 0, even if service is
- # already running to match LSB spec.
- startproc $LIGHTTPD_BIN -f $LIGHTTPD_CONF_PATH
-
- # Remember status and be verbose
- rc_status -v
- ;;
- stop)
- echo -n "Shutting down lighttpd"
- ## Stop daemon with killproc(8) and if this fails
- ## set echo the echo return value.
-
- killproc -TERM $LIGHTTPD_BIN
-
- # Remember status and be verbose
- rc_status -v
- ;;
- try-restart)
- ## Stop the service and if this succeeds (i.e. the
- ## service was running before), start it again.
- ## Note: try-restart is not (yet) part of LSB (as of 0.7.5)
- $0 status >/dev/null && $0 restart
-
- # Remember status and be quiet
- rc_status
- ;;
- restart)
- ## Stop the service and regardless of whether it was
- ## running or not, start it again.
- $0 stop
- $0 start
-
- # Remember status and be quiet
- rc_status
- ;;
- force-reload|reload)
- ## Like force-reload, but if daemon does not support
- ## signalling, do nothing (!)
-
- # If it supports signalling:
- echo -n "Reload service LIGHTTPD"
- killproc -INT $LIGHTTPD_BIN
- $0 start
- touch /var/run/lighttpd.pid
- rc_status -v
-
- ## Otherwise if it does not support reload:
- #rc_failed 3
- #rc_status -v
- ;;
- status)
- echo -n "Checking for service LIGHTTPD: "
- ## Check status with checkproc(8), if process is running
- ## checkproc will return with exit status 0.
-
- # Return value is slightly different for the status command:
- # 0 - service running
- # 1 - service dead, but /var/run/ pid file exists
- # 2 - service dead, but /var/lock/ lock file exists
- # 3 - service not running
-
- # NOTE: checkproc returns LSB compliant status values.
- checkproc $LIGHTTPD_BIN
- rc_status -v
- ;;
- probe)
- ## Optional: Probe for the necessity of a reload,
- ## print out the argument which is required for a reload.
-
- test /etc/lighttpd/lighttpd.conf -nt /var/run/lighttpd.pid && echo reload
- ;;
- *)
- echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
- exit 1
- ;;
-esac
-rc_exit
diff --git a/doc/rc.lighttpd.redhat b/doc/rc.lighttpd.redhat
deleted file mode 100644
index e22d551d..00000000
--- a/doc/rc.lighttpd.redhat
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/sh
-#
-# lighttpd Startup script for the lighttpd server
-#
-# chkconfig: - 85 15
-# description: Lightning fast webserver with light system requirements
-#
-# processname: lighttpd
-# config: /etc/lighttpd/lighttpd.conf
-# config: /etc/sysconfig/lighttpd
-# pidfile: /var/run/lighttpd.pid
-#
-# Note: pidfile is assumed to be created
-# by lighttpd (config: server.pid-file).
-# If not, uncomment 'pidof' line.
-
-# Source function library
-. /etc/rc.d/init.d/functions
-
-if [ -f /etc/sysconfig/lighttpd ]; then
- . /etc/sysconfig/lighttpd
-fi
-
-if [ -z "$LIGHTTPD_CONF_PATH" ]; then
- LIGHTTPD_CONF_PATH="/etc/lighttpd/lighttpd.conf"
-fi
-
-prog="lighttpd"
-lighttpd="/usr/sbin/lighttpd"
-RETVAL=0
-
-start() {
- echo -n $"Starting $prog: "
- daemon $lighttpd -f $LIGHTTPD_CONF_PATH
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
- return $RETVAL
-}
-
-stop() {
- echo -n $"Stopping $prog: "
- killproc $lighttpd
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
- return $RETVAL
-}
-
-reload() {
- echo -n $"Reloading $prog: "
- killproc $lighttpd -HUP
- RETVAL=$?
- echo
- return $RETVAL
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- stop
- start
- ;;
- condrestart)
- if [ -f /var/lock/subsys/$prog ]; then
- stop
- start
- fi
- ;;
- reload)
- reload
- ;;
- status)
- status $lighttpd
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|condrestart|reload|status}"
- RETVAL=1
-esac
-
-exit $RETVAL
diff --git a/doc/redirect.txt b/doc/redirect.txt
deleted file mode 100644
index ab4e7a83..00000000
--- a/doc/redirect.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-===============
-URL Redirection
-===============
-
---------------------
-Module: mod_redirect
---------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- url redirection
-
-.. meta::
- :keywords: lighttpd, redirect
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-...
-
-Options
-=======
-
-url.redirect
- redirects a set of URLs externally
-
- e.g. ::
-
- url.redirect = ( "^/show/([0-9]+)/([0-9]+)$" => "http://www.example.org/show.php?isdn=$1&page$2",
- "^/get/([0-9]+)/([0-9]+)$" => "http://www.example.org/get.php?isdn=$1&page$2" )
-
- # make a external redirect
- # from any www.host (with www.) to the host (without www.)
- $HTTP["host"] =~ "^www\.(.*)" {
- url.redirect = ( "^/(.*)" => "http://%1/$1" )
- }
diff --git a/doc/rewrite.txt b/doc/rewrite.txt
deleted file mode 100644
index ec00f5d8..00000000
--- a/doc/rewrite.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-============
-URL Rewrites
-============
-
--------------------
-Module: mod_rewrite
--------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- url rewrite
-
-.. meta::
- :keywords: lighttpd, rewrite
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-internal redirects, url rewrite
-
-Options
-=======
-
-url.rewrite-once
- rewrites a set of URLs interally in the webserver BEFORE they are handled.
-
- e.g. ::
-
- url.rewrite-once = ( "<regex>" => "<relative-uri>" )
-
-url.rewrite-repeat
- rewrites a set of URLs interally in the webserver BEFORE they are handled
-
- e.g. ::
-
- url.rewrite-repeat = ( "<regex>" => "<relative-uri>" )
-
-The options ``url.rewrite`` and ``url.rewrite-final`` were mapped to ``url.rewrite-once``
-in 1.3.16.
-
-Examples
-========
-
-The regex is matching the full REQUEST_URI which is supplied by the user including
-query-string.::
-
- url.rewrite-once = ( "^/id/([0-9]+)$" => "/index.php?id=$1",
- "^/link/([a-zA-Z]+)" => "/index.php?link=$1" )
-
-
-
- # the following example, is, however just simulating vhost by rewrite
- # * you can never change document-root by mod_rewrite
- # use mod_*host instead to make real mass-vhost
-
- # request: http://any.domain.com/url/
- # before rewrite: REQUEST_URI="/www/htdocs/url/"
- # and DOCUMENT_ROOT="/www/htdocs/" %0="www.domain.com" $1="url/"
- # after rewrite: REQUEST_URI="/www/htdocs/domain.com/url/"
- # still, you have DOCUMENT_ROOT=/www/htdocs/
-
- server.document-root = "/www/htdocs/"
- $HTTP["host"] =~ "^.*\.([^.]+\.com)$" {
- url.rewrite-once = ( "^/(.*)" => "/%0/$1" )
- }
-
diff --git a/doc/rrdtool-graph.sh b/doc/rrdtool-graph.sh
deleted file mode 100644
index 1157a285..00000000
--- a/doc/rrdtool-graph.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-RRDTOOL=/usr/bin/rrdtool
-OUTDIR=/var/www/servers/www.example.org/pages/rrd/
-INFILE=/var/www/lighttpd.rrd
-OUTPRE=lighttpd-traffic
-
-DISP="DEF:bin=$INFILE:InOctets:AVERAGE \
- DEF:binmin=$INFILE:InOctets:MIN \
- DEF:binmax=$INFILE:InOctets:MAX \
- DEF:bout=$INFILE:OutOctets:AVERAGE \
- DEF:boutmin=$INFILE:OutOctets:MIN \
- DEF:boutmax=$INFILE:OutOctets:MAX \
- LINE1:bin#0000FF:in \
- LINE1:binmin#2222FF: \
- STACK:binmax#2222FF: \
- LINE1:bout#FF0000:out \
- LINE1:boutmin#FF2222: \
- STACK:boutmax#FF2222: \
- -v bytes/s"
-
-$RRDTOOL graph $OUTDIR/$OUTPRE-hour.png -a PNG --start -14400 $DISP
-$RRDTOOL graph $OUTDIR/$OUTPRE-day.png -a PNG --start -86400 $DISP
-$RRDTOOL graph $OUTDIR/$OUTPRE-month.png -a PNG --start -2592000 $DISP
-
-OUTPRE=lighttpd-requests
-
-DISP="DEF:req=$INFILE:Requests:AVERAGE \
- DEF:reqmin=$INFILE:Requests:MIN \
- DEF:reqmax=$INFILE:Requests:MAX \
- LINE1:req#0000FF:requests \
- LINE1:reqmin#2222FF: \
- STACK:reqmax#2222FF: \
- -v req/s"
-
-$RRDTOOL graph $OUTDIR/$OUTPRE-hour.png -a PNG --start -14400 $DISP
-$RRDTOOL graph $OUTDIR/$OUTPRE-day.png -a PNG --start -86400 $DISP
-$RRDTOOL graph $OUTDIR/$OUTPRE-month.png -a PNG --start -2592000 $DISP
diff --git a/doc/rrdtool.txt b/doc/rrdtool.txt
deleted file mode 100644
index ef0a13b2..00000000
--- a/doc/rrdtool.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-=======
-rrdtool
-=======
-
--------------------
-Module: mod_rrdtool
--------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- mod_rrdtool is used to monitor the traffic and load on the webserver
-
-.. meta::
- :keywords: lighttpd, skeleton
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-RRD_ is a system to store and display time-series data (i.e. network
-bandwidth, machine-room temperature, server load average).
-
-.. _RRD: http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/
-
-Options
-=======
-
-rrdtool.binary
- path to the rrdtool binary
-
- e.g.: ::
-
- rrdtool.binary = "/usr/bin/rrdtool"
-
-rrdtool.db-name
- filename of the rrd-database. Make sure that <rrdtool.db-name> doesn't exist
- before the first run, as lighttpd has to create the DB for you.
-
- e.g.: ::
-
- rrdtool.db-name = "/var/www/lighttpd.rrd"
-
-Generating Graphs
-=================
-
-::
-
- #!/bin/sh
-
- RRDTOOL=/usr/bin/rrdtool
- OUTDIR=/var/www/servers/www.example.org/pages/rrd/
- INFILE=/var/www/lighttpd.rrd
- OUTPRE=lighttpd-traffic
-
- DISP="-v bytes --title TrafficWebserver \
- DEF:binraw=$INFILE:InOctets:AVERAGE \
- DEF:binmaxraw=$INFILE:InOctets:MAX \
- DEF:binminraw=$INFILE:InOctets:MIN \
- DEF:bout=$INFILE:OutOctets:AVERAGE \
- DEF:boutmax=$INFILE:OutOctets:MAX \
- DEF:boutmin=$INFILE:OutOctets:MIN \
- CDEF:bin=binraw,-1,* \
- CDEF:binmax=binmaxraw,-1,* \
- CDEF:binmin=binminraw,-1,* \
- CDEF:binminmax=binmaxraw,binminraw,- \
- CDEF:boutminmax=boutmax,boutmin,- \
- AREA:binmin#ffffff: \
- STACK:binmax#f00000: \
- LINE1:binmin#a0a0a0: \
- LINE1:binmax#a0a0a0: \
- LINE2:bin#a0a735:incoming \
- GPRINT:bin:MIN:%.2lf \
- GPRINT:bin:AVERAGE:%.2lf \
- GPRINT:bin:MAX:%.2lf \
- AREA:boutmin#ffffff: \
- STACK:boutminmax#00f000: \
- LINE1:boutmin#a0a0a0: \
- LINE1:boutmax#a0a0a0: \
- LINE2:bout#a0a735:outgoing \
- GPRINT:bout:MIN:%.2lf \
- GPRINT:bout:AVERAGE:%.2lf \
- GPRINT:bout:MAX:%.2lf \
- "
-
-
- $RRDTOOL graph $OUTDIR/$OUTPRE-hour.png -a PNG --start -14400 $DISP
- $RRDTOOL graph $OUTDIR/$OUTPRE-day.png -a PNG --start -86400 $DISP
- $RRDTOOL graph $OUTDIR/$OUTPRE-month.png -a PNG --start -2592000 $DISP
-
- OUTPRE=lighttpd-requests
-
- DISP="-v req --title RequestsperSecond -u 1 \
- DEF:req=$INFILE:Requests:AVERAGE \
- DEF:reqmax=$INFILE:Requests:MAX \
- DEF:reqmin=$INFILE:Requests:MIN \
- CDEF:reqminmax=reqmax,reqmin,- \
- AREA:reqmin#ffffff: \
- STACK:reqminmax#0e0e0e: \
- LINE1:reqmin#a0a0a0: \
- LINE1:reqmax#a0a0a0: \
- LINE2:req#00a735:requests"
-
-
- $RRDTOOL graph $OUTDIR/$OUTPRE-hour.png -a PNG --start -14400 $DISP
- $RRDTOOL graph $OUTDIR/$OUTPRE-day.png -a PNG --start -86400 $DISP
- $RRDTOOL graph $OUTDIR/$OUTPRE-month.png -a PNG --start -2592000 $DISP
-
diff --git a/doc/secdownload.txt b/doc/secdownload.txt
deleted file mode 100644
index af0d6c22..00000000
--- a/doc/secdownload.txt
+++ /dev/null
@@ -1,147 +0,0 @@
-===========================
-Secure and Fast Downloading
-===========================
-
------------------------
-Module: mod_secdownload
------------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-06-06T21:19:25.993967Z $
-:Revision: $Revision: 374 $
-
-:abstract:
- authenticated file requests and a countermeasure against
- deep-linking can be achieved easily by using mod_secdownload
-
-.. meta::
- :keywords: lighttpd, secure, fast, downloads
-
-.. contents:: Table of Contents
-
-Options
-=======
-
-::
-
- secdownload.secret = <string>
- secdownload.document-root = <string>
- secdownload.uri-prefix = <string> (default: /)
- secdownload.timeout = <short> (default: 60 seconds)
-
-Description
-===========
-
-there are multiple ways to handle secured download mechanisms:
-
-1. use the webserver and the internal HTTP authentication
-2. use the application to authenticate and send the file
- through the application
-
-Both ways have limitations:
-
-webserver:
-
-- ``+`` fast download
-- ``+`` no additional system load
-- ``-`` inflexible authentication handling
-
-application:
-
-- ``+`` integrated into the overall layout
-- ``+`` very flexible permission management
-- ``-`` the download occupies an application thread/process
-
-A simple way to combine the two ways could be:
-
-1. app authenticates user and checks permissions to
- download the file.
-2. app redirects user to the file accessable by the webserver
- for further downloading.
-3. the webserver transfers the file to the user.
-
-As the webserver doesn't know anything about the permissions
-used in the app, the resulting URL would be available to every
-user who knows the URL.
-
-mod_secdownload removes this problem by introducing a way to
-authenticate a URL for a specified time. The application has
-to generate a token and a timestamp which are checked by the
-webserver before it allows the file to be downloaded by the
-webserver.
-
-The generated URL has to have the format:
-
-<uri-prefix><token>/<timestamp-in-hex><rel-path>
-
-<token> is an MD5 of
-
-1. a secret string (user supplied)
-2. <rel-path> (starts with /)
-3. <timestamp-in-hex>
-
-
-As you can see, the token is not bound to the user at all. The
-only limiting factor is the timestamp which is used to
-invalidate the URL after a given timeout (secdownload.timeout).
-
-.. Note::
- Be sure to choose a another secret than the one used in the
- examples, as this is the only part of the token that is not
- known to the user.
-
-
-
-If the user tries to fake the URL by choosing a random token,
-status 403 'Forbidden' will be sent out.
-
-If the timeout is reached, status 408 'Request Timeout' will be
-sent. (This does not really conform to the standard, but should
-do the trick).
-
-If token and timeout are valid, the <rel-path> is appended to
-the configured (secdownload.document-root) and passed to the
-normal internal file transfer functionality. This might lead to
-status 200 or 404.
-
-Example
-=======
-
-Application
------------
-
-Your application has to generate the correct URLs. The following sample
-code for PHP should be easily adaptable to any other language: ::
-
- <?php
-
- $secret = "verysecret";
- $uri_prefix = "/dl/";
-
- # filename, make sure it's started with a "/" or you'll get 404 in the browser
- $f = "/secret-file.txt";
-
- # current timestamp
- $t = time();
-
- $t_hex = sprintf("%08x", $t);
- $m = md5($secret.$f.$t_hex);
-
- # generate link
- printf('<a href="%s%s/%s%s">%s</a>',
- $uri_prefix, $m, $t_hex, $f, $f);
- ?>
-
-Webserver
----------
-
-The server has to be configured in the same way. The URI prefix and
-secret have to match: ::
-
- server.modules = ( ..., "mod_secdownload", ... )
-
- secdownload.secret = "verysecret"
- secdownload.document-root = "/home/www/servers/download-area/"
- secdownload.uri-prefix = "/dl/"
- secdownload.timeout = 120
-
diff --git a/doc/security.txt b/doc/security.txt
deleted file mode 100644
index 441a28a4..00000000
--- a/doc/security.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-=================
-Security Features
-=================
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- lighttpd was developed with security in mind ...
-
-.. meta::
- :keywords: lighttpd, security
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Limiting POST requests
-----------------------
-
-
-
-::
-
- server.max-request-size = <kbyte>
-
-System Security
----------------
-
-Running daemons as root with full privileges is a bad idea in general.
-lighttpd runs best without any extra privileges and runs perfectly in chroot.
-
-Change Root
-```````````
-
-server.chroot = "..."
-
-Drop root privileges
-````````````````````
-
-server.username = "..."
-server.groupname = "..."
-
-FastCGI
-```````
-
-fastcgi + chroot
-
-Permissions
-```````````
-
-::
-
- $ useradd wwwrun ...
diff --git a/doc/setenv.txt b/doc/setenv.txt
deleted file mode 100644
index 12d94958..00000000
--- a/doc/setenv.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-===========================
-Conditional Request Headers
-===========================
-
-------------------
-Module: mod_setenv
-------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- mod_setenv is used to add request
-
-.. meta::
- :keywords: lighttpd, skeleton
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-...
-
-Options
-=======
-
-setenv.add-environment
- adds a value to the process environment that is passed to the external applications
-
-
-setenv.add-response-header
- adds a header to the HTTP response sent to the client
-
-setenv.add-request-header
- adds a header to the HTTP request that was received from the client
diff --git a/doc/simple-vhost.txt b/doc/simple-vhost.txt
deleted file mode 100644
index 75c10d22..00000000
--- a/doc/simple-vhost.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-======================
-Simple Virtual-Hosting
-======================
-
-------------------------
-Module: mod_simple_vhost
-------------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- virtual hosting
-
-.. meta::
- :keywords: lighttpd, virtual hosting
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Simple assumption:
-
-Every virtual host is in a directory below a base directory in a path that
-is the same as the name of the vhost. Below this vhost path might be an
-extra directory which is the document root of the vhost.
-
-The document root for each vhost is built from three values:
-
-- server-root
-- hostname
-- document-root
-
-The complete document root is constructed either by ::
-
- server-root + hostname + document-root
-
-or if this path does not exist by ::
-
- server-root + default-host + document-root
-
-A small example should make this idea clear: ::
-
- /var/www/
- /var/www/logs/
- /var/www/servers/
- /var/www/servers/www.example.org/
- /var/www/servers/www.example.org/lib/
- /var/www/servers/www.example.org/pages/
- /var/www/servers/mail.example.org/
- /var/www/servers/mail.example.org/lib/
- /var/www/servers/mail.example.org/pages/
-
- simple-vhost.server-root = "/var/www/servers/"
- simple-vhost.default-host = "www.example.org"
- simple-vhost.document-root = "pages"
-
-You can use symbolic links to map several hostnames to the same directory.
-
-Conditionals vs. simple-vhost
------------------------------
-
-You have to keep in mind that conditionals and simple-vhost interfere
-with one another. ::
-
- simple-vhost.server-root = "/var/www/servers/"
- simple-vhost.default-host = "www.example.org"
- simple-vhost.document-root = "pages"
-
- $HTTP["host"] == "news.example.org" {
- server.document-root = "/var/www/servers/news2.example.org/pages/"
- }
-
-When ``news.example.org`` is requested, the ``server.document-root``
-will be set to ``/var/www/servers/news2.example.org/pages/``, but
-simple-vhost will overwrite it shortly afterwards.
-
-If ``/var/www/servers/news.example.org/pages/`` exists, that will be
-used. If not, ``/var/www/servers/www.example.org/pages/`` will be taken
-because it is the default.
-
-To use conditionals together with simple-vhost, you should do this: ::
-
- $HTTP["host"] !~ "^(news\.example\.org)$" {
- simple-vhost.server-root = "/var/www/servers/"
- simple-vhost.default-host = "www.example.org"
- simple-vhost.document-root = "pages"
- }
-
- $HTTP["host"] == "news.example.org" {
- server.document-root = "/var/www/servers/news2.example.org/pages/"
- }
-
-It will enable simple vhosting for all hosts other than ``news.example.org``.
-
-Options
-=======
-
-simple-vhost.server-root
- root of the virtual host
-
-simple-vhost.default-host
- use this hostname if the requested hostname does not have its own directory
-
-simple-vhost.document-root
- path below the vhost directory
-
diff --git a/doc/skeleton.txt b/doc/skeleton.txt
deleted file mode 100644
index 20519d4e..00000000
--- a/doc/skeleton.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-===================
-headline
-===================
-
---------------------
-Module: mod_skeleton
---------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- a nice, short abstrace about the module
-
-.. meta::
- :keywords: lighttpd, skeleton
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-...
-
-Options
-=======
-
-...
diff --git a/doc/spawn-php.sh b/doc/spawn-php.sh
deleted file mode 100755
index 83b7b167..00000000
--- a/doc/spawn-php.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-
-## ABSOLUTE path to the spawn-fcgi binary
-SPAWNFCGI="/home/weigon/projects/spawn-fcgi/src/spawn-fcgi"
-
-## ABSOLUTE path to the PHP binary
-FCGIPROGRAM="/usr/local/bin/php"
-
-## TCP port to which to bind on localhost
-FCGIPORT="1026"
-
-## number of PHP children to spawn
-PHP_FCGI_CHILDREN=10
-
-## maximum number of requests a single PHP process can serve before it is restarted
-PHP_FCGI_MAX_REQUESTS=1000
-
-## IP addresses from which PHP should access server connections
-FCGI_WEB_SERVER_ADDRS="127.0.0.1,192.168.2.10"
-
-# allowed environment variables, separated by spaces
-ALLOWED_ENV="ORACLE_HOME PATH USER"
-
-## if this script is run as root, switch to the following user
-USERID=wwwrun
-GROUPID=wwwrun
-
-
-################## no config below this line
-
-if test x$PHP_FCGI_CHILDREN = x; then
- PHP_FCGI_CHILDREN=5
-fi
-
-export PHP_FCGI_MAX_REQUESTS
-export FCGI_WEB_SERVER_ADDRS
-
-ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"
-
-if test x$UID = x0; then
- EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN"
-else
- EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN"
-fi
-
-# copy the allowed environment variables
-E=
-
-for i in $ALLOWED_ENV; do
- E="$E $i=${!i}"
-done
-
-# clean the environment and set up a new one
-env - $E $EX
diff --git a/doc/ssi.txt b/doc/ssi.txt
deleted file mode 100644
index ce0665b1..00000000
--- a/doc/ssi.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-====================
-Server-Side Includes
-====================
-
----------------
-Module: mod_ssi
----------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The module for server-side includes provides a compatability
- layer for NSCA/Apache SSI.
-
-.. meta::
- :keywords: lighttpd, ssi, Server-Side Includes
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Configuration
--------------
-
-::
-
- server.modules = ( ..., "mod_ssi", ... )
- ssi.extension = ( ".shtml" )
-
-Supported Options
------------------
-
-- ``<!--#echo var="..." -->``
-- ``<!--#include (file="..."\|virtual="...") -->``
-- ``<!--#flastmod (file="..."\|virtual="...") -->``
-- ``<!--#fsize (file="..."\|virtual="...") -->``
-- ``<!--#config timefmt="..." sizefmt="(bytes|abbrev)" -->``
-- ``<!--#printenv -->``
-- ``<!--#set var="..." value="..." -->``
-- ``<!--#if expr="..." -->``
-- ``<!--#elif expr="..." -->``
-- ``<!--#else -->``
-- ``<!--#endif -->``
-
-Expression Handling
--------------------
-
-Every ''expr'' is interpreted:
-
-- logical: AND, OR, !
-- compare: =, <, <=, >, =>, !=
-- precedence: (, )
-- quoted strings: 'string with a dollar: $FOO'
-- variable substitution: $REMOTE_ADDR
-- unquoted strings: string
-
-Flow Control
-------------
-
-if, elif, else and endif can only be used to insert content under special
-conditions.
-
-Unsupported Features
---------------------
-
-The original SSI module from NCSA and Apache provided some more options
-which are not supported by this module for various reasons:
-
-- exec
-- nested virtual
-- config.errmsg
-- echo.encoding
-
diff --git a/doc/ssl.txt b/doc/ssl.txt
deleted file mode 100644
index 28b5891d..00000000
--- a/doc/ssl.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-===========
-Secure HTTP
-===========
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-04-25T23:00:48.654439Z $
-:Revision: $Revision: 305 $
-
-:abstract:
- How to set up SSL in lighttpd
-
-.. meta::
- :keywords: lighttpd, ssl
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-lighttpd supports SSLv2 and SSLv3 if it is compiled against openssl.
-
-Configuration
--------------
-
-To enable SSL for the whole server you have to provide a valid
-certificate and have to enable the SSL engine.::
-
- ssl.engine = "enable"
- ssl.pemfile = "/path/to/server.pem"
-
-The HTTPS protocol does not allow you to use name-based virtual
-hosting with SSL. If you want to run multiple SSL servers with
-one lighttpd instance you must use IP-based virtual hosting: ::
-
- $SERVER["socket"] == "10.0.0.1:443" {
- ssl.engine = "enable"
- ssl.pemfile = "www.example.org.pem"
- server.name = "www.example.org"
-
- server.document-root = "/www/servers/www.example.org/pages/"
- }
-
-If you have a .crt and a .key file, cat them together into a
-single PEM file:
-::
-
- $ cat host.key host.crt > host.pem
-
-
-Self-Signed Certificates
-------------------------
-
-A self-signed SSL certificate can be generated like this: ::
-
- $ openssl req -new -x509 \
- -keyout server.pem -out server.pem \
- -days 365 -nodes
-
diff --git a/doc/state.dot b/doc/state.dot
deleted file mode 100644
index 551b2323..00000000
--- a/doc/state.dot
+++ /dev/null
@@ -1,18 +0,0 @@
-digraph state {
- edge [color=green];
- connect -> reqstart -> read -> reqend -> handlereq -> respstart -> write -> respend -> connect;
- edge [color=grey];
- reqend -> readpost -> handlereq [ label="POST" ];
- edge [ color=blue]
- respend -> reqstart [ label="keep-alive" ];
- edge [ color=lightblue]
- handlereq -> handlereq [ label="sub-request" ];
- edge [style=dashed, color=red];
- error -> close -> connect;
- error -> connect;
- handlereq -> error;
- read -> error;
- readpost -> error;
- write -> error;
- connect [shape=box];
-}
diff --git a/doc/state.txt b/doc/state.txt
deleted file mode 100644
index c45152f8..00000000
--- a/doc/state.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-============================
-The State Engine of lighttpd
-============================
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- This is a short summary of the state-engine which is driving the lighttpd
- webserver. It describes the basic concepts and the way the different parts
- of the server are connected.
-
-.. meta::
- :keywords: lighttpd, state-engine
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-States
-------
-
-The state-engine is currently made of 11 states which are walk-through on
-the way each connection. Some of them are specific for a special operation
-and some may never be hit at all.
-
-:connect:
- waiting for a connection
-:reqstart:
- init the read-idle timer
-:read:
- read http-request-header from network
-:reqend:
- parse request
-:readpost:
- read http-request-content from network
-:handlereq:
- handle the request internally (might result in sub-requests)
-:respstart:
- prepare response header
-:write:
- write response-header + content to network
-:respend:
- cleanup environment, log request
-:error:
- reset connection (incl. close())
-:close:
- close connection (handle lingering close)
-
-.. image:: state.png
-
-A simple GET request (green path)
----------------------------------
-
-The connection is idling in the 'connect' state waiting for a connection.
-As soon as the connection is set up we init the read-timer in 'reqstart'
-and start to read data from the network. As soon as we get the
-HTTP-request terminator (CRLFCRLF) we forward the header to the parser.
-
-The parsed request is handled by 'handlereq' and as soon as a decision out
-the request is made it is sent to 'respstart' to prepare the
-HTTP-response header. In the 'write' state the prepare content is sent out
-to the network. When everything is sent 'respend' is entered to log the
-request and cleanup the environment. After the close() call the connection
-is set back to the 'connect' state again.
-
-Keep-Alive (blue path)
-----------------------
-
-The Keep-Alive handling is implemented by going from the 'respend'
-directly to 'reqstart' without the close() and the accept() calls.
-
-POST requests (grey path)
--------------------------
-
-As requests might contain a request-body the state 'readpost' entered as
-soon as the header is parsed and we know how much data we expect.
-
-Pipelining
-----------
-
-HTTP/1.1 supportes pipelining (sending multiple requests without waiting
-for the response of the first request). This is handled transparently by
-the 'read' state.
-
-Unexpected errors (red path)
-----------------------------
-
-For really hard errors we use the 'error' state which resets the
-connection and can be call from every state. It is only use if there is no
-other way to handle the issue (e.g. client-side close of the connection).
-If possible we should use http-status 500 ('internal server error') and
-log the issue in the errorlog.
-
-If we have to take care of some data which is coming in after we ran into
-the error condition the 'close' state is used the init a half-close and
-read all the delay packet from the network.
-
-Sub-Requests (lightblue)
-------------------------
-
-The FastCGI, CGI, ... intergration is done by introducing a loop in
-'handlereq' to handle all aspect which are neccesary to find out what has
-to be sent back to the client.
-
-Functions
-=========
-
-Important functions used by the state-engine
-
-:state-engine:
-
-- ``connection_state_machine()``
-
-:connect:
-
-- (nothing)
-
-:reqstart:
-
-- (nothing)
-
-:read:
-
-- ``connection_handle_read_state()``
-- ``connection_handle_read()``
-
-:reqend:
-
-- ``http_request_parse()``
-
-:readpost:
-
-- ``connection_handle_read_state()``
-- ``connection_handle_read()``
-
-:handlereq:
-
-- ``http_response_prepare()``
-
-:respstart:
-
-- ``connection_handle_write_prepare()``
-
-:write:
-
-- ``connection_handle_write()``
-
-:respend:
-
-- ``plugins_call_handle_request_done()``
-- ``plugins_call_handle_connection_close()``
-- ``connection_close()`` (if not keep-alive)
-- ``connection_reset()``
-
-:error:
-
-- ``plugins_call_handle_request_done()``
-- ``plugins_call_handle_connection_close()``
-- ``connection_reset()``
-
-:close:
-
-- ``connection_close()``
diff --git a/doc/status.txt b/doc/status.txt
deleted file mode 100644
index 5045c0f4..00000000
--- a/doc/status.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-=============
-Server Status
-=============
-
-------------------
-Module: mod_status
-------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- mod_status displays the server's status and configuration
-
-.. meta::
- :keywords: lighttpd, server status
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-The server status module generates the status overview of the webserver. The
-information covers:
-
-- uptime
-- average throughput
-- current throughput
-- active connections and their state
-
-
-We need to load the module first. ::
-
- server.modules = ( ..., "mod_ssi", ... )
-
-By default the status page is disabled to hide internal information from
-unauthorized users. ::
-
- status.status-url = "/server-status"
-
-If you want to open the status page just for users from the local network
-cover it in a conditional. ::
-
- $HTTP["remoteip"] == "10.0.0.0/8" {
- status.status-url = "/server-status"
- }
-
-Or require authorization: ::
-
- auth.require = ( "/server-status" =>
- ( "realm" ... ) )
-
-
-Please note that when using the server.max-worker directive, the stati of the
-childs are not combined yet, so you're going to see different stats with each
-request.
-
-
-Output Format
--------------
-
-By default a nice looking HTML page is generated. If you append ?auto to the
-status-url you can get a text version which is simpler to parse. ::
-
- Total Accesses: 1234
- Total kBytes: 1043
- Uptime: 1234
- BusyServers: 123
-
-Total Accesses is the number of handled requests, kBytes the overall outgoing
-traffic, Uptime the uptime in seconds and BusyServers the number of currently
-active connections.
-
-The naming is kept compatible to Apache even if we have another concept and
-don't start new servers for each connection.
-
-
-Options
-=======
-
-status.status-url
-
- relative URL which is used to retrieve the status-page
-
- Default: unset
-
- Example: status.status-url = "/server-status"
-
-status.enable-sort
-
- add JavaScript which allows client-side sorting for the connection overview
-
- Default: enable
-
-status.config-url
-
- relative URL for the config page which displays the loaded modules
-
- Default: unset
-
- Example: status.config-url = "/server-config"
-
-status.statistics-url
-
- relative URL for a plain-text page containing the internal statistics
-
- Default: unset
-
- Example: status.statistics-url = "/server-statistics"
-
diff --git a/doc/sysconfig.lighttpd b/doc/sysconfig.lighttpd
deleted file mode 100644
index c8154c96..00000000
--- a/doc/sysconfig.lighttpd
+++ /dev/null
@@ -1 +0,0 @@
-LIGHTTPD_CONF_PATH=/etc/lighttpd/lighttpd.conf
diff --git a/doc/traffic-shaping.txt b/doc/traffic-shaping.txt
deleted file mode 100644
index d2d0a807..00000000
--- a/doc/traffic-shaping.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-===============
-Traffic Shaping
-===============
-
-------------
-Module: core
-------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- limiting bandwidth usage
-
-.. meta::
- :keywords: lighttpd, bandwidth limit, traffic shaping
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Starting with 1.3.8, lighttpd supports limiting the bandwidth for
-a single connection or config context like a virtual host or a URL.
-
-Options
-=======
-
-:connection.kbytes-per-second:
- limit the throughput for each single connection to the given
- limit in kbyte/s
-
- default: 0 (no limit)
-
-:server.kbytes-per-second:
- limit the throughput for all connections to the given limit
- in kbyte/s
-
- if you want to specify a limit for a special virtual server
- use: ::
-
- $HTTP["host"] == "www.example.org" {
- server.kbytes-per-second = 128
- }
-
- which will override the default for this host.
-
- default: 0 (no limit)
-
-Additional Notes
-================
-
-Keep in mind that a limit below 32kb/s might actually limit the traffic to 32kb/s. This
-is caused by the size of the TCP send buffer.
diff --git a/doc/trigger_b4_dl.txt b/doc/trigger_b4_dl.txt
deleted file mode 100644
index f5c9d299..00000000
--- a/doc/trigger_b4_dl.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-=======================
-Trigger before Download
-=======================
-
--------------------------
-Module: mod_trigger_b4_dl
--------------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2004/11/03 22:26:05 $
-:Revision: $Revision: 1.2 $
-
-:abstract:
- another anti-hot-linking module
-
-.. meta::
- :keywords: lighttpd, hot-linking, deep-linking
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-Anti Hotlinking:
-
- * if user requests ''download-url'' directly, the request is denied and he is redirected to ''deny-url'
- * if user visits ''trigger-url'' before requesting ''download-url'', access is granted
- * if user visits ''download-url'' again after ''trigger-timeout'' has elapsed, the request is denied and he is redirected to ''deny-url''
-
-The trigger information is either stored locally in a gdbm file or remotely in memcached.
-
-Requirements
-------------
-
- * libpcre
- * libgdbm or libmemcache
-
-Options
-=======
-
-::
-
- trigger-before-download.gdbm-filename = "/home/weigon/testbase/trigger.db"
- trigger-before-download.memcache-hosts = ( "127.0.0.1:11211" )
- trigger-before-download.trigger-url = "^/trigger/"
- trigger-before-download.download-url = "^/download/"
- trigger-before-download.deny-url = "http://192.168.1.5:1025/index.html"
- trigger-before-download.trigger-timeout = 10
-
-If both trigger-before-download.gdbm-filename and
-trigger-before-download.memcache-hosts is set gdbm will take precedence.
-
-Installation
-============
-
-memcached should be started with the option -M as we don't want to remove entry if the memory is full.
-
diff --git a/doc/userdir.txt b/doc/userdir.txt
deleted file mode 100644
index 9dde1fb8..00000000
--- a/doc/userdir.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-=======
-userdir
-=======
-
--------------------
-Module: mod_userdir
--------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2005-03-28T08:30:05.699628Z $
-:Revision: $Revision: 227 $
-
-:abstract:
- The userdir module ...
-
-.. meta::
- :keywords: lighttpd, userdir
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-The userdir module provides a simple way to link user-based directories into the global namespace of the webserver.
-
-Requests in the form ``/~user/page.html`` are rewritten to take the file ``page.html`` from the home directory of the user.
-If ``userdir.path`` is set, the path will be appended to the home directory
-building the classic mapping of: ::
-
- userdir.path = "public_html"
-
- URL: http://www.example.org/~jan/index.html
- Path: /home/jan/public_html/
-
-To control which users should be able to use this feature you can set a list of usernames to include or exclude.
-
-In case your mapping is independent of /etc/passwd you can use
-``userdir.basepath``: ::
-
- userdir.path = "htdocs"
- userdir.basepath = "/var/www/users/"
-
- URL: http://www.example.org/~jan/index.html
- Path: /var/www/users/jan/htdocs/index.html
-
-Options
-=======
-
-userdir.path
- usually it should be set to "public_html" to take ~/public_html/ as the document root
-
- Default: empty (document root is the home directory)
- Example: ::
-
- userdir.path = "public_html"
-
-userdir.exclude-user
- list of usernames which may not use this feature
-
- Default: empty (all users may use it)
- Example: ::
-
- userdir.exclude-user = ( "root", "postmaster" )
-
-
-userdir.include-user
- if set, only users from this list may use the feature
-
- Default: empty (all users may use it)
-
-userdir.basepath
- if set, don't check /etc/passwd for homedir
diff --git a/doc/webdav.txt b/doc/webdav.txt
deleted file mode 100644
index b10012f7..00000000
--- a/doc/webdav.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-======
-WebDAV
-======
-
---------------------
-Module: mod_webdav
---------------------
-
-:Author: Jan Kneschke
-:Date: $Date: 2004/11/03 22:26:05 $
-:Revision: $Revision: 1.2 $
-
-:abstract:
- WebDAV module for lighttpd
-
-.. meta::
- :keywords: lighttpd, webdav
-
-.. contents:: Table of Contents
-
-Description
-===========
-
-The WebDAV module is a very minimalistic implementation of RFC 2518.
-Minimalistic means that not all operations are implemented yet.
-
-So far we have
-
- * PROPFIND
- * OPTIONS
- * MKCOL
- * DELETE
- * PUT
-
-and the usual GET, POST, HEAD from HTTP/1.1.
-
-So far, mounting a WebDAV resource into Windows XP works and the basic litmus
-tests are passed.
-
-Options
-=======
-
-webdav.activate
- If you load the webdav module, the WebDAV functionality has to be
- enabled for the directories you want to provide to the user.
-
- Default: disable
-
-webdav.is-readonly
- Only allow reading methods (GET, PROPFIND, OPTIONS) on WebDAV resources.
-
- Default: writable
-
-Examples
-========
-
-To enable WebDAV for the /dav directory, you wrap your webdav options in
-a conditional. You have to use the regex like below as you want to match
-the directory /dav and everything below it, but not e.g. /davos. ::
-
- $HTTP["url"] =~ "^/dav($|/)" {
- webdav.activate = "enable"
- webdav.is-readonly = "enable"
- }
diff --git a/make.example b/make.example
deleted file mode 100755
index e78529f5..00000000
--- a/make.example
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-# example file for building with cmake
-# copy this file as "make" before modify
-# $ cp make.example make
-# $ ./make
-
-cd $(dirname $(readlink -f $0))
-buildtype=Release
-# comments out next line for Release build
-buildtype=Debug
-
-builddir=build-linux-$buildtype
-mkdir -p "$builddir"
-ln -sf "$builddir"/build ./
-cd "$builddir"
-cmake \
- -D CMAKE_BUILD_TYPE:STRING=$buildtype \
- -D WITH_LUA=ON \
- -D WITH_OPENSSL=ON \
- -D WITH_PCRE=ON \
- -D WITH_ZLIB=ON \
- .. \
- && /usr/bin/make "$@"
diff --git a/src/.cvsignore b/src/.cvsignore
deleted file mode 100644
index 55061b0a..00000000
--- a/src/.cvsignore
+++ /dev/null
@@ -1,17 +0,0 @@
-Makefile.in
-Makefile
-spawn-fcgi
-chunk
-lemon
-lighttpd
-*.loT
-*.exe
-.deps
-.libs
-array
-proc_open
-regex
-mod_ssi_exprparser.c
-mod_ssi_exprparser.h
-configparser.c
-configparser.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index 1323272d..00000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,678 +0,0 @@
-INCLUDE(CheckCSourceCompiles)
-INCLUDE(CheckIncludeFiles)
-INCLUDE(CheckFunctionExists)
-INCLUDE(CheckVariableExists)
-INCLUDE(CheckTypeSize)
-INCLUDE(CheckLibraryExists)
-INCLUDE(CMakeDetermineCCompiler)
-INCLUDE(FindThreads)
-INCLUDE(CPack)
-INCLUDE(UsePkgConfig)
-
-INCLUDE(LighttpdMacros)
-
-ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES)
-
-OPTION(WITH_XATTR "with xattr-support for the stat-cache [default: off]")
-OPTION(WITH_MYSQL "with mysql-support for the mod_sql_vhost [default: off]")
-OPTION(WITH_POSTGRESQL "with postgress-support for the mod_sql_vhost [default: off]")
-OPTION(WITH_OPENSSL "with openssl-support [default: off]")
-OPTION(WITH_PCRE "with regex support [default: on]" ON)
-OPTION(WITH_WEBDAV_PROPS "with property-support for mod_webdav [default: off]")
-OPTION(WITH_BZIP "with bzip2-support for mod_compress [default: off]")
-OPTION(WITH_ZLIB "with deflate-support for mod_compress [default: on]" ON)
-OPTION(WITH_LDAP "with LDAP-support for the mod_auth [default: off]")
-OPTION(WITH_LIBAIO "with libaio for the linux [default: off]")
-OPTION(WITH_LIBFCGI "with libfcgi for fcgi-stat-accel [default: off]")
-OPTION(WITH_LUA "with lua 5.1 for mod_magnet [default: off]")
-OPTION(WITH_GLIB "with glib support for internal caches [default: on]" ON)
-
-IF(CMAKE_COMPILER_IS_GNUCC)
- OPTION(BUILD_EXTRA_WARNINGS "extra warnings")
-
- IF(BUILD_EXTRA_WARNINGS)
- SET(WARN_FLAGS "-g -O2 -g2 -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Winline -Wsign-compare -Wnested-externs -Wpointer-arith -Wformat-security")
- # -Wl,--as-needed
- # -Werror -Wbad-function-cast -Wmissing-prototypes
- ELSE(BUILD_EXTRA_WARNINGS)
- SET(WARN_FLAGS "")
- ENDIF(BUILD_EXTRA_WARNINGS)
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
-
-OPTION(BUILD_STATIC "build a static lighttpd with all modules added")
-IF(BUILD_STATIC)
- SET(LIGHTTPD_STATIC 1)
-ELSE(BUILD_STATIC)
- SET(CMAKE_SHARED_LIBRARY_PREFIX "")
-ENDIF(BUILD_STATIC)
-
-IF(WITH_WEBDAV_PROPS)
- SET(WITH_XML 1)
- SET(WITH_SQLITE3 1)
- SET(WITH_UUID 1)
-ENDIF(WITH_WEBDAV_PROPS)
-
-CHECK_INCLUDE_FILES(sys/devpoll.h HAVE_SYS_DEVPOLL_H)
-CHECK_INCLUDE_FILES(sys/epoll.h HAVE_SYS_EPOLL_H)
-CHECK_INCLUDE_FILES(sys/event.h HAVE_SYS_EVENT_H)
-CHECK_INCLUDE_FILES(sys/mman.h HAVE_SYS_MMAN_H)
-CHECK_INCLUDE_FILES(sys/poll.h HAVE_SYS_POLL_H)
-CHECK_INCLUDE_FILES(sys/port.h HAVE_SYS_PORT_H)
-CHECK_INCLUDE_FILES(sys/prctl.h HAVE_SYS_PRCTL_H)
-CHECK_INCLUDE_FILES(sys/resource.h HAVE_SYS_RESOURCE_H)
-CHECK_INCLUDE_FILES(sys/sendfile.h HAVE_SYS_SENDFILE_H)
-CHECK_INCLUDE_FILES(sys/select.h HAVE_SYS_SELECT_H)
-CHECK_INCLUDE_FILES(sys/syslimits.h HAVE_SYS_SYSLIMITS_H)
-CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H)
-CHECK_INCLUDE_FILES(sys/uio.h HAVE_SYS_UIO_H)
-CHECK_INCLUDE_FILES(sys/un.h HAVE_SYS_UN_H)
-CHECK_INCLUDE_FILES(sys/wait.h HAVE_SYS_WAIT_H)
-CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H)
-CHECK_INCLUDE_FILES(time.h HAVE_TIME_H)
-CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H)
-CHECK_INCLUDE_FILES(pthread.h HAVE_PTHREAD_H)
-
-
-## refactor me
-MACRO(XCONFIG _package _include_DIR _link_DIR _link_FLAGS _cflags)
-# reset the variables at the beginning
- SET(${_include_DIR})
- SET(${_link_DIR})
- SET(${_link_FLAGS})
- SET(${_cflags})
-
- FIND_PROGRAM(${_package}CONFIG_EXECUTABLE NAMES ${_package} PATHS /usr/local/bin )
-
- # if pkg-config has been found
- IF(${_package}CONFIG_EXECUTABLE)
- SET(XCONFIG_EXECUTABLE "${${_package}CONFIG_EXECUTABLE}")
- MESSAGE(STATUS "found ${_package}: ${XCONFIG_EXECUTABLE}")
-
- EXEC_PROGRAM(${XCONFIG_EXECUTABLE} ARGS --libs OUTPUT_VARIABLE __link_FLAGS)
- STRING(REPLACE "\n" "" ${_link_FLAGS} ${__link_FLAGS})
- EXEC_PROGRAM(${XCONFIG_EXECUTABLE} ARGS --cflags OUTPUT_VARIABLE __cflags)
- STRING(REPLACE "\n" "" ${_cflags} ${__cflags})
-
- ELSE(${_package}CONFIG_EXECUTABLE)
- MESSAGE(STATUS "found ${_package}: no")
- ENDIF(${_package}CONFIG_EXECUTABLE)
-ENDMACRO(XCONFIG _package _include_DIR _link_DIR _link_FLAGS _cflags)
-
-##INCLUDE_DIRECTORIES(${GTHREAD_INCDIR})
-ADD_DEFINITIONS(${GTHREAD_CFLAGS})
-
-IF(WITH_XATTR)
- CHECK_INCLUDE_FILES(attr/attributes.h HAVE_ATTR_ATTRIBUTES_H)
-ENDIF(WITH_XATTR)
-
-IF(WITH_MYSQL)
- XCONFIG(mysql_config MYSQL_INCDIR MYSQL_LIBDIR MYSQL_LDFLAGS MYSQL_CFLAGS)
-
- SET(CMAKE_REQUIRED_INCLUDES /usr/include/mysql)
- CHECK_INCLUDE_FILES(mysql.h HAVE_MYSQL_H)
- SET(CMAKE_REQUIRED_INCLUDES)
- IF(HAVE_MYSQL_H)
- CHECK_LIBRARY_EXISTS(mysqlclient mysql_real_connect "" HAVE_LIBMYSQL)
- ENDIF(HAVE_MYSQL_H)
-ENDIF(WITH_MYSQL)
-
-IF(WITH_POSTGRESQL)
- SET(CMAKE_REQUIRED_INCLUDES /usr/include/pgsql)
- CHECK_INCLUDE_FILES(libpq-fe.h HAVE_LIBPQ_FE_H)
- SET(CMAKE_REQUIRED_INCLUDES)
- IF(HAVE_LIBPG_FE_H)
- CHECK_LIBRARY_EXISTS(pq PQconnectdb "" HAVE_LIBPQ)
- ENDIF(HAVE_LIBPG_FE_H)
-ENDIF(WITH_POSTGRESQL)
-
-IF(WITH_OPENSSL)
- CHECK_INCLUDE_FILES(openssl/ssl.h HAVE_OPENSSL_SSL_H)
- IF(HAVE_OPENSSL_SSL_H)
- CHECK_LIBRARY_EXISTS(crypto BIO_f_base64 "" HAVE_LIBCRYPTO)
- IF(HAVE_LIBCRYPTO)
- SET(OPENSSL_NO_KRB5 1)
- CHECK_LIBRARY_EXISTS(ssl SSL_new "" HAVE_LIBSSL)
- ENDIF(HAVE_LIBCRYPTO)
- ENDIF(HAVE_OPENSSL_SSL_H)
-ENDIF(WITH_OPENSSL)
-
-CHECK_INCLUDE_FILES(aio.h HAVE_AIO_H)
-IF(WITH_BZIP)
- CHECK_INCLUDE_FILES(bzlib.h HAVE_BZLIB_H)
- CHECK_LIBRARY_EXISTS(bz2 BZ2_bzCompressInit "" HAVE_LIBBZ2)
-ENDIF(WITH_BZIP)
-
-CHECK_INCLUDE_FILES(getopt.h HAVE_GETOPT_H)
-CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H)
-IF(WITH_LDAP)
- CHECK_INCLUDE_FILES(ldap.h HAVE_LDAP_H)
- CHECK_LIBRARY_EXISTS(ldap ldap_open "" HAVE_LIBLDAP)
-ENDIF(WITH_LDAP)
-
-IF(WITH_LIBAIO)
- CHECK_INCLUDE_FILES(libaio.h HAVE_LIBAIO_H)
- CHECK_LIBRARY_EXISTS(aio io_getevents "" HAVE_LIBAIO)
-ENDIF(WITH_LIBAIO)
-
-IF(WITH_XML)
- XCONFIG(xml2-config XML2_INCDIR XML2_LIBDIR XML2_LDFLAGS XML2_CFLAGS)
- IF(XML2_LDFLAGS OR XML2_CFLAGS)
- MESSAGE(STATUS "found xml2 at: LDFLAGS: ${XML2_LDFLAGS} CFLAGS: ${XML2_CFLAGS}")
-
- ## if it is empty we'll get newline returned
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XML2_CFLAGS}")
-
- CHECK_INCLUDE_FILES(libxml/tree.h HAVE_LIBXML_H)
-
- SET(CMAKE_REQUIRED_FLAGS ${XML2_LDFLAGS})
- CHECK_LIBRARY_EXISTS(xml2 xmlParseChunk "" HAVE_LIBXML)
- SET(CMAKE_REQUIRED_FLAGS)
- ELSE(XML2_LDFLAGS OR XML2_CFLAGS)
- CHECK_INCLUDE_FILES(libxml.h HAVE_LIBXML_H)
- CHECK_LIBRARY_EXISTS(xml2 xmlParseChunk "" HAVE_LIBXML)
- ENDIF(XML2_LDFLAGS OR XML2_CFLAGS)
-
- IF(NOT HAVE_LIBXML_H)
- MESSAGE(FATAL_ERROR "libxml/tree.h couldn't be found")
- ENDIF(NOT HAVE_LIBXML_H)
- IF(NOT HAVE_LIBXML)
- MESSAGE(FATAL_ERROR "libxml2 couldn't be found")
- ENDIF(NOT HAVE_LIBXML)
-
-ENDIF(WITH_XML)
-
-IF(WITH_PCRE)
- ## if we have pcre-config, use it
- XCONFIG(pcre-config PCRE_INCDIR PCRE_LIBDIR PCRE_LDFLAGS PCRE_CFLAGS)
- IF(PCRE_LDFLAGS OR PCRE_CFLAGS)
- MESSAGE(STATUS "found pcre at: LDFLAGS: ${PCRE_LDFLAGS} CFLAGS: ${PCRE_CFLAGS}")
-
- IF(NOT PCRE_CFLAGS STREQUAL "\n")
- ## if it is empty we'll get newline returned
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PCRE_CFLAGS}")
- ENDIF(NOT PCRE_CFLAGS STREQUAL "\n")
-
- CHECK_INCLUDE_FILES(pcre.h HAVE_PCRE_H)
-
- SET(CMAKE_REQUIRED_FLAGS ${PCRE_LDFLAGS})
- CHECK_LIBRARY_EXISTS(pcre pcre_exec "" HAVE_LIBPCRE)
- SET(CMAKE_REQUIRED_FLAGS)
-
- ELSE(PCRE_LDFLAGS OR PCRE_CFLAGS)
- IF(NOT WIN32)
- CHECK_INCLUDE_FILES(pcre.h HAVE_PCRE_H)
- CHECK_LIBRARY_EXISTS(pcre pcre_exec "" HAVE_LIBPCRE)
- SET(PCRE_LIBRARY pcre)
- ELSE(NOT WIN32)
- FIND_PATH(PCRE_INCLUDE_DIR pcre.h
- /usr/local/include
- /usr/include
- )
-
- SET(PCRE_NAMES pcre)
- FIND_LIBRARY(PCRE_LIBRARY
- NAMES ${PCRE_NAMES}
- PATHS /usr/lib /usr/local/lib
- )
-
- IF(PCRE_INCLUDE_DIR AND PCRE_LIBRARY)
- SET(CMAKE_REQUIRED_INCLUDES ${PCRE_INCLUDE_DIR})
- SET(CMAKE_REQUIRED_LIBRARIES ${PCRE_LIBRARY})
- CHECK_INCLUDE_FILES(pcre.h HAVE_PCRE_H)
- CHECK_LIBRARY_EXISTS(pcre pcre_exec "" HAVE_LIBPCRE)
- SET(CMAKE_REQUIRED_INCLUDES)
- SET(CMAKE_REQUIRED_LIBRARIES)
- INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR})
- ENDIF(PCRE_INCLUDE_DIR AND PCRE_LIBRARY)
- ENDIF(NOT WIN32)
- ENDIF(PCRE_LDFLAGS OR PCRE_CFLAGS)
-
- IF(NOT HAVE_PCRE_H)
- MESSAGE(FATAL_ERROR "pcre.h couldn't be found")
- ENDIF(NOT HAVE_PCRE_H)
- IF(NOT HAVE_LIBPCRE)
- MESSAGE(FATAL_ERROR "libpcre couldn't be found")
- ENDIF(NOT HAVE_LIBPCRE)
-
-ENDIF(WITH_PCRE)
-
-CHECK_INCLUDE_FILES(poll.h HAVE_POLL_H)
-CHECK_INCLUDE_FILES(pwd.h HAVE_PWD_H)
-
-OPTION(WITH_SQLITE3 "with property-support [sqlite3] for mod_webdav [default: off]")
-IF(WITH_SQLITE3)
- CHECK_INCLUDE_FILES(sqlite3.h HAVE_SQLITE3_H)
- CHECK_LIBRARY_EXISTS(sqlite3 sqlite3_reset "" HAVE_SQLITE3)
-ENDIF(WITH_SQLITE3)
-
-IF(WITH_GLIB)
- PKGCONFIG(gthread-2.0 GTHREAD_INCDIR GTHREAD_LIBDIR GTHREAD_LDFLAGS GTHREAD_CFLAGS)
- MESSAGE(STATUS "found gthread-2.0 at: INCDIR: ${GTHREAD_INCDIR} LIBDIR: ${GTHREAD_LIBDIR} LDFLAGS: ${GTHREAD_LDFLAGS} CFLAGS: ${GTHREAD_CFLAGS}")
-
- SET(GLIB_INC_DIRS ${GTHREAD_INCDIR}/glib-2.0/ ${GTHREAD_LIBDIR}/glib-2.0/include/)
- INCLUDE_DIRECTORIES(${GLIB_INC_DIRS})
-
- SET(CMAKE_REQUIRED_INCLUDES ${GLIB_INC_DIRS})
- CHECK_INCLUDE_FILES(glib.h HAVE_GLIB_H)
- SET(CMAKE_REQUIRED_INCLUDES)
-ENDIF(WITH_GLIB)
-
-IF(WITH_LIBFCGI)
- CHECK_INCLUDE_FILES(fastcgi.h HAVE_FASTCGI_H)
- CHECK_INCLUDE_FILES(fastcgi/fastcgi.h HAVE_FASTCGI_FASTCGI_H)
- IF(HAVE_FASTCGI_H OR HAVE_FASTCGI_FASTCGI_H)
- CHECK_LIBRARY_EXISTS(fcgi FCGI_Accept "" HAVE_LIBFCGI)
- ENDIF(HAVE_FASTCGI_H OR HAVE_FASTCGI_FASTCGI_H)
-ENDIF(WITH_LIBFCGI)
-
-CHECK_INCLUDE_FILES(stddef.h HAVE_STDDEF_H)
-CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H)
-CHECK_INCLUDE_FILES(syslog.h HAVE_SYSLOG_H)
-IF(WITH_UUID)
- CHECK_INCLUDE_FILES(uuid/uuid.h HAVE_UUID_H)
- CHECK_LIBRARY_EXISTS(uuid uuid_generate "" NEED_LIBUUID)
- IF(NOT NEED_LIBUUID)
- CHECK_FUNCTION_EXISTS(uuid_generate HAVE_LIBUUID)
- ELSE(NOT NEED_LIBUUID)
- SET(HAVE_LIBUUID 1)
- ENDIF(NOT NEED_LIBUUID)
-ENDIF(WITH_UUID)
-
-CHECK_INCLUDE_FILES(sys/inotify.h HAVE_SYS_INOTIFY_H)
-IF(HAVE_SYS_INOTIFY_H)
- CHECK_FUNCTION_EXISTS(inotify_init HAVE_INOTIFY_INIT)
-ENDIF(HAVE_SYS_INOTIFY_H)
-
-IF(WITH_ZLIB)
- IF(NOT WIN32)
- CHECK_INCLUDE_FILES(zlib.h HAVE_ZLIB_H)
- CHECK_LIBRARY_EXISTS(z deflate "" HAVE_LIBZ)
- SET(ZLIB_LIBRARY z)
- ELSE(NOT WIN32)
- FIND_PATH(ZLIB_INCLUDE_DIR zlib.h
- /usr/local/include
- /usr/include
- )
-
- SET(ZLIB_NAMES z zlib zdll)
- FIND_LIBRARY(ZLIB_LIBRARY
- NAMES ${ZLIB_NAMES}
- PATHS /usr/lib /usr/local/lib
- )
-
-
- IF(ZLIB_INCLUDE_DIR AND ZLIB_LIBRARY)
- SET(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR})
- SET(CMAKE_REQUIRED_LIBRARIES ${ZLIB_LIBRARY})
- GET_FILENAME_COMPONENT(ZLIB_NAME ${ZLIB_LIBRARY} NAME)
- CHECK_INCLUDE_FILES(zlib.h HAVE_ZLIB_H)
- CHECK_LIBRARY_EXISTS(${ZLIB_NAME} deflate "" HAVE_LIBZ)
- SET(CMAKE_REQUIRED_INCLUDES)
- SET(CMAKE_REQUIRED_LIBRARIES)
- INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
-
- ENDIF(ZLIB_INCLUDE_DIR AND ZLIB_LIBRARY)
- ENDIF(NOT WIN32)
-ENDIF(WITH_ZLIB)
-
-IF(WITH_LUA)
- PKGCONFIG(lua LUA_INCDIR LUA_LIBDIR LUA_LDFLAGS LUA_CFLAGS)
- IF(NOT LUA_LDFLAGS)
- PKGCONFIG(lua5.1 LUA_INCDIR LUA_LIBDIR LUA_LDFLAGS LUA_CFLAGS)
- ENDIF(NOT LUA_LDFLAGS)
- IF(NOT LUA_LDFLAGS)
- PKGCONFIG(lua-5.1 LUA_INCDIR LUA_LIBDIR LUA_LDFLAGS LUA_CFLAGS)
- ENDIF(NOT LUA_LDFLAGS)
- MESSAGE(STATUS "found lua at: INCDIR: ${LUA_INCDIR} LIBDIR: ${LUA_LIBDIR} LDFLAGS: ${LUA_LDFLAGS} CFLAGS: ${LUA_CFLAGS}")
- IF(LUA_LDFLAGS)
- SET(HAVE_LIBLUA 1 "Have liblua")
- INCLUDE_DIRECTORIES(${LUA_INCDIR})
-
- SET(CMAKE_REQUIRED_INCLUDES ${LUA_INCDIR})
- SET(CMAKE_REQUIRED_FLAGS ${LUA_CFLAGS})
- CHECK_INCLUDE_FILES(lua.h HAVE_LUA_H)
- SET(CMAKE_REQUIRED_INCLUDES)
- SET(CMAKE_REQUIRED_FLAGS)
- ELSE(LUA_LDFLAGS)
- SET(HAVE_LIBLUA "" "Have liblua")
- SET(HAVE_LUA_H "" "Have liblua header")
- ENDIF(LUA_LDFLAGS)
-ENDIF(WITH_LUA)
-
-CHECK_INCLUDE_FILES(crypt.h HAVE_CRYPT_H)
-IF(NOT BUILD_STATIC)
- CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN_H)
-ENDIF(NOT BUILD_STATIC)
-
-SET(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
-CHECK_TYPE_SIZE(socklen_t HAVE_SOCKLEN_T)
-SET(CMAKE_EXTRA_INCLUDE_FILES)
-
-CHECK_TYPE_SIZE(long SIZEOF_LONG)
-CHECK_TYPE_SIZE(off_t SIZEOF_OFF_T)
-
-CHECK_FUNCTION_EXISTS(chroot HAVE_CHROOT)
-CHECK_FUNCTION_EXISTS(crypt HAVE_CRYPT)
-CHECK_FUNCTION_EXISTS(epoll_ctl HAVE_EPOLL_CTL)
-CHECK_FUNCTION_EXISTS(fork HAVE_FORK)
-CHECK_FUNCTION_EXISTS(getrlimit HAVE_GETRLIMIT)
-CHECK_FUNCTION_EXISTS(getuid HAVE_GETUID)
-CHECK_FUNCTION_EXISTS(gmtime_r HAVE_GMTIME_R)
-CHECK_FUNCTION_EXISTS(inet_ntop HAVE_INET_NTOP)
-CHECK_FUNCTION_EXISTS(kqueue HAVE_KQUEUE)
-CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
-CHECK_FUNCTION_EXISTS(lstat HAVE_LSTAT)
-CHECK_FUNCTION_EXISTS(madvise HAVE_MADVISE)
-CHECK_FUNCTION_EXISTS(memcpy HAVE_MEMCPY)
-CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET)
-CHECK_FUNCTION_EXISTS(mmap HAVE_MMAP)
-CHECK_FUNCTION_EXISTS(pathconf HAVE_PATHCONF)
-CHECK_FUNCTION_EXISTS(poll HAVE_POLL)
-CHECK_FUNCTION_EXISTS(port_create HAVE_PORT_CREATE)
-CHECK_FUNCTION_EXISTS(prctl HAVE_PRCTL)
-CHECK_FUNCTION_EXISTS(pread HAVE_PREAD)
-CHECK_FUNCTION_EXISTS(posix_fadvise HAVE_POSIX_FADVISE)
-CHECK_FUNCTION_EXISTS(select HAVE_SELECT)
-CHECK_FUNCTION_EXISTS(sendfile HAVE_SENDFILE)
-CHECK_FUNCTION_EXISTS(sendfile64 HAVE_SENDFILE64)
-CHECK_FUNCTION_EXISTS(sendfilev HAVE_SENDFILEV)
-CHECK_FUNCTION_EXISTS(sigaction HAVE_SIGACTION)
-CHECK_FUNCTION_EXISTS(signal HAVE_SIGNAL)
-CHECK_FUNCTION_EXISTS(sigtimedwait HAVE_SIGTIMEDWAIT)
-CHECK_FUNCTION_EXISTS(strptime HAVE_STRPTIME)
-CHECK_FUNCTION_EXISTS(strtoll HAVE_STRTOLL)
-CHECK_FUNCTION_EXISTS(syslog HAVE_SYSLOG)
-CHECK_FUNCTION_EXISTS(writev HAVE_WRITEV)
-CHECK_FUNCTION_EXISTS(inet_aton HAVE_INET_ATON)
-CHECK_C_SOURCE_COMPILES("
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
-
- int main() {
- struct sockaddr_in6 s; struct in6_addr t=in6addr_any; int i=AF_INET6; s; t.s6_addr[0] = 0;
- return 0;
- }" HAVE_IPV6)
-CHECK_FUNCTION_EXISTS(issetugid HAVE_ISSETUGID)
-
-IF(NOT HAVE_CRYPT)
- ## check if we need libcrypt for crypt()
- CHECK_LIBRARY_EXISTS(crypt crypt "" HAVE_LIBCRYPT)
-ENDIF(NOT HAVE_CRYPT)
-
-IF(HAVE_DLFCN_H)
- CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL)
-ENDIF(HAVE_DLFCN_H)
-
-ADD_DEFINITIONS(
- -DLIGHTTPD_VERSION_ID=10500
- -DPACKAGE_NAME="\\"${CMAKE_PROJECT_NAME}\\""
- -DPACKAGE_VERSION="\\"${CPACK_PACKAGE_VERSION}\\""
- )
-
-IF(NOT SBINDIR)
- SET(SBINDIR "sbin")
-ENDIF(NOT SBINDIR)
-
-SET(LIGHTTPD_MODULES_DIR "lib${LIB_SUFFIX}/lighttpd")
-IF(NOT WIN32)
-ADD_DEFINITIONS(
- -DLIBRARY_DIR="\\"${CMAKE_INSTALL_PREFIX}/${LIGHTTPD_MODULES_DIR}\\""
-)
-ELSE(NOT WIN32)
-## We use relative path in windows
-ADD_DEFINITIONS(
- -DLIBRARY_DIR="\\"lib\\""
-)
-ENDIF(NOT WIN32)
-
-## Write out config.h
-CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
-
-ADD_DEFINITIONS(-DHAVE_CONFIG_H)
-
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
-
-SET(COMMON_SRC
- buffer.c log.c
- keyvalue.c 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
- 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 iosocket.c
- configfile-glue.c
- http-header-glue.c status_counter.c
- network_writev.c
- network_write.c
- network_linux_sendfile.c
- network_freebsd_sendfile.c
- network_win32_send.c
- network_solaris_sendfilev.c
- network_openssl.c
- network_linux_aio.c
- network_posix_aio.c
- network_gthread_aio.c
- network_gthread_sendfile.c
- network_gthread_freebsd_sendfile.c
- http_resp.c
- http_resp_parser.c
- http_req.c
- http_req_parser.c
- http_req_range.c
- http_req_range_parser.c
- sys-files.c
- sys-socket.c
- filter.c
- timing.c
-)
-
-IF(WIN32)
- MESSAGE(STATUS "Adding local getopt implementation.")
- SET(COMMON_SRC ${COMMON_SRC} xgetopt.c)
-ENDIF(WIN32)
-
-ADD_EXECUTABLE(lemon lemon.c)
-
-## Build parsers by using lemon...
-LEMON_PARSER(configparser.y)
-LEMON_PARSER(http_req_parser.y)
-LEMON_PARSER(http_req_range_parser.y)
-LEMON_PARSER(http_resp_parser.y)
-LEMON_PARSER(mod_ssi_exprparser.y)
-
-SET(L_INSTALL_TARGETS)
-
-IF(HAVE_LIBFCGI)
- ADD_EXECUTABLE(fcgi-stat-accel fcgi-stat-accel.c)
- TARGET_LINK_LIBRARIES(fcgi-stat-accel fcgi)
- SET_TARGET_PROPERTIES(fcgi-stat-accel PROPERTIES LINK_FLAGS "-pthread")
- SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} fcgi-stat-accel)
-ENDIF(HAVE_LIBFCGI)
-
-ADD_EXECUTABLE(lighttpd
- server.c
- network.c
- configfile.c
- configparser.c
- connections.c
- proc_open.c
- request.c
- response.c
- ${COMMON_SRC})
-SET(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} lighttpd)
-
-
-ADD_AND_INSTALL_LIBRARY(mod_access mod_access.c)
-ADD_AND_INSTALL_LIBRARY(mod_alias mod_alias.c)
-ADD_AND_INSTALL_LIBRARY(mod_dirlisting mod_dirlisting.c)
-ADD_AND_INSTALL_LIBRARY(mod_staticfile mod_staticfile.c)
-
-ADD_AND_INSTALL_LIBRARY(mod_indexfile mod_indexfile.c)
-ADD_AND_INSTALL_LIBRARY(mod_setenv mod_setenv.c)
-ADD_AND_INSTALL_LIBRARY(mod_rrdtool mod_rrdtool.c)
-ADD_AND_INSTALL_LIBRARY(mod_usertrack mod_usertrack.c)
-ADD_AND_INSTALL_LIBRARY(mod_proxy_core "mod_proxy_core.c;mod_proxy_core_pool.c;mod_proxy_core_backend.c;mod_proxy_core_address.c;mod_proxy_core_backlog.c;mod_proxy_core_protocol.c;mod_proxy_core_rewrites.c")
-ADD_AND_INSTALL_LIBRARY(mod_proxy_backend_http mod_proxy_backend_http.c)
-ADD_AND_INSTALL_LIBRARY(mod_proxy_backend_fastcgi mod_proxy_backend_fastcgi.c)
-ADD_AND_INSTALL_LIBRARY(mod_proxy_backend_scgi mod_proxy_backend_scgi.c)
-ADD_AND_INSTALL_LIBRARY(mod_proxy_backend_ajp13 mod_proxy_backend_ajp13.c)
-ADD_AND_INSTALL_LIBRARY(mod_userdir mod_userdir.c)
-ADD_AND_INSTALL_LIBRARY(mod_secdownload mod_secure_download.c)
-ADD_AND_INSTALL_LIBRARY(mod_accesslog mod_accesslog.c)
-ADD_AND_INSTALL_LIBRARY(mod_simple_vhost mod_simple_vhost.c)
-ADD_AND_INSTALL_LIBRARY(mod_evhost mod_evhost.c)
-ADD_AND_INSTALL_LIBRARY(mod_expire mod_expire.c)
-ADD_AND_INSTALL_LIBRARY(mod_status mod_status.c)
-ADD_AND_INSTALL_LIBRARY(mod_compress mod_compress.c)
-ADD_AND_INSTALL_LIBRARY(mod_redirect mod_redirect.c)
-ADD_AND_INSTALL_LIBRARY(mod_rewrite mod_rewrite.c)
-ADD_AND_INSTALL_LIBRARY(mod_auth "mod_auth.c;http_auth_digest.c;http_auth.c")
-ADD_AND_INSTALL_LIBRARY(mod_sql_vhost_core mod_sql_vhost_core.c)
-ADD_AND_INSTALL_LIBRARY(mod_mysql_vhost mod_mysql_vhost.c)
-ADD_AND_INSTALL_LIBRARY(mod_postgresql_vhost mod_postgresql_vhost.c)
-ADD_AND_INSTALL_LIBRARY(mod_trigger_b4_dl mod_trigger_b4_dl.c)
-ADD_AND_INSTALL_LIBRARY(mod_uploadprogress mod_uploadprogress.c)
-ADD_AND_INSTALL_LIBRARY(mod_evasive mod_evasive.c)
-ADD_AND_INSTALL_LIBRARY(mod_ssi "mod_ssi_exprparser.c;mod_ssi_expr.c;mod_ssi.c")
-ADD_AND_INSTALL_LIBRARY(mod_flv_streaming mod_flv_streaming.c)
-ADD_AND_INSTALL_LIBRARY(mod_chunked mod_chunked.c)
-ADD_AND_INSTALL_LIBRARY(mod_magnet "mod_magnet.c;mod_magnet_cache.c")
-ADD_AND_INSTALL_LIBRARY(mod_deflate mod_deflate.c)
-ADD_AND_INSTALL_LIBRARY(mod_webdav mod_webdav.c)
-
-IF(NOT WIN32)
-ADD_AND_INSTALL_LIBRARY(mod_cgi mod_cgi.c)
-ENDIF(NOT WIN32)
-
-IF(HAVE_PCRE_H)
- TARGET_LINK_LIBRARIES(lighttpd ${PCRE_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_rewrite ${PCRE_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_dirlisting ${PCRE_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_redirect ${PCRE_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_ssi ${PCRE_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_trigger_b4_dl ${PCRE_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_proxy_core ${PCRE_LIBRARY})
-ENDIF(HAVE_PCRE_H)
-
-ADD_TARGET_PROPERTIES(mod_magnet LINK_FLAGS "${LUA_LDFLAGS}")
-ADD_TARGET_PROPERTIES(mod_magnet COMPILE_FLAGS "${LUA_CFLAGS}")
-
-IF(HAVE_MYSQL_H AND HAVE_LIBMYSQL)
- TARGET_LINK_LIBRARIES(mod_mysql_vhost mysqlclient)
- INCLUDE_DIRECTORIES(/usr/include/mysql)
-ENDIF(HAVE_MYSQL_H AND HAVE_LIBMYSQL)
-
-IF(HAVE_LIBPQ_FE_H AND HAVE_LIBPQ)
- TARGET_LINK_LIBRARIES(mod_postgresql_vhost pq)
- INCLUDE_DIRECTORIES(/usr/include/pgsql)
-ENDIF(HAVE_LIBPQ_FE_H AND HAVE_LIBPQ)
-
-SET(L_MOD_WEBDAV)
-IF(HAVE_SQLITE3_H)
- SET(L_MOD_WEBDAV ${L_MOD_WEBDAV} sqlite3)
-ENDIF(HAVE_SQLITE3_H)
-IF(HAVE_LIBXML_H)
- SET_TARGET_PROPERTIES(mod_webdav PROPERTIES LINK_FLAGS ${XML2_LDFLAGS})
-ENDIF(HAVE_LIBXML_H)
-IF(HAVE_UUID_H)
- IF(NEED_LIBUUID)
- SET(L_MOD_WEBDAV ${L_MOD_WEBDAV} uuid)
- ENDIF(NEED_LIBUUID)
-ENDIF(HAVE_UUID_H)
-
-TARGET_LINK_LIBRARIES(mod_webdav ${L_MOD_WEBDAV})
-
-SET(L_MOD_AUTH)
-IF(HAVE_LIBCRYPT)
- SET(L_MOD_AUTH ${L_MOD_AUTH} crypt)
-ENDIF(HAVE_LIBCRYPT)
-
-IF(HAVE_LDAP_H)
- SET(L_MOD_AUTH ${L_MOD_AUTH} ldap lber)
-ENDIF(HAVE_LDAP_H)
-TARGET_LINK_LIBRARIES(mod_auth ${L_MOD_AUTH})
-
-IF(HAVE_ZLIB_H)
- IF(HAVE_BZLIB_H)
- TARGET_LINK_LIBRARIES(mod_compress ${ZLIB_LIBRARY} bz2)
- TARGET_LINK_LIBRARIES(mod_deflate ${ZLIB_LIBRARY} bz2)
- ELSE(HAVE_BZLIB_H)
- TARGET_LINK_LIBRARIES(mod_compress ${ZLIB_LIBRARY})
- TARGET_LINK_LIBRARIES(mod_deflate ${ZLIB_LIBRARY})
- ENDIF(HAVE_BZLIB_H)
-ENDIF(HAVE_ZLIB_H)
-
-IF(CMAKE_COMPILER_IS_GNUCC)
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -g -Wshadow -W -pedantic ${WARN_FLAGS}")
- SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
- SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_WITHDEBINFO} -O2")
- ADD_DEFINITIONS(-D_GNU_SOURCE)
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
-
-ADD_TARGET_PROPERTIES(lighttpd LINK_FLAGS "-export-dynamic ${GTHREAD_LDFLAGS} ${XML2_LDFLAGS}")
-IF(CMAKE_SYSTEM MATCHES "Linux")
- ## on linux we need pthread and librt for posix-aio
- ADD_TARGET_PROPERTIES(lighttpd LINK_FLAGS "-lrt")
-ENDIF(CMAKE_SYSTEM MATCHES "Linux")
-
-ADD_TARGET_PROPERTIES(lighttpd COMPILE_FLAGS "${GTHREAD_CFLAGS}")
-SET_TARGET_PROPERTIES(lighttpd PROPERTIES CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
-
-IF(WIN32)
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVALGRIND")
- ADD_TARGET_PROPERTIES(lighttpd COMPILE_FLAGS "-DLI_DECLARE_EXPORTS")
- TARGET_LINK_LIBRARIES(lighttpd ws2_32)
- TARGET_LINK_LIBRARIES(mod_proxy_core ws2_32)
- TARGET_LINK_LIBRARIES(mod_proxy_backend_ajp13 ws2_32)
- TARGET_LINK_LIBRARIES(mod_proxy_backend_fastcgi ws2_32)
- TARGET_LINK_LIBRARIES(mod_proxy_backend_scgi ws2_32)
- TARGET_LINK_LIBRARIES(mod_ssi ws2_32)
- # required for mingw gcc/ld
- IF(WITH_GLIB)
- TARGET_LINK_LIBRARIES(lighttpd glib-2.0 gthread-2.0)
- ENDIF(WITH_GLIB)
-
- IF(MINGW)
- TARGET_LINK_LIBRARIES(lighttpd msvcr70)
- ADD_TARGET_PROPERTIES(lighttpd LINK_FLAGS "-Wl,-subsystem,console")
- ENDIF(MINGW)
-ENDIF(WIN32)
-
-IF(NOT BUILD_STATIC)
- IF(HAVE_LIBDL)
- TARGET_LINK_LIBRARIES(lighttpd dl)
- ENDIF(HAVE_LIBDL)
-ENDIF(NOT BUILD_STATIC)
-
-IF(HAVE_LIBAIO_H)
- TARGET_LINK_LIBRARIES(lighttpd aio)
-ENDIF(HAVE_LIBAIO_H)
-
-IF(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
- TARGET_LINK_LIBRARIES(lighttpd ssl)
- TARGET_LINK_LIBRARIES(lighttpd crypto)
-ENDIF(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
-
-IF(NOT WIN32)
-INSTALL(TARGETS ${L_INSTALL_TARGETS}
- RUNTIME DESTINATION ${SBINDIR}
- LIBRARY DESTINATION ${LIGHTTPD_MODULES_DIR}
- ARCHIVE DESTINATION ${LIGHTTPD_MODULES_DIR}/static)
-ELSE(NOT WIN32)
-## HACK to make win32 to install our libraries in desired directory..
-INSTALL(TARGETS lighttpd
- RUNTIME DESTINATION ${SBINDIR}
- ARCHIVE DESTINATION lib/static)
-LIST(REMOVE_ITEM L_INSTALL_TARGETS lighttpd)
-INSTALL(TARGETS ${L_INSTALL_TARGETS}
- RUNTIME DESTINATION ${SBINDIR}/lib
- LIBRARY DESTINATION lib
- ARCHIVE DESTINATION lib/static)
-ENDIF(NOT WIN32)
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index eb50e379..00000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,365 +0,0 @@
-AM_CFLAGS = $(GTHREAD_CFLAGS)
-
-noinst_PROGRAMS=proc_open lemon # simple-fcgi
-if CHECK_WITH_FASTCGI
-sbin_PROGRAMS=lighttpd fcgi-stat-accel
-else
-sbin_PROGRAMS=lighttpd
-endif
-LEMON=$(top_builddir)/src/lemon
-
-lemon_SOURCES=lemon.c
-
-#simple_fcgi_SOURCES=simple-fcgi.c
-#simple_fcgi_LDADD=-lfcgi
-
-if CROSS_COMPILING
-configparser.c configparser.h:
-mod_ssi_exprparser.c mod_ssi_exprparser.h:
-http_req_parser.c http_req_parser.h:
-http_req_range_parser.c http_req_range_parser.h:
-mod_ssi_exprparser.c mod_ssi_exprparser.h:
-else
-configparser.c configparser.h: $(srcdir)/configparser.y $(srcdir)/lempar.c | $(LEMON)
- rm -f configparser.h
- $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
-
-http_resp_parser.c http_resp_parser.h: $(srcdir)/http_resp_parser.y $(srcdir)/lempar.c | $(LEMON)
- rm -f http_resp_parser.h
- $(LEMON) -q $(srcdir)/http_resp_parser.y $(srcdir)/lempar.c
-
-http_req_parser.c http_req_parser.h: $(srcdir)/http_req_parser.y $(srcdir)/lempar.c | $(LEMON)
- rm -f http_req_parser.h
- $(LEMON) -q $(srcdir)/http_req_parser.y $(srcdir)/lempar.c
-
-http_req_range_parser.c http_req_range_parser.h: $(srcdir)/http_req_range_parser.y $(srcdir)/lempar.c | $(LEMON)
- rm -f http_req_range_parser.h
- $(LEMON) -q $(srcdir)/http_req_range_parser.y $(srcdir)/lempar.c
-
-mod_ssi_exprparser.c mod_ssi_exprparser.h: $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c | $(LEMON)
- rm -f mod_ssi_exprparser.h
- $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
-endif
-
-BUILT_SOURCES = configparser.c configparser.h \
- http_resp_parser.c http_resp_parser.h \
- http_req_parser.c http_req_parser.h \
- http_req_range_parser.c http_req_range_parser.h \
- mod_ssi_exprparser.c mod_ssi_exprparser.h
-
-common_src=buffer.c log.c \
- keyvalue.c chunk.c filter.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 \
- 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 iosocket.c \
- configfile-glue.c status_counter.c \
- http-header-glue.c \
- network_write.c network_linux_sendfile.c \
- network_freebsd_sendfile.c network_writev.c \
- network_solaris_sendfilev.c network_openssl.c \
- network_linux_aio.c \
- network_posix_aio.c \
- network_gthread_aio.c network_gthread_sendfile.c \
- network_gthread_freebsd_sendfile.c \
- http_resp.c http_resp_parser.c \
- http_req.c http_req_parser.c \
- http_req_range.c http_req_range_parser.c timing.c
-
-src = server.c response.c connections.c network.c \
- configfile.c configparser.c request.c proc_open.c
-
-if CHECK_WITH_FASTCGI
-fcgi_stat_accel_SOURCES=fcgi-stat-accel.c
-fcgi_stat_accel_LDADD = -lfcgi
-endif
-
-lib_LTLIBRARIES =
-
-if NO_RDYNAMIC
-# if the linker doesn't allow referencing symbols of the binary
-# we have to put everything into a shared-lib and link it into
-# everything
-lib_LTLIBRARIES += liblightcomp.la
-liblightcomp_la_SOURCES=$(common_src)
-liblightcomp_la_CFLAGS=$(AM_CFLAGS)
-liblightcomp_la_LDFLAGS = -avoid-version -no-undefined
-liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(GTHREAD_LIBS)
-common_libadd = liblightcomp.la
-else
-src += $(common_src)
-common_libadd =
-endif
-
-lib_LTLIBRARIES += mod_flv_streaming.la
-mod_flv_streaming_la_SOURCES = mod_flv_streaming.c
-mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_flv_streaming_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_uploadprogress.la
-mod_uploadprogress_la_SOURCES = mod_uploadprogress.c
-mod_uploadprogress_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_uploadprogress_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_evasive.la
-mod_evasive_la_SOURCES = mod_evasive.c
-mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_evasive_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_webdav.la
-mod_webdav_la_SOURCES = mod_webdav.c
-mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
-mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
-
-lib_LTLIBRARIES += mod_magnet.la
-mod_magnet_la_SOURCES = mod_magnet.c mod_magnet_cache.c
-mod_magnet_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS)
-mod_magnet_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_magnet_la_LIBADD = $(MEMCACHE_LIB) $(common_libadd) $(LUA_LIBS) -lm
-
-lib_LTLIBRARIES += mod_trigger_b4_dl.la
-mod_trigger_b4_dl_la_SOURCES = mod_trigger_b4_dl.c
-mod_trigger_b4_dl_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_trigger_b4_dl_la_LIBADD = $(GDBM_LIB) $(MEMCACHE_LIB) $(PCRE_LIB) $(common_libadd)
-
-lib_LTLIBRARIES += mod_mysql_vhost.la
-mod_mysql_vhost_la_SOURCES = mod_mysql_vhost.c
-mod_mysql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
-mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
-
-lib_LTLIBRARIES += mod_postgresql_vhost.la
-mod_postgresql_vhost_la_SOURCES = mod_postgresql_vhost.c
-mod_postgresql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_postgresql_vhost_la_LIBADD = $(POSTGRESQL_LIBS) $(common_libadd)
-mod_postgresql_vhost_la_CPPFLAGS = $(POSTGRESQL_INCLUDE)
-
-
-lib_LTLIBRARIES += mod_sql_vhost_core.la
-mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
-mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_sql_vhost_core_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_cgi.la
-mod_cgi_la_SOURCES = mod_cgi.c
-mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_cgi_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_staticfile.la
-mod_staticfile_la_SOURCES = mod_staticfile.c
-mod_staticfile_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_staticfile_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_deflate.la
-mod_deflate_la_SOURCES = mod_deflate.c
-mod_deflate_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_deflate_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd)
-
-lib_LTLIBRARIES += mod_chunked.la
-mod_chunked_la_SOURCES = mod_chunked.c
-mod_chunked_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_chunked_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_dirlisting.la
-mod_dirlisting_la_SOURCES = mod_dirlisting.c
-mod_dirlisting_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_dirlisting_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-lib_LTLIBRARIES += mod_indexfile.la
-mod_indexfile_la_SOURCES = mod_indexfile.c
-mod_indexfile_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_indexfile_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_setenv.la
-mod_setenv_la_SOURCES = mod_setenv.c
-mod_setenv_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_setenv_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_alias.la
-mod_alias_la_SOURCES = mod_alias.c
-mod_alias_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_alias_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_userdir.la
-mod_userdir_la_SOURCES = mod_userdir.c
-mod_userdir_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_userdir_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_rrdtool.la
-mod_rrdtool_la_SOURCES = mod_rrdtool.c
-mod_rrdtool_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_rrdtool_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_usertrack.la
-mod_usertrack_la_SOURCES = mod_usertrack.c
-mod_usertrack_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_usertrack_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_proxy_core.la
-mod_proxy_core_la_SOURCES = mod_proxy_core.c mod_proxy_core_pool.c \
- mod_proxy_core_backend.c mod_proxy_core_address.c \
- mod_proxy_core_backlog.c mod_proxy_core_rewrites.c \
- mod_proxy_core_protocol.c
-mod_proxy_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_proxy_core_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-lib_LTLIBRARIES += mod_proxy_backend_http.la
-mod_proxy_backend_http_la_SOURCES = mod_proxy_backend_http.c
-mod_proxy_backend_http_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_proxy_backend_http_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-lib_LTLIBRARIES += mod_proxy_backend_fastcgi.la
-mod_proxy_backend_fastcgi_la_SOURCES = mod_proxy_backend_fastcgi.c
-mod_proxy_backend_fastcgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_proxy_backend_fastcgi_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-lib_LTLIBRARIES += mod_proxy_backend_scgi.la
-mod_proxy_backend_scgi_la_SOURCES = mod_proxy_backend_scgi.c
-mod_proxy_backend_scgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_proxy_backend_scgi_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-lib_LTLIBRARIES += mod_proxy_backend_ajp13.la
-mod_proxy_backend_ajp13_la_SOURCES = mod_proxy_backend_ajp13.c
-mod_proxy_backend_ajp13_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_proxy_backend_ajp13_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-
-lib_LTLIBRARIES += mod_ssi.la
-mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c
-mod_ssi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_ssi_la_LIBADD = $(common_libadd) $(PCRE_LIB)
-
-lib_LTLIBRARIES += mod_secdownload.la
-mod_secdownload_la_SOURCES = mod_secure_download.c
-mod_secdownload_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_secdownload_la_LIBADD = $(common_libadd)
-
-#lib_LTLIBRARIES += mod_httptls.la
-#mod_httptls_la_SOURCES = mod_httptls.c
-#mod_httptls_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-#mod_httptls_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_expire.la
-mod_expire_la_SOURCES = mod_expire.c
-mod_expire_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_expire_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_evhost.la
-mod_evhost_la_SOURCES = mod_evhost.c
-mod_evhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_evhost_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_simple_vhost.la
-mod_simple_vhost_la_SOURCES = mod_simple_vhost.c
-mod_simple_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_simple_vhost_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_access.la
-mod_access_la_SOURCES = mod_access.c
-mod_access_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_access_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_compress.la
-mod_compress_la_SOURCES = mod_compress.c
-mod_compress_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_compress_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd)
-
-lib_LTLIBRARIES += mod_auth.la
-mod_auth_la_SOURCES = mod_auth.c http_auth_digest.c http_auth.c
-mod_auth_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_auth_la_LIBADD = $(CRYPT_LIB) $(LDAP_LIB) $(LBER_LIB) $(common_libadd)
-
-lib_LTLIBRARIES += mod_rewrite.la
-mod_rewrite_la_SOURCES = mod_rewrite.c
-mod_rewrite_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_rewrite_la_LIBADD = $(PCRE_LIB) $(common_libadd)
-
-lib_LTLIBRARIES += mod_redirect.la
-mod_redirect_la_SOURCES = mod_redirect.c
-mod_redirect_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_redirect_la_LIBADD = $(PCRE_LIB) $(common_libadd)
-
-lib_LTLIBRARIES += mod_status.la
-mod_status_la_SOURCES = mod_status.c
-mod_status_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_status_la_LIBADD = $(common_libadd)
-
-lib_LTLIBRARIES += mod_accesslog.la
-mod_accesslog_la_SOURCES = mod_accesslog.c
-mod_accesslog_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
-mod_accesslog_la_LIBADD = $(common_libadd)
-
-
-hdr = server.h buffer.h network.h log.h keyvalue.h \
- response.h request.h fastcgi.h chunk.h filter.h \
- settings.h http_auth_digest.h \
- md5.h http_auth.h stream.h \
- fdevent.h connections.h base.h stat_cache.h \
- plugin.h mod_auth.h \
- etag.h joblist.h array.h crc32.h \
- network_backends.h configfile.h bitset.h \
- mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
- configparser.h mod_ssi_exprparser.h \
- sys-mmap.h sys-socket.h \
- proc_open.h mod_sql_vhost_core.h \
- sys-files.h sys-process.h sys-strings.h \
- iosocket.h array-static.h \
- mod_proxy_core_address.h \
- mod_proxy_core_backend.h \
- mod_proxy_core_backlog.h \
- mod_proxy_core.h \
- mod_proxy_core_pool.h \
- mod_proxy_core_rewrites.h \
- status_counter.h \
- http_req.h \
- http_req_parser.h \
- http_req_range.h \
- http_req_range_parser.h \
- http_resp.h \
- http_resp_parser.h \
- http_parser.h \
- ajp13.h \
- mod_proxy_core_protocol.h \
- mod_magnet_cache.h \
- timing.h
-
-DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
-
-lighttpd_SOURCES = $(src)
-lighttpd_LDADD = $(PCRE_LIB) $(DL_LIB) $(SENDFILE_LIB) $(ATTR_LIB) $(common_libadd) $(SSL_LIB) $(AIO_LIB) $(POSIX_AIO_LIB) $(GTHREAD_LIBS)
-lighttpd_LDFLAGS = -export-dynamic
-
-proc_open_SOURCES = proc_open.c buffer.c
-proc_open_CPPFLAGS= -DDEBUG_PROC_OPEN
-
-#gen_license_SOURCES = license.c md5.c buffer.c gen_license.c
-
-#ssl_SOURCES = ssl.c
-
-
-#adserver_SOURCES = buffer.c iframe.c
-#adserver_LDADD = -lfcgi -lmysqlclient
-
-#error_test_SOURCES = error_test.c
-
-#evalo_SOURCES = buffer.c eval.c
-#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 \
- http_resp_parser.y \
- http_req_parser.y \
- http_req_range_parser.y
-
-SUBDIRS=valgrind
diff --git a/src/XGetopt.h b/src/XGetopt.h
deleted file mode 100644
index 7e75f26e..00000000
--- a/src/XGetopt.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// XGetopt.h Version 1.2
-//
-// Author: Hans Dietrich
-// hdietrich2@hotmail.com
-//
-// This software is released into the public domain.
-// You are free to use it in any way you like.
-//
-// This software is provided "as is" with no expressed
-// or implied warranty. I accept no liability for any
-// damage or loss of business that this software may cause.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef XGETOPT_H
-#define XGETOPT_H
-
-extern int optind, opterr;
-extern TCHAR *optarg;
-
-int getopt(int argc, TCHAR *argv[], TCHAR *optstring);
-
-#endif //XGETOPT_H
diff --git a/src/ajp13.h b/src/ajp13.h
deleted file mode 100644
index 8ad6a577..00000000
--- a/src/ajp13.h
+++ /dev/null
@@ -1,136 +0,0 @@
-
-#ifndef _AJP13_H
-#define _AJP13_H
-/**
- * AJP13 protocol definitions.
- */
-#define AJP13_MAX_PACKET_SIZE (8 * 1024)
-#define AJP13_MAX_BODY_PACKET_SIZE (AJP13_MAX_PACKET_SIZE - AJP13_HEADER_LEN - 2)
-
-/**
- * two byte maigc codes
- */
-#define AJP13_SERVER_MAGIC 0x1234
-#define AJP13_CONTAINER_MAGIC 0x4142
-
-/**
- * packet types.
- */
-typedef enum {
- AJP13_TYPE_DATA = 0, /* 0 */
- AJP13_TYPE_UNKNOWN, /* 1 */
- AJP13_TYPE_FORWARD_REQUEST, /* 2 */
- AJP13_TYPE_SEND_BODY_CHUNK, /* 3 */
- AJP13_TYPE_SEND_HEADERS, /* 4 */
- AJP13_TYPE_END_RESPONSE, /* 5 */
- AJP13_TYPE_GET_BODY_CHUNK, /* 6 */
- AJP13_TYPE_SHUTDOWN, /* 7 */
- AJP13_TYPE_PING_REQUEST, /* 8 */
- AJP13_TYPE_CPONG_REPLY, /* 9 */
- AJP13_TYPE_CPING_REQUEST, /* 10 */
-} ajp13_type_t;
-
-/*
- * http method codes
- */
-typedef enum {
- AJP13_METHOD_UNKNOWN = 0, /* 0 */
- AJP13_METHOD_OPTIONS, /* 1 */
- AJP13_METHOD_GET, /* 2 */
- AJP13_METHOD_HEAD, /* 3 */
- AJP13_METHOD_POST, /* 4 */
- AJP13_METHOD_PUT, /* 5 */
- AJP13_METHOD_DELETE, /* 6 */
- AJP13_METHOD_TRACE, /* 7 */
- AJP13_METHOD_PROPFIND, /* 8 */
- AJP13_METHOD_PROPPATCH, /* 9 */
- AJP13_METHOD_MKCOL, /* 10 */
- AJP13_METHOD_COPY, /* 11 */
- AJP13_METHOD_MOVE, /* 12 */
- AJP13_METHOD_LOCK, /* 13 */
- AJP13_METHOD_UNLOCK, /* 14 */
- AJP13_METHOD_ACL, /* 15 */
- AJP13_METHOD_REPORT, /* 16 */
- AJP13_METHOD_VERSION_CONTROL, /* 17 */
- AJP13_METHOD_CHECKIN, /* 18 */
- AJP13_METHOD_CHECKOUT, /* 19 */
- AJP13_METHOD_UNCHECKOUT, /* 20 */
- AJP13_METHOD_SEARCH, /* 21 */
- AJP13_METHOD_MKWORKSPACE, /* 22 */
- AJP13_METHOD_UPDATE, /* 23 */
- AJP13_METHOD_LABEL, /* 24 */
- AJP13_METHOD_MERGE, /* 25 */
- AJP13_METHOD_BASELINE_CONTROL,/* 26 */
- AJP13_METHOD_MKACTIVITY /* 27 */
-} ajp13_method_t;
-
-/*
- * request headers
- */
-typedef enum {
- AJP13_REQ_ACCEPT = 0x01, /* 0x01 */
- AJP13_REQ_ACCEPT_CHARSET, /* 0x02 */
- AJP13_REQ_ACCEPT_ENCODING, /* 0x03 */
- AJP13_REQ_ACCEPT_LANGUAGE, /* 0x04 */
- AJP13_REQ_AUTHORIZATION, /* 0x05 */
- AJP13_REQ_CONNECTION, /* 0x06 */
- AJP13_REQ_CONTENT_TYPE, /* 0x07 */
- AJP13_REQ_CONTENT_LENGTH, /* 0x08 */
- AJP13_REQ_COOKIE, /* 0x09 */
- AJP13_REQ_COOKIE2, /* 0x0A */
- AJP13_REQ_HOST, /* 0x0B */
- AJP13_REQ_PRAGMA, /* 0x0C */
- AJP13_REQ_REFERER, /* 0x0D */
- AJP13_REQ_USER_AGENT /* 0x0E */
-} ajp13_request_header_t;
-
-/*
- * request attributes
- */
-typedef enum {
- AJP13_ATTRIBUTE_CONTEXT = 1, /* 1 */
- AJP13_ATTRIBUTE_SERVLET_PATH, /* 2 */
- AJP13_ATTRIBUTE_REMOTE_USER, /* 3 */
- AJP13_ATTRIBUTE_AUTH_TYPE, /* 4 */
- AJP13_ATTRIBUTE_QUERY_STRING, /* 5 */
- AJP13_ATTRIBUTE_JVM_ROUTE, /* 6 */
- AJP13_ATTRIBUTE_SSL_CERT, /* 7 */
- AJP13_ATTRIBUTE_SSL_CIPHER, /* 8 */
- AJP13_ATTRIBUTE_SSL_SESSION, /* 9 */
- AJP13_ATTRIBUTE_REQ_ATTRIBUTE, /* 10 */
- AJP13_ATTRIBUTE_SSL_KEY_SIZE, /* 11 */
- AJP13_ATTRIBUTE_SECRET, /* 12 */
- AJP13_ATTRIBUTE_STORED_METHOD, /* 13 */
- AJP13_ATTRIBUTE_ARE_DONE = 0xFF, /* 0xFF */
-} ajp13_attributes_t;
-
-/*
- * response headers
- */
-typedef enum {
- AJP13_RESP_CONTENT_TYPE = 0x01, /* 0x01 */
- AJP13_RESP_CONTENT_LANGUAGE, /* 0x02 */
- AJP13_RESP_CONTENT_LENGTH, /* 0x03 */
- AJP13_RESP_DATE, /* 0x04 */
- AJP13_RESP_LAST_MODIFIED, /* 0x05 */
- AJP13_RESP_LOCATION, /* 0x06 */
- AJP13_RESP_SET_COOKIE, /* 0x07 */
- AJP13_RESP_SET_COOKIE2, /* 0x08 */
- AJP13_RESP_SERVLET_ENGINE, /* 0x09 */
- AJP13_RESP_STATUS, /* 0x0A */
- AJP13_RESP_WWW_AUTHENTICATE, /* 0x0B */
-} ajp13_response_header_t;
-
-/*
- *
- */
-#define AJP13_COMMON_HEADER_CODE 0xA000
-
-/*
- * fixed header lengths.
- */
-#define AJP13_HEADER_LEN 4
-#define AJP13_FULL_HEADER_LEN 5
-
-#endif /* _AJP13_H */
-
diff --git a/src/array-static.h b/src/array-static.h
deleted file mode 100644
index fdeebf63..00000000
--- a/src/array-static.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef _ARRAY_STATIC_H_
-#define _ARRAY_STATIC_H_
-
-/* define a generic array of <type>
- * */
-
-#define ARRAY_STATIC_DEF(name, type, extra) \
-typedef struct { \
- type **ptr; \
- size_t used; \
- size_t size; \
- extra\
-} name
-
-/* all append operations need a 'resize' for the +1 */
-
-#define ARRAY_STATIC_PREPARE_APPEND(a) \
- if (a->size == 0) { \
- a->size = 16; \
- a->ptr = malloc(a->size * sizeof(*(a->ptr))); \
- } else if (a->size == a->used) { \
- a->size += 16; \
- a->ptr = realloc(a->ptr, a->size * sizeof(*(a->ptr))); \
- }
-
-#define FOREACH(array, type, element, func) \
-do { size_t _i; for (_i = 0; _i < array->used; _i++) { type *element = array->ptr[_i]; func; } } while(0);
-
-#define STRUCT_INIT(type, var) \
- type *var;\
- var = calloc(1, sizeof(*var))
-
-#define ARRAY_STATIC_FREE(array, type, element, func) \
- FOREACH(array, type, element, func); \
- if(array->ptr) free(array->ptr); \
- array->ptr = NULL;
-
-#endif
diff --git a/src/array.c b/src/array.c
deleted file mode 100644
index 6d740f1a..00000000
--- a/src/array.c
+++ /dev/null
@@ -1,398 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include <errno.h>
-#include <assert.h>
-
-#include "array.h"
-#include "buffer.h"
-
-array *array_init(void) {
- array *a;
-
- a = calloc(1, sizeof(*a));
- assert(a);
-
- a->next_power_of_2 = 1;
-
- return a;
-}
-
-array *array_init_array(array *src) {
- size_t i;
- array *a = array_init();
-
- a->used = src->used;
- a->size = src->size;
- a->next_power_of_2 = src->next_power_of_2;
- a->unique_ndx = src->unique_ndx;
-
- a->data = malloc(sizeof(*src->data) * src->size);
- for (i = 0; i < src->size; i++) {
- if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]);
- else a->data[i] = NULL;
- }
-
- a->sorted = malloc(sizeof(*src->sorted) * src->size);
- memcpy(a->sorted, src->sorted, sizeof(*src->sorted) * src->size);
- return a;
-}
-
-void array_free(array *a) {
- size_t i;
- if (!a) return;
-
- if (!a->is_weakref) {
- for (i = 0; i < a->size; i++) {
- if (a->data[i]) a->data[i]->free(a->data[i]);
- }
- }
-
- if (a->data) free(a->data);
- if (a->sorted) free(a->sorted);
-
- free(a);
-}
-
-void array_reset(array *a) {
- size_t i;
- if (!a) return;
-
- if (!a->is_weakref) {
- for (i = 0; i < a->used; i++) {
- a->data[i]->reset(a->data[i]);
- }
- }
-
- a->used = 0;
-}
-
-data_unset *array_pop(array *a) {
- data_unset *du;
-
- assert(a->used != 0);
-
- a->used --;
- du = a->data[a->used];
- a->data[a->used] = NULL;
-
- return du;
-}
-
-static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
- int ndx = -1;
- int i, pos = 0;
-
- if (key == NULL) return -1;
-
- /* try to find the string */
- for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
- int cmp;
-
- if (pos < 0) {
- pos += i;
- } else if (pos >= (int)a->used) {
- pos -= i;
- } else {
- cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
-
- if (cmp == 0) {
- /* found */
- ndx = a->sorted[pos];
- break;
- } else if (cmp < 0) {
- pos -= i;
- } else {
- pos += i;
- }
- }
- if (i == 0) break;
- }
-
- if (rndx) *rndx = pos;
-
- return ndx;
-}
-
-data_unset *array_get_element(array *a, const char *key, size_t keylen) {
- int ndx;
-
- if (-1 != (ndx = array_get_index(a, key, keylen + 1, NULL))) {
- /* found, leave here */
-
- return a->data[ndx];
- }
-
- return NULL;
-}
-
-data_unset *array_get_unused_element(array *a, data_type_t t) {
- data_unset *ds = NULL;
-
- UNUSED(t);
-
- if (a->size == 0) return NULL;
-
- if (a->used == a->size) return NULL;
-
- if (a->data[a->used]) {
- ds = a->data[a->used];
-
- a->data[a->used] = NULL;
- }
-
- return ds;
-}
-
-void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
- data_string *ds_dst;
-
- if (NULL != (ds_dst = (data_string *)array_get_element(hdrs, key, key_len))) {
- buffer_copy_string_len(ds_dst->value, value, val_len);
- return;
- }
-
- if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
- ds_dst = data_string_init();
- }
-
- buffer_copy_string_len(ds_dst->key, key, key_len);
- buffer_copy_string_len(ds_dst->value, value, val_len);
- array_insert_unique(hdrs, (data_unset *)ds_dst);
-}
-
-void array_append_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
- data_string *ds_dst;
-
- if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
- ds_dst = data_string_init();
- }
-
- buffer_copy_string_len(ds_dst->key, key, key_len);
- buffer_copy_string_len(ds_dst->value, value, val_len);
- array_insert_unique(hdrs, (data_unset *)ds_dst);
-}
-
-/* replace or insert data, return the old one with the same key */
-data_unset *array_replace(array *a, data_unset *du) {
- int ndx;
-
- if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
- array_insert_unique(a, du);
- return NULL;
- } else {
- data_unset *old = a->data[ndx];
- a->data[ndx] = du;
- return old;
- }
-}
-
-int array_insert_unique(array *a, data_unset *str) {
- int ndx = -1;
- int pos = 0;
- size_t j;
-
- /* generate unique index if necessary */
- if (str->key->used == 0 || str->is_index_key) {
- buffer_copy_long(str->key, a->unique_ndx++);
- str->is_index_key = 1;
- }
-
- /* try to find the string */
- if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
- /* found, leave here */
- if (a->data[ndx]->type == str->type) {
- str->insert_dup(a->data[ndx], str);
- } else {
- fprintf(stderr, "a\n");
- }
- return 0;
- }
-
- /* insert */
-
- if (a->used+1 > INT_MAX) {
- /* we can't handle more then INT_MAX entries: see array_get_index() */
- return -1;
- }
-
- if (a->size == 0) {
- a->size = 16;
- a->data = malloc(sizeof(*a->data) * a->size);
- a->sorted = malloc(sizeof(*a->sorted) * a->size);
- assert(a->data);
- assert(a->sorted);
- for (j = a->used; j < a->size; j++) a->data[j] = NULL;
- } else if (a->size == a->used) {
- a->size += 16;
- a->data = realloc(a->data, sizeof(*a->data) * a->size);
- a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size);
- assert(a->data);
- assert(a->sorted);
- for (j = a->used; j < a->size; j++) a->data[j] = NULL;
- }
-
- ndx = (int) a->used;
-
- a->data[a->used++] = str;
-
- if (pos != ndx &&
- ((pos < 0) ||
- buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
- pos++;
- }
-
- /* move everything one step to the right */
- if (pos != ndx) {
- memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
- }
-
- /* insert */
- a->sorted[pos] = ndx;
-
- if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
-
- return 0;
-}
-
-void array_print_indent(int depth) {
- int i;
- for (i = 0; i < depth; i ++) {
- fprintf(stdout, " ");
- }
-}
-
-size_t array_get_max_key_length(array *a) {
- size_t maxlen, i;
-
- maxlen = 0;
- for (i = 0; i < a->used; i ++) {
- data_unset *du = a->data[i];
- size_t len = strlen(du->key->ptr);
-
- if (len > maxlen) {
- maxlen = len;
- }
- }
- return maxlen;
-}
-
-int array_print(array *a, int depth) {
- size_t i;
- size_t maxlen;
- int oneline = 1;
-
- if (a->used > 5) {
- oneline = 0;
- }
- for (i = 0; i < a->used && oneline; i++) {
- data_unset *du = a->data[i];
- if (!du->is_index_key) {
- oneline = 0;
- break;
- }
- switch (du->type) {
- case TYPE_INTEGER:
- case TYPE_STRING:
- case TYPE_COUNT:
- break;
- default:
- oneline = 0;
- break;
- }
- }
- if (oneline) {
- fprintf(stdout, "(");
- for (i = 0; i < a->used; i++) {
- data_unset *du = a->data[i];
- if (i != 0) {
- fprintf(stdout, ", ");
- }
- du->print(du, depth + 1);
- }
- fprintf(stdout, ")");
- return 0;
- }
-
- maxlen = array_get_max_key_length(a);
- fprintf(stdout, "(\n");
- for (i = 0; i < a->used; i++) {
- data_unset *du = a->data[i];
- array_print_indent(depth + 1);
- if (!du->is_index_key) {
- int j;
-
- if (i && (i % 5) == 0) {
- fprintf(stdout, "# %zd\n", i);
- array_print_indent(depth + 1);
- }
- fprintf(stdout, "\"%s\"", du->key->ptr);
- for (j = maxlen - strlen(du->key->ptr); j > 0; j --) {
- fprintf(stdout, " ");
- }
- fprintf(stdout, " => ");
- }
- du->print(du, depth + 1);
- fprintf(stdout, ",\n");
- }
- if (!(i && (i - 1 % 5) == 0)) {
- array_print_indent(depth + 1);
- fprintf(stdout, "# %zd\n", i);
- }
- array_print_indent(depth);
- fprintf(stdout, ")");
-
- return 0;
-}
-
-#ifdef DEBUG_ARRAY
-int main (int argc, char **argv) {
- array *a;
- data_string *ds;
- data_count *dc;
-
- UNUSED(argc);
- UNUSED(argv);
-
- a = array_init();
-
- ds = data_string_init();
- buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
- buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
-
- array_insert_unique(a, (data_unset *)ds);
-
- ds = data_string_init();
- buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
- buffer_copy_string_len(ds->value, CONST_STR_LEN("hameplman"));
-
- array_insert_unique(a, (data_unset *)ds);
-
- ds = data_string_init();
- buffer_copy_string_len(ds->key, CONST_STR_LEN("123"));
- buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
-
- array_insert_unique(a, (data_unset *)ds);
-
- dc = data_count_init();
- buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
-
- array_insert_unique(a, (data_unset *)dc);
-
- dc = data_count_init();
- buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
-
- array_insert_unique(a, (data_unset *)dc);
-
- array_print(a, 0);
-
- array_free(a);
-
- fprintf(stderr, "%d\n",
- buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
-
- return 0;
-}
-#endif
diff --git a/src/array.h b/src/array.h
deleted file mode 100644
index 0fa73e87..00000000
--- a/src/array.h
+++ /dev/null
@@ -1,160 +0,0 @@
-#ifndef ARRAY_H
-#define ARRAY_H
-
-#include "settings.h"
-
-#include <stdlib.h>
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef HAVE_PCRE_H
-# include <pcre.h>
-#endif
-#include "buffer.h"
-
-#define DATA_IS_STRING(x) (x->type == TYPE_STRING)
-
-typedef enum { TYPE_UNSET, TYPE_STRING, TYPE_COUNT, TYPE_ARRAY, TYPE_INTEGER, TYPE_FASTCGI, TYPE_CONFIG } data_type_t;
-#define DATA_UNSET \
- data_type_t type; \
- buffer *key; \
- int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
- struct data_unset *(*copy)(const struct data_unset *src); \
- void (* free)(struct data_unset *p); \
- void (* reset)(struct data_unset *p); \
- int (*insert_dup)(struct data_unset *dst, struct data_unset *src); \
- void (*print)(const struct data_unset *p, int depth)
-
-typedef struct data_unset {
- DATA_UNSET;
-} data_unset;
-
-typedef struct {
- data_unset **data;
-
- size_t *sorted;
-
- size_t used;
- size_t size;
-
- size_t unique_ndx;
-
- size_t next_power_of_2;
- int is_weakref; /* data is weakref, don't bother the data */
-} array;
-
-typedef struct {
- DATA_UNSET;
-
- int count;
-} data_count;
-
-LI_API data_count* data_count_init(void);
-
-typedef struct {
- DATA_UNSET;
-
- buffer *value;
-} data_string;
-
-LI_API data_string* data_string_init(void);
-LI_API data_string* data_response_init(void);
-
-typedef struct {
- DATA_UNSET;
-
- array *value;
-} data_array;
-
-LI_API data_array* data_array_init(void);
-
-/**
- * possible compare ops in the configfile parser
- */
-typedef enum {
- CONFIG_COND_UNSET,
- CONFIG_COND_EQ, /** == */
- CONFIG_COND_MATCH, /** =~ */
- CONFIG_COND_NE, /** != */
- CONFIG_COND_NOMATCH /** !~ */
-} config_cond_t;
-
-/**
- * possible fields to match against
- */
-typedef enum {
- COMP_UNSET,
- COMP_SERVER_SOCKET,
- COMP_HTTP_URL,
- COMP_HTTP_HOST,
- COMP_HTTP_REFERER,
- COMP_HTTP_USER_AGENT,
- COMP_HTTP_COOKIE,
- COMP_HTTP_SCHEME,
- COMP_HTTP_REMOTE_IP,
- COMP_HTTP_QUERY_STRING,
- COMP_HTTP_REQUEST_METHOD,
- COMP_PHYSICAL_PATH,
- COMP_PHYSICAL_PATH_EXISTS,
-
- COMP_LAST_ELEMENT
-} comp_key_t;
-
-/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
- * for print: comp_key op string
- * for compare: comp cond string/regex
- */
-
-typedef struct _data_config data_config;
-struct _data_config {
- DATA_UNSET;
-
- array *value;
-
- buffer *comp_key;
- comp_key_t comp;
-
- config_cond_t cond;
- buffer *op;
-
- int context_ndx; /* more or less like an id */
- array *childs;
- /* nested */
- data_config *parent;
- /* for chaining only */
- data_config *prev;
- data_config *next;
-
- buffer *string;
-#ifdef HAVE_PCRE_H
- pcre *regex;
- pcre_extra *regex_study;
-#endif
-};
-
-LI_API data_config* data_config_init(void);
-
-typedef struct {
- DATA_UNSET;
-
- int value;
-} data_integer;
-
-LI_API data_integer* data_integer_init(void);
-LI_API array* array_init(void);
-LI_API array* array_init_array(array *a);
-LI_API void array_free(array *a);
-LI_API void array_reset(array *a);
-LI_API int array_insert_unique(array *a, data_unset *str);
-LI_API data_unset* array_pop(array *a);
-LI_API int array_print(array *a, int depth);
-LI_API data_unset* array_get_unused_element(array *a, data_type_t t);
-LI_API data_unset* array_get_element(array *a, const char *key, size_t key_len);
-LI_API void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len);
-LI_API void array_append_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len);
-LI_API data_unset* array_replace(array *a, data_unset *du);
-LI_API int array_strcasecmp(const char *a, size_t a_len, const char *b, size_t b_len);
-LI_API void array_print_indent(int depth);
-LI_API size_t array_get_max_key_length(array *a);
-
-#endif
diff --git a/src/base.h b/src/base.h
deleted file mode 100644
index a61a755a..00000000
--- a/src/base.h
+++ /dev/null
@@ -1,731 +0,0 @@
-#ifndef _BASE_H_
-#define _BASE_H_
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <limits.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-#include "settings.h"
-
-#ifdef HAVE_GLIB_H
-/* include glib.h before our buffer.h and array.h to make sure their parameter-names
- * don't clash with our type-names */
-#include <glib.h>
-#endif
-
-#include "buffer.h"
-#include "array.h"
-#include "chunk.h"
-#include "filter.h"
-#include "keyvalue.h"
-#include "settings.h"
-#include "fdevent.h"
-#include "sys-socket.h"
-#include "http_req.h"
-#include "etag.h"
-
-#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
-# define USE_OPENSSL
-# include <openssl/ssl.h>
-# if ! defined OPENSSL_NO_TLSEXT && ! defined SSL_CTRL_SET_TLSEXT_HOSTNAME
-# define OPENSSL_NO_TLSEXT
-# endif
-#endif
-
-#ifdef HAVE_SYS_INOTIFY_H
-# include <sys/inotify.h>
-#endif
-
-#ifdef USE_LINUX_AIO_SENDFILE
-# include <libaio.h>
-#endif
-
-#ifdef USE_POSIX_AIO
-# include <aio.h>
-#endif
-
-/** some compat */
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-#ifndef SIZE_MAX
-# ifdef SIZE_T_MAX
-# define SIZE_MAX SIZE_T_MAX
-# else
-# define SIZE_MAX ((size_t)~0)
-# endif
-#endif
-
-#ifndef SSIZE_MAX
-# define SSIZE_MAX ((size_t)~0 >> 1)
-#endif
-
-#ifdef __APPLE__
-#include <crt_externs.h>
-#define environ (* _NSGetEnviron())
-#elif !defined(_WIN32)
-extern char **environ;
-#endif
-
-/* for solaris 2.5 and NetBSD 1.3.x */
-#ifndef HAVE_SOCKLEN_T
-typedef int socklen_t;
-#endif
-
-/* solaris and NetBSD 1.3.x again */
-#if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
-/* # define uint32_t u_int32_t */
-typedef unsigned __int32 uint32_t;
-#endif
-
-
-#ifndef SHUT_WR
-# define SHUT_WR 1
-#endif
-
-#include "settings.h"
-
-typedef enum {
- TIME_CONNECTION_ACCEPT,
- TIME_REQUEST_START,
- TIME_BACKEND_CONNECT,
-
- TIME_BACKEND_SEND_HEADER_START,
- TIME_BACKEND_SEND_HEADER_END,
- TIME_BACKEND_SEND_CONTENT_START,
- TIME_BACKEND_SEND_CONTENT_END,
-
- TIME_BACKEND_RECV_HEADER_START,
- TIME_BACKEND_RECV_HEADER_END,
- TIME_BACKEND_RECV_CONTENT_START,
- TIME_BACKEND_RECV_CONTENT_END,
-
- TIME_BACKEND_DISCONNECT,
-
- TIME_SEND_HEADER_START,
- TIME_SEND_HEADER_END,
-
- TIME_SEND_CONTENT_START,
-
- TIME_SEND_ASYNC_READ_QUEUED, /* for async-io read */
- TIME_SEND_ASYNC_READ_START, /* for async-io read */
- TIME_SEND_ASYNC_READ_END, /* for async-io read */
- TIME_SEND_ASYNC_READ_END_QUEUED, /* for async-io read */
-
- TIME_SEND_WRITE_START,
- TIME_SEND_WRITE_END,
-
- TIME_SEND_CONTENT_END,
-
- TIME_REQUEST_END,
- TIME_CONNECTION_CLOSE,
-
- TIME_LAST_ELEMENT
-} connection_time_field_t;
-
-typedef enum { T_CONFIG_UNSET,
- T_CONFIG_STRING,
- T_CONFIG_SHORT,
- T_CONFIG_INT,
- T_CONFIG_BOOLEAN,
- T_CONFIG_ARRAY,
- T_CONFIG_LOCAL,
- T_CONFIG_DEPRECATED,
- T_CONFIG_UNSUPPORTED
-} config_values_type_t;
-
-typedef enum { T_CONFIG_SCOPE_UNSET,
- T_CONFIG_SCOPE_SERVER,
- T_CONFIG_SCOPE_CONNECTION
-} config_scope_type_t;
-
-typedef struct {
- const char *key;
- void *destination;
-
- config_values_type_t type;
- config_scope_type_t scope;
-} config_values_t;
-
-typedef enum { DIRECT, EXTERNAL } connection_type;
-
-typedef struct {
- char *key;
- connection_type type;
- char *value;
-} request_handler;
-
-typedef struct {
- char *key;
- char *host;
- unsigned short port;
- int used;
- short factor;
-} fcgi_connections;
-
-typedef struct {
- /** HEADER */
- /* the request-line */
- buffer *request;
- buffer *uri;
-
- buffer *orig_uri;
-
- http_method_t http_method;
- http_version_t http_version;
-
- buffer *http_host;
-
- array *headers;
-
- /* CONTENT */
- off_t content_length; /* returned by strtoul() */
-
- /* internal representation */
- int accept_encoding;
-
- /* internal */
- buffer *pathinfo;
-} request;
-
-typedef struct {
- off_t content_length;
- int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
-
- array *headers;
-
- enum {
- HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
- } transfer_encoding;
-} response;
-
-typedef struct {
- buffer *scheme; /* scheme without colon or slashes ( "http" or "https" ) */
-
- /* authority with optional portnumber ("site.name" or "site.name:8080" ) NOTE: without "username:password@" */
- buffer *authority;
-
- /* path including leading slash ("/" or "/index.html") - urldecoded, and sanitized ( buffer_path_simplify() && buffer_urldecode_path() ) */
- buffer *path;
- buffer *path_raw; /* raw path, as sent from client. no urldecoding or path simplifying */
- buffer *query; /* querystring ( everything after "?", ie: in "/index.php?foo=1", query is "foo=1" ) */
-} request_uri;
-
-typedef struct {
- buffer *path;
- buffer *basedir; /* path = "(basedir)(.*)" */
-
- buffer *doc_root; /* path = doc_root + rel_path */
- buffer *rel_path;
-
- buffer *etag;
-} physical;
-
-typedef struct {
- buffer *name;
- buffer *etag;
-
- struct stat st;
-
- time_t stat_ts;
-
- enum {
- STAT_CACHE_ENTRY_UNSET,
- STAT_CACHE_ENTRY_ASYNC_STAT,
- STAT_CACHE_ENTRY_STAT_FINISHED
- } state;
-
-#ifdef HAVE_LSTAT
- char is_symlink;
-#endif
-
-#if defined(HAVE_SYS_INOTIFY_H)
- int dir_version; /* when this entry was created the dir had this version */
- int dir_ndx;
-#endif
-
- buffer *content_type;
-} stat_cache_entry;
-
-typedef struct {
-#ifdef HAVE_GLIB_H
- GHashTable *files; /* a HashTable of stat_cache_entries for the files */
- GHashTable *dirs; /* a HashTable of stat_cache_entries for the dirs */
-#endif
-
- buffer *dir_name; /* for building the dirname from the filename */
- buffer *hash_key; /* tmp-buf for building the hash-key */
-
-#if defined(HAVE_SYS_INOTIFY_H)
- iosocket *sock; /* socket to the inotify fd (this should be in a backend struct */
-#endif
-} stat_cache;
-
-typedef struct {
- array *mimetypes;
-
- /* virtual-servers */
- buffer *document_root;
- buffer *server_name;
- buffer *error_handler;
- buffer *server_tag;
- buffer *dirlist_encoding;
- buffer *errorfile_prefix;
-
- unsigned short max_keep_alive_requests;
- unsigned short max_keep_alive_idle;
- unsigned short max_read_idle;
- unsigned short max_write_idle;
- unsigned short max_connection_idle;
- unsigned short use_xattr;
- unsigned short follow_symlink;
- unsigned short range_requests;
-
- /* debug */
-
- unsigned short log_file_not_found;
- unsigned short log_request_header;
- unsigned short log_request_handling;
- unsigned short log_response_header;
- unsigned short log_condition_handling;
- unsigned short log_condition_cache_handling;
- unsigned short log_ssl_noise;
- unsigned short log_timeouts;
-
-
- /* server wide */
- buffer *ssl_pemfile;
- buffer *ssl_ca_file;
- buffer *ssl_cipher_list;
- unsigned short ssl_use_sslv2;
- unsigned short ssl_verifyclient;
- unsigned short ssl_verifyclient_enforce;
- unsigned short ssl_verifyclient_depth;
- buffer *ssl_verifyclient_username;
- unsigned short ssl_verifyclient_export_cert;
-
- unsigned short use_ipv6;
- unsigned short is_ssl;
- unsigned short allow_http11;
- unsigned short etag_use_inode;
- unsigned short etag_use_mtime;
- unsigned short etag_use_size;
- unsigned short force_lowercase_filenames; /* if the FS is case-insensitive, force all files to lower-case */
- unsigned int max_request_size;
-
- unsigned short kbytes_per_second; /* connection kb/s limit */
-
- /* configside */
- unsigned short global_kbytes_per_second; /* */
-
- off_t global_bytes_per_second_cnt;
- /* server-wide traffic-shaper
- *
- * each context has the counter which is inited once
- * per second by the global_kbytes_per_second config-var
- *
- * as soon as global_kbytes_per_second gets below 0
- * the connected conns are "offline" a little bit
- *
- * the problem:
- * we somehow have to lose our "we are writable" signal
- * on the way.
- *
- */
- off_t *global_bytes_per_second_cnt_ptr; /* */
-
-#ifdef USE_OPENSSL
- SSL_CTX *ssl_ctx;
-#endif
-} specific_config;
-
-/* the order of the items should be the same as they are processed
- * read before write as we use this later */
-typedef enum {
- CON_STATE_CONNECT, /** we are wait for a connect */
- CON_STATE_REQUEST_START, /** after the connect, the request is initialized, keep-alive starts here again */
- CON_STATE_READ_REQUEST_HEADER, /** loop in the read-request-header until the full header is received */
- CON_STATE_VALIDATE_REQUEST_HEADER, /** validate the request-header */
- CON_STATE_HANDLE_REQUEST_HEADER, /** find a handler for the request */
- CON_STATE_READ_REQUEST_CONTENT, /** forward the request content to the handler */
- CON_STATE_HANDLE_RESPONSE_HEADER, /** the backend bounces the response back to the client */
- CON_STATE_WRITE_RESPONSE_HEADER,
- CON_STATE_WRITE_RESPONSE_CONTENT,
- CON_STATE_RESPONSE_END,
- CON_STATE_ERROR,
- CON_STATE_CLOSE
-} connection_state_t;
-
-typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
-typedef struct {
- cond_result_t result;
- int patterncount;
- int matches[3 * 10];
- buffer *comp_value; /* just a pointer */
-
- comp_key_t comp_type;
-} cond_cache_t;
-
-typedef struct {
- connection_state_t state;
-
- /* timestamps */
- time_t read_idle_ts;
- time_t close_timeout_ts;
- time_t write_request_ts;
-
- time_t connection_start;
- time_t request_start;
-
- struct timeval start_tv;
-
- size_t request_count; /* number of requests handled in this connection */
- size_t loops_per_request; /* to catch endless loops in a single request
- *
- * used by mod_rewrite, mod_fastcgi, ... and others
- * this is self-protection
- */
-
- iosocket *sock;
- int ndx; /* reverse mapping to server->connection[ndx] */
-
- /* fd states */
- int is_readable;
- int is_writable;
-
- int keep_alive; /* only request.c can enable it, all others just disable */
- int keep_alive_idle; /* remember max_keep_alive_idle from config */
-
- int file_started;
-
- chunkqueue *send; /* the response-content before filters are applied */
- chunkqueue *recv; /* the request-content, without encoding */
-
- filter_chain *send_filters; /* the chain of filters to apply to response-content. */
- chunkqueue *send_raw; /* the full response (HTTP-Header + compression + chunking ) */
- chunkqueue *recv_raw; /* the full request (HTTP-Header + chunking ) */
-
- int traffic_limit_reached;
-
- off_t bytes_written; /* used by mod_accesslog, mod_rrd */
- off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
- off_t bytes_read; /* used by mod_accesslog, mod_rrd */
- off_t bytes_header;
-
- int http_status;
-
- sock_addr dst_addr;
- buffer *dst_addr_buf;
-
- /* request */
- buffer *parse_request;
-
- http_req *http_req;
- request request;
- request_uri uri;
- physical physical;
- response response;
-
- size_t header_len;
-
- buffer *authed_user;
- array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
-
- /* response */
- int got_response;
-
- int in_joblist;
-
- connection_type mode;
-
- void **plugin_ctx; /* plugin connection specific config */
-
- specific_config conf; /* global connection specific config */
- cond_cache_t *cond_cache;
-
- buffer *server_name;
-
- /* error-handler */
- buffer *error_handler;
- int error_handler_saved_status;
- int in_error_handler;
-
- void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
-
- /* etag handling */
- etag_flags_t etag_flags;
-
-
-#ifdef HAVE_GLIB_H
- GTimeVal timestamps[TIME_LAST_ELEMENT]; /**< used by timing.h */
-#endif
-
- int conditional_is_valid[COMP_LAST_ELEMENT];
-} connection;
-
-typedef struct {
- connection **ptr;
- size_t size;
- size_t used;
-} connections;
-
-
-#ifdef HAVE_IPV6
-typedef struct {
- int family;
- union {
- struct in6_addr ipv6;
- struct in_addr ipv4;
- } addr;
- char b2[INET6_ADDRSTRLEN + 1];
- time_t ts;
-} inet_ntop_cache_type;
-#endif
-
-
-typedef struct {
- buffer *uri;
- time_t mtime;
- int http_status;
-} realpath_cache_type;
-
-typedef struct {
- time_t mtime; /* the key */
- buffer *str; /* a buffer for the string represenation */
-} mtime_cache_type;
-
-typedef struct {
- void *ptr;
- size_t used;
- size_t size;
-} buffer_plugin;
-
-typedef enum {
- NETWORK_STATUS_UNSET,
- NETWORK_STATUS_SUCCESS,
- NETWORK_STATUS_FATAL_ERROR,
- NETWORK_STATUS_CONNECTION_CLOSE,
- NETWORK_STATUS_WAIT_FOR_EVENT,
- NETWORK_STATUS_WAIT_FOR_AIO_EVENT,
- NETWORK_STATUS_WAIT_FOR_FD,
- NETWORK_STATUS_INTERRUPTED
-} network_status_t;
-
-typedef struct {
- unsigned short port;
- buffer *bindhost;
-
- unsigned short dont_daemonize;
- unsigned short daemonize_on_shutdown;
- buffer *changeroot;
- buffer *username;
- buffer *groupname;
-
- buffer *pid_file;
-
- buffer *event_handler;
-
- buffer *modules_dir;
- buffer *network_backend;
- array *modules;
- array *upload_tempdirs;
-
- unsigned short use_noatime;
-
- unsigned short max_worker;
- unsigned short max_fds;
- unsigned short max_conns;
- unsigned int max_request_size;
-
- unsigned short log_request_header_on_error;
- unsigned short log_state_handling;
- unsigned short log_timing;
-
- enum { STAT_CACHE_ENGINE_UNSET,
- STAT_CACHE_ENGINE_NONE,
- STAT_CACHE_ENGINE_SIMPLE,
- STAT_CACHE_ENGINE_FAM,
- STAT_CACHE_ENGINE_INOTIFY
- } stat_cache_engine;
- unsigned short enable_cores;
-
- buffer *errorlog_file;
- unsigned short errorlog_use_syslog;
- buffer *breakagelog_file;
-
- unsigned short max_stat_threads;
- unsigned short max_read_threads;
-} server_config;
-
-typedef enum {
- NETWORK_BACKEND_UNSET,
-
- NETWORK_BACKEND_WRITE,
- NETWORK_BACKEND_WRITEV,
-
- NETWORK_BACKEND_LINUX_SENDFILE,
- NETWORK_BACKEND_LINUX_AIO_SENDFILE,
- NETWORK_BACKEND_POSIX_AIO,
- NETWORK_BACKEND_GTHREAD_AIO,
- NETWORK_BACKEND_GTHREAD_SENDFILE,
- NETWORK_BACKEND_GTHREAD_FREEBSD_SENDFILE,
-
- NETWORK_BACKEND_FREEBSD_SENDFILE,
- NETWORK_BACKEND_SOLARIS_SENDFILEV,
-
- NETWORK_BACKEND_WIN32_SEND,
- NETWORK_BACKEND_WIN32_TRANSMITFILE,
-
-} network_backend_t;
-
-
-typedef struct {
- sock_addr addr;
- iosocket *sock;
-
- buffer *ssl_pemfile;
- buffer *ssl_ca_file;
- buffer *ssl_cipher_list;
- unsigned short ssl_use_sslv2;
- unsigned short use_ipv6;
- unsigned short is_ssl;
-
- buffer *srv_token;
-
-#ifdef USE_OPENSSL
- SSL_CTX *ssl_ctx;
-#endif
-} server_socket;
-
-typedef struct {
- server_socket **ptr;
-
- size_t size;
- size_t used;
-} server_socket_array;
-
-typedef struct server {
- server_socket_array srv_sockets;
-
- fdevents *ev, *ev_ins;
-
- buffer_plugin plugins;
- void *plugin_slots;
-
- /* counters */
- int con_opened;
- int con_read;
- int con_written;
- int con_closed;
-
- int ssl_is_init;
-
- int max_fds; /* max possible fds */
- int sockets_disabled;
-
- size_t max_conns;
-
- /* buffers */
- buffer *parse_full_path;
- buffer *response_header;
- buffer *response_range;
- buffer *tmp_buf;
-
- buffer *tmp_chunk_len;
-
- buffer *empty_string; /* is necessary for cond_match */
-
- buffer *cond_check_buf;
-
- /* caches */
-#ifdef HAVE_IPV6
- inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
-#endif
- mtime_cache_type mtime_cache[FILE_CACHE_MAX];
-
- array *split_vals;
-
- /* Timestamps */
- time_t cur_ts;
- time_t last_generated_date_ts;
- time_t last_generated_debug_ts;
- time_t startup_ts;
-
- char entropy[8]; /* from /dev/[u]random if possible, otherwise rand() */
- char is_real_entropy; /* whether entropy is from /dev/[u]random */
-
- buffer *ts_debug_str;
- buffer *ts_date_str;
-
- /* config-file */
- array *config;
- array *config_touched;
-
- array *config_context;
- specific_config **config_storage;
-
- server_config srvconf;
-
- short unsigned config_deprecated;
- short unsigned config_unsupported;
-
- connections *conns;
- connections *joblist;
- connections *joblist_prev;
- connections *fdwaitqueue;
-
- stat_cache *stat_cache;
-
- fdevent_handler_t event_handler;
-
- network_status_t (* network_backend_write)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
- network_status_t (* network_backend_read)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
-#ifdef USE_OPENSSL
- network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
- network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
-#endif
-
-#ifdef HAVE_PWD_H
- uid_t uid;
- gid_t gid;
-#endif
-#ifdef USE_GTHREAD
-#ifdef USE_LINUX_AIO_SENDFILE
- io_context_t linux_io_ctx;
-
- struct iocb *linux_io_iocbs;
-
-#endif
-#ifdef USE_POSIX_AIO
- struct aiocb *posix_aio_iocbs;
-#endif
-
- GAsyncQueue *stat_queue; /* send a stat_job into this queue and joblist_queue will get a wakeup when the stat is finished */
- GAsyncQueue *joblist_queue;
- GAsyncQueue *aio_write_queue;
-
- int did_wakeup;
- int wakeup_pipe[2];
- iosocket *wakeup_iosocket;
-#endif
- network_backend_t network_backend;
- int is_shutdown;
-} server;
-
-int server_out_of_fds(server *srv, connection *con);
-
-LI_EXPORT unsigned short sock_addr_get_port(sock_addr *addr); /* configfile-glue.c */
-
-#endif
diff --git a/src/bitset.c b/src/bitset.c
deleted file mode 100644
index 9e7e38b2..00000000
--- a/src/bitset.c
+++ /dev/null
@@ -1,69 +0,0 @@
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "bitset.h"
-#include "buffer.h"
-#include "log.h"
-
-#define BITSET_BITS \
- ( CHAR_BIT * sizeof(size_t) )
-
-#define BITSET_MASK(pos) \
- ( ((size_t)1) << ((pos) % BITSET_BITS) )
-
-#define BITSET_WORD(set, pos) \
- ( (set)->bits[(pos) / BITSET_BITS] )
-
-#define BITSET_USED(nbits) \
- ( ((nbits) + (BITSET_BITS - 1)) / BITSET_BITS )
-
-bitset *bitset_init(size_t nbits) {
- bitset *set;
-
- set = malloc(sizeof(*set));
- assert(set);
-
- set->bits = calloc(BITSET_USED(nbits), sizeof(*set->bits));
- set->nbits = nbits;
-
- assert(set->bits);
-
- return set;
-}
-
-void bitset_reset(bitset *set) {
- memset(set->bits, 0, BITSET_USED(set->nbits) * sizeof(*set->bits));
-}
-
-void bitset_free(bitset *set) {
- free(set->bits);
- free(set);
-}
-
-void bitset_clear_bit(bitset *set, size_t pos) {
- if (pos >= set->nbits) {
- SEGFAULT("pos >= set->nbits: %zd >= %zd", pos, set->nbits);
- }
-
- BITSET_WORD(set, pos) &= ~BITSET_MASK(pos);
-}
-
-void bitset_set_bit(bitset *set, size_t pos) {
- if (pos >= set->nbits) {
- SEGFAULT("pos >= set->nbits: %zd >= %zd", pos, set->nbits);
- }
-
- BITSET_WORD(set, pos) |= BITSET_MASK(pos);
-}
-
-int bitset_test_bit(bitset *set, size_t pos) {
- if (pos >= set->nbits) {
- SEGFAULT("pos >= set->nbits: %zd >= %zd", pos, set->nbits);
- }
-
- return (BITSET_WORD(set, pos) & BITSET_MASK(pos)) != 0;
-}
-
diff --git a/src/bitset.h b/src/bitset.h
deleted file mode 100644
index 45f9a9d5..00000000
--- a/src/bitset.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _BITSET_H_
-#define _BITSET_H_
-
-#include <stddef.h>
-
-#include "settings.h"
-
-typedef struct {
- size_t *bits;
- size_t nbits;
-} bitset;
-
-LI_API bitset* bitset_init(size_t nbits);
-LI_API void bitset_reset(bitset *set);
-LI_API void bitset_free(bitset *set);
-
-LI_API void bitset_clear_bit(bitset *set, size_t pos);
-LI_API void bitset_set_bit(bitset *set, size_t pos);
-LI_API int bitset_test_bit(bitset *set, size_t pos);
-
-#endif
diff --git a/src/buffer.c b/src/buffer.c
deleted file mode 100644
index 7354bda5..00000000
--- a/src/buffer.c
+++ /dev/null
@@ -1,1169 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <stdio.h>
-#include <assert.h>
-#include <ctype.h>
-
-#include "buffer.h"
-
-
-static const char hex_chars[] = "0123456789abcdef";
-
-
-/**
- * init the buffer
- *
- */
-
-buffer* buffer_init(void) {
- buffer *b;
-
- b = malloc(sizeof(*b));
- assert(b);
-
- b->ptr = NULL;
- b->size = 0;
- b->used = 0;
-
- return b;
-}
-
-buffer *buffer_init_buffer(buffer *src) {
- buffer *b = buffer_init();
- buffer_copy_string_buffer(b, src);
- return b;
-}
-
-/**
- * free the buffer
- *
- */
-
-void buffer_free(buffer *b) {
- if (!b) return;
-
- free(b->ptr);
- free(b);
-}
-
-void buffer_reset(buffer *b) {
- if (!b) return;
-
- /* limit don't reuse buffer larger than ... bytes */
- if (b->size > BUFFER_MAX_REUSE_SIZE) {
- free(b->ptr);
- b->ptr = NULL;
- b->size = 0;
- } else if (b->size) {
- b->ptr[0] = '\0';
- }
-
- b->used = 0;
-}
-
-
-/**
- *
- * allocate (if necessary) enough space for 'size' (+1, if 'size' > 0) bytes and
- * set the 'used' counter to 0
- *
- */
-
-#define BUFFER_PIECE_SIZE 64
-
-int buffer_prepare_copy(buffer *b, size_t size) {
- if (!b) return -1;
-
- if ((0 == b->size) ||
- (size >= b->size)) {
- if (b->size) free(b->ptr);
-
- b->size = size;
-
- /* always allocate a multiple of BUFFER_PIECE_SIZE */
- /* adds a least 1 byte */
- b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
-
- b->ptr = malloc(b->size);
- assert(b->ptr);
- }
- b->used = 0;
- return 0;
-}
-
-/**
- *
- * increase the internal buffer (if necessary) to append another 'size' byte
- * ->used isn't changed
- *
- */
-
-int buffer_prepare_append(buffer *b, size_t size) {
- if (!b) return -1;
-
- if (0 == b->size) {
- b->size = size;
-
- /* always allocate a multiple of BUFFER_PIECE_SIZE */
- b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
-
- b->ptr = malloc(b->size);
- b->used = 0;
- assert(b->ptr);
- } else if (b->used + size >= b->size) {
- b->size += size;
-
- /* always allocate a multiple of BUFFER_PIECE_SIZE */
- b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
-
- b->ptr = realloc(b->ptr, b->size);
- assert(b->ptr);
- }
- return 0;
-}
-
-int buffer_copy_string(buffer *b, const char *s) {
- size_t s_len;
-
- if (!s || !b) return -1;
-
- s_len = strlen(s) + 1;
- buffer_prepare_copy(b, s_len);
-
- memcpy(b->ptr, s, s_len);
- b->used = s_len;
-
- return 0;
-}
-
-int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
- if (!s || !b) return -1;
-#if 0
- /* removed optimization as we have to keep the empty string
- * in some cases for the config handling
- *
- * url.access-deny = ( "" )
- */
- if (s_len == 0) return 0;
-#endif
- buffer_prepare_copy(b, s_len + 1);
-
- memcpy(b->ptr, s, s_len);
- b->ptr[s_len] = '\0';
- b->used = s_len + 1;
-
- return 0;
-}
-
-int buffer_copy_string_buffer(buffer *b, const buffer *src) {
- if (!src) return -1;
-
- if (src->used == 0) {
- buffer_reset(b);
- return 0;
- }
- return buffer_copy_string_len(b, src->ptr, src->used - 1);
-}
-
-int buffer_append_string(buffer *b, const char *s) {
- size_t s_len;
-
- if (!s || !b) return -1;
-
- s_len = strlen(s);
- buffer_prepare_append(b, s_len + 1);
- if (b->used == 0)
- b->used++;
-
- memcpy(b->ptr + b->used - 1, s, s_len + 1);
- b->used += s_len;
-
- return 0;
-}
-
-int buffer_append_string_rfill(buffer *b, const char *s, size_t maxlen) {
- size_t s_len;
-
- if (!s || !b) return -1;
-
- s_len = strlen(s);
- if (s_len > maxlen) s_len = maxlen;
- buffer_prepare_append(b, maxlen + 1);
- if (b->used == 0)
- b->used++;
-
- memcpy(b->ptr + b->used - 1, s, s_len);
- if (maxlen > s_len) {
- memset(b->ptr + b->used - 1 + s_len, ' ', maxlen - s_len);
- }
-
- b->used += maxlen;
- b->ptr[b->used - 1] = '\0';
- return 0;
-}
-
-/**
- * append a string to the end of the buffer
- *
- * the resulting buffer is terminated with a '\0'
- * s is treated as an un-terminated string (a \0 is handled as a normal character)
- *
- * @param b a buffer
- * @param s the string
- * @param s_len size of the string (without the terminating \0)
- */
-
-int buffer_append_string_len(buffer *b, const char *s, size_t s_len) {
- if (!s || !b) return -1;
- if (s_len == 0) return 0;
-
- buffer_prepare_append(b, s_len + 1);
- if (b->used == 0)
- b->used++;
-
- memcpy(b->ptr + b->used - 1, s, s_len);
- b->used += s_len;
- b->ptr[b->used - 1] = '\0';
-
- return 0;
-}
-
-int buffer_append_string_buffer(buffer *b, const buffer *src) {
- if (!src) return -1;
- if (src->used == 0) return 0;
-
- return buffer_append_string_len(b, src->ptr, src->used - 1);
-}
-
-int buffer_append_memory(buffer *b, const char *s, size_t s_len) {
- if (!s || !b) return -1;
- if (s_len == 0) return 0;
-
- buffer_prepare_append(b, s_len);
- memcpy(b->ptr + b->used, s, s_len);
- b->used += s_len;
-
- return 0;
-}
-
-int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
- if (!s || !b) return -1;
-
- b->used = 0;
-
- return buffer_append_memory(b, s, s_len);
-}
-
-int buffer_append_long_hex(buffer *b, unsigned long value) {
- char *buf;
- int shift = 0;
- unsigned long copy = value;
-
- while (copy) {
- copy >>= 4;
- shift++;
- }
- if (shift == 0)
- shift++;
- if (shift & 0x01)
- shift++;
-
- buffer_prepare_append(b, shift + 1);
- if (b->used == 0)
- b->used++;
- buf = b->ptr + (b->used - 1);
- b->used += shift;
-
- shift <<= 2;
- while (shift > 0) {
- shift -= 4;
- *(buf++) = hex_chars[(value >> shift) & 0x0F];
- }
- *buf = '\0';
-
- return 0;
-}
-
-int LI_ltostr(char *buf, long val) {
- char swap;
- char *end;
- int len = 1;
-
- if (val < 0) {
- len++;
- *(buf++) = '-';
- val = -val;
- }
-
- end = buf;
- while (val > 9) {
- *(end++) = '0' + (val % 10);
- val = val / 10;
- }
- *(end) = '0' + val;
- *(end + 1) = '\0';
- len += end - buf;
-
- while (buf < end) {
- swap = *end;
- *end = *buf;
- *buf = swap;
-
- buf++;
- end--;
- }
-
- return len;
-}
-
-int buffer_append_long(buffer *b, long val) {
- if (!b) return -1;
-
- buffer_prepare_append(b, 32);
- if (b->used == 0)
- b->used++;
-
- b->used += LI_ltostr(b->ptr + (b->used - 1), val);
- return 0;
-}
-
-int buffer_copy_long(buffer *b, long val) {
- if (!b) return -1;
-
- b->used = 0;
- return buffer_append_long(b, val);
-}
-
-#if !defined(SIZEOF_LONG) || (SIZEOF_LONG != SIZEOF_OFF_T)
-int buffer_append_off_t(buffer *b, off_t val) {
- char swap;
- char *end;
- char *start;
- int len = 1;
-
- if (!b) return -1;
-
- buffer_prepare_append(b, 32);
- if (b->used == 0)
- b->used++;
-
- start = b->ptr + (b->used - 1);
- if (val < 0) {
- len++;
- *(start++) = '-';
- val = -val;
- }
-
- end = start;
- while (val > 9) {
- *(end++) = '0' + (val % 10);
- val = val / 10;
- }
- *(end) = '0' + val;
- *(end + 1) = '\0';
- len += end - start;
-
- while (start < end) {
- swap = *end;
- *end = *start;
- *start = swap;
-
- start++;
- end--;
- }
-
- b->used += len;
- return 0;
-}
-
-int buffer_copy_off_t(buffer *b, off_t val) {
- if (!b) return -1;
-
- b->used = 0;
- return buffer_append_off_t(b, val);
-}
-#endif /* !defined(SIZEOF_LONG) || (SIZEOF_LONG != SIZEOF_OFF_T) */
-
-char int2hex(char c) {
- return hex_chars[(c & 0x0F)];
-}
-
-/* converts hex char (0-9, A-Z, a-z) to decimal.
- * returns 0xFF on invalid input.
- */
-char hex2int(unsigned char hex) {
- hex = hex - '0';
- if (hex > 9) {
- hex = (hex + '0' - 1) | 0x20;
- hex = hex - 'a' + 11;
- }
- if (hex > 15)
- hex = 0xFF;
-
- return hex;
-}
-
-
-/**
- * init the ptr buffer
- *
- */
-buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
-{
- buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
- l->free = freer;
-
- return l;
-}
-
-/**
- * free the buffer_array
- *
- */
-void buffer_ptr_free(buffer_ptr *l)
-{
- if (NULL != l) {
- buffer_ptr_clear(l);
- free(l);
- }
-}
-
-void buffer_ptr_clear(buffer_ptr *l)
-{
- assert(NULL != l);
-
- if (l->free && l->used) {
- size_t i;
- for (i = 0; i < l->used; i ++) {
- l->free(l->ptr[i]);
- }
- }
-
- if (l->ptr) {
- free(l->ptr);
- l->ptr = NULL;
- }
- l->used = 0;
- l->size = 0;
-}
-
-void buffer_ptr_append(buffer_ptr* l, void *item)
-{
- assert(NULL != l);
- if (l->ptr == NULL) {
- l->size = 16;
- l->ptr = (void **)malloc(sizeof(void *) * l->size);
- }
- else if (l->used == l->size) {
- l->size += 16;
- l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
- }
- l->ptr[l->used++] = item;
-}
-
-void *buffer_ptr_pop(buffer_ptr* l)
-{
- assert(NULL != l && l->used > 0);
- return l->ptr[--l->used];
-}
-
-void *buffer_ptr_top(buffer_ptr* l)
-{
- assert(NULL != l && l->used > 0);
- return l->ptr[l->used-1];
-}
-
-/**
- * init the buffer
- *
- */
-
-buffer_array* buffer_array_init(void) {
- buffer_array *b;
-
- b = malloc(sizeof(*b));
-
- assert(b);
- b->ptr = NULL;
- b->size = 0;
- b->used = 0;
-
- return b;
-}
-
-void buffer_array_reset(buffer_array *b) {
- size_t i;
-
- if (!b) return;
-
- /* if they are too large, reduce them */
- for (i = 0; i < b->used; i++) {
- buffer_reset(b->ptr[i]);
- }
-
- b->used = 0;
-}
-
-
-/**
- * free the buffer_array
- *
- */
-
-void buffer_array_free(buffer_array *b) {
- size_t i;
- if (!b) return;
-
- for (i = 0; i < b->size; i++) {
- if (b->ptr[i]) buffer_free(b->ptr[i]);
- }
- free(b->ptr);
- free(b);
-}
-
-buffer *buffer_array_append_get_buffer(buffer_array *b) {
- size_t i;
-
- if (b->size == 0) {
- b->size = 16;
- b->ptr = malloc(sizeof(*b->ptr) * b->size);
- assert(b->ptr);
- for (i = 0; i < b->size; i++) {
- b->ptr[i] = NULL;
- }
- } else if (b->size == b->used) {
- b->size += 16;
- b->ptr = realloc(b->ptr, sizeof(*b->ptr) * b->size);
- assert(b->ptr);
- for (i = b->used; i < b->size; i++) {
- b->ptr[i] = NULL;
- }
- }
-
- if (b->ptr[b->used] == NULL) {
- b->ptr[b->used] = buffer_init();
- }
-
- b->ptr[b->used]->used = 0;
-
- return b->ptr[b->used++];
-}
-
-
-char * buffer_search_string_len(buffer *b, const char *needle, size_t len) {
- size_t i;
- if (len == 0) return NULL;
- if (needle == NULL) return NULL;
-
- if (b->used < len) return NULL;
-
- for(i = 0; i < b->used - len; i++) {
- if (0 == memcmp(b->ptr + i, needle, len)) {
- return b->ptr + i;
- }
- }
-
- return NULL;
-}
-
-buffer *buffer_init_string(const char *str) {
- buffer *b = buffer_init();
-
- buffer_copy_string(b, str);
-
- return b;
-}
-
-int buffer_is_empty(buffer *b) {
- if (!b) return 1;
-
- return (b->used == 0);
-}
-
-/**
- * check if two buffers contain the same data
- *
- * HISTORY: this function was pretty much optimized, but didn't handled
- * alignment properly.
- */
-
-int buffer_is_equal(buffer *a, buffer *b) {
- if (a->used != b->used) return 0;
- if (a->used == 0) return 1;
-
- return (0 == strncmp(a->ptr, b->ptr, a->used - 1));
-}
-
-int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
- buffer b;
-
- b.ptr = (char *)s;
- b.used = b_len + 1;
-
- return buffer_is_equal(a, &b);
-}
-
-/* simple-assumption:
- *
- * most parts are equal and doing a case conversion takes time
- *
- */
-int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
- size_t ndx = 0, max_ndx;
- size_t *al, *bl;
- size_t mask = sizeof(*al) - 1;
-
- al = (size_t *)a;
- bl = (size_t *)b;
-
- /* is the alignment correct? */
- if ( ((size_t)al & mask) == 0 &&
- ((size_t)bl & mask) == 0 ) {
-
- max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
-
- for (; ndx < max_ndx; ndx += sizeof(*al)) {
- if (*al != *bl) break;
- al++; bl++;
-
- }
-
- }
-
- a = (char *)al;
- b = (char *)bl;
-
- max_ndx = ((a_len < b_len) ? a_len : b_len);
-
- for (; ndx < max_ndx; ndx++) {
- int a1 = *a++, b1 = *b++;
-
- if (a1 != b1) {
- /* always lowercase for transitive results */
- if (a1 >= 'A' && a1 <= 'Z') a1 |= 32;
- if (b1 >= 'A' && b1 <= 'Z') b1 |= 32;
-
- if ((a1 - b1) != 0) return (a1 - b1);
- }
- }
-
- /* all chars are the same, and the length match too
- *
- * they are the same */
- if (a_len == b_len) return 0;
-
- /* if a is shorter then b, then b is larger */
- return (a_len - b_len);
-}
-
-
-/**
- * check if the rightmost bytes of the string are equal.
- *
- *
- */
-
-int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
- /* no, len -> equal */
- if (len == 0) return 1;
-
- /* len > 0, but empty buffers -> not equal */
- if (b1->used == 0 || b2->used == 0) return 0;
-
- /* buffers too small -> not equal */
- if (b1->used - 1 < len || b2->used - 1 < len) return 0;
-
- if (0 == strncmp(b1->ptr + b1->used - 1 - len,
- b2->ptr + b2->used - 1 - len, len)) {
- return 1;
- }
-
- return 0;
-}
-
-int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
- size_t i;
-
- /* BO protection */
- if (in_len * 2 < in_len) return -1;
-
- buffer_prepare_copy(b, in_len * 2 + 1);
-
- for (i = 0; i < in_len; i++) {
- b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
- b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
- }
- b->ptr[b->used++] = '\0';
-
- return 0;
-}
-
-/* everything except: ! ( ) * - . 0-9 A-Z _ a-z */
-const char encoded_chars_rel_uri_part[] = {
- /*
- 0 1 2 3 4 5 6 7 8 9 A B C D E F
- */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
- 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F @ */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 5F [ \ ] ^ */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F ` */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 7F { | } ~ DEL */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */
-};
-
-/* everything except: ! ( ) * - . / 0-9 A-Z _ a-z */
-const char encoded_chars_rel_uri[] = {
- /*
- 0 1 2 3 4 5 6 7 8 9 A B C D E F
- */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
- 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F @ */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 5F [ \ ] ^ */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F ` */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 7F { | } ~ DEL */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */
-};
-
-const char encoded_chars_html[] = {
- /*
- 0 1 2 3 4 5 6 7 8 9 A B C D E F
- */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 5F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 70 - 7F DEL */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */
-};
-
-const char encoded_chars_minimal_xml[] = {
- /*
- 0 1 2 3 4 5 6 7 8 9 A B C D E F
- */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 5F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 70 - 7F DEL */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
-};
-
-const char encoded_chars_hex[] = {
- /*
- 0 1 2 3 4 5 6 7 8 9 A B C D E F
- */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */
-};
-
-
-int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_encoding_t encoding) {
- unsigned char *ds, *d;
- size_t d_len, ndx;
- const char *map = NULL;
-
- if (!s || !b) return -1;
- if (b->used == 0) return -1;
-
- if (b->ptr[b->used - 1] != '\0') return -1;
-
- if (s_len == 0) return 0;
-
- switch(encoding) {
- case ENCODING_REL_URI:
- map = encoded_chars_rel_uri;
- break;
- case ENCODING_REL_URI_PART:
- map = encoded_chars_rel_uri_part;
- break;
- case ENCODING_HTML:
- map = encoded_chars_html;
- break;
- case ENCODING_MINIMAL_XML:
- map = encoded_chars_minimal_xml;
- break;
- case ENCODING_HEX:
- map = encoded_chars_hex;
- break;
- case ENCODING_UNSET:
- return buffer_append_string_len(b, s, s_len);
- }
-
- assert(map != NULL);
-
- /* count to-be-encoded characters */
- for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
- if (map[*ds]) {
- switch(encoding) {
- case ENCODING_REL_URI:
- case ENCODING_REL_URI_PART:
- d_len += 3;
- break;
- case ENCODING_HTML:
- case ENCODING_MINIMAL_XML:
- d_len += 6;
- break;
- case ENCODING_HEX:
- d_len += 2;
- break;
- case ENCODING_UNSET:
- break;
- }
- } else {
- d_len ++;
- }
- }
-
- buffer_prepare_append(b, d_len);
-
- for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
- if (map[*ds]) {
- switch(encoding) {
- case ENCODING_REL_URI:
- case ENCODING_REL_URI_PART:
- d[d_len++] = '%';
- d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
- d[d_len++] = hex_chars[(*ds) & 0x0F];
- break;
- case ENCODING_HTML:
- case ENCODING_MINIMAL_XML:
- d[d_len++] = '&';
- d[d_len++] = '#';
- d[d_len++] = 'x';
- d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
- d[d_len++] = hex_chars[(*ds) & 0x0F];
- d[d_len++] = ';';
- break;
- case ENCODING_HEX:
- d[d_len++] = hex_chars[((*ds) >> 4) & 0x0F];
- d[d_len++] = hex_chars[(*ds) & 0x0F];
- break;
- case ENCODING_UNSET:
- break;
- }
- } else {
- d[d_len++] = *ds;
- }
- }
-
- /* terminate buffer and calculate new length */
- b->ptr[b->used + d_len - 1] = '\0';
-
- b->used += d_len;
-
- return 0;
-}
-
-
-/* decodes url-special chars in-place.
- * replaces non-printable characters with '_'
- */
-
-static int buffer_urldecode_internal(buffer *url, int is_query) {
- unsigned char high, low;
- const char *src;
- char *dst;
-
- if (!url || !url->ptr) return -1;
-
- src = (const char*) url->ptr;
- dst = (char*) url->ptr;
-
- while ((*src) != '\0') {
- if (is_query && *src == '+') {
- *dst = ' ';
- } else if (*src == '%') {
- *dst = '%';
-
- high = hex2int(*(src + 1));
- if (high != 0xFF) {
- low = hex2int(*(src + 2));
- if (low != 0xFF) {
- high = (high << 4) | low;
-
- /* map out control characters */
- if (high < 32 || high == 127) high = '_';
-
- *dst = high;
- src += 2;
- }
- }
- } else {
- *dst = *src;
- }
-
- dst++;
- src++;
- }
-
- *dst = '\0';
- url->used = (dst - url->ptr) + 1;
-
- return 0;
-}
-
-int buffer_urldecode_path(buffer *url) {
- return buffer_urldecode_internal(url, 0);
-}
-
-int buffer_urldecode_query(buffer *url) {
- return buffer_urldecode_internal(url, 1);
-}
-
-/* Remove "/../", "//", "/./" parts from path.
- *
- * /blah/.. gets /
- * /blah/../foo gets /foo
- * /abc/./xyz gets /abc/xyz
- * /abc//xyz gets /abc/xyz
- *
- * NOTE: src and dest can point to the same buffer, in which case
- * the operation is performed in-place.
- */
-
-int buffer_path_simplify(buffer *dest, buffer *src)
-{
- int toklen;
- char c, pre1;
- char *start, *slash, *walk, *out;
- unsigned short pre;
-
- if (src == NULL || src->ptr == NULL || dest == NULL)
- return -1;
-
- if (src == dest)
- buffer_prepare_append(dest, 1);
- else
- buffer_prepare_copy(dest, src->used + 1);
-
- walk = src->ptr;
- start = dest->ptr;
- out = dest->ptr;
- slash = dest->ptr;
- while (*walk == ' ') {
- walk++;
- }
-
- pre1 = *(walk++);
- c = *(walk++);
- pre = pre1;
- if (pre1 != '/') {
- pre = ('/' << 8) | pre1;
- *(out++) = '/';
- }
- *(out++) = pre1;
-
- if (pre1 == '\0') {
- dest->used = (out - start) + 1;
- return 0;
- }
-
- while (1) {
- if (c == '/' || c == '\0') {
- toklen = out - slash;
- if (toklen == 3 && pre == (('.' << 8) | '.')) {
- out = slash;
- if (out > start) {
- out--;
- while (out > start && *out != '/') {
- out--;
- }
- }
-
- if (c == '\0')
- out++;
- } else if (toklen == 1 || pre == (('/' << 8) | '.')) {
- out = slash;
- if (c == '\0')
- out++;
- }
-
- slash = out;
- }
-
- if (c == '\0')
- break;
-
- pre1 = c;
- pre = (pre << 8) | pre1;
- c = *walk;
- *out = pre1;
-
- out++;
- walk++;
- }
-
- *out = '\0';
- dest->used = (out - start) + 1;
-
- return 0;
-}
-
-int light_isdigit(int c) {
- return (c >= '0' && c <= '9');
-}
-
-int light_isxdigit(int c) {
- if (light_isdigit(c)) return 1;
-
- c |= 32;
- return (c >= 'a' && c <= 'f');
-}
-
-int light_isalpha(int c) {
- c |= 32;
- return (c >= 'a' && c <= 'z');
-}
-
-int light_isalnum(int c) {
- return light_isdigit(c) || light_isalpha(c);
-}
-
-#undef BUFFER_CTYPE_FUNC
-#define BUFFER_CTYPE_FUNC(type) \
- int buffer_is##type(buffer *b) { \
- size_t i, len; \
- if (b->used < 2) return 0; \
- /* strlen */ \
- len = b->used - 1; \
- /* c-string only */ \
- if (b->ptr[len] != '\0') { \
- return 0; \
- } \
- /* check on the whole string */ \
- for (i = 0; i < len; i ++) { \
- if (!light_is##type(b->ptr[i])) { \
- return 0; \
- } \
- } \
- return 1; \
- }
-
-BUFFER_CTYPE_FUNC(digit)
-BUFFER_CTYPE_FUNC(xdigit)
-BUFFER_CTYPE_FUNC(alpha)
-BUFFER_CTYPE_FUNC(alnum)
-
-int buffer_to_lower(buffer *b) {
- char *c;
-
- if (b->used == 0) return 0;
-
- for (c = b->ptr; *c; c++) {
- if (*c >= 'A' && *c <= 'Z') {
- *c |= 32;
- }
- }
-
- return 0;
-}
-
-
-int buffer_to_upper(buffer *b) {
- char *c;
-
- if (b->used == 0) return 0;
-
- for (c = b->ptr; *c; c++) {
- if (*c >= 'a' && *c <= 'z') {
- *c &= ~32;
- }
- }
-
- return 0;
-}
-
-buffer_pool *buffer_pool_init() {
- buffer_pool *bp;
-
- bp = calloc(1, sizeof(*bp));
-
- return bp;
-}
-
-void buffer_pool_free(buffer_pool *bp) {
- if (!bp) return;
-
- ARRAY_STATIC_FREE(bp, buffer, b, buffer_free(b));
-
- free(bp);
-
- return;
-}
-
-buffer *buffer_pool_get(buffer_pool *bp) {
- buffer *b;
-
- if (bp->used == 0) {
- return buffer_init();
- }
-
- b = bp->ptr[--bp->used];
-
- buffer_reset(b);
-
- return b;
-}
-
-void buffer_pool_append(buffer_pool *bp, buffer *b) {
- ARRAY_STATIC_PREPARE_APPEND(bp);
-
- bp->ptr[bp->used++] = b;
-}
-
-
diff --git a/src/buffer.h b/src/buffer.h
deleted file mode 100644
index 16d05601..00000000
--- a/src/buffer.h
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef _BUFFER_H_
-#define _BUFFER_H_
-
-#include "settings.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include "array-static.h"
-
-typedef struct {
- char *ptr;
-
- size_t used;
- size_t size;
-} buffer;
-
-typedef void (*buffer_ptr_free_t)(void *p);
-
-typedef struct {
- void **ptr;
- size_t size;
- size_t used;
- buffer_ptr_free_t free;
-} buffer_ptr;
-
-typedef struct {
- buffer **ptr;
-
- size_t used;
- size_t size;
-} buffer_array;
-
-typedef struct {
- char *ptr;
-
- size_t offset; /* input pointer */
-
- size_t used; /* output pointer */
- size_t size;
-} read_buffer;
-
-LI_API buffer_ptr* buffer_ptr_init(buffer_ptr_free_t freer);
-LI_API void buffer_ptr_free(buffer_ptr *b);
-LI_API void buffer_ptr_clear(buffer_ptr *b);
-LI_API void buffer_ptr_append(buffer_ptr *b, void *item);
-LI_API void* buffer_ptr_pop(buffer_ptr *b);
-LI_API void* buffer_ptr_top(buffer_ptr *b);
-
-LI_API buffer_array* buffer_array_init(void);
-LI_API void buffer_array_free(buffer_array *b);
-LI_API void buffer_array_reset(buffer_array *b);
-LI_API buffer* buffer_array_append_get_buffer(buffer_array *b);
-
-LI_API buffer* buffer_init(void);
-LI_API buffer* buffer_init_buffer(buffer *b);
-LI_API buffer* buffer_init_string(const char *str);
-LI_API void buffer_free(buffer *b);
-LI_API void buffer_reset(buffer *b);
-
-LI_API int buffer_prepare_copy(buffer *b, size_t size);
-LI_API int buffer_prepare_append(buffer *b, size_t size);
-
-LI_API int buffer_copy_string(buffer *b, const char *s);
-LI_API int buffer_copy_string_len(buffer *b, const char *s, size_t s_len);
-LI_API int buffer_copy_string_buffer(buffer *b, const buffer *src);
-LI_API int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len);
-
-LI_API int buffer_copy_long(buffer *b, long val);
-
-LI_API int buffer_copy_memory(buffer *b, const char *s, size_t s_len);
-
-LI_API int buffer_append_string(buffer *b, const char *s);
-LI_API int buffer_append_string_len(buffer *b, const char *s, size_t s_len);
-LI_API int buffer_append_string_buffer(buffer *b, const buffer *src);
-LI_API int buffer_append_string_lfill(buffer *b, const char *s, size_t maxlen);
-LI_API int buffer_append_string_rfill(buffer *b, const char *s, size_t maxlen);
-
-LI_API int buffer_append_long_hex(buffer *b, unsigned long len);
-LI_API int buffer_append_long(buffer *b, long val);
-
-#if defined(SIZEOF_LONG) && (SIZEOF_LONG == SIZEOF_OFF_T)
-#define buffer_copy_off_t(x, y) buffer_copy_long(x, y)
-#define buffer_append_off_t(x, y) buffer_append_long(x, y)
-#else
-LI_API int buffer_copy_off_t(buffer *b, off_t val);
-LI_API int buffer_append_off_t(buffer *b, off_t val);
-#endif
-
-LI_API int buffer_append_memory(buffer *b, const char *s, size_t s_len);
-
-LI_API char* buffer_search_string_len(buffer *b, const char *needle, size_t len);
-
-LI_API int buffer_is_empty(buffer *b);
-LI_API int buffer_is_equal(buffer *a, buffer *b);
-LI_API int buffer_is_equal_right_len(buffer *a, buffer *b, size_t len);
-LI_API int buffer_is_equal_string(buffer *a, const char *s, size_t b_len);
-LI_API int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len);
-
-typedef enum {
- ENCODING_UNSET,
- ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
- ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
- ENCODING_HTML, /* "&" becomes "&amp;" and so on */
- ENCODING_MINIMAL_XML, /* minimal encoding for xml */
- ENCODING_HEX /* encode string as hex */
-} buffer_encoding_t;
-
-LI_API int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_encoding_t encoding);
-
-LI_API int buffer_urldecode_path(buffer *url);
-LI_API int buffer_urldecode_query(buffer *url);
-LI_API int buffer_path_simplify(buffer *dest, buffer *src);
-
-LI_API int buffer_to_lower(buffer *b);
-LI_API int buffer_to_upper(buffer *b);
-
-/** deprecated */
-LI_API int LI_ltostr(char *buf, long val);
-LI_API char hex2int(unsigned char c);
-LI_API char int2hex(char i);
-
-LI_API int light_isdigit(int c);
-LI_API int light_isxdigit(int c);
-LI_API int light_isalpha(int c);
-LI_API int light_isalnum(int c);
-
-#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
-BUFFER_CTYPE_FUNC(digit)
-BUFFER_CTYPE_FUNC(xdigit)
-BUFFER_CTYPE_FUNC(alpha)
-BUFFER_CTYPE_FUNC(alnum)
-
-#define BUF_STR(x) x->ptr
-#define BUF_STR_LEN(x) (x->used ? x->used - 1 : 0)
-
-/* used on solaris as their vprintf() hates NULL for %s */
-#define SAFE_BUF_STR(x) x && x->ptr ? x->ptr : "(null)"
-
-#define BUFFER_APPEND_STRING_CONST(x, y) \
- buffer_append_string_len(x, y, sizeof(y) - 1)
-
-#define BUFFER_COPY_STRING_CONST(x, y) \
- buffer_copy_string_len(x, y, sizeof(y) - 1)
-
-#define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
-#define CONST_BUF_LEN(x) BUF_STR(x), x->used ? x->used - 1 : 0
-
-
-#define UNUSED(x) ( (void)(x) )
-
-/**
- * a pool of unused buffer *
- */
-
-ARRAY_STATIC_DEF(buffer_pool, buffer, );
-
-buffer_pool* buffer_pool_init();
-void buffer_pool_free(buffer_pool* );
-
-buffer *buffer_pool_get(buffer_pool *bp);
-void buffer_pool_append(buffer_pool *bp, buffer *);
-
-#endif
-
-
diff --git a/src/chunk.c b/src/chunk.c
deleted file mode 100644
index a5742e51..00000000
--- a/src/chunk.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/**
- * the network chunk-API
- *
- *
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <stdlib.h>
-#include <fcntl.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-
-#include "chunk.h"
-
-#include "sys-mmap.h"
-#include "sys-files.h"
-
-#include "log.h"
-
-/**
- * create a global pool for unused chunks
- *
- * the chunk is moved from queue to queue (by stealing)
- * and moved back into the unused pool.
- *
- * Instead of having a local pool of unused chunks per queue
- * we use a global pool
- *
- */
-
-static chunk *chunkpool = NULL;
-static size_t chunkpool_chunks = 0;
-
-chunkqueue *chunkqueue_init(void) {
- chunkqueue *cq;
-
- cq = calloc(1, sizeof(*cq));
-
- cq->first = NULL;
- cq->last = NULL;
-
- return cq;
-}
-
-static chunk *chunk_init(void) {
- chunk *c;
-
- c = calloc(1, sizeof(*c));
-
- c->mem = buffer_init();
- c->file.name = buffer_init();
- c->file.fd = -1;
- c->file.copy.fd = -1;
- c->file.mmap.start = MAP_FAILED;
- c->next = NULL;
-
- c->async.written = -1;
-
- return c;
-}
-
-static void chunk_reset(chunk *c) {
- if (!c) return;
-
- buffer_reset(c->mem);
-
- if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
- unlink(c->file.name->ptr);
- }
- c->file.is_temp = 0;
-
- buffer_reset(c->file.name);
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
-
- if (c->file.copy.fd != -1) {
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- if (MAP_FAILED != c->file.mmap.start) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
- }
-
- c->file.length = 0;
- c->file.start = 0;
-
- c->file.mmap.length = 0;
- c->file.mmap.offset = 0;
-
- c->file.copy.length = 0;
- c->file.copy.offset = 0;
-
- c->async.written = -1;
- c->async.ret_val = 0;
-
- c->offset = 0;
- c->next = NULL;
-}
-
-static void chunk_free(chunk *c) {
- if (!c) return;
-
- /* make sure fd's are closed and tempfile's are deleted. */
- chunk_reset(c);
-
- buffer_free(c->mem);
- buffer_free(c->file.name);
-
- free(c);
-}
-
-/**
- * mark the chunk as done
- *
- * @param c chunk to set done
- * @return 1 if done, 0 if not
- */
-void chunk_set_done(chunk *c) {
- switch (c->type) {
- case MEM_CHUNK:
- c->offset = c->mem->used - 1;
-
- break;
- case FILE_CHUNK:
- c->offset = c->file.length;
-
- break;
- default:
- break;
- }
-}
-
-/**
- * check if chunk is finished
- *
- * @param c chunk to set done
- * @return 1 if done, 0 if not
- */
-int chunk_is_done(chunk *c) {
- switch (c->type) {
- case MEM_CHUNK:
- return ((c->mem->used == 0) || (c->offset == (off_t)c->mem->used - 1));
- case FILE_CHUNK:
- return ((c->file.length == 0) || (c->offset == c->file.length));
- case UNUSED_CHUNK:
- default:
- return 1;
- }
-}
-
-off_t chunk_length(chunk *c) {
- switch (c->type) {
- case MEM_CHUNK:
- if (c->mem->used == 0) return 0;
- return (off_t)c->mem->used - 1 - c->offset;
- case FILE_CHUNK:
- return c->file.length - c->offset;
- case UNUSED_CHUNK:
- break;
- }
- return 0;
-}
-
-void chunkpool_free(void) {
- if (!chunkpool) return;
-
- /* free the pool */
- while(chunkpool) {
- chunk *c = chunkpool->next;
- chunk_free(chunkpool);
- chunkpool = c;
- }
- chunkpool_chunks = 0;
-}
-
-static chunk *chunkpool_get_unused_chunk(void) {
- chunk *c;
-
- /* check if we have an unused chunk */
- if (!chunkpool) {
- c = chunk_init();
- } else {
- /* take the first element from the list (a stack) */
- c = chunkpool;
- chunkpool = c->next;
- c->next = NULL;
-
- chunkpool_chunks--;
- }
-
- return c;
-}
-
-/**
- * keep unused chunks alive and store them in the chunkpool
- *
- * we only want to keep a small set of chunks alive to balance between
- * memory-usage and mallocs
- *
- * each filter will ask for a chunk
- */
-static void chunkpool_add_unused_chunk(chunk *c) {
- if (chunkpool_chunks > 128) {
- chunk_free(c);
- } else {
- chunk_reset(c);
-
- /* prepend the chunk to the chunkpool */
- c->next = chunkpool;
- chunkpool = c;
- chunkpool_chunks++;
- }
-}
-
-
-void chunkqueue_free(chunkqueue *cq) {
- chunk *c, *pc;
-
- if (!cq) return;
-
- for (c = cq->first; c; ) {
- pc = c;
- c = c->next;
- chunk_free(pc);
- }
-
- free(cq);
-}
-
-static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
- c->next = cq->first;
- cq->first = c;
-
- if (cq->last == NULL) {
- cq->last = c;
- }
-
- return 0;
-}
-
-static int chunkqueue_append_chunk(chunkqueue *cq, chunk *c) {
- if (cq->last) {
- cq->last->next = c;
- }
- cq->last = c;
-
- if (cq->first == NULL) {
- cq->first = c;
- }
-
- return 0;
-}
-
-/**
- * reset all chunks of the queue
- */
-void chunkqueue_reset(chunkqueue *cq) {
- chunk *c;
-
- /* mark all read done */
- for (c = cq->first; c; c = c->next) {
- chunk_set_done(c);
- }
-
- chunkqueue_remove_finished_chunks(cq);
-
- cq->bytes_in = 0;
- cq->bytes_out = 0;
- cq->is_closed = 0;
-}
-
-int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
- chunk *c;
-
- if (len == 0) return 0;
-
- c = chunkpool_get_unused_chunk();
-
- c->type = FILE_CHUNK;
-
- buffer_copy_string_buffer(c->file.name, fn);
- c->file.start = offset;
- c->file.length = len;
- c->offset = 0;
-
- chunkqueue_append_chunk(cq, c);
-
- return 0;
-}
-
-int chunkqueue_steal_tempfile(chunkqueue *cq, chunk *in) {
- chunk *c;
-
- assert(in->type == FILE_CHUNK);
- assert(in->file.is_temp == 1);
-
- c = chunkpool_get_unused_chunk();
-
- c->type = FILE_CHUNK;
- buffer_copy_string_buffer(c->file.name, in->file.name);
- c->file.start = in->file.start + in->offset;
- c->file.length = in->file.length - in->offset;
- c->offset = 0;
- c->file.is_temp = 1;
- in->file.is_temp = 0;
-
- chunkqueue_append_chunk(cq, c);
-
- return 0;
-}
-
-/**
- * move the content of chunk to another chunkqueue. return total bytes copied/stolen.
- */
-off_t chunkqueue_steal_chunk(chunkqueue *cq, chunk *c) {
- /* we are copying the whole buffer, just steal it */
- off_t total = 0;
- buffer *b, btmp;
-
- if (!cq) return 0;
- if (chunk_is_done(c)) return 0;
-
- switch (c->type) {
- case MEM_CHUNK:
- total = c->mem->used - c->offset - 1;
- if (c->offset == 0) {
- b = chunkqueue_get_append_buffer(cq);
- btmp = *b; *b = *(c->mem); *(c->mem) = btmp;
- } else {
- chunkqueue_append_mem(cq, c->mem->ptr + c->offset, total);
- chunk_set_done(c);
- }
- break;
- case FILE_CHUNK:
- total = c->file.length - c->offset;
-
- if (c->file.is_temp) {
- chunkqueue_steal_tempfile(cq, c);
- } else {
- chunkqueue_append_file(cq, c->file.name, c->file.start + c->offset, c->file.length - c->offset);
- chunk_set_done(c);
- }
-
- break;
- case UNUSED_CHUNK:
- return 0;
- }
-
- return total;
-}
-
-/*
- * copy/steal all chunks from in chunkqueue. return total bytes copied/stolen.
- *
- */
-off_t chunkqueue_steal_all_chunks(chunkqueue *cq, chunkqueue *in) {
- off_t total = 0;
- chunk *c;
-
- if (!cq || !in) return 0;
-
- for (c = in->first; c; c = c->next) {
- total += chunkqueue_steal_chunk(cq, c);
- }
-
- return total;
-}
-
-/*
- * copy/steal max_len bytes from chunk chain. return total bytes copied/stolen.
- *
- */
-off_t chunkqueue_steal_chunks_len(chunkqueue *out, chunk *c, off_t max_len) {
- off_t total = 0;
- off_t we_have = 0, we_want = 0;
- buffer *b;
-
- if (!out || !c) return 0;
-
- /* copy/steal chunks */
- for (; c && max_len > 0; c = c->next) {
- switch (c->type) {
- case FILE_CHUNK:
- we_have = c->file.length - c->offset;
-
- if (we_have == 0) break;
-
- if (we_have > max_len) we_have = max_len;
-
- chunkqueue_append_file(out, c->file.name, c->offset, we_have);
-
- c->offset += we_have;
- max_len -= we_have;
- total += we_have;
-
- /* steal the tempfile
- *
- * This is tricky:
- * - we reference the tempfile from the in-queue several times
- * if the chunk is larger than max_len
- * - we can't simply cleanup the in-queue as soon as possible
- * as it would remove the tempfiles
- * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
- * referencing chunk of the fastcgi-write-queue
- *
- */
-
- if (c->offset == c->file.length) {
- chunk *out_c;
-
- out_c = out->last;
-
- /* the last of the out-queue should be a FILE_CHUNK (we just created it)
- * and the incoming side should have given use a temp-file-chunk */
- assert(out_c->type == FILE_CHUNK);
- assert(c->file.is_temp == 1);
-
- out_c->file.is_temp = 1;
- c->file.is_temp = 0;
- }
-
- break;
- case MEM_CHUNK:
- /* skip empty chunks */
- if (c->mem->used == 0) break;
-
- we_have = c->mem->used - c->offset - 1;
- if (we_have == 0) break;
-
- we_want = we_have < max_len ? we_have : max_len;
-
- if (we_have == we_want) {
- /* steal whole chunk */
- chunkqueue_steal_chunk(out, c);
- } else {
- /* copy unused data from chunk */
- b = chunkqueue_get_append_buffer(out);
- buffer_copy_string_len(b, c->mem->ptr + c->offset, we_want);
- c->offset += we_want;
- }
- total += we_want;
- max_len -= we_want;
-
- break;
- default:
- break;
- }
- }
- return total;
-}
-
-/**
- * skip bytes in the chunkqueue
- *
- * @param cq chunkqueue
- * @param skip bytes to skip
- * @return bytes skipped
- */
-off_t chunkqueue_skip(chunkqueue *cq, off_t skip) {
- off_t total = 0;
- off_t we_have = 0, we_want = 0;
- chunk *c;
-
- if (!cq) return 0;
-
- /* consume chunks */
- for (c = cq->first; c && skip > 0; c = c->next) {
- we_have = chunk_length(c);
-
- /* skip empty chunks */
- if (!we_have) continue;
-
- we_want = we_have < skip ? we_have : skip;
-
- c->offset += we_want;
- total += we_want;
- skip -= we_want;
- }
-
- return total;
-}
-
-int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
- chunk *c;
-
- if (mem->used == 0) return 0;
-
- c = chunkpool_get_unused_chunk();
- c->type = MEM_CHUNK;
- c->offset = 0;
- buffer_copy_string_buffer(c->mem, mem);
-
- chunkqueue_append_chunk(cq, c);
-
- return 0;
-}
-
-int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
- chunk *c;
-
- if (mem->used == 0) return 0;
-
- c = chunkpool_get_unused_chunk();
- c->type = MEM_CHUNK;
- c->offset = 0;
- buffer_copy_string_buffer(c->mem, mem);
-
- chunkqueue_prepend_chunk(cq, c);
-
- return 0;
-}
-
-int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
- chunk *c;
-
- if (len == 0) return 0;
-
- c = chunkpool_get_unused_chunk();
- c->type = MEM_CHUNK;
- c->offset = 0;
- buffer_copy_string_len(c->mem, mem, len);
-
- chunkqueue_append_chunk(cq, c);
-
- return 0;
-}
-
-buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
- chunk *c;
-
- c = chunkpool_get_unused_chunk();
-
- c->type = MEM_CHUNK;
- c->offset = 0;
- buffer_reset(c->mem);
-
- chunkqueue_prepend_chunk(cq, c);
-
- return c->mem;
-}
-
-buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
- chunk *c;
-
- c = chunkpool_get_unused_chunk();
-
- c->type = MEM_CHUNK;
- c->offset = 0;
- buffer_reset(c->mem);
-
- chunkqueue_append_chunk(cq, c);
-
- return c->mem;
-}
-
-int chunkqueue_set_tempdirs(chunkqueue *cq, array *tempdirs) {
- if (!cq) return -1;
-
- cq->tempdirs = tempdirs;
-
- return 0;
-}
-
-chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
- chunk *c;
- buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
-
- c = chunkpool_get_unused_chunk();
-
- c->type = FILE_CHUNK;
- c->offset = 0;
-
- if (cq->tempdirs && cq->tempdirs->used) {
- size_t i;
-
- /* we have several tempdirs, only if all of them fail we jump out */
-
- for (i = 0; i < cq->tempdirs->used; i++) {
- data_string *ds = (data_string *)cq->tempdirs->data[i];
-
- buffer_copy_string_buffer(template, ds->value);
- PATHNAME_APPEND_SLASH(template);
- buffer_append_string_len(template, CONST_STR_LEN("lighttpd-upload-XXXXXX"));
-
- if (-1 != (c->file.fd = mkstemp(template->ptr))) {
- /* only trigger the unlink if we created the temp-file successfully */
- c->file.is_temp = 1;
- break;
- }
- }
- } else {
- if (-1 != (c->file.fd = mkstemp(template->ptr))) {
- /* only trigger the unlink if we created the temp-file successfully */
- c->file.is_temp = 1;
- }
- }
-
- buffer_copy_string_buffer(c->file.name, template);
- c->file.length = 0;
-
- chunkqueue_append_chunk(cq, c);
-
- buffer_free(template);
-
- return c;
-}
-
-
-off_t chunkqueue_length(chunkqueue *cq) {
- off_t len = 0;
- chunk *c;
-
- for (c = cq->first; c; c = c->next) {
- switch (c->type) {
- case MEM_CHUNK:
- len += c->mem->used ? c->mem->used - 1 : 0;
- break;
- case FILE_CHUNK:
- len += c->file.length;
- break;
- default:
- break;
- }
- }
-
- return len;
-}
-
-off_t chunkqueue_written(chunkqueue *cq) {
- off_t len = 0;
- chunk *c;
-
- for (c = cq->first; c; c = c->next) {
- switch (c->type) {
- case MEM_CHUNK:
- case FILE_CHUNK:
- len += c->offset;
- break;
- default:
- break;
- }
- }
-
- return len;
-}
-
-int chunkqueue_is_empty(chunkqueue *cq) {
- return cq->first ? 0 : 1;
-}
-
-int chunkqueue_remove_finished_chunks(chunkqueue *cq) {
- chunk *c;
-
- for (c = cq->first; c; c = cq->first) {
- if (!chunk_is_done(c)) break;
-
- /* the chunk is finished, remove it from the queue */
- cq->first = c->next;
- if (c == cq->last) cq->last = NULL;
-
- chunkpool_add_unused_chunk(c);
-
- }
-
- return 0;
-}
-
-void chunkqueue_print(chunkqueue *cq) {
- chunk *c;
-
- for (c = cq->first; c; c = c->next) {
- fprintf(stderr, "(mem) %s", c->mem->ptr + c->offset);
- }
- fprintf(stderr, "\r\n");
-}
-
-
-/**
- * remove the last chunk if it is empty
- */
-
-void chunkqueue_remove_empty_last_chunk(chunkqueue *cq) {
- chunk *c;
- if (!cq->last) return;
- if (!cq->first) return;
-
- if (cq->last->type != MEM_CHUNK || cq->last->mem->used != 0) return;
-
- if (cq->first == cq->last) {
- c = cq->first;
-
- chunk_free(c);
- cq->first = cq->last = NULL;
- } else {
- for (c = cq->first; c->next; c = c->next) {
- if (c->next == cq->last) {
- cq->last = c;
-
- chunk_free(c->next);
- c->next = NULL;
-
- return;
- }
- }
- }
-}
-
-
diff --git a/src/chunk.h b/src/chunk.h
deleted file mode 100644
index 63793b2f..00000000
--- a/src/chunk.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef _CHUNK_H_
-#define _CHUNK_H_
-
-#include "buffer.h"
-#include "array.h"
-#include "sys-mmap.h"
-
-typedef struct chunk {
- enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
-
- buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
-
- struct {
- /* filechunk */
- buffer *name; /* name of the file */
- off_t start; /* starting offset in the file */
- off_t length; /* octets to send from the starting offset */
-
- int fd;
- struct {
- char *start; /* the start pointer of the mmap'ed area */
- size_t length; /* size of the mmap'ed area */
- off_t offset; /* start is <n> octets away from the start of the file */
- } mmap;
-
- int is_temp; /* file is temporary and will be deleted on cleanup */
-
- struct {
- int fd;
- off_t length;
- off_t offset;
- } copy;
- } file;
-
- off_t offset; /* octets sent from this chunk
- the size of the chunk is either
- - mem-chunk: mem->used - 1
- - file-chunk: file.length
- */
-
- struct {
- off_t written;
- int ret_val;
- } async;
-
- struct chunk *next;
-} chunk;
-
-typedef struct {
- chunk *first;
- chunk *last;
-
- array *tempdirs;
-
- int is_closed; /* the input to this CQ is closed */
-
- off_t bytes_in, bytes_out;
-} chunkqueue;
-
-LI_API void chunkpool_free(void);
-
-LI_API chunkqueue* chunkqueue_init(void);
-LI_API int chunkqueue_set_tempdirs(chunkqueue *c, array *tempdirs);
-LI_API int chunkqueue_append_file(chunkqueue *c, buffer *fn, off_t offset, off_t len);
-LI_API int chunkqueue_append_mem(chunkqueue *c, const char *mem, size_t len);
-LI_API int chunkqueue_append_buffer(chunkqueue *c, buffer *mem);
-LI_API int chunkqueue_prepend_buffer(chunkqueue *c, buffer *mem);
-
-LI_API buffer * chunkqueue_get_append_buffer(chunkqueue *c);
-LI_API buffer * chunkqueue_get_prepend_buffer(chunkqueue *c);
-LI_API chunk * chunkqueue_get_append_tempfile(chunkqueue *cq);
-LI_API int chunkqueue_steal_tempfile(chunkqueue *cq, chunk *in);
-LI_API off_t chunkqueue_steal_chunk(chunkqueue *cq, chunk *c);
-LI_API off_t chunkqueue_steal_chunks_len(chunkqueue *cq, chunk *c, off_t max_len);
-LI_API off_t chunkqueue_steal_all_chunks(chunkqueue *cq, chunkqueue *in);
-LI_API off_t chunkqueue_skip(chunkqueue *cq, off_t skip);
-LI_API void chunkqueue_remove_empty_last_chunk(chunkqueue *cq);
-
-LI_API int chunkqueue_remove_finished_chunks(chunkqueue *cq);
-
-LI_API off_t chunkqueue_length(chunkqueue *c);
-LI_API off_t chunkqueue_written(chunkqueue *c);
-LI_API void chunkqueue_free(chunkqueue *c);
-LI_API void chunkqueue_reset(chunkqueue *c);
-
-LI_API int chunkqueue_is_empty(chunkqueue *c);
-
-LI_API void chunkqueue_print(chunkqueue *cq);
-
-LI_API int chunk_is_done(chunk *c);
-LI_API void chunk_set_done(chunk *c);
-LI_API off_t chunk_length(chunk *c);
-
-#endif
diff --git a/src/config.h.cmake b/src/config.h.cmake
deleted file mode 100644
index 0aaeaa4f..00000000
--- a/src/config.h.cmake
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- CMake autogenerated config.h file. Do not edit!
-*/
-
-/* System */
-#cmakedefine HAVE_SYS_DEVPOLL_H
-#cmakedefine HAVE_SYS_EPOLL_H
-#cmakedefine HAVE_SYS_EVENT_H
-#cmakedefine HAVE_SYS_MMAN_H
-#cmakedefine HAVE_SYS_POLL_H
-#cmakedefine HAVE_SYS_PORT_H
-#cmakedefine HAVE_SYS_PRCTL_H
-#cmakedefine HAVE_SYS_RESOURCE_H
-#cmakedefine HAVE_SYS_SENDFILE_H
-#cmakedefine HAVE_SYS_SELECT_H
-#cmakedefine HAVE_SYS_SYSLIMITS_H
-#cmakedefine HAVE_SYS_TYPES_H
-#cmakedefine HAVE_SYS_UIO_H
-#cmakedefine HAVE_SYS_UN_H
-#cmakedefine HAVE_SYS_WAIT_H
-#cmakedefine HAVE_SYS_TIME_H
-#cmakedefine HAVE_TIME_H
-#cmakedefine HAVE_UNISTD_H
-#cmakedefine HAVE_PTHREAD_H
-#cmakedefine HAVE_INET_ATON
-#cmakedefine HAVE_IPV6
-#cmakedefine HAVE_ISSETUGID
-
-/* XATTR */
-#cmakedefine HAVE_ATTR_ATTRIBUTES_H
-
-/* mySQL */
-#cmakedefine HAVE_MYSQL_H
-#cmakedefine HAVE_LIBMYSQL
-
-/* postgresql */
-#cmakedefine HAVE_LIBPQ_FE_H
-#cmakedefine HAVE_LIBPQ
-
-/* OpenSSL */
-#cmakedefine HAVE_OPENSSL_SSL_H
-#cmakedefine HAVE_LIBCRYPTO
-#cmakedefine OPENSSL_NO_KRB5
-#cmakedefine HAVE_LIBSSL
-
-#cmakedefine HAVE_AIO_H
-
-/* BZip */
-#cmakedefine HAVE_BZLIB_H
-#cmakedefine HAVE_LIBBZ2
-
-/* FAM */
-#cmakedefine HAVE_FAM_H
-
-/* getopt */
-#cmakedefine HAVE_GETOPT_H
-
-#cmakedefine HAVE_INTTYPES_H
-
-/* LDAP */
-#cmakedefine HAVE_LDAP_H
-#cmakedefine HAVE_LIBLDAP
-
-/* libaio */
-#cmakedefine HAVE_LIBAIO_H
-#cmakedefine HAVE_LIBAIO
-
-/* XML */
-#cmakedefine HAVE_LIBXML_H
-#cmakedefine HAVE_LIBXML
-
-/* PCRE */
-#cmakedefine HAVE_PCRE_H
-#cmakedefine HAVE_LIBPCRE
-
-#cmakedefine HAVE_POLL_H
-#cmakedefine HAVE_PWD_H
-
-/* sqlite3 */
-#cmakedefine HAVE_SQLITE3_H
-#cmakedefine HAVE_LIBPCRE
-
-#cmakedefine HAVE_STDDEF_H
-#cmakedefine HAVE_STDINT_H
-#cmakedefine HAVE_SYSLOG_H
-
-/* UUID */
-#cmakedefine HAVE_UUID_H
-#cmakedefine HAVE_LIBUUID
-
-/* ZLIB */
-#cmakedefine HAVE_ZLIB_H
-#cmakedefine HAVE_LIBZ
-
-/* GLIB */
-#cmakedefine HAVE_GLIB_H
-#cmakedefine HAVE_GLIB
-
-/* lua */
-#cmakedefine HAVE_LUA_H
-#cmakedefine HAVE_LIBLUA
-
-/* inotify */
-#cmakedefine HAVE_INOTIFY_INIT
-#cmakedefine HAVE_SYS_INOTIFY_H
-
-/* Types */
-#cmakedefine HAVE_SOCKLEN_T
-#cmakedefine SIZEOF_LONG ${SIZEOF_LONG}
-#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T}
-
-/* Functions */
-#cmakedefine HAVE_CHROOT
-#cmakedefine HAVE_CRYPT
-#cmakedefine HAVE_EPOLL_CTL
-#cmakedefine HAVE_FORK
-#cmakedefine HAVE_GETRLIMIT
-#cmakedefine HAVE_GETUID
-#cmakedefine HAVE_GMTIME_R
-#cmakedefine HAVE_INET_NTOP
-#cmakedefine HAVE_KQUEUE
-#cmakedefine HAVE_LOCALTIME_R
-#cmakedefine HAVE_LSTAT
-#cmakedefine HAVE_MADVISE
-#cmakedefine HAVE_MEMCPY
-#cmakedefine HAVE_MEMSET
-#cmakedefine HAVE_MMAP
-#cmakedefine HAVE_PATHCONF
-#cmakedefine HAVE_POLL
-#cmakedefine HAVE_PORT_CREATE
-#cmakedefine HAVE_PRCTL
-#cmakedefine HAVE_PREAD
-#cmakedefine HAVE_POSIX_FADVISE
-#cmakedefine HAVE_SELECT
-#cmakedefine HAVE_SENDFILE
-#cmakedefine HAVE_SENDFILE64
-#cmakedefine HAVE_SENDFILEV
-#cmakedefine HAVE_SIGACTION
-#cmakedefine HAVE_SIGNAL
-#cmakedefine HAVE_SIGTIMEDWAIT
-#cmakedefine HAVE_STRPTIME
-#cmakedefine HAVE_STRTOLL
-#cmakedefine HAVE_SYSLOG
-#cmakedefine HAVE_WRITEV
-
-/* libcrypt */
-#cmakedefine HAVE_LIBCRYPT
-
-/* fastcgi */
-#cmakedefine HAVE_FASTCGI_H
-#cmakedefine HAVE_FASTCGI_FASTCGI_H
-
-#cmakedefine LIGHTTPD_STATIC
diff --git a/src/configfile-glue.c b/src/configfile-glue.c
deleted file mode 100644
index 8a31e333..00000000
--- a/src/configfile-glue.c
+++ /dev/null
@@ -1,675 +0,0 @@
-#include <string.h>
-#include <ctype.h>
-
-#include "base.h"
-#include "buffer.h"
-#include "array.h"
-#include "log.h"
-#include "plugin.h"
-#include "configfile.h"
-
-/**
- * like all glue code this file contains functions which
- * are the external interface of lighttpd. The functions
- * are used by the server itself and the plugins.
- *
- * The main-goal is to have a small library in the end
- * which is linked against both and which will define
- * the interface itself in the end.
- *
- */
-
-
-/* handle global options */
-
-/* parse config array */
-int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
- size_t i;
- data_unset *du;
-
- for (i = 0; cv[i].key; i++) {
-
- if (NULL == (du = array_get_element(ca, cv[i].key, strlen(cv[i].key)))) {
- /* no found */
-
- continue;
- }
-
- switch (cv[i].type) {
- case T_CONFIG_ARRAY:
- if (du->type == TYPE_ARRAY) {
- size_t j;
- data_array *da = (data_array *)du;
-
- for (j = 0; j < da->value->used; j++) {
- if (da->value->data[j]->type == TYPE_STRING) {
- data_string *ds;
-
- if (NULL == (ds = (data_string *)array_get_unused_element(cv[i].destination, TYPE_STRING))) {
- ds = data_string_init();
- }
-
- buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
- if (!da->is_index_key) {
- /* the id's were generated automaticly, as we copy now we might have to renumber them
- * this is used to prepend server.modules by mod_indexfile as it has to be loaded
- * before mod_fastcgi and friends */
- buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
- }
-
- array_insert_unique(cv[i].destination, (data_unset *)ds);
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sssd",
- "the key of an array can only be a string or a integer, variable:",
- cv[i].key, "type:", da->value->data[j]->type);
-
- return -1;
- }
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
-
- return -1;
- }
- break;
- case T_CONFIG_STRING:
- if (du->type == TYPE_STRING) {
- data_string *ds = (data_string *)du;
-
- buffer_copy_string_buffer(cv[i].destination, ds->value);
- } else if (du->type == TYPE_INTEGER) {
- data_integer *di = (data_integer *)du;
-
- buffer_copy_long(cv[i].destination, di->value);
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
-
- return -1;
- }
- break;
- case T_CONFIG_SHORT:
- switch(du->type) {
- case TYPE_INTEGER: {
- data_integer *di = (data_integer *)du;
-
- *((unsigned short *)(cv[i].destination)) = di->value;
- break;
- }
- case TYPE_STRING: {
- data_string *ds = (data_string *)du;
-
- if (buffer_isdigit(ds->value)) {
- *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
- break;
- }
-
- log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a short:", cv[i].key, ds->value);
-
- return -1;
- }
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a short integer, range 0 ... 65535");
- return -1;
- }
- break;
- case T_CONFIG_INT:
- switch(du->type) {
- case TYPE_INTEGER: {
- data_integer *di = (data_integer *)du;
-
- *((unsigned int *)(cv[i].destination)) = di->value;
- break;
- }
- case TYPE_STRING: {
- data_string *ds = (data_string *)du;
-
- if (buffer_isdigit(ds->value)) {
- *((unsigned int *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
- break;
- }
-
- log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a integer:", cv[i].key, ds->value);
-
- return -1;
- }
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a integer, range 0 ... 4294967295");
- return -1;
- }
- break;
- case T_CONFIG_BOOLEAN:
- if (du->type == TYPE_STRING) {
- data_string *ds = (data_string *)du;
-
- if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
- *((unsigned short *)(cv[i].destination)) = 1;
- } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
- *((unsigned short *)(cv[i].destination)) = 0;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
-
- return -1;
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
-
- return -1;
- }
- break;
- case T_CONFIG_LOCAL:
- case T_CONFIG_UNSET:
- break;
- case T_CONFIG_UNSUPPORTED:
- ERROR("found unsupported key in '%s' = '%s'", cv[i].key, (char *)(cv[i].destination));
-
- srv->config_unsupported = 1;
-
- break;
- case T_CONFIG_DEPRECATED:
- ERROR("found deprecated key in '%s' = '%s'", cv[i].key, (char *)(cv[i].destination));
-
- srv->config_deprecated = 1;
-
- break;
- }
- }
- return 0;
-}
-
-int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
- size_t i;
- data_unset *du;
-
- for (i = 0; cv[i].key; i++) {
- data_string *touched;
-
- if (NULL == (du = array_get_element(ca, cv[i].key, strlen(cv[i].key)))) {
- /* no found */
-
- continue;
- }
-
- /* touched */
- touched = data_string_init();
-
- buffer_copy_string_len(touched->value, CONST_STR_LEN(""));
- buffer_copy_string_buffer(touched->key, du->key);
-
- array_insert_unique(srv->config_touched, (data_unset *)touched);
- }
-
- return config_insert_values_internal(srv, ca, cv);
-}
-
-unsigned short sock_addr_get_port(sock_addr *addr) {
- switch (addr->plain.sa_family) {
- case AF_INET:
- return ntohs(addr->ipv4.sin_port);
-#ifdef HAVE_IPV6
- case AF_INET6:
- return ntohs(addr->ipv6.sin6_port);
-#endif
- default:
- return 0;
- }
-}
-
-static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc);
-
-static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) {
- buffer *l;
- server_socket *srv_sock = con->srv_socket;
- /* check parent first */
- if (dc->parent && dc->parent->context_ndx) {
- if (con->conf.log_condition_handling) {
- TRACE("checking if the parent (%s) evaluates to 'true'", SAFE_BUF_STR(dc->parent->key));
- }
-
- switch (config_check_cond_cached(srv, con, dc->parent)) {
- case COND_RESULT_FALSE:
- return COND_RESULT_FALSE;
- case COND_RESULT_UNSET:
- return COND_RESULT_UNSET;
- default:
- break;
- }
- }
-
- if (dc->prev) {
- if (con->conf.log_condition_handling) {
- TRACE("triggering eval of successors of (%s) [in else]", SAFE_BUF_STR(dc->key));
- }
-
- /* make sure prev is checked first */
- config_check_cond_cached(srv, con, dc->prev);
-
- if (con->conf.log_condition_handling) {
- TRACE("(%s) [in else] -> %s", SAFE_BUF_STR(dc->key), con->cond_cache[dc->context_ndx].result == COND_RESULT_FALSE ? "false" : "we will see");
- }
-
- switch (con->cond_cache[dc->context_ndx].result) {
- case COND_RESULT_FALSE: /* one of prev set me to FALSE */
- return con->cond_cache[dc->context_ndx].result;
- default:
- break;
- }
- }
-
- if (!con->conditional_is_valid[dc->comp]) {
- if (con->conf.log_condition_handling) {
- TRACE("is condition [%d] (%s) already valid ? %s",
- dc->comp,
- SAFE_BUF_STR(dc->key),
- con->conditional_is_valid[dc->comp] ? "yeah" : "nej");
- }
-
- return COND_RESULT_UNSET;
- }
-
- /* pass the rules */
-
- switch (dc->comp) {
- case COMP_HTTP_HOST: {
- char *ck_colon = NULL, *val_colon = NULL;
-
- if (!buffer_is_empty(con->uri.authority)) {
-
- /*
- * append server-port to the HTTP_POST if necessary
- */
-
- l = con->uri.authority;
-
- switch(dc->cond) {
- case CONFIG_COND_NE:
- case CONFIG_COND_EQ:
- ck_colon = strchr(dc->string->ptr, ':');
- val_colon = strchr(l->ptr, ':');
-
- if (NULL != ck_colon && NULL == val_colon) {
- /* condition "host:port" but client send "host" */
- buffer_copy_string_buffer(srv->cond_check_buf, l);
- buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":"));
- buffer_append_long(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr)));
- l = srv->cond_check_buf;
- } else if (NULL != val_colon && NULL == ck_colon) {
- /* condition "host" but client send "host:port" */
- buffer_copy_string_len(srv->cond_check_buf, l->ptr, val_colon - l->ptr);
- l = srv->cond_check_buf;
- }
- break;
- default:
- break;
- }
-#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
- } else if (!buffer_is_empty(con->sock->tlsext_server_name)) {
- l = con->sock->tlsext_server_name;
-#endif
- } else {
- l = srv->empty_string;
- }
- break;
- }
- case COMP_HTTP_REMOTE_IP: {
- char *nm_slash;
- /* handle remoteip limitations
- *
- * "10.0.0.1" is provided for all comparisions
- *
- * only for == and != we support
- *
- * "10.0.0.1/24"
- */
-
- if ((dc->cond == CONFIG_COND_EQ ||
- dc->cond == CONFIG_COND_NE) &&
- (con->dst_addr.plain.sa_family == AF_INET) &&
- (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) {
- int nm_bits;
- long nm;
- char *err;
- struct in_addr val_inp;
-
- if (con->conf.log_condition_handling) {
- l = srv->empty_string;
-
- log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
- "(", l, ") compare to", dc->string);
- }
-
- if (*(nm_slash+1) == '\0') {
- log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
-
- return COND_RESULT_FALSE;
- }
-
- nm_bits = strtol(nm_slash + 1, &err, 10);
-
- if (*err) {
- log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
-
- return COND_RESULT_FALSE;
- }
-
- /* take IP convert to the native */
- buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
-#ifdef _WIN32
- if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
-
- return COND_RESULT_FALSE;
- }
-
-#else
- if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
-
- return COND_RESULT_FALSE;
- }
-#endif
-
- /* build netmask */
- nm = htonl(~((1 << (32 - nm_bits)) - 1));
-
- if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
- return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
- } else {
- return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
- }
- } else {
- l = con->dst_addr_buf;
- }
- break;
- }
- case COMP_HTTP_SCHEME:
- l = con->uri.scheme;
- break;
-
- case COMP_HTTP_URL:
- l = con->uri.path;
- break;
-
- case COMP_HTTP_QUERY_STRING:
- l = con->uri.query;
- break;
-
- case COMP_SERVER_SOCKET:
- l = srv_sock->srv_token;
- break;
-
- case COMP_HTTP_REFERER: {
- data_string *ds;
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Referer")))) {
- l = ds->value;
- } else {
- l = srv->empty_string;
- }
- break;
- }
- case COMP_HTTP_COOKIE: {
- data_string *ds;
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Cookie")))) {
- l = ds->value;
- } else {
- l = srv->empty_string;
- }
- break;
- }
- case COMP_HTTP_USER_AGENT: {
- data_string *ds;
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("User-Agent")))) {
- l = ds->value;
- } else {
- l = srv->empty_string;
- }
- 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;
- }
- case COMP_PHYSICAL_PATH_EXISTS:
- case COMP_PHYSICAL_PATH:
- l = con->physical.path;
- break;
- default:
- return COND_RESULT_FALSE;
- }
-
- if (NULL == l) {
- if (con->conf.log_condition_handling) {
- log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
- "(", l, ") compare to NULL");
- }
- return COND_RESULT_FALSE;
- }
-
- if (con->conf.log_condition_handling) {
- TRACE("'%s': '%s' is matched against '%s'",
- SAFE_BUF_STR(dc->comp_key),
- SAFE_BUF_STR(l),
- SAFE_BUF_STR(dc->string));
- }
-
- switch(dc->cond) {
- case CONFIG_COND_NE:
- case CONFIG_COND_EQ:
- if (buffer_is_equal(l, dc->string)) {
- return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
- } else {
- return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
- }
- break;
-#ifdef HAVE_PCRE_H
- case CONFIG_COND_NOMATCH:
- case CONFIG_COND_MATCH: {
- cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
- int n;
-
-#ifndef elementsof
-#define elementsof(x) (sizeof(x) / sizeof(x[0]))
-#endif
- n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
- cache->matches, elementsof(cache->matches));
-
- cache->patterncount = n;
- if (n > 0) {
- cache->comp_value = l;
- cache->comp_type = dc->comp;
-
- return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
- } else {
- /* cache is already cleared */
- return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
- }
- break;
- }
-#endif
- default:
- /* no way */
- break;
- }
-
- return COND_RESULT_FALSE;
-}
-
-static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc) {
- cond_cache_t *caches = con->cond_cache;
-
- if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
- if (con->conf.log_condition_handling) {
- TRACE("=== start of %d condition block ===", dc->context_ndx);
- }
- if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
- /* a node evaluted to true, all else nodes have to false */
- if (dc->next) {
- data_config *c;
- if (con->conf.log_condition_handling) {
- TRACE("setting remains of chaining to %s", "false");
- }
- for (c = dc->next; c; c = c->next) {
- caches[c->context_ndx].result = COND_RESULT_FALSE;
- }
- }
- }
- caches[dc->context_ndx].comp_type = dc->comp;
-
- if (con->conf.log_condition_handling) {
- TRACE("[%d] result: %s",
- dc->context_ndx,
- caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" :
- (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false")
- );
- }
- } else {
- if (con->conf.log_condition_cache_handling) {
- TRACE("[%d] (cached) result: %s",
- dc->context_ndx,
- caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" :
- (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false")
- );
- }
- }
-
- return caches[dc->context_ndx].result;
-}
-
-/**
- * reset the config-cache for a named item
- *
- * if the item is COND_LAST_ELEMENT we reset all items
- */
-void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- if (item == COMP_LAST_ELEMENT ||
- con->cond_cache[i].comp_type == item) {
- con->cond_cache[i].result = COND_RESULT_UNSET;
- con->cond_cache[i].patterncount = 0;
- con->cond_cache[i].comp_value = NULL;
- }
- }
-}
-
-/**
- * reset the config cache to its initial state at connection start
- */
-void config_cond_cache_reset(server *srv, connection *con) {
- size_t i;
-
- config_cond_cache_reset_all_items(srv, con);
-
- for (i = 0; i < COMP_LAST_ELEMENT; i++) {
- con->conditional_is_valid[i] = 0;
- }
-}
-
-int config_check_cond(server *srv, connection *con, data_config *dc) {
- return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
-}
-
-int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n)
-{
- cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
- if (n >= cache->patterncount) {
- return 0;
- }
-
- n <<= 1; /* n *= 2 */
- buffer_append_string_len(buf,
- cache->comp_value->ptr + cache->matches[n],
- cache->matches[n + 1] - cache->matches[n]);
- return 1;
-}
-
-/* return <0 on error
- * return 0-x if matched (and replaced)
- */
-int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
-{
-#ifdef HAVE_PCRE_H
- pcre *match;
- pcre_extra *extra;
- const char *pattern;
- size_t pattern_len;
- int n;
- size_t i;
- pcre_keyvalue *kv;
-# define N 10
- int ovec[N * 3];
-
- for (i = 0; i < kvb->used; i++) {
- kv = kvb->kv[i];
-
- match = kv->key;
- extra = kv->key_extra;
- pattern = kv->value->ptr;
- pattern_len = kv->value->used - 1;
-
- if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
- if (n != PCRE_ERROR_NOMATCH) {
- return n;
- }
- } else {
- const char **list;
- size_t start, end;
- size_t k;
-
- /* it matched */
- pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
-
- /* search for $[0-9] */
-
- buffer_reset(result);
-
- start = 0; end = pattern_len;
- for (k = 0; k < pattern_len; k++) {
- if ((pattern[k] == '$' || pattern[k] == '%') &&
- isdigit((unsigned char)pattern[k + 1])) {
- /* got one */
-
- size_t num = pattern[k + 1] - '0';
-
- end = k;
-
- buffer_append_string_len(result, pattern + start, end - start);
-
- if (pattern[k] == '$') {
- /* n is always > 0 */
- if (num < (size_t)n) {
- buffer_append_string(result, list[num]);
- }
- } else {
- config_append_cond_match_buffer(con, context, result, num);
- }
-
- k++;
- start = k + 1;
- }
- }
-
- buffer_append_string_len(result, pattern + start, pattern_len - start);
-
- pcre_free(list);
-
- return i;
- }
- }
-
- return PCRE_ERROR_NOMATCH;
-#undef N
-#else
- UNUSED(kvb);
- return -2;
-#endif
-}
-
diff --git a/src/configfile.c b/src/configfile.c
deleted file mode 100644
index 1254c270..00000000
--- a/src/configfile.c
+++ /dev/null
@@ -1,1376 +0,0 @@
-#include <sys/stat.h>
-
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "server.h"
-#include "log.h"
-#include "stream.h"
-#include "plugin.h"
-#include "configparser.h"
-#include "configfile.h"
-#include "proc_open.h"
-#include "fdevent.h"
-#include "network_backends.h"
-
-#include "sys-files.h"
-#include "sys-process.h"
-
-#ifndef PATH_MAX
-/* win32 */
-#define PATH_MAX 64
-#endif
-
-static int config_insert(server *srv) {
- size_t i;
- int ret = 0;
- buffer *stat_cache_string;
-
- config_values_t cv[] = {
- { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
- { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
- { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
- { "server.chroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 */
- { "server.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 */
- { "server.groupname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 */
- { "server.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 */
- { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
- { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
- { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
-
- { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
- { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
- { "server.max-request-size", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
- { "server.max-worker", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 13 */
- { "server.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
- { "server.force-lowercase-filenames", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 15 */
- { "debug.log-condition-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 16 */
- { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
- { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
- { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
-
- { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
- { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
- { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
- { "server.max-fds", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 23 */
-#ifdef HAVE_LSTAT
- { "server.follow-symlink", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 24 */
-#else
- { "server.follow-symlink",
- "Your system lacks lstat(). We cant differ symlinks from files."
- "Please remove server.follow-symlinks from your config.",
- T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET }, /* 24 */
-#endif
- { "server.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 25 */
- { "connection.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 26 */
- { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
- { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
- { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
-
- { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
-
- { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
- { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
- { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
- { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
-
- { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
- { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
- { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
- { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
-
- { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
- { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
- { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
- { "server.max-connections", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 42 */
- { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
- { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
- { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
- { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
- { "server.use-noatime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 49 */
- { "server.max-stat-threads", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 48 */
- { "server.max-read-threads", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 49 */
- { "server.max-connection-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 50 */
- { "debug.log-timing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 51 */
- { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 52 */
- { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 53 */
- { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 54 */
- { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 55 */
- { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 56 */
- { "server.breakagelog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 57 */
- { "debug.log-timeouts", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 58 */
- { "debug.log-ssl-noise", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 59 */
- { "ssl.verifyclient.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 60 */
- { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 61 */
- { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 62 */
- { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 63 */
- { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 64 */
-
- { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.virtual-default-host", "load mod_simple_vhost and use simple-vhost.default-host instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.virtual-docroot", "load mod_simple_vhost and use simple-vhost.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.userid", "use server.username instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
- { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
-
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
-
- /* 0 */
- cv[0].destination = srv->srvconf.bindhost;
- cv[1].destination = srv->srvconf.errorlog_file;
- cv[3].destination = srv->srvconf.changeroot;
- cv[4].destination = srv->srvconf.username;
- cv[5].destination = srv->srvconf.groupname;
- cv[6].destination = &(srv->srvconf.port);
-
- cv[9].destination = srv->srvconf.modules;
- cv[10].destination = srv->srvconf.event_handler;
- cv[11].destination = srv->srvconf.pid_file;
-
- cv[13].destination = &(srv->srvconf.max_worker);
- cv[23].destination = &(srv->srvconf.max_fds);
- cv[36].destination = &(srv->srvconf.log_request_header_on_error);
- cv[37].destination = &(srv->srvconf.log_state_handling);
-
- cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
-
- stat_cache_string = buffer_init();
- cv[41].destination = stat_cache_string;
- cv[43].destination = srv->srvconf.network_backend;
- cv[44].destination = srv->srvconf.upload_tempdirs;
- cv[45].destination = &(srv->srvconf.enable_cores);
-
- cv[42].destination = &(srv->srvconf.max_conns);
- cv[12].destination = &(srv->srvconf.max_request_size);
- cv[47].destination = &(srv->srvconf.use_noatime);
- cv[48].destination = &(srv->srvconf.max_stat_threads);
- cv[49].destination = &(srv->srvconf.max_read_threads);
-
- cv[51].destination = &(srv->srvconf.log_timing);
- cv[57].destination = srv->srvconf.breakagelog_file;
-
- srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- assert(srv->config_storage);
-
- for (i = 0; i < srv->config_context->used; i++) {
- specific_config *s;
-
- s = calloc(1, sizeof(specific_config));
- assert(s);
- s->document_root = buffer_init();
- s->mimetypes = array_init();
- s->server_name = buffer_init();
- s->ssl_pemfile = buffer_init();
- s->ssl_ca_file = buffer_init();
- s->error_handler = buffer_init();
- s->server_tag = buffer_init();
- s->errorfile_prefix = buffer_init();
- s->ssl_cipher_list = buffer_init();
- s->ssl_use_sslv2 = 1;
- s->ssl_verifyclient = 0;
- s->ssl_verifyclient_enforce = 1;
- s->ssl_verifyclient_username = buffer_init();
- s->ssl_verifyclient_depth = 9;
- s->ssl_verifyclient_export_cert = 0;
- s->max_keep_alive_requests = 16;
- s->max_keep_alive_idle = 5;
- s->max_read_idle = 60;
- s->max_write_idle = 360;
- s->max_connection_idle = 360;
- s->use_xattr = 0;
- s->is_ssl = 0;
- s->use_ipv6 = 0;
-#ifdef HAVE_LSTAT
- s->follow_symlink = 1;
-#endif
- s->kbytes_per_second = 0;
- s->allow_http11 = 1;
- s->range_requests = 1;
- s->etag_use_inode = 1;
- s->etag_use_mtime = 1;
- s->etag_use_size = 1;
- s->force_lowercase_filenames = 0;
- s->global_kbytes_per_second = 0;
- s->global_bytes_per_second_cnt = 0;
- s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
-
- cv[2].destination = s->errorfile_prefix;
-
- cv[7].destination = s->server_tag;
- cv[8].destination = &(s->use_ipv6);
-
-
- /* 13 max-worker */
- cv[14].destination = s->document_root;
- cv[15].destination = &(s->force_lowercase_filenames);
- cv[16].destination = &(s->log_condition_handling);
- cv[46].destination = &(s->log_condition_cache_handling);
- cv[17].destination = &(s->max_keep_alive_requests);
- cv[18].destination = s->server_name;
- cv[19].destination = &(s->max_keep_alive_idle);
- cv[20].destination = &(s->max_read_idle);
- cv[21].destination = &(s->max_write_idle);
- cv[22].destination = s->error_handler;
-#ifdef HAVE_LSTAT
- cv[24].destination = &(s->follow_symlink);
-#endif
- /* 23 -> max-fds */
- cv[25].destination = &(s->global_kbytes_per_second);
- cv[26].destination = &(s->kbytes_per_second);
- cv[27].destination = &(s->use_xattr);
- cv[28].destination = s->mimetypes;
- cv[29].destination = s->ssl_pemfile;
- cv[30].destination = &(s->is_ssl);
-
- cv[31].destination = &(s->log_file_not_found);
- cv[32].destination = &(s->log_request_handling);
- cv[33].destination = &(s->log_response_header);
- cv[34].destination = &(s->log_request_header);
-
- cv[35].destination = &(s->allow_http11);
- cv[38].destination = s->ssl_ca_file;
- cv[40].destination = &(s->range_requests);
-
- cv[50].destination = &(s->max_connection_idle);
- cv[52].destination = s->ssl_cipher_list;
- cv[53].destination = &(s->ssl_use_sslv2);
-
- cv[54].destination = &(s->etag_use_inode);
- cv[55].destination = &(s->etag_use_mtime);
- cv[56].destination = &(s->etag_use_size);
- cv[58].destination = &(s->log_timeouts);
- cv[59].destination = &(s->log_ssl_noise);
-
- /* ssl.verify */
- cv[60].destination = &(s->ssl_verifyclient);
- cv[61].destination = &(s->ssl_verifyclient_enforce);
- cv[62].destination = &(s->ssl_verifyclient_depth);
- cv[63].destination = s->ssl_verifyclient_username;
- cv[64].destination = &(s->ssl_verifyclient_export_cert);
-
- srv->config_storage[i] = s;
-
- if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
- break;
- }
- }
-
- if (buffer_is_empty(stat_cache_string)) {
- srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
- } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
- srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
-#ifdef HAVE_FAM_H
- } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("fam"))) {
- srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_FAM;
-#endif
-#if defined(HAVE_SYS_INOTIFY_H)
- } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("inotify"))) {
- srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_INOTIFY;
-#endif
- } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
- srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "server.stat-cache-engine can be one of \"disable\", \"simple\""
-#ifdef HAVE_FAM_H
- ", \"fam\""
-#endif
-#if defined(HAVE_SYS_INOTIFY_H)
- ", \"inotify\""
-#endif
- " but not:", stat_cache_string);
- ret = HANDLER_ERROR;
- }
-
- buffer_free(stat_cache_string);
-
- return ret;
-
-}
-
-#define PATCH(x) \
- con->conf.x = s->x
-int config_setup_connection(server *srv, connection *con) {
- specific_config *s = srv->config_storage[0];
-
- PATCH(allow_http11);
- PATCH(mimetypes);
- PATCH(document_root);
- PATCH(max_keep_alive_requests);
- PATCH(max_keep_alive_idle);
- PATCH(max_read_idle);
- PATCH(max_write_idle);
- PATCH(max_connection_idle);
- PATCH(use_xattr);
- PATCH(error_handler);
- PATCH(errorfile_prefix);
-#ifdef HAVE_LSTAT
- PATCH(follow_symlink);
-#endif
- PATCH(server_tag);
- PATCH(kbytes_per_second);
- PATCH(global_kbytes_per_second);
- PATCH(global_bytes_per_second_cnt);
-
- con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
- buffer_copy_string_buffer(con->server_name, s->server_name);
-
- PATCH(log_request_header);
- PATCH(log_response_header);
- PATCH(log_request_handling);
- PATCH(log_condition_handling);
- PATCH(log_condition_cache_handling);
- PATCH(log_file_not_found);
- PATCH(log_ssl_noise);
- PATCH(log_timeouts);
-
- PATCH(range_requests);
- PATCH(force_lowercase_filenames);
- PATCH(is_ssl);
-
- PATCH(ssl_pemfile);
-#ifdef USE_OPENSSL
- PATCH(ssl_ctx);
-#endif
- PATCH(ssl_ca_file);
- PATCH(ssl_cipher_list);
- PATCH(ssl_use_sslv2);
- PATCH(etag_use_inode);
- PATCH(etag_use_mtime);
- PATCH(etag_use_size);
-
- PATCH(ssl_verifyclient);
- PATCH(ssl_verifyclient_enforce);
- PATCH(ssl_verifyclient_depth);
- PATCH(ssl_verifyclient_username);
- PATCH(ssl_verifyclient_export_cert);
-
- return 0;
-}
-
-int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
- size_t i, j;
-
- con->conditional_is_valid[comp] = 1;
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- specific_config *s = srv->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
- PATCH(document_root);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
- PATCH(range_requests);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler-404"))) {
- PATCH(error_handler);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.errorfile-prefix"))) {
- PATCH(errorfile_prefix);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.assign"))) {
- PATCH(mimetypes);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-requests"))) {
- PATCH(max_keep_alive_requests);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-idle"))) {
- PATCH(max_keep_alive_idle);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-write-idle"))) {
- PATCH(max_write_idle);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-read-idle"))) {
- PATCH(max_read_idle);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-connection-idle"))) {
- PATCH(max_connection_idle);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) {
- PATCH(use_xattr);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
- PATCH(ssl_pemfile);
-#ifdef USE_OPENSSL
- PATCH(ssl_ctx);
-#endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
- PATCH(ssl_ca_file);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
- PATCH(is_ssl);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) {
- PATCH(ssl_cipher_list);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
- PATCH(ssl_use_sslv2);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) {
- PATCH(etag_use_inode);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) {
- PATCH(etag_use_mtime);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) {
- PATCH(etag_use_size);
-#ifdef HAVE_LSTAT
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) {
- PATCH(follow_symlink);
-#endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) {
- buffer_copy_string_buffer(con->server_name, s->server_name);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) {
- PATCH(server_tag);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("connection.kbytes-per-second"))) {
- PATCH(kbytes_per_second);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-handling"))) {
- PATCH(log_request_handling);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-header"))) {
- PATCH(log_request_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) {
- PATCH(log_response_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
- PATCH(log_condition_handling);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
- PATCH(log_condition_cache_handling);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
- PATCH(log_file_not_found);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-ssl-noise"))) {
- PATCH(log_ssl_noise);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-timeouts"))) {
- PATCH(log_timeouts);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
- PATCH(allow_http11);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
- PATCH(force_lowercase_filenames);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
- PATCH(global_kbytes_per_second);
- PATCH(global_bytes_per_second_cnt);
- con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) {
- PATCH(ssl_verifyclient);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) {
- PATCH(ssl_verifyclient_enforce);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) {
- PATCH(ssl_verifyclient_depth);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) {
- PATCH(ssl_verifyclient_username);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) {
- PATCH(ssl_verifyclient_export_cert);
- }
- }
- }
-
-
- con->etag_flags =
- (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) |
- (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) |
- (con->conf.etag_use_size ? ETAG_USE_SIZE : 0);
-
- return 0;
-}
-#undef PATCH
-
-typedef struct {
- int foo;
- int bar;
-
- const buffer *source;
- const char *input;
- size_t offset;
- size_t size;
-
- int line_pos;
- int line;
-
- int in_key;
- int in_brace;
- int in_cond;
-} tokenizer_t;
-
-#if 0
-static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) {
- if (buffer_is_empty(basedir) &&
- (fn[0] == '/' || fn[0] == '\\') &&
- (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
- t->file = buffer_init_string(fn);
- } else {
- t->file = buffer_init_buffer(basedir);
- buffer_append_string(t->file, fn);
- }
-
- if (0 != stream_open(&(t->s), t->file)) {
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "opening configfile ", t->file, "failed:", strerror(errno));
- buffer_free(t->file);
- return -1;
- }
-
- t->input = t->s.start;
- t->offset = 0;
- t->size = t->s.size;
- t->line = 1;
- t->line_pos = 1;
-
- t->in_key = 1;
- t->in_brace = 0;
- t->in_cond = 0;
- return 0;
-}
-
-static int tokenizer_close(server *srv, tokenizer_t *t) {
- UNUSED(srv);
-
- buffer_free(t->file);
- return stream_close(&(t->s));
-}
-#endif
-static int config_skip_newline(tokenizer_t *t) {
- int skipped = 1;
- assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n');
- if (t->input[t->offset] == '\r' && t->input[t->offset + 1] == '\n') {
- skipped ++;
- t->offset ++;
- }
- t->offset ++;
- return skipped;
-}
-
-static int config_skip_comment(tokenizer_t *t) {
- int i;
- assert(t->input[t->offset] == '#');
- for (i = 1; t->input[t->offset + i] &&
- (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
- i++);
- t->offset += i;
- return i;
-}
-
-static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
- int tid = 0;
- size_t i;
-
- for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
- char c = t->input[t->offset];
- const char *start = NULL;
-
- switch (c) {
- case '=':
- if (t->in_brace) {
- if (t->input[t->offset + 1] == '>') {
- t->offset += 2;
-
- buffer_copy_string_len(token, CONST_STR_LEN("=>"));
-
- tid = TK_ARRAY_ASSIGN;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "use => for assignments in arrays");
- return -1;
- }
- } else if (t->in_cond) {
- if (t->input[t->offset + 1] == '=') {
- t->offset += 2;
-
- buffer_copy_string_len(token, CONST_STR_LEN("=="));
-
- tid = TK_EQ;
- } else if (t->input[t->offset + 1] == '~') {
- t->offset += 2;
-
- buffer_copy_string_len(token, CONST_STR_LEN("=~"));
-
- tid = TK_MATCH;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "only =~ and == are allowed in the condition");
- return -1;
- }
- t->in_key = 1;
- t->in_cond = 0;
- } else if (t->in_key) {
- tid = TK_ASSIGN;
-
- buffer_copy_string_len(token, t->input + t->offset, 1);
-
- t->offset++;
- t->line_pos++;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "unexpected equal-sign: =");
- return -1;
- }
-
- break;
- case '!':
- if (t->in_cond) {
- if (t->input[t->offset + 1] == '=') {
- t->offset += 2;
-
- buffer_copy_string_len(token, CONST_STR_LEN("!="));
-
- tid = TK_NE;
- } else if (t->input[t->offset + 1] == '~') {
- t->offset += 2;
-
- buffer_copy_string_len(token, CONST_STR_LEN("!~"));
-
- tid = TK_NOMATCH;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "only !~ and != are allowed in the condition");
- return -1;
- }
- t->in_key = 1;
- t->in_cond = 0;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "unexpected exclamation-marks: !");
- return -1;
- }
-
- break;
- case '\t':
- case ' ':
- t->offset++;
- t->line_pos++;
- break;
- case '\n':
- case '\r':
- if (t->in_brace == 0) {
- int done = 0;
- while (!done && t->offset < t->size) {
- switch (t->input[t->offset]) {
- case '\r':
- case '\n':
- config_skip_newline(t);
- t->line_pos = 1;
- t->line++;
- break;
-
- case '#':
- t->line_pos += config_skip_comment(t);
- break;
-
- case '\t':
- case ' ':
- t->offset++;
- t->line_pos++;
- break;
-
- default:
- done = 1;
- }
- }
- t->in_key = 1;
- tid = TK_EOL;
- buffer_copy_string_len(token, CONST_STR_LEN("(EOL)"));
- } else {
- config_skip_newline(t);
- t->line_pos = 1;
- t->line++;
- }
- break;
- case ',':
- if (t->in_brace > 0) {
- tid = TK_COMMA;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(COMMA)"));
- }
-
- t->offset++;
- t->line_pos++;
- break;
- case '"':
- /* search for the terminating " */
- start = t->input + t->offset + 1;
- buffer_copy_string_len(token, CONST_STR_LEN(""));
-
- for (i = 1; t->input[t->offset + i]; i++) {
- if (t->input[t->offset + i] == '\\' &&
- t->input[t->offset + i + 1] == '"') {
-
- buffer_append_string_len(token, start, t->input + t->offset + i - start);
-
- start = t->input + t->offset + i + 1;
-
- /* skip the " */
- i++;
- continue;
- }
-
-
- if (t->input[t->offset + i] == '"') {
- tid = TK_STRING;
-
- buffer_append_string_len(token, start, t->input + t->offset + i - start);
-
- break;
- }
- }
-
- if (t->input[t->offset + i] == '\0') {
- /* ERROR */
-
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "missing closing quote");
-
- return -1;
- }
-
- t->offset += i + 1;
- t->line_pos += i + 1;
-
- break;
- case '(':
- t->offset++;
- t->in_brace++;
-
- tid = TK_LPARAN;
-
- buffer_copy_string_len(token, CONST_STR_LEN("("));
- break;
- case ')':
- t->offset++;
- t->in_brace--;
-
- tid = TK_RPARAN;
-
- buffer_copy_string_len(token, CONST_STR_LEN(")"));
- break;
- case '$':
- t->offset++;
-
- tid = TK_DOLLAR;
- t->in_cond = 1;
- t->in_key = 0;
-
- buffer_copy_string_len(token, CONST_STR_LEN("$"));
-
- break;
-
- case '+':
- if (t->input[t->offset + 1] == '=') {
- t->offset += 2;
- buffer_copy_string_len(token, CONST_STR_LEN("+="));
- tid = TK_APPEND;
- } else {
- t->offset++;
- tid = TK_PLUS;
- buffer_copy_string_len(token, CONST_STR_LEN("+"));
- }
- break;
-
- case '{':
- t->offset++;
-
- tid = TK_LCURLY;
-
- buffer_copy_string_len(token, CONST_STR_LEN("{"));
-
- break;
-
- case '}':
- t->offset++;
-
- tid = TK_RCURLY;
-
- buffer_copy_string_len(token, CONST_STR_LEN("}"));
-
- break;
-
- case '[':
- t->offset++;
-
- tid = TK_LBRACKET;
-
- buffer_copy_string_len(token, CONST_STR_LEN("["));
-
- break;
-
- case ']':
- t->offset++;
-
- tid = TK_RBRACKET;
-
- buffer_copy_string_len(token, CONST_STR_LEN("]"));
-
- break;
- case '#':
- t->line_pos += config_skip_comment(t);
-
- break;
- default:
- if (t->in_cond) {
- for (i = 0; t->input[t->offset + i] &&
- (isalpha((unsigned char)t->input[t->offset + i])
- ); i++);
-
- if (i && t->input[t->offset + i]) {
- tid = TK_SRVVARNAME;
- buffer_copy_string_len(token, t->input + t->offset, i);
-
- t->offset += i;
- t->line_pos += i;
- } else {
- /* ERROR */
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "invalid character in condition");
- return -1;
- }
- } else if (isdigit((unsigned char)c)) {
- /* take all digits */
- for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
-
- /* was there it least a digit ? */
- if (i) {
- tid = TK_INTEGER;
-
- buffer_copy_string_len(token, t->input + t->offset, i);
-
- t->offset += i;
- t->line_pos += i;
- }
- } else {
- /* the key might consist of [-.0-9a-z] */
- for (i = 0; t->input[t->offset + i] &&
- (isalnum((unsigned char)t->input[t->offset + i]) ||
- t->input[t->offset + i] == '.' ||
- t->input[t->offset + i] == '_' || /* for env.* */
- t->input[t->offset + i] == '-'
- ); i++);
-
- if (i && t->input[t->offset + i]) {
- buffer_copy_string_len(token, t->input + t->offset, i);
-
- if (buffer_is_equal_string(token, CONST_STR_LEN("include"))) {
- tid = TK_INCLUDE;
- } else if (buffer_is_equal_string(token, CONST_STR_LEN("include_shell"))) {
- tid = TK_INCLUDE_SHELL;
- } else if (buffer_is_equal_string(token, CONST_STR_LEN("global"))) {
- tid = TK_GLOBAL;
- } else if (buffer_is_equal_string(token, CONST_STR_LEN("else"))) {
- tid = TK_ELSE;
- } else {
- tid = TK_LKEY;
- }
-
- t->offset += i;
- t->line_pos += i;
- } else {
- /* ERROR */
- log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "invalid character in variable name");
- return -1;
- }
- }
- break;
- }
- }
-
- if (tid) {
- *token_id = tid;
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- token, token->used - 1, tid);
-#endif
-
- return 1;
- } else if (t->offset < t->size) {
- fprintf(stderr, "%s.%d: %d, %s\n",
- __FILE__, __LINE__,
- tid, token->ptr);
- }
- return 0;
-}
-
-static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
- void *pParser;
- int token_id;
- buffer *token, *lasttoken;
- int ret;
-
- pParser = configparserAlloc( malloc );
- lasttoken = buffer_init();
- token = buffer_init();
-
- while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
- buffer_copy_string_buffer(lasttoken, token);
- configparser(pParser, token_id, token, context);
-
- token = buffer_init();
- }
- buffer_free(token);
-
- if (ret != -1 && context->ok) {
- /* add an EOL at EOF, better than say sorry */
- configparser(pParser, TK_EOL, buffer_init_string("(EOL)"), context);
- if (context->ok) {
- configparser(pParser, 0, NULL, context);
- }
- }
- configparserFree(pParser, free);
-
- if (ret == -1) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "configfile parser failed:", lasttoken);
- } else if (context->ok == 0) {
- log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
- "source:", t->source,
- "line:", t->line, "pos:", t->line_pos,
- "parser failed somehow near here:", lasttoken);
- ret = -1;
- }
- buffer_free(lasttoken);
-
- return ret == -1 ? -1 : 0;
-}
-
-static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) {
-
- t->source = source;
- t->input = input;
- t->size = size;
- t->offset = 0;
- t->line = 1;
- t->line_pos = 1;
-
- t->in_key = 1;
- t->in_brace = 0;
- t->in_cond = 0;
- return 0;
-}
-
-int config_parse_file(server *srv, config_t *context, const char *fn) {
- tokenizer_t t;
- stream s;
- int ret;
- buffer *filename;
-
- if (buffer_is_empty(context->basedir) ||
- (fn[0] == '/' || fn[0] == '\\') ||
- (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
- filename = buffer_init_string(fn);
- } else {
- filename = buffer_init_buffer(context->basedir);
- buffer_append_string(filename, fn);
- }
-
- if (0 != stream_open(&s, filename)) {
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "opening configfile ", filename, "failed:", strerror(errno));
- ret = -1;
- } else {
- tokenizer_init(&t, filename, s.start, s.size);
- ret = config_parse(srv, context, &t);
- }
-
- stream_close(&s);
- buffer_free(filename);
- return ret;
-}
-
-int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
- tokenizer_t t;
- int ret;
- buffer *source;
- buffer *out;
- char oldpwd[PATH_MAX];
-
- if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "cannot get cwd", strerror(errno));
- return -1;
- }
-
- source = buffer_init_string(cmd);
- out = buffer_init();
-
- if (!buffer_is_empty(context->basedir)) {
- chdir(context->basedir->ptr);
- }
-
- if (0 != proc_open_buffer(cmd, NULL, out, NULL)) {
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "opening", source, "failed:", strerror(errno));
- ret = -1;
- } else {
- tokenizer_init(&t, source, out->ptr, out->used);
- ret = config_parse(srv, context, &t);
- }
-
- buffer_free(source);
- buffer_free(out);
- chdir(oldpwd);
- return ret;
-}
-
-static void context_init(server *srv, config_t *context) {
- context->srv = srv;
- context->ok = 1;
- context->configs_stack = buffer_ptr_init(NULL);
- context->basedir = buffer_init();
-}
-
-static void context_free(config_t *context) {
- buffer_ptr_free(context->configs_stack);
- buffer_free(context->basedir);
-}
-
-int config_read(server *srv, const char *fn) {
- config_t context;
- data_config *dc;
- data_integer *dpid;
- data_string *dcwd;
- int ret;
- char *pos;
- data_array *modules;
-
- context_init(srv, &context);
- context.all_configs = srv->config_context;
-
- /* use the current dir as basedir for all other includes
- */
- pos = strrchr(fn, DIR_SEPERATOR);
-
- if (pos) {
- buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
- fn = pos + 1;
- }
-
- dc = data_config_init();
- buffer_copy_string_len(dc->key, CONST_STR_LEN("global"));
-
- assert(context.all_configs->used == 0);
- dc->context_ndx = context.all_configs->used;
- array_insert_unique(context.all_configs, (data_unset *)dc);
- context.current = dc;
-
- /* default context */
- srv->config = dc->value;
- dpid = data_integer_init();
- dpid->value = getpid();
- buffer_copy_string_len(dpid->key, CONST_STR_LEN("var.PID"));
- array_insert_unique(srv->config, (data_unset *)dpid);
-
- dcwd = data_string_init();
- buffer_prepare_copy(dcwd->value, 1024);
- if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
- dcwd->value->used = strlen(dcwd->value->ptr) + 1;
- buffer_copy_string_len(dcwd->key, CONST_STR_LEN("var.CWD"));
- array_insert_unique(srv->config, (data_unset *)dcwd);
- }
-
- ret = config_parse_file(srv, &context, fn);
-
- /* remains nothing if parser is ok */
- assert(!(0 == ret && context.ok && 0 != context.configs_stack->used));
- context_free(&context);
-
- if (0 != ret) {
- return ret;
- }
-
- if (NULL != (dc = (data_config *)array_get_element(srv->config_context, CONST_STR_LEN("global")))) {
- srv->config = dc->value;
- } else {
- return -1;
- }
-
- if (NULL != (modules = (data_array *)array_get_element(srv->config, CONST_STR_LEN("server.modules")))) {
- data_string *ds;
- data_array *prepends;
- int prepend_mod_indexfile = 1;
- int append_mod_dirlisting = 1;
- int append_mod_staticfile = 1;
- int append_mod_chunked = 1;
- size_t i;
-
- if (modules->type != TYPE_ARRAY) {
- fprintf(stderr, "server.modules must be an array");
- return -1;
- }
-
- prepends = data_array_init();
-
- /* prepend default modules */
- for (i = 0; i < modules->value->used; i++) {
- ds = (data_string *)modules->value->data[i];
-
- if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_indexfile"))) {
- prepend_mod_indexfile = 0;
- }
-
- if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_staticfile"))) {
- append_mod_staticfile = 0;
- }
-
- if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_dirlisting"))) {
- append_mod_dirlisting = 0;
- }
-
- if (buffer_is_equal_string(ds->value, CONST_STR_LEN("mod_chunked"))) {
- append_mod_chunked = 0;
- }
-
- if (0 == prepend_mod_indexfile &&
- 0 == append_mod_dirlisting &&
- 0 == append_mod_staticfile &&
- 0 == append_mod_chunked) {
-
- break;
- }
- }
-
- if (prepend_mod_indexfile) {
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
- array_insert_unique(prepends->value, (data_unset *)ds);
- }
-
- prepends = (data_array *)configparser_merge_data((data_unset *)prepends, (data_unset *)modules);
- buffer_copy_string_buffer(prepends->key, modules->key);
- array_replace(srv->config, (data_unset *)prepends);
- modules->free((data_unset *)modules);
- modules = prepends;
-
- /* append default modules */
- if (append_mod_dirlisting) {
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
- array_insert_unique(modules->value, (data_unset *)ds);
- }
-
- if (append_mod_staticfile) {
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
- array_insert_unique(modules->value, (data_unset *)ds);
- }
-
- if (append_mod_chunked) {
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_chunked"));
- array_insert_unique(modules->value, (data_unset *)ds);
- }
- } else {
- data_string *ds;
-
- modules = data_array_init();
-
- /* server.modules is not set */
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile"));
- array_insert_unique(modules->value, (data_unset *)ds);
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting"));
- array_insert_unique(modules->value, (data_unset *)ds);
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile"));
- array_insert_unique(modules->value, (data_unset *)ds);
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_chunked"));
- array_insert_unique(modules->value, (data_unset *)ds);
-
- buffer_copy_string_len(modules->key, CONST_STR_LEN("server.modules"));
- array_insert_unique(srv->config, (data_unset *)modules);
- }
-
-
- if (0 != config_insert(srv)) {
- return -1;
- }
-
- return 0;
-}
-
-
-int config_set_defaults(server *srv) {
- specific_config *s = srv->config_storage[0];
- const fdevent_handler_info_t *handler;
- const network_backend_info_t *backend;
- struct stat st1, st2;
-
- if (buffer_is_empty(s->document_root)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "a default document-root has to be set");
-
- return -1;
- }
-
- if (buffer_is_empty(srv->srvconf.changeroot)) {
- pathname_unix2local(s->document_root);
- if (-1 == stat(s->document_root->ptr, &st1)) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "base-docroot doesn't exist:",
- s->document_root, strerror(errno));
- return -1;
- }
-
- } else {
- buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
- buffer_append_string_buffer(srv->tmp_buf, s->document_root);
-
- if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "base-docroot doesn't exist:",
- srv->tmp_buf);
- return -1;
- }
-
- }
-
- buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
-
- buffer_to_lower(srv->tmp_buf);
-
- if (0 == stat(srv->tmp_buf->ptr, &st1)) {
- int is_lower = 0;
-
- is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
-
- /* lower-case existed, check upper-case */
- buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
-
- buffer_to_upper(srv->tmp_buf);
-
- /* we have to handle the special case that upper and lower-casing results in the same filename
- * as in server.document-root = "/" or "/12345/" */
-
- if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
- /* lower-casing and upper-casing didn't result in
- * an other filename, no need to stat(),
- * just assume it is case-sensitive. */
-
- s->force_lowercase_filenames = 0;
- } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
-
- /* upper case exists too, doesn't the FS handle this ? */
-
- /* upper and lower have the same inode -> case-insensitve FS */
-
- if (st1.st_ino == st2.st_ino) {
- /* upper and lower have the same inode -> case-insensitve FS */
-
- s->force_lowercase_filenames = 1;
- }
- }
- }
-
- if (srv->srvconf.port == 0) {
- srv->srvconf.port = s->is_ssl ? 443 : 80;
- }
-
- if (srv->srvconf.event_handler->used == 0) {
- /* get a useful default */
- handler = fdevent_get_defaulthandler();
- if (!handler) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "sorry, there is no event handler for this system");
-
- return -1;
- }
- } else {
- /*
- * User override
- */
-
- handler = fdevent_get_handler_info_by_name(srv->srvconf.event_handler->ptr);
- if (!handler) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "the selected event-handler is unknown:",
- srv->srvconf.event_handler );
-
- return -1;
- }
-
- if (!handler->init) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "the selected event-handler is known but not supported:",
- srv->srvconf.event_handler );
-
- return -1;
- }
- }
- srv->event_handler = handler->type;
-
- if (buffer_is_empty(srv->srvconf.network_backend)) {
- /* get a useful default */
- backend = network_get_defaultbackend();
- if (!backend) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "sorry, there is no network backend for this system");
-
- return -1;
- }
- } else {
- /*
- * User override
- */
-
- backend = network_get_backend_info_by_name(srv->srvconf.network_backend->ptr);
- if (!backend) {
- /* we don't know it */
-
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "server.network-backend has a unknown value:",
- srv->srvconf.network_backend);
-
- return -1;
- }
-
- if (backend->write_handler == NULL) {
- /* we know it but not supported */
-
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "server.network-backend not supported:",
- srv->srvconf.network_backend);
-
- return -1;
- }
- }
- srv->network_backend = backend->type;
-
- if (s->is_ssl) {
- if (buffer_is_empty(s->ssl_pemfile)) {
- /* PEM file is require */
-
- log_error_write(srv, __FILE__, __LINE__, "s",
- "ssl.pemfile has to be set");
- return -1;
- }
-
-#ifndef USE_OPENSSL
- log_error_write(srv, __FILE__, __LINE__, "s",
- "ssl support is missing, recompile with --with-openssl");
-
- return -1;
-#endif
- }
-
- return 0;
-}
diff --git a/src/configfile.h b/src/configfile.h
deleted file mode 100644
index 5694517d..00000000
--- a/src/configfile.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _CONFIG_PARSER_H_
-#define _CONFIG_PARSER_H_
-
-#include "settings.h"
-#include "server.h"
-#include "array.h"
-#include "buffer.h"
-
-typedef struct {
- server *srv;
- int ok;
- array *all_configs;
- buffer_ptr *configs_stack; /* to parse nested block */
- data_config *current; /* current started with { */
- buffer *basedir;
-} config_t;
-
-LI_API void * configparserAlloc(void *(*mallocProc)(size_t));
-LI_API void configparserFree(void *p, void (*freeProc)(void*));
-LI_API void configparser(void *yyp, int yymajor, buffer *yyminor, config_t *ctx);
-LI_API int config_parse_file(server *srv, config_t *context, const char *fn);
-LI_API int config_parse_cmd(server *srv, config_t *context, const char *cmd);
-LI_API data_unset * configparser_merge_data(data_unset *op1, const data_unset *op2);
-LI_API void config_cond_cache_reset(server *srv, connection *con);
-LI_API void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item);
-
-#define config_cond_cache_reset_all_items(srv, con) \
- config_cond_cache_reset_item(srv, con, COMP_LAST_ELEMENT);
-
-#endif
diff --git a/src/configparser.y b/src/configparser.y
deleted file mode 100644
index 3d8caa57..00000000
--- a/src/configparser.y
+++ /dev/null
@@ -1,571 +0,0 @@
-%token_prefix TK_
-%extra_argument {config_t *ctx}
-%name configparser
-
-%include {
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "configfile.h"
-#include "buffer.h"
-#include "array.h"
-
-static void configparser_push(config_t *ctx, data_config *dc, int isnew) {
- if (isnew) {
- dc->context_ndx = ctx->all_configs->used;
- assert(dc->context_ndx > ctx->current->context_ndx);
- array_insert_unique(ctx->all_configs, (data_unset *)dc);
- dc->parent = ctx->current;
- array_insert_unique(dc->parent->childs, (data_unset *)dc);
- }
- buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
- ctx->current = dc;
-}
-
-static data_config *configparser_pop(config_t *ctx) {
- data_config *old = ctx->current;
- ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
- return old;
-}
-
-/* return a copied variable */
-static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
- data_unset *du;
- data_config *dc;
-
-#if 0
- fprintf(stderr, "get var %s\n", key->ptr);
-#endif
- for (dc = ctx->current; dc; dc = dc->parent) {
-#if 0
- fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
- array_print(dc->value, 0);
-#endif
- if (NULL != (du = array_get_element(dc->value, CONST_BUF_LEN(key)))) {
- return du->copy(du);
- }
- }
- return NULL;
-}
-
-/* op1 is to be eat/return by this function, op1->key is not cared
- op2 is left untouch, unreferenced
- */
-data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
- /* type mismatch */
- if (op1->type != op2->type) {
- if (op1->type == TYPE_STRING && op2->type == TYPE_INTEGER) {
- data_string *ds = (data_string *)op1;
- buffer_append_long(ds->value, ((data_integer*)op2)->value);
- return op1;
- } else if (op1->type == TYPE_INTEGER && op2->type == TYPE_STRING) {
- data_string *ds = data_string_init();
- buffer_append_long(ds->value, ((data_integer*)op1)->value);
- buffer_append_string_buffer(ds->value, ((data_string*)op2)->value);
- op1->free(op1);
- return (data_unset *)ds;
- } else {
- fprintf(stderr, "data type mismatch, cannot be merge\n");
- op1->free(op1);
- return NULL;
- }
- }
-
- switch (op1->type) {
- case TYPE_STRING:
- buffer_append_string_buffer(((data_string *)op1)->value, ((data_string *)op2)->value);
- break;
- case TYPE_INTEGER:
- ((data_integer *)op1)->value += ((data_integer *)op2)->value;
- break;
- case TYPE_ARRAY: {
- array *dst = ((data_array *)op1)->value;
- array *src = ((data_array *)op2)->value;
- data_unset *du;
- size_t i;
-
- for (i = 0; i < src->used; i ++) {
- du = (data_unset *)src->data[i];
- if (du) {
- array_insert_unique(dst, du->copy(du));
- }
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- return op1;
-}
-
-}
-
-%parse_failure {
- ctx->ok = 0;
-}
-
-input ::= metalines.
-metalines ::= metalines metaline.
-metalines ::= .
-metaline ::= varline.
-metaline ::= global.
-metaline ::= condlines(A) EOL. { A = NULL; }
-metaline ::= include.
-metaline ::= include_shell.
-metaline ::= EOL.
-
-%type value {data_unset *}
-%type expression {data_unset *}
-%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 *}
-%type stringop {buffer *}
-
-%type cond {config_cond_t }
-
-%destructor value { $$->free($$); }
-%destructor expression { $$->free($$); }
-%destructor aelement { $$->free($$); }
-%destructor aelements { array_free($$); }
-%destructor array { array_free($$); }
-%destructor key { buffer_free($$); }
-%destructor stringop { buffer_free($$); }
-
-%token_type {buffer *}
-%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, CONST_BUF_LEN(B->key))) {
- array_insert_unique(ctx->current->value, B);
- B = NULL;
- } else {
- if (0 == strcmp(B->key->ptr, "var.PID") ||
- 0 == strcmp(B->key->ptr, "var.CWD")) {
- fprintf(stderr, "var.PID and var.CWD are magic config vars and can't be set in the config file itself\n");
- } 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;
-}
-
-varline ::= key(A) APPEND expression(B). {
- array *vars = ctx->current->value;
- data_unset *du;
-
- if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
- fprintf(stderr, "Appending 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 != (du = array_get_element(vars, CONST_BUF_LEN(A)))) {
- /* exists in current block */
- du = configparser_merge_data(du, B);
- if (NULL == du) {
- ctx->ok = 0;
- }
- else {
- buffer_copy_string_buffer(du->key, A);
- array_replace(vars, du);
- }
- B->free(B);
- } else if (NULL != (du = configparser_get_variable(ctx, A))) {
- du = configparser_merge_data(du, B);
- if (NULL == du) {
- ctx->ok = 0;
- }
- else {
- buffer_copy_string_buffer(du->key, A);
- array_insert_unique(ctx->current->value, du);
- }
- B->free(B);
- } else {
- buffer_copy_string_buffer(B->key, A);
- array_insert_unique(ctx->current->value, B);
- }
- buffer_free(A);
- A = NULL;
- B = NULL;
-}
-
-key(A) ::= LKEY(B). {
- if (strchr(B->ptr, '.') == NULL) {
- /* prepend the user-vars with var. */
- A = buffer_init_string("var.");
- buffer_append_string_buffer(A, B);
- buffer_free(B);
- B = NULL;
- } else {
- A = B;
- B = NULL;
- }
-}
-
-expression(A) ::= expression(B) PLUS value(C). {
- A = configparser_merge_data(B, C);
- if (NULL == A) {
- ctx->ok = 0;
- }
- B = NULL;
- C->free(C);
- C = NULL;
-}
-
-expression(A) ::= value(B). {
- A = B;
- B = NULL;
-}
-
-value(A) ::= key(B). {
- if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
- char *env;
-
- if (NULL != (env = getenv(B->ptr + 4))) {
- data_string *ds;
- ds = data_string_init();
- buffer_append_string(ds->value, env);
- A = (data_unset *)ds;
- }
- else {
- A = NULL;
- fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
- ctx->ok = 0;
- }
- } else if (NULL == (A = configparser_get_variable(ctx, B))) {
- fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
- ctx->ok = 0;
- }
- if (!A) {
- /* make a dummy so it won't crash */
- A = (data_unset *)data_string_init();
- }
- buffer_free(B);
- B = NULL;
-}
-
-value(A) ::= STRING(B). {
- A = (data_unset *)data_string_init();
- buffer_copy_string_buffer(((data_string *)(A))->value, B);
- buffer_free(B);
- B = NULL;
-}
-
-value(A) ::= INTEGER(B). {
- A = (data_unset *)data_integer_init();
- ((data_integer *)(A))->value = strtol(B->ptr, NULL, 10);
- buffer_free(B);
- B = NULL;
-}
-value(A) ::= array(B). {
- A = (data_unset *)data_array_init();
- array_free(((data_array *)(A))->value);
- ((data_array *)(A))->value = B;
- B = NULL;
-}
-array(A) ::= LPARAN RPARAN. {
- A = array_init();
-}
-array(A) ::= LPARAN aelements(B) RPARAN. {
- A = B;
- B = NULL;
-}
-
-aelements(A) ::= aelements(C) COMMA aelement(B). {
- if (buffer_is_empty(B->key) ||
- NULL == array_get_element(C, CONST_BUF_LEN(B->key))) {
- array_insert_unique(C, B);
- B = NULL;
- } else {
- fprintf(stderr, "Duplicate array-key: %s\n",
- B->key->ptr);
- ctx->ok = 0;
- B->free(B);
- B = NULL;
- }
-
- A = C;
- C = NULL;
-}
-
-aelements(A) ::= aelements(C) COMMA. {
- A = C;
- C = NULL;
-}
-
-aelements(A) ::= aelement(B). {
- A = array_init();
- array_insert_unique(A, B);
- B = NULL;
-}
-
-aelement(A) ::= expression(B). {
- A = B;
- B = NULL;
-}
-aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). {
- buffer_copy_string_buffer(C->key, B);
- buffer_free(B);
- B = NULL;
-
- A = C;
- C = NULL;
-}
-
-eols ::= EOL.
-eols ::= .
-
-globalstart ::= GLOBAL. {
- data_config *dc;
- dc = (data_config *)array_get_element(ctx->srv->config_context, CONST_STR_LEN("global"));
- assert(dc);
- configparser_push(ctx, dc, 0);
-}
-
-global(A) ::= globalstart LCURLY metalines RCURLY. {
- data_config *cur;
-
- cur = ctx->current;
- configparser_pop(ctx);
-
- assert(cur && ctx->current);
-
- A = cur;
-}
-
-condlines(A) ::= condlines(B) eols ELSE condline(C). {
- assert(B->context_ndx < C->context_ndx);
- C->prev = B;
- B->next = C;
- A = C;
- B = NULL;
- C = NULL;
-}
-
-condlines(A) ::= condline(B). {
- A = B;
- B = NULL;
-}
-
-condline(A) ::= context LCURLY metalines RCURLY. {
- data_config *cur;
-
- cur = ctx->current;
- configparser_pop(ctx);
-
- assert(cur && ctx->current);
-
- A = cur;
-}
-
-context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expression(D). {
- data_config *dc;
- buffer *b, *rvalue, *op;
-
- if (ctx->ok && D->type != TYPE_STRING) {
- fprintf(stderr, "rvalue must be string");
- ctx->ok = 0;
- }
-
- switch(E) {
- case CONFIG_COND_NE:
- op = buffer_init_string("!=");
- break;
- case CONFIG_COND_EQ:
- op = buffer_init_string("==");
- break;
- case CONFIG_COND_NOMATCH:
- op = buffer_init_string("!~");
- break;
- case CONFIG_COND_MATCH:
- op = buffer_init_string("=~");
- break;
- default:
- assert(0);
- return;
- }
-
- b = buffer_init();
- buffer_copy_string_buffer(b, ctx->current->key);
- buffer_append_string(b, "/");
- buffer_append_string_buffer(b, B);
- buffer_append_string_buffer(b, C);
- buffer_append_string_buffer(b, op);
- rvalue = ((data_string*)D)->value;
- buffer_append_string_buffer(b, rvalue);
-
- if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, CONST_BUF_LEN(b)))) {
- configparser_push(ctx, dc, 0);
- } else {
- struct {
- comp_key_t comp;
- char *comp_key;
- size_t len;
- } comps[] = {
- { COMP_SERVER_SOCKET, CONST_STR_LEN("SERVER[\"socket\"]" ) },
- { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) },
- { 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_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_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_PHYSICAL_PATH, CONST_STR_LEN("PHYSICAL[\"path\"]") },
- { COMP_PHYSICAL_PATH_EXISTS,CONST_STR_LEN("PHYSICAL[\"existing-path\"]") },
-
- { COMP_UNSET, NULL, 0 },
- };
- size_t i;
-
- dc = data_config_init();
-
- buffer_copy_string_buffer(dc->key, b);
- buffer_copy_string_buffer(dc->op, op);
- buffer_copy_string_buffer(dc->comp_key, B);
- buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\""));
- buffer_append_string_buffer(dc->comp_key, C);
- buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]"));
- dc->cond = E;
-
- for (i = 0; comps[i].comp_key; i ++) {
- if (buffer_is_equal_string(
- dc->comp_key, comps[i].comp_key, comps[i].len)) {
- dc->comp = comps[i].comp;
- break;
- }
- }
- if (COMP_UNSET == dc->comp) {
- fprintf(stderr, "error comp_key %s", dc->comp_key->ptr);
- ctx->ok = 0;
- }
-
- switch(E) {
- case CONFIG_COND_NE:
- case CONFIG_COND_EQ:
- dc->string = buffer_init_buffer(rvalue);
- break;
- case CONFIG_COND_NOMATCH:
- case CONFIG_COND_MATCH: {
-#ifdef HAVE_PCRE_H
- const char *errptr;
- int erroff;
-
- if (NULL == (dc->regex =
- pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) {
- dc->string = buffer_init_string(errptr);
- dc->cond = CONFIG_COND_UNSET;
-
- fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n",
- rvalue->ptr, errptr, erroff);
-
- ctx->ok = 0;
- } else if (NULL == (dc->regex_study =
- pcre_study(dc->regex, 0, &errptr)) &&
- errptr != NULL) {
- fprintf(stderr, "studying regex failed: %s -> %s\n",
- rvalue->ptr, errptr);
- ctx->ok = 0;
- } else {
- dc->string = buffer_init_buffer(rvalue);
- }
-#else
- fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n"
- "(perhaps just a missing pcre-devel package ?) \n",
- B->ptr, C->ptr);
- ctx->ok = 0;
-#endif
- break;
- }
-
- default:
- fprintf(stderr, "unknown condition for $%s[%s]\n",
- B->ptr, C->ptr);
- ctx->ok = 0;
- break;
- }
-
- configparser_push(ctx, dc, 1);
- }
-
- buffer_free(b);
- buffer_free(op);
- buffer_free(B);
- B = NULL;
- buffer_free(C);
- C = NULL;
- D->free(D);
- D = NULL;
-}
-cond(A) ::= EQ. {
- A = CONFIG_COND_EQ;
-}
-cond(A) ::= MATCH. {
- A = CONFIG_COND_MATCH;
-}
-cond(A) ::= NE. {
- A = CONFIG_COND_NE;
-}
-cond(A) ::= NOMATCH. {
- A = CONFIG_COND_NOMATCH;
-}
-
-stringop(A) ::= expression(B). {
- A = NULL;
- if (ctx->ok) {
- if (B->type == TYPE_STRING) {
- A = buffer_init_buffer(((data_string*)B)->value);
- } else if (B->type == TYPE_INTEGER) {
- A = buffer_init();
- buffer_copy_long(A, ((data_integer *)B)->value);
- } else {
- fprintf(stderr, "operand must be string");
- ctx->ok = 0;
- }
- }
- B->free(B);
- B = NULL;
-}
-
-include ::= INCLUDE stringop(A). {
- if (ctx->ok) {
- if (0 != config_parse_file(ctx->srv, ctx, A->ptr)) {
- ctx->ok = 0;
- }
- buffer_free(A);
- A = NULL;
- }
-}
-
-include_shell ::= INCLUDE_SHELL stringop(A). {
- if (ctx->ok) {
- if (0 != config_parse_cmd(ctx->srv, ctx, A->ptr)) {
- ctx->ok = 0;
- }
- buffer_free(A);
- A = NULL;
- }
-}
diff --git a/src/connections-glue.c b/src/connections-glue.c
deleted file mode 100644
index fa5cf36f..00000000
--- a/src/connections-glue.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "base.h"
-#include "connections.h"
-
-const char *connection_get_state(connection_state_t state) {
- switch (state) {
- case CON_STATE_CONNECT: return "connect";
-
- case CON_STATE_REQUEST_START: return "req-start";
- case CON_STATE_READ_REQUEST_HEADER: return "read-header";
- case CON_STATE_HANDLE_REQUEST_HEADER: return "handle-req";
- case CON_STATE_READ_REQUEST_CONTENT: return "read-content";
-
- case CON_STATE_HANDLE_RESPONSE_HEADER: return "resp-start";
- case CON_STATE_WRITE_RESPONSE_HEADER: return "write-header";
- case CON_STATE_WRITE_RESPONSE_CONTENT: return "write-content";
- case CON_STATE_RESPONSE_END: return "resp-end";
-
- case CON_STATE_CLOSE: return "close";
- case CON_STATE_ERROR: return "error";
- default: return "(unknown)";
- }
-}
-
-const char *connection_get_short_state(connection_state_t state) {
- switch (state) {
- case CON_STATE_CONNECT: return ".";
- case CON_STATE_REQUEST_START: return "q";
-
- case CON_STATE_READ_REQUEST_HEADER: return "r";
- case CON_STATE_HANDLE_REQUEST_HEADER: return "h";
- case CON_STATE_READ_REQUEST_CONTENT: return "R";
-
- case CON_STATE_HANDLE_RESPONSE_HEADER: return "s";
- case CON_STATE_WRITE_RESPONSE_HEADER: return "w";
- case CON_STATE_WRITE_RESPONSE_CONTENT: return "W";
- case CON_STATE_RESPONSE_END: return "S";
-
- case CON_STATE_CLOSE: return "C";
- case CON_STATE_ERROR: return "E";
- default: return "x";
- }
-}
-
-int connection_set_state(server *srv, connection *con, connection_state_t state) {
- UNUSED(srv);
-
- con->state = state;
-
- return 0;
-}
-
diff --git a/src/connections.c b/src/connections.c
deleted file mode 100644
index 1069adab..00000000
--- a/src/connections.c
+++ /dev/null
@@ -1,1599 +0,0 @@
-#include <sys/stat.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "settings.h"
-
-#include "server.h"
-#include "connections.h"
-#include "fdevent.h"
-#include "log.h"
-
-#include "request.h"
-#include "response.h"
-#include "network.h"
-#include "stat_cache.h"
-#include "joblist.h"
-
-#include "plugin.h"
-
-#include "inet_ntop_cache.h"
-#include "configfile.h"
-#include "http_req.h"
-
-#ifdef USE_OPENSSL
-# include <openssl/ssl.h>
-# include <openssl/err.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-
-#include "sys-socket.h"
-#include "sys-files.h"
-
-typedef struct {
- PLUGIN_DATA;
-} plugin_data;
-
-static connection *connections_get_new_connection(server *srv) {
- connections *conns = srv->conns;
- size_t i;
-
- if (conns->size == 0) {
- conns->size = 128;
- conns->ptr = NULL;
- conns->ptr = malloc(sizeof(*conns->ptr) * conns->size);
- for (i = 0; i < conns->size; i++) {
- conns->ptr[i] = connection_init(srv);
- }
- } else if (conns->size == conns->used) {
- conns->size += 128;
- conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
-
- for (i = conns->used; i < conns->size; i++) {
- conns->ptr[i] = connection_init(srv);
- }
- }
-
- connection_reset(srv, conns->ptr[conns->used]);
-
- conns->ptr[conns->used]->ndx = conns->used;
- return conns->ptr[conns->used++];
-}
-
-static int connection_del(server *srv, connection *con) {
- size_t i;
- connections *conns = srv->conns;
- connection *temp;
-
- if (con == NULL) return -1;
-
- if (-1 == con->ndx) return -1;
-
- i = con->ndx;
-
- /* not last element */
-
- if (i != conns->used - 1) {
- temp = conns->ptr[i];
- conns->ptr[i] = conns->ptr[conns->used - 1];
- conns->ptr[conns->used - 1] = temp;
-
- conns->ptr[i]->ndx = i;
- conns->ptr[conns->used - 1]->ndx = -1;
- }
-
- conns->used--;
-
- con->ndx = -1;
-
- return 0;
-}
-
-int connection_close(server *srv, connection *con) {
-#ifdef USE_OPENSSL
- /* should be in iosocket_close() */
-
- if (con->sock->ssl) {
- int ret, ssl_r;
- unsigned long err;
-
- ERR_clear_error();
- switch (ret = SSL_shutdown(con->sock->ssl)) {
- case 1:
- /* done */
- break;
- case 0:
- /* wait for fd-event
- *
- * FIXME: wait for fdevent and call SSL_shutdown again
- * (But it is not that important as we close the underlying connection anyway)
- */
-
- break;
- default:
- switch ((ssl_r = SSL_get_error(con->sock->ssl, ret))) {
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_READ:
- break;
- case SSL_ERROR_SYSCALL:
- /* perhaps we have error waiting in our error-queue */
- if (0 != (err = ERR_get_error())) {
- do {
- ERROR("SSL_shutdown failed (%i, %i): %s", ssl_r, ret, ERR_error_string(err, NULL));
- } while((err = ERR_get_error()));
- } else {
- ERROR("SSL_shutdown failed (%i, %i, %i): %s", ssl_r, ret, errno, strerror(errno));
- }
-
- break;
- default:
- while((err = ERR_get_error())) {
- ERROR("SSL_shutdown failed (%i, %i): %s", ssl_r, ret, ERR_error_string(err, NULL));
- }
- }
- }
-
- SSL_free(con->sock->ssl);
- ERR_clear_error();
- con->sock->ssl = NULL;
- }
-#endif
-
- fdevent_event_del(srv->ev, con->sock);
- fdevent_unregister(srv->ev, con->sock);
-
- if (closesocket(con->sock->fd)) {
- ERROR("close failed (%i): %s", con->sock->fd, strerror(errno));
- }
-
- connection_del(srv, con);
- connection_set_state(srv, con, CON_STATE_CONNECT);
-
- return 0;
-}
-
-#if 0
-static void dump_packet(const unsigned char *data, size_t len) {
- size_t i, j;
-
- if (len == 0) return;
-
- for (i = 0; i < len; i++) {
- if (i % 16 == 0) fprintf(stderr, " ");
-
- fprintf(stderr, "%02x ", data[i]);
-
- if ((i + 1) % 16 == 0) {
- fprintf(stderr, " ");
- for (j = 0; j <= i % 16; j++) {
- unsigned char c;
-
- if (i-15+j >= len) break;
-
- c = data[i-15+j];
-
- fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
- }
-
- fprintf(stderr, "\n");
- }
- }
-
- if (len % 16 != 0) {
- for (j = i % 16; j < 16; j++) {
- fprintf(stderr, " ");
- }
-
- fprintf(stderr, " ");
- for (j = i & ~0xf; j < len; j++) {
- unsigned char c;
-
- c = data[j];
- fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
- }
- fprintf(stderr, "\n");
- }
-}
-#endif
-
-static int connection_handle_response_header(server *srv, connection *con) {
- int no_response_body = 0;
-
- if (con->mode == DIRECT) {
- /* static files */
- switch(con->request.http_method) {
- case HTTP_METHOD_GET:
- case HTTP_METHOD_POST:
- case HTTP_METHOD_HEAD:
- /* webdav */
- case HTTP_METHOD_PUT:
- case HTTP_METHOD_MKCOL:
- case HTTP_METHOD_DELETE:
- case HTTP_METHOD_COPY:
- case HTTP_METHOD_MOVE:
- case HTTP_METHOD_PROPFIND:
- case HTTP_METHOD_PROPPATCH:
- case HTTP_METHOD_LOCK:
- case HTTP_METHOD_UNLOCK:
- break;
- case HTTP_METHOD_OPTIONS:
- /*
- * 400 is coming from the request-parser BEFORE uri.path is set
- * 403 is from the response handler when noone else catched it
- *
- * */
- if ((!con->http_status || con->http_status == 200 || con->http_status == 403) &&
- 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"));
-
- /* trash the content */
- no_response_body = 1;
-
- con->http_status = 200;
- }
- break;
- default:
- switch(con->http_status) {
- case 400: /* bad request */
- case 414: /* overload request header */
- case 505: /* unknown protocol */
- case 207: /* this was webdav */
- break;
- default:
- con->http_status = 501;
- break;
- }
- break;
- }
- }
-
- if (con->http_status == 0) {
- TRACE("%s", "no status, setting 403");
- con->http_status = 403;
- }
-
- switch(con->http_status) {
- case 400: /* class: header + custom body */
- case 401:
- case 403:
- case 404:
- case 408:
- case 409:
- case 410:
- case 411:
- case 416:
- case 423:
- case 500:
- case 501:
- case 502:
- case 503:
- case 504:
- case 505:
- case 509:
- if (con->mode != DIRECT) break;
-
- con->send->is_closed = 0;
- con->response.content_length = -1;
-
- buffer_reset(con->physical.path);
-
- /* try to send static errorfile */
- if (!buffer_is_empty(con->conf.errorfile_prefix)) {
- stat_cache_entry *sce = NULL;
-
- buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
- buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
-
- if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- chunkqueue_append_file(con->send, con->physical.path, 0, sce->st.st_size);
- con->send->bytes_in += sce->st.st_size;
- con->send->is_closed = 1;
- if (buffer_is_empty(sce->content_type)) {
- /* for error docs default to html instead of application-data */
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
- } else {
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
- }
- }
- }
-
- if (!con->send->is_closed) {
- buffer *b;
-
- buffer_reset(con->physical.path);
-
- con->send->is_closed = 1;
- b = chunkqueue_get_append_buffer(con->send);
-
- /* build default error-page */
- buffer_copy_string_len(b, CONST_STR_LEN(
- "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
- " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
- "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
- " <head>\n"
- " <title>"));
- buffer_append_long(b, con->http_status);
- buffer_append_string_len(b, CONST_STR_LEN(" - "));
- buffer_append_string(b, get_http_status_name(con->http_status));
-
- buffer_append_string(b,
- "</title>\n"
- " </head>\n"
- " <body>\n"
- " <h1>");
- buffer_append_long(b, con->http_status);
- buffer_append_string_len(b, CONST_STR_LEN(" - "));
- buffer_append_string(b, get_http_status_name(con->http_status));
-
- buffer_append_string(b,"</h1>\n"
- " </body>\n"
- "</html>\n"
- );
-
- con->send->bytes_in += b->used - 1;
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
- }
- /* fall through */
- case 207:
- case 200: /* class: header + body */
- case 201:
- case 301:
- case 302:
- case 303:
- break;
-
- case 206: /* write_queue is already prepared */
- break;
- case 205: /* class: header only */
- case 304:
- default:
- if (con->mode == DIRECT) {
- /* only if we have handled the request internally
- * we will see no response-content
- *
- * if it was a fastcgi request we will see a END_REQUEST packet
- * after the header was parsed.
- *
- * */
- no_response_body = 1;
- }
- break;
- }
-
- if (no_response_body) {
- /* disable chunked encoding again as we have no body */
- con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
- chunkqueue_reset(con->send);
-
- con->send->is_closed = 1;
- }
-
- return 0;
-}
-
-connection *connection_init(server *srv) {
- connection *con;
-
- UNUSED(srv);
-
- con = calloc(1, sizeof(*con));
-
- con->sock = iosocket_init();
- con->ndx = -1;
- con->bytes_written = 0;
- con->bytes_read = 0;
- con->bytes_header = 0;
- con->loops_per_request = 0;
-
-#define CLEAN(x) \
- con->x = buffer_init();
-
- CLEAN(request.uri);
- CLEAN(request.request);
- CLEAN(request.pathinfo);
- CLEAN(request.http_host);
-
- CLEAN(request.orig_uri);
-
- CLEAN(uri.scheme);
- CLEAN(uri.authority);
- CLEAN(uri.path);
- CLEAN(uri.path_raw);
- CLEAN(uri.query);
-
- CLEAN(physical.doc_root);
- CLEAN(physical.path);
- CLEAN(physical.basedir);
- CLEAN(physical.rel_path);
- CLEAN(physical.etag);
- CLEAN(parse_request);
-
- CLEAN(authed_user);
- CLEAN(server_name);
- CLEAN(error_handler);
- CLEAN(dst_addr_buf);
-
-#undef CLEAN
- con->send_filters = filter_chain_init();
- /* send is the chunkqueue of the first send filter */
- con->send = con->send_filters->first->cq;
- con->recv = chunkqueue_init();
- chunkqueue_set_tempdirs(con->recv, srv->srvconf.upload_tempdirs);
-
- con->send_raw = chunkqueue_init();
- con->recv_raw = chunkqueue_init();
-
- con->request.headers = array_init();
- con->response.headers = array_init();
- con->environment = array_init();
-
- con->http_req = http_request_init();
-
- /* init plugin specific connection structures */
-
- con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
-
- con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
- config_setup_connection(srv, con);
-
- return con;
-}
-
-void connections_free(server *srv) {
- connections *conns = srv->conns;
- size_t i;
-
- for (i = 0; i < conns->size; i++) {
- connection *con = conns->ptr[i];
-
- connection_reset(srv, con);
- iosocket_free(con->sock);
-
- filter_chain_free(con->send_filters);
- con->send = NULL;
- chunkqueue_free(con->recv);
- chunkqueue_free(con->send_raw);
- chunkqueue_free(con->recv_raw);
- array_free(con->request.headers);
- array_free(con->response.headers);
- array_free(con->environment);
-
-#define CLEAN(x) \
- buffer_free(con->x);
-
- CLEAN(request.uri);
- CLEAN(request.request);
- CLEAN(request.pathinfo);
- CLEAN(request.http_host);
-
- CLEAN(request.orig_uri);
-
- CLEAN(uri.scheme);
- CLEAN(uri.authority);
- CLEAN(uri.path);
- CLEAN(uri.path_raw);
- CLEAN(uri.query);
-
- CLEAN(physical.doc_root);
- CLEAN(physical.path);
- CLEAN(physical.basedir);
- CLEAN(physical.etag);
- CLEAN(physical.rel_path);
- CLEAN(parse_request);
-
- CLEAN(authed_user);
- CLEAN(server_name);
- CLEAN(error_handler);
- CLEAN(dst_addr_buf);
-#undef CLEAN
- free(con->plugin_ctx);
- free(con->cond_cache);
-
- http_request_free(con->http_req);
-
- free(con);
- }
-
- free(conns->ptr);
-}
-
-
-int connection_reset(server *srv, connection *con) {
- size_t i;
-
- plugins_call_connection_reset(srv, con);
-
- con->is_readable = 1;
- con->is_writable = 1;
- con->http_status = 0;
- con->file_started = 0;
- con->got_response = 0;
-
- con->bytes_written = 0;
- con->bytes_written_cur_second = 0;
- con->bytes_read = 0;
- con->bytes_header = 0;
- con->loops_per_request = 0;
-
- con->request.http_method = HTTP_METHOD_UNSET;
- con->request.http_version = HTTP_VERSION_UNSET;
- con->request.content_length = -1;
-
- con->response.keep_alive = 0;
- con->response.content_length = -1;
- con->response.transfer_encoding = 0;
-
- con->mode = DIRECT;
-
-#define CLEAN(x) \
- if (con->x) buffer_reset(con->x);
-
- CLEAN(request.uri);
- CLEAN(request.pathinfo);
- CLEAN(request.request);
- CLEAN(request.http_host);
-
- CLEAN(request.orig_uri);
-
- CLEAN(uri.scheme);
- CLEAN(uri.authority);
- CLEAN(uri.path);
- CLEAN(uri.path_raw);
- CLEAN(uri.query);
-
- CLEAN(physical.doc_root);
- CLEAN(physical.path);
- CLEAN(physical.basedir);
- CLEAN(physical.rel_path);
- CLEAN(physical.etag);
-
- CLEAN(parse_request);
-
- CLEAN(authed_user);
- CLEAN(server_name);
- CLEAN(error_handler);
-#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
- CLEAN(sock->tlsext_server_name);
-#endif
-#undef CLEAN
-
-#define CLEAN(x) \
- if (con->x) con->x->used = 0;
-
-#undef CLEAN
-
- array_reset(con->request.headers);
- array_reset(con->response.headers);
- array_reset(con->environment);
-
- filter_chain_reset(con->send_filters);
- con->send = con->send_filters->first->cq;
- chunkqueue_reset(con->recv);
- chunkqueue_reset(con->send_raw);
-
- http_request_reset(con->http_req);
-
- /* the plugins should cleanup themself */
- for (i = 0; i < srv->plugins.used; i++) {
- plugin *p = ((plugin **)(srv->plugins.ptr))[i];
- plugin_data *pd = p->data;
-
- if (!pd) continue;
-
- if (con->plugin_ctx[pd->id] != NULL) {
- ERROR("missing cleanup in %s", SAFE_BUF_STR(p->name));
- }
-
- con->plugin_ctx[pd->id] = NULL;
- }
-
- config_cond_cache_reset(srv, con);
-
- con->header_len = 0;
- con->in_error_handler = 0;
-
- config_setup_connection(srv, con);
-
- return 0;
-}
-
-/**
- * handle all header and content read
- *
- * we get called by the state-engine and by the fdevent-handler
- */
-static handler_t connection_handle_read_request_header(server *srv, connection *con) {
- /* let's see if we need more data later */
- fdevent_event_del(srv->ev, con->sock);
-
- con->read_idle_ts = srv->cur_ts; /* start a read-call() */
-
- /* read from the network */
- switch (network_read(srv, con, con->sock, con->recv_raw)) {
- case NETWORK_STATUS_SUCCESS:
- /* we read everything from the socket, do we have a full header ? */
- break;
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- fdevent_event_add(srv->ev, con->sock, FDEVENT_IN);
- return HANDLER_WAIT_FOR_EVENT;
- case NETWORK_STATUS_CONNECTION_CLOSE:
- /* the connection went away before we got something back */
- con->close_timeout_ts = srv->cur_ts - 2;
- connection_set_state(srv, con, CON_STATE_CLOSE);
-
- return HANDLER_GO_ON;
- default:
- ERROR("++ %s", "oops, something went wrong while reading");
- return HANDLER_ERROR;
- }
-
- switch (http_request_parse_cq(con->recv_raw, con->http_req)) {
- case PARSE_ERROR:
- con->http_status = 400; /* the header is broken */
- con->send->is_closed = 1; /* we have nothing to send */
-
- chunkqueue_remove_finished_chunks(con->recv_raw);
-
- return HANDLER_FINISHED;
- case PARSE_NEED_MORE:
- /* we need more */
- fdevent_event_add(srv->ev, con->sock, FDEVENT_IN);
-
- return HANDLER_WAIT_FOR_EVENT;
- case PARSE_SUCCESS:
- chunkqueue_remove_finished_chunks(con->recv_raw);
- break;
- default:
- chunkqueue_remove_finished_chunks(con->recv_raw);
- TRACE("%s", "(error)");
- return HANDLER_ERROR;
- }
-
- return HANDLER_GO_ON;
-}
-
-/* decode the HTTP/1.1 chunk encoding */
-
-static handler_t connection_handle_read_request_content(server *srv, connection *con) {
- /* read data from the socket and push it to the backend */
-
- chunkqueue *in = con->recv_raw;
- chunkqueue *out = con->recv; /* the pure content */
- chunk *c;
-
- /* let's see if we need more data later */
- fdevent_event_del(srv->ev, con->sock);
-
- con->read_idle_ts = srv->cur_ts; /* start a read-call() */
-
- if (con->request.content_length == -1) return HANDLER_GO_ON;
-
- /* if the content was short enough, it might be read already */
- if (in->first &&
- chunkqueue_length(in) - in->first->offset > 0) {
-
- /*
- * looks like the request-header also had some content for us
- */
-
- } else {
- /* read from the network */
- switch (network_read(srv, con, con->sock, in)) {
- case NETWORK_STATUS_SUCCESS:
- /* we have data */
- break;
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- fdevent_event_add(srv->ev, con->sock, FDEVENT_IN);
- return HANDLER_WAIT_FOR_EVENT;
- case NETWORK_STATUS_CONNECTION_CLOSE:
- /* the connection went away before we got something back */
- con->close_timeout_ts = srv->cur_ts - 2;
- connection_set_state(srv, con, CON_STATE_CLOSE);
-
- return HANDLER_GO_ON;
- default:
- ERROR("++ %s", "oops, something went wrong while reading");
- return HANDLER_ERROR;
- }
- }
-
- /* how much data do we want to extract ? */
- for (c = in->first; c && (out->bytes_in != con->request.content_length); c = c->next) {
- off_t weWant, weHave, toRead;
-
- weWant = con->request.content_length - out->bytes_in;
-
- if (c->mem->used == 0) continue;
-
- weHave = c->mem->used - c->offset - 1;
-
- toRead = weHave > weWant ? weWant : weHave;
-
- /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
- if (con->request.content_length > 64 * 1024) {
- chunk *dst_c = NULL;
- /* copy everything to max 1Mb sized tempfiles */
-
- /*
- * if the last chunk is
- * - smaller than 1Mb (size < 1Mb)
- * - not read yet (offset == 0)
- * -> append to it
- * otherwise
- * -> create a new chunk
- *
- * */
-
- if (out->last &&
- out->last->type == FILE_CHUNK &&
- out->last->file.is_temp &&
- out->last->offset == 0) {
- /* ok, take the last chunk for our job */
-
- if (out->last->file.length < 1 * 1024 * 1024) {
- dst_c = out->last;
-
- if (dst_c->file.fd == -1) {
- /* this should not happen as we cache the fd, but you never know */
- dst_c->file.fd = open(dst_c->file.name->ptr, O_WRONLY | O_APPEND);
- }
- } else {
- /* the chunk is too large now, close it */
- dst_c = out->last;
-
- if (dst_c->file.fd != -1) {
- close(dst_c->file.fd);
- dst_c->file.fd = -1;
- }
- dst_c = chunkqueue_get_append_tempfile(out);
- }
- } else {
- dst_c = chunkqueue_get_append_tempfile(out);
- }
-
- /* we have a chunk, let's write to it */
-
- if (dst_c->file.fd == -1) {
- /* we don't have file to write to,
- * EACCES might be one reason.
- *
- * Instead of sending 500 we send 413 and say the request is too large
- * */
-
- ERROR("denying upload as opening to temp-file for upload failed: '%s': %s",
- SAFE_BUF_STR(dst_c->file.name), strerror(errno));
-
- con->http_status = 413; /* Request-Entity too large */
- con->keep_alive = 0;
- return HANDLER_FINISHED;
- }
-
- if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
- /* write failed for some reason ... disk full ? */
- ERROR("denying upload as writing to file failed: '%s': %s",
- SAFE_BUF_STR(dst_c->file.name), strerror(errno));
-
- con->http_status = 413; /* Request-Entity too large */
- con->keep_alive = 0;
-
- close(dst_c->file.fd);
- dst_c->file.fd = -1;
-
- return HANDLER_FINISHED;
- }
-
- dst_c->file.length += toRead;
-
- if (out->bytes_in + toRead == con->request.content_length) {
- /* we read everything, close the chunk */
- close(dst_c->file.fd);
- dst_c->file.fd = -1;
- }
- } else {
- buffer *b;
-
- b = (out->last) ? out->last->mem : NULL;
-
- if (NULL == b) {
- b = chunkqueue_get_append_buffer(out);
- buffer_prepare_copy(b, con->request.content_length - out->bytes_in + 1);
- }
-
- buffer_append_string_len(b, c->mem->ptr + c->offset, toRead);
- }
-
- c->offset += toRead;
-
- out->bytes_in += toRead;
- in->bytes_out += toRead;
- }
-
- if (out->bytes_in < con->request.content_length) {
- /* we have to read more content */
- fdevent_event_add(srv->ev, con->sock, FDEVENT_IN);
- }
-
- return HANDLER_GO_ON;
-}
-
-static handler_t connection_handle_fdevent(void *s, void *context, int revents) {
- server *srv = (server *)s;
- connection *con = context;
-
- if (revents & FDEVENT_IN) {
- switch (con->state) {
- case CON_STATE_READ_REQUEST_HEADER:
- case CON_STATE_READ_REQUEST_CONTENT:
- joblist_append(srv, con);
- break;
- case CON_STATE_CLOSE: /* ignore the even, we will clean-up soon */
- break;
- case CON_STATE_ERROR:
- ERROR("we are in (CON_STATE_ERROR), but still get a FDEVENT_IN, removing event from fd = %d, %04x for (%s)",
- con->sock->fd,
- revents,
- SAFE_BUF_STR(con->uri.path));
-
- fdevent_event_del(srv->ev, con->sock);
-
- joblist_append(srv, con);
- break;
- default:
- ERROR("I thought only READ_REQUEST_* need fdevent-in: %d, fd = %d, %04x for (%s)",
- con->state,
- con->sock->fd,
- revents,
- SAFE_BUF_STR(con->uri.path));
- break;
- }
- }
-
- if (revents & FDEVENT_OUT) {
- switch (con->state) {
- case CON_STATE_WRITE_RESPONSE_HEADER:
- case CON_STATE_WRITE_RESPONSE_CONTENT:
- joblist_append(srv, con);
- break;
- case CON_STATE_ERROR:
- ERROR("we are in (CON_STATE_ERROR), but still get a FDEVENT_OUT, removing event from fd = %d, %04x for (%s)",
- con->sock->fd,
- revents,
- SAFE_BUF_STR(con->uri.path));
-
- fdevent_event_del(srv->ev, con->sock);
-
- joblist_append(srv, con);
- break;
- default:
- TRACE("got FDEVENT_OUT for state %d, calling the job-handler, let's see what happens", con->state);
- joblist_append(srv, con);
- break;
- }
- }
-
- if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
- /* looks like an error */
-
- connection_set_state(srv, con, CON_STATE_ERROR);
- joblist_append(srv, con);
- }
-
-
- return HANDLER_FINISHED;
-}
-
-
-connection *connection_accept(server *srv, server_socket *srv_socket) {
- /* accept everything */
-
- /* search an empty place */
- int cnt;
- sock_addr cnt_addr;
- socklen_t cnt_len;
- /* accept it and register the fd */
-
- cnt_len = sizeof(cnt_addr);
-
- if (-1 == (cnt = accept(srv_socket->sock->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
-#ifdef _WIN32
- errno = WSAGetLastError();
-#endif
- switch (errno) {
- case EAGAIN:
-#if EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
-#endif
- case EINTR:
- /* we were stopped _before_ we had a connection */
- case ECONNABORTED: /* this is a FreeBSD thingy */
- /* we were stopped _after_ we had a connection */
- break;
-
- case EMFILE: /* we are out of FDs */
- server_out_of_fds(srv, NULL);
- break;
- default:
- ERROR("accept failed on fd=%d with error: (%d) %s", srv_socket->sock->fd, errno, strerror(errno));
- break;
- }
- return NULL;
- } else {
- connection *con;
-
- /* ok, we have the connection, register it */
-#if 0
- TRACE("appected() = %i", cnt);
-#endif
- srv->con_opened++;
-
- con = connections_get_new_connection(srv);
- con->sock->fd = cnt;
- con->sock->fde_ndx = -1;
-#if 0
- gettimeofday(&(con->start_tv), NULL);
-#endif
- fdevent_register(srv->ev, con->sock, connection_handle_fdevent, con);
-
- connection_set_state(srv, con, CON_STATE_REQUEST_START);
-
- con->connection_start = srv->cur_ts;
- con->dst_addr = cnt_addr;
- buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
- con->srv_socket = srv_socket;
-
- if (-1 == (fdevent_fcntl_set(srv->ev, con->sock))) {
- ERROR("fcntl failed: %s", strerror(errno));
- connection_close(srv, con);
- return NULL;
- }
-
-#ifdef USE_OPENSSL
- /* connect FD to SSL */
- if (srv_socket->is_ssl) {
- if (NULL == (con->sock->ssl = SSL_new(srv_socket->ssl_ctx))) {
- ERROR("SSL: %s",
- ERR_error_string(ERR_get_error(), NULL));
- connection_close(srv, con);
- return NULL;
- }
-
-#ifndef OPENSSL_NO_TLSEXT
- SSL_set_app_data(con->sock->ssl, con);
-#endif
- SSL_set_accept_state(con->sock->ssl);
- con->conf.is_ssl=1;
-
- if (1 != (SSL_set_fd(con->sock->ssl, cnt))) {
- ERROR("SSL: %s",
- ERR_error_string(ERR_get_error(), NULL));
- connection_close(srv, con);
- return NULL;
- }
- }
-#endif
- return con;
- }
-}
-
-void connection_state_machine(server *srv, connection *con) {
- int done = 0, r;
- off_t bytes_moved = 0;
-#ifdef USE_OPENSSL
- server_socket *srv_sock = con->srv_socket;
-#endif
-
- if (srv->srvconf.log_state_handling) {
- TRACE("state at start for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- while (done == 0) {
- size_t ostate = con->state;
- int b;
-
- switch (con->state) {
- case CON_STATE_CONNECT:
- if (srv->srvconf.log_state_handling) {
- TRACE("state for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- chunkqueue_reset(con->recv_raw); /* this is a new connection, trash the pipeline */
-
- con->request_count = 0;
-
- break;
- case CON_STATE_REQUEST_START:
- /* init the request handling */
- if (srv->srvconf.log_state_handling) {
- TRACE("state for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- con->request_start = srv->cur_ts; /* start of the request */
- con->read_idle_ts = srv->cur_ts; /* start a read-call() */
-
- con->request_count++; /* max-keepalive requests */
- con->loops_per_request = 0; /* infinite loops */
-
- /* if the content was short enough, it might have a header already in the pipe */
- if (con->recv_raw->first &&
- chunkqueue_length(con->recv_raw) - con->recv_raw->first->offset > 0) {
- /* pipelining */
-
- switch (http_request_parse_cq(con->recv_raw, con->http_req)) {
- case PARSE_ERROR:
- con->http_status = 400; /* the header is broken */
- con->keep_alive = 0;
-
- chunkqueue_remove_finished_chunks(con->recv_raw);
-
- connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER);
- break;
- case PARSE_NEED_MORE:
- /* the read() call is on the way */
- connection_set_state(srv, con, CON_STATE_READ_REQUEST_HEADER);
- break;
- case PARSE_SUCCESS:
- /* pipelining worked, validate the header */
- chunkqueue_remove_finished_chunks(con->recv_raw);
-
- connection_set_state(srv, con, CON_STATE_VALIDATE_REQUEST_HEADER);
- break;
- default:
- chunkqueue_remove_finished_chunks(con->recv_raw);
- TRACE("%s", "(error)");
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
- } else {
- connection_set_state(srv, con, CON_STATE_READ_REQUEST_HEADER);
- }
-
- break;
- case CON_STATE_READ_REQUEST_HEADER:
- /* read us much data as needed into the recv_raw-cq for a valid header */
- if (srv->srvconf.log_state_handling) {
- TRACE("state for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- switch (connection_handle_read_request_header(srv, con)) {
- case HANDLER_GO_ON: /** we have a full header, or connection close */
- if (con->state == CON_STATE_READ_REQUEST_HEADER) {
- connection_set_state(srv, con, CON_STATE_VALIDATE_REQUEST_HEADER);
- }
- break;
- case HANDLER_FINISHED: /** parsing failed, ->http_status is set */
- connection_set_state(srv, con, CON_STATE_WRITE_RESPONSE_HEADER);
- break;
- case HANDLER_WAIT_FOR_EVENT:
- return;
- case HANDLER_ERROR:
- TRACE("%s", "(error)");
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- default:
- TRACE("%s", "(error)");
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
- break;
- case CON_STATE_VALIDATE_REQUEST_HEADER:
- /* we have the full header, parse it */
-
- http_request_parse(srv, con, con->http_req);
-
- if (con->http_status != 0) {
- con->keep_alive = 0;
- con->send->is_closed = 1; /* there is no content */
-
- connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER);
- } else if (array_get_element(con->request.headers, CONST_STR_LEN("Expect"))) {
- /* write */
- con->http_status = 100;
- con->send->is_closed = 1;
-
- connection_set_state(srv, con, CON_STATE_WRITE_RESPONSE_HEADER);
- } else {
- /* parsing the request went fine
- * let's find a handler for this request */
- connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
- }
-
- break;
- case CON_STATE_HANDLE_REQUEST_HEADER:
- /* the request header is parsed,
- * find someone who wants to handle this request */
-
- if (srv->srvconf.log_state_handling) {
- TRACE("state for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- switch (r = handle_get_backend(srv, con)) {
- case HANDLER_GO_ON:
- case HANDLER_FINISHED:
- break;
- case HANDLER_WAIT_FOR_FD:
- connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
-
- server_out_of_fds(srv, con);
-
- break;
- case HANDLER_COMEBACK:
- done = -1;
- case HANDLER_WAIT_FOR_EVENT:
- /* come back here */
- connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
-
- break;
- case HANDLER_ERROR:
- /* something went wrong */
- TRACE("%s", "(error)");
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- default:
- TRACE("handle_get_backend returned %d on fd %d", r, con->sock->fd);
- break;
- }
-
- if (r != HANDLER_FINISHED && r != HANDLER_GO_ON) break;
-
- if (con->http_status == 404 ||
- con->http_status == 403) {
- /* 404 error-handler */
-
- if (con->in_error_handler == 0 &&
- (!buffer_is_empty(con->conf.error_handler) ||
- !buffer_is_empty(con->error_handler))) {
- /* call error-handler */
-
- con->error_handler_saved_status = con->http_status;
- con->http_status = 0;
-
- if (buffer_is_empty(con->error_handler)) {
- buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
- } else {
- buffer_copy_string_buffer(con->request.uri, con->error_handler);
- }
- buffer_reset(con->physical.path);
-
- con->in_error_handler = 1;
-
- connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
-
- /* need to reset condition cache since request uri changed. */
- config_cond_cache_reset(srv, con);
-
- done = -1;
- break;
- } else if (con->in_error_handler) {
- /* error-handler is a 404 */
-
- /* continue as normal, status is the same */
- ERROR("Warning: Either the error-handler returned status 404 or the error-handler itself was not found: %s", SAFE_BUF_STR(con->request.uri));
- ERROR("returning the original status: %i", con->error_handler_saved_status);
- ERROR("%s", "If this is a rails app: check your production.log");
- con->http_status = con->error_handler_saved_status;
- }
- } else if (con->in_error_handler) {
- /* error-handler is back and has generated content */
- /* if Status: was set, take it otherwise use 200 */
- con->http_status = con->error_handler_saved_status;
- }
-
- if (con->http_status == 0) con->http_status = 200;
-
- /* the backend is prepared, forward the content */
- connection_set_state(srv, con, CON_STATE_READ_REQUEST_CONTENT);
-
- break;
- case CON_STATE_READ_REQUEST_CONTENT:
- /* the request-handle is setup, read all the data and push it into the request-handler */
-
- if (con->request.content_length == -1 ||
- con->request.content_length == 0) {
- con->recv->is_closed = 1;
- }
-
- if (!con->recv->is_closed &&
- con->recv->bytes_in < con->request.content_length) {
- switch (connection_handle_read_request_content(srv, con)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_ERROR:
- TRACE("%s", "(error)");
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- case HANDLER_WAIT_FOR_EVENT:
- break;
- default:
- ERROR("%s", "oops, unknown return value: ...");
- }
-
- if (con->recv->bytes_in == con->request.content_length) {
- /* we read everything */
- fdevent_event_del(srv->ev, con->sock);
- con->recv->is_closed = 1;
- }
- chunkqueue_remove_finished_chunks(con->recv_raw);
- }
-
- chunkqueue_remove_finished_chunks(con->recv);
-
- /*
- * this should call the backend
- * they might build the connection now or stream the content to the upstream server
- * */
-
- switch(r = plugins_call_handle_send_request_content(srv, con)) {
- case HANDLER_GO_ON:
- /* everything was forwarded */
- break;
- case HANDLER_FINISHED:
- /* oops, we don't want this here */
- break;
- case HANDLER_COMEBACK:
- break;
- case HANDLER_WAIT_FOR_EVENT:
- return;
- default:
- /* something strange happened */
- TRACE("(error) plugins_call_handle_send_request_content(): r = %d", r);
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
-
- chunkqueue_remove_finished_chunks(con->recv);
-
- /* jump back, this should be proceeded by mod_staticfile */
- if (r == HANDLER_COMEBACK && con->mode == DIRECT) {
- connection_set_state(srv,con,CON_STATE_HANDLE_REQUEST_HEADER);
- break;
- }
-
- if (con->state == CON_STATE_ERROR) break;
-
- if (con->recv->is_closed &&
- con->recv->bytes_in == con->recv->bytes_out) {
- /* everything we read is sent */
- connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER);
- }
-
- break;
- case CON_STATE_HANDLE_RESPONSE_HEADER:
- /* handle the HTTP response headers, or generate error-page */
- connection_handle_response_header(srv, con);
-
- /* we got a response header from the backend
- * call all plugins who want to modify the response header
- * - mod_compress/deflate
- * - HTTP/1.1 chunking
- *
- */
- switch (plugins_call_handle_response_header(srv, con)) {
- case HANDLER_GO_ON:
- case HANDLER_FINISHED:
- break;
- case HANDLER_WAIT_FOR_EVENT:
- /* need to wait for more data */
- return;
- default:
- /* something strange happened */
- if (con->conf.log_request_handling) {
- TRACE("%s", "handle response header failed");
- }
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
-
- if (con->state == CON_STATE_ERROR) break;
-
- /* all the response-headers are set, check if we have a */
-
- connection_set_state(srv, con, CON_STATE_WRITE_RESPONSE_HEADER);
-
- break;
- case CON_STATE_WRITE_RESPONSE_HEADER:
- /* write response headers */
- http_response_write_header(srv, con, con->send_raw);
-
- connection_set_state(srv, con, CON_STATE_WRITE_RESPONSE_CONTENT);
-
- if (con->request.http_method == HTTP_METHOD_HEAD) {
- /* remove the content now */
- chunkqueue_reset(con->send);
-
- con->send->is_closed = 1;
- }
-
- break;
- case CON_STATE_WRITE_RESPONSE_CONTENT:
- fdevent_event_del(srv->ev, con->sock);
-
- con->write_request_ts = srv->cur_ts;
-
- /* looks like we shall read some content from the backend */
- switch (plugins_call_handle_read_response_content(srv, con)) {
- case HANDLER_WAIT_FOR_EVENT:
- if (!con->send->is_closed && con->send->bytes_in == con->send->bytes_out) {
- /* need to wait for more data */
- return;
- }
- break;
- case HANDLER_GO_ON:
- case HANDLER_FINISHED:
- break;
- default:
- /* something strange happened */
- if (con->conf.log_request_handling) {
- TRACE("%s", "read response content failed");
- }
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
-
- if (con->state == CON_STATE_ERROR) break;
-
- /* we might have new content in the con->send buffer
- * encode it for the network
- * - chunking
- * - compression
- */
- switch (plugins_call_handle_filter_response_content(srv, con)) {
- case HANDLER_GO_ON:
- case HANDLER_FINISHED:
- break;
- case HANDLER_WAIT_FOR_EVENT:
- /* need to wait for more data */
- return;
- default:
- /* something strange happened */
- if (con->conf.log_request_handling) {
- TRACE("%s", "filter response content failed");
- }
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
-
- if (con->state == CON_STATE_ERROR) break;
-
- /* copy output from filters into send_raw. */
- bytes_moved = filter_chain_copy_output(con->send_filters, con->send_raw);
-
- /**
- * check that all previous filters have cleaned there chunkqueue
- */
- if (con->send_raw->is_closed) {
- filter *f;
-
- for (f = con->send_filters->first;
- f;
- f = f->next) {
- off_t cq_len;
-
- cq_len = chunkqueue_length(f->cq);
-
- if (cq_len > 0) {
- TRACE("filter[%d] is not empty: %jd (report me)", f->id, (intmax_t) cq_len);
- }
- }
- }
-
-
- /* limit download speed. */
- if (con->traffic_limit_reached) {
- return;
- }
-
- /* no response data available to send right now. wait for more. */
- if (!con->send_raw->is_closed &&
- con->send_raw->bytes_in == con->send_raw->bytes_out) {
- return;
- }
-
- switch(network_write_chunkqueue(srv, con, con->send_raw)) {
- case NETWORK_STATUS_SUCCESS:
- /* we send everything from the chunkqueue and the chunkqueue-sender signaled it is finished */
- if (con->send_raw->is_closed) {
- if (con->http_status == 100) {
- /* send out the 100 Continue header and handle the request as normal afterwards */
- con->http_status = 0;
-
- /* cleanup send chunkqueue's. */
- chunkqueue_reset(con->send);
- chunkqueue_reset(con->send_raw);
-
- connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
- } else {
- connection_set_state(srv, con, CON_STATE_RESPONSE_END);
- }
- } else {
- /* still have data to send in send_raw queue */
- fdevent_event_add(srv->ev, con->sock, FDEVENT_OUT);
- return;
- }
- break;
- case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
- TRACE("%s", "(network-subsys sent us a fatal-error)");
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
- return;
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- fdevent_event_add(srv->ev, con->sock, FDEVENT_OUT);
-
- return;
- case NETWORK_STATUS_WAIT_FOR_FD:
- /* the backend received a EMFILE
- * - e.g. for a mmap() of /dev/zero */
-
- server_out_of_fds(srv, con);
-
- return;
- case NETWORK_STATUS_INTERRUPTED:
- case NETWORK_STATUS_UNSET:
- break;
- }
-
-
- break;
- case CON_STATE_RESPONSE_END: /* transient */
- /* log the request */
-
- if (srv->srvconf.log_state_handling) {
- TRACE("state for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- plugins_call_handle_response_done(srv, con);
-
- srv->con_written++;
-
- if (con->keep_alive) {
- connection_set_state(srv, con, CON_STATE_REQUEST_START);
-
-#if 0
- con->request_start = srv->cur_ts;
- con->read_idle_ts = srv->cur_ts;
-#endif
- } else {
- switch(r = plugins_call_handle_connection_close(srv, con)) {
- case HANDLER_GO_ON:
- case HANDLER_FINISHED:
- break;
- default:
- ERROR("unhandled return value from plugins_call_handle_connection_close: %i", r);
- break;
- }
-
- connection_close(srv, con);
-
- srv->con_closed++;
- }
-
- connection_reset(srv, con);
-
- break;
- case CON_STATE_CLOSE:
- if (srv->srvconf.log_state_handling) {
- TRACE("state for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- if (con->keep_alive) {
- if (ioctl(con->sock->fd, FIONREAD, &b)) {
- ERROR("ioctl() failed: %s", strerror(errno));
- }
- if (b > 0) {
- char buf[1024];
- ERROR("CLOSE-read() for fd %i, %i bytes", con->sock->fd, b);
-
- /* */
- sockread(con->sock->fd, buf, sizeof(buf));
- } else {
- /* nothing to read */
-
- con->close_timeout_ts = srv->cur_ts - 2;
- }
- } else {
- con->close_timeout_ts = srv->cur_ts - 2;
- }
-
- if (srv->cur_ts - con->close_timeout_ts > 1) {
- connection_close(srv, con);
-
- if (srv->srvconf.log_state_handling) {
- TRACE("connection closed for fd %i", con->sock->fd);
- }
- }
-
- break;
- case CON_STATE_ERROR: /* transient */
- /* even if the connection was drop we still have to write it to the access log */
- if (con->http_status) {
- plugins_call_handle_response_done(srv, con);
- }
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- int ret;
- switch ((ret = SSL_shutdown(con->sock->ssl))) {
- case 1:
- /* ok */
- break;
- case 0:
- SSL_shutdown(con->sock->ssl);
- break;
- default:
- ERROR("SSL (%i): %s",
- SSL_get_error(con->sock->ssl, ret),
- ERR_error_string(ERR_get_error(), NULL));
- break;
- }
- }
-#endif
-
- switch(con->mode) {
- case DIRECT:
-#if 0
- TRACE("emergency exit for fd %i: direct", con->sock->fd);
-#endif
- break;
- default:
- switch(r = plugins_call_handle_connection_close(srv, con)) {
- case HANDLER_GO_ON:
- case HANDLER_FINISHED:
- break;
- default:
- ERROR("unhandled return value from plugins_call_handle_connection_close: %i", r);
- break;
- }
- break;
- }
-
- connection_reset(srv, con);
-
- /* close the connection */
- if ((con->keep_alive == 1) &&
- (0 == shutdown(con->sock->fd, SHUT_WR))) {
- con->close_timeout_ts = srv->cur_ts;
- connection_set_state(srv, con, CON_STATE_CLOSE);
-
- if (srv->srvconf.log_state_handling) {
- TRACE("shutdown for fd %i", con->sock->fd);
- }
- } else {
- connection_close(srv, con);
- }
-
- con->keep_alive = 0;
-
- srv->con_closed++;
-
- break;
- default:
- ERROR("unknown state for fd %i: %i", con->sock->fd, con->state);
- connection_set_state(srv, con, CON_STATE_ERROR);
- break;
- }
-
- if (done == -1) {
- done = 0;
- } else if (ostate == con->state) {
- done = 1;
- }
- }
-
- if (srv->srvconf.log_state_handling) {
- TRACE("state at exit for fd %i: %s", con->sock->fd, connection_get_state(con->state));
- }
-
- return;
-}
diff --git a/src/connections.h b/src/connections.h
deleted file mode 100644
index 1d15b806..00000000
--- a/src/connections.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _CONNECTIONS_H_
-#define _CONNECTIONS_H_
-
-#include "settings.h"
-#include "server.h"
-#include "fdevent.h"
-
-LI_API connection* connection_init(server *srv);
-LI_API int connection_reset(server *srv, connection *con);
-LI_API void connections_free(server *srv);
-
-LI_API connection* connection_accept(server *srv, server_socket *srv_sock);
-LI_API int connection_close(server *srv, connection *con);
-
-LI_API int connection_set_state(server *srv, connection *con, connection_state_t state);
-LI_API const char * connection_get_state(connection_state_t state);
-LI_API const char * connection_get_short_state(connection_state_t state);
-LI_API void connection_state_machine(server *srv, connection *con);
-
-#endif
diff --git a/src/crc32.c b/src/crc32.c
deleted file mode 100644
index cdad7bce..00000000
--- a/src/crc32.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "crc32.h"
-
-#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
-
-static const unsigned int crc_c[256] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
-};
-
-
-uint32_t generate_crc32c(char *buffer, size_t length) {
- size_t i;
- uint32_t crc32 = ~0L;
-
- for (i = 0; i < length; i++){
- CRC32C(crc32, (unsigned char)buffer[i]);
- }
- return ~crc32;
-}
-
diff --git a/src/crc32.h b/src/crc32.h
deleted file mode 100644
index 22b112d9..00000000
--- a/src/crc32.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __crc32cr_table_h__
-#define __crc32cr_table_h__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <stdlib.h>
-
-#if defined HAVE_STDINT_H
-#include <stdint.h>
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-#ifdef _WIN32
-#define uint32_t unsigned __int32
-#endif
-
-#include "settings.h"
-
-LI_API uint32_t generate_crc32c(char *string, size_t length);
-
-#endif
diff --git a/src/data_array.c b/src/data_array.c
deleted file mode 100644
index c07effb5..00000000
--- a/src/data_array.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "array.h"
-
-static data_unset *data_array_copy(const data_unset *s) {
- data_array *src = (data_array *)s;
- data_array *ds = data_array_init();
-
- buffer_copy_string_buffer(ds->key, src->key);
- array_free(ds->value);
- ds->value = array_init_array(src->value);
- ds->is_index_key = src->is_index_key;
- return (data_unset *)ds;
-}
-
-static void data_array_free(data_unset *d) {
- data_array *ds = (data_array *)d;
-
- buffer_free(ds->key);
- array_free(ds->value);
-
- free(d);
-}
-
-static void data_array_reset(data_unset *d) {
- data_array *ds = (data_array *)d;
-
- /* reused array elements */
- buffer_reset(ds->key);
- array_reset(ds->value);
-}
-
-static int data_array_insert_dup(data_unset *dst, data_unset *src) {
- UNUSED(dst);
-
- src->free(src);
-
- return 0;
-}
-
-static void data_array_print(const data_unset *d, int depth) {
- data_array *ds = (data_array *)d;
-
- array_print(ds->value, depth);
-}
-
-data_array *data_array_init(void) {
- data_array *ds;
-
- ds = calloc(1, sizeof(*ds));
-
- ds->key = buffer_init();
- ds->value = array_init();
-
- ds->copy = data_array_copy;
- ds->free = data_array_free;
- ds->reset = data_array_reset;
- ds->insert_dup = data_array_insert_dup;
- ds->print = data_array_print;
- ds->type = TYPE_ARRAY;
-
- return ds;
-}
diff --git a/src/data_config.c b/src/data_config.c
deleted file mode 100644
index 8e2e75d6..00000000
--- a/src/data_config.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "array.h"
-
-static data_unset *data_config_copy(const data_unset *s) {
- data_config *src = (data_config *)s;
- data_config *ds = data_config_init();
-
- buffer_copy_string_buffer(ds->key, src->key);
- buffer_copy_string_buffer(ds->comp_key, src->comp_key);
- array_free(ds->value);
- ds->value = array_init_array(src->value);
- return (data_unset *)ds;
-}
-
-static void data_config_free(data_unset *d) {
- data_config *ds = (data_config *)d;
-
- buffer_free(ds->key);
- buffer_free(ds->op);
- buffer_free(ds->comp_key);
-
- array_free(ds->value);
- array_free(ds->childs);
-
- if (ds->string) buffer_free(ds->string);
-#ifdef HAVE_PCRE_H
- if (ds->regex) pcre_free(ds->regex);
- if (ds->regex_study) pcre_free(ds->regex_study);
-#endif
-
- free(d);
-}
-
-static void data_config_reset(data_unset *d) {
- data_config *ds = (data_config *)d;
-
- /* reused array elements */
- buffer_reset(ds->key);
- buffer_reset(ds->comp_key);
- array_reset(ds->value);
-}
-
-static int data_config_insert_dup(data_unset *dst, data_unset *src) {
- UNUSED(dst);
-
- src->free(src);
-
- return 0;
-}
-
-static void data_config_print(const data_unset *d, int depth) {
- data_config *ds = (data_config *)d;
- array *a = (array *)ds->value;
- size_t i;
- size_t maxlen;
-
- if (0 != ds->context_ndx) {
- fprintf(stdout, "$%s %s \"%s\" {\n",
- ds->comp_key->ptr, ds->op->ptr, ds->string->ptr);
- array_print_indent(depth + 1);
- fprintf(stdout, "# block %d\n", ds->context_ndx);
- depth ++;
- }
-
- maxlen = array_get_max_key_length(a);
- for (i = 0; i < a->used; i ++) {
- data_unset *du = a->data[i];
- size_t len = strlen(du->key->ptr);
- size_t j;
-
- array_print_indent(depth);
- fprintf(stdout, "%s", du->key->ptr);
- for (j = maxlen - len; j > 0; j --) {
- fprintf(stdout, " ");
- }
- fprintf(stdout, " = ");
- du->print(du, depth);
- fprintf(stdout, "\n");
- }
-
- if (ds->childs) {
- fprintf(stdout, "\n");
- for (i = 0; i < ds->childs->used; i ++) {
- data_unset *du = ds->childs->data[i];
-
- /* only the 1st block of chaining */
- if (NULL == ((data_config *)du)->prev) {
- fprintf(stdout, "\n");
- array_print_indent(depth);
- du->print(du, depth);
- fprintf(stdout, "\n");
- }
- }
- }
-
- if (0 != ds->context_ndx) {
- depth --;
- array_print_indent(depth);
- fprintf(stdout, "}");
-
- fprintf(stdout, " # end of $%s %s \"%s\"",
- ds->comp_key->ptr, ds->op->ptr, ds->string->ptr);
- }
-
- if (ds->next) {
- fprintf(stdout, "\n");
- array_print_indent(depth);
- fprintf(stdout, "else ");
- ds->next->print((data_unset *)ds->next, depth);
- }
-}
-
-data_config *data_config_init(void) {
- data_config *ds;
-
- ds = calloc(1, sizeof(*ds));
-
- ds->key = buffer_init();
- ds->op = buffer_init();
- ds->comp_key = buffer_init();
- ds->value = array_init();
- ds->childs = array_init();
- ds->childs->is_weakref = 1;
-
- ds->copy = data_config_copy;
- ds->free = data_config_free;
- ds->reset = data_config_reset;
- ds->insert_dup = data_config_insert_dup;
- ds->print = data_config_print;
- ds->type = TYPE_CONFIG;
-
- return ds;
-}
diff --git a/src/data_count.c b/src/data_count.c
deleted file mode 100644
index 5c5a5f06..00000000
--- a/src/data_count.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "array.h"
-
-static data_unset *data_count_copy(const data_unset *s) {
- data_count *src = (data_count *)s;
- data_count *ds = data_count_init();
-
- buffer_copy_string_buffer(ds->key, src->key);
- ds->count = src->count;
- ds->is_index_key = src->is_index_key;
- return (data_unset *)ds;
-}
-
-static void data_count_free(data_unset *d) {
- data_count *ds = (data_count *)d;
-
- buffer_free(ds->key);
-
- free(d);
-}
-
-static void data_count_reset(data_unset *d) {
- data_count *ds = (data_count *)d;
-
- buffer_reset(ds->key);
-
- ds->count = 0;
-}
-
-static int data_count_insert_dup(data_unset *dst, data_unset *src) {
- data_count *ds_dst = (data_count *)dst;
- data_count *ds_src = (data_count *)src;
-
- ds_dst->count += ds_src->count;
-
- src->free(src);
-
- return 0;
-}
-
-static void data_count_print(const data_unset *d, int depth) {
- data_count *ds = (data_count *)d;
- UNUSED(depth);
-
- fprintf(stdout, "count(%d)", ds->count);
-}
-
-
-data_count *data_count_init(void) {
- data_count *ds;
-
- ds = calloc(1, sizeof(*ds));
-
- ds->key = buffer_init();
- ds->count = 1;
-
- ds->copy = data_count_copy;
- ds->free = data_count_free;
- ds->reset = data_count_reset;
- ds->insert_dup = data_count_insert_dup;
- ds->print = data_count_print;
- ds->type = TYPE_COUNT;
-
- return ds;
-}
diff --git a/src/data_integer.c b/src/data_integer.c
deleted file mode 100644
index 54234077..00000000
--- a/src/data_integer.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "array.h"
-
-static data_unset *data_integer_copy(const data_unset *s) {
- data_integer *src = (data_integer *)s;
- data_integer *ds = data_integer_init();
-
- buffer_copy_string_buffer(ds->key, src->key);
- ds->is_index_key = src->is_index_key;
- ds->value = src->value;
- return (data_unset *)ds;
-}
-
-static void data_integer_free(data_unset *d) {
- data_integer *ds = (data_integer *)d;
-
- buffer_free(ds->key);
-
- free(d);
-}
-
-static void data_integer_reset(data_unset *d) {
- data_integer *ds = (data_integer *)d;
-
- /* reused integer elements */
- buffer_reset(ds->key);
- ds->value = 0;
-}
-
-static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
- UNUSED(dst);
-
- src->free(src);
-
- return 0;
-}
-
-static void data_integer_print(const data_unset *d, int depth) {
- data_integer *ds = (data_integer *)d;
- UNUSED(depth);
-
- fprintf(stdout, "%d", ds->value);
-}
-
-
-data_integer *data_integer_init(void) {
- data_integer *ds;
-
- ds = calloc(1, sizeof(*ds));
-
- ds->key = buffer_init();
- ds->value = 0;
-
- ds->copy = data_integer_copy;
- ds->free = data_integer_free;
- ds->reset = data_integer_reset;
- ds->insert_dup = data_integer_insert_dup;
- ds->print = data_integer_print;
- ds->type = TYPE_INTEGER;
-
- return ds;
-}
diff --git a/src/data_string.c b/src/data_string.c
deleted file mode 100644
index 1b9da692..00000000
--- a/src/data_string.c
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "array.h"
-
-static data_unset *data_string_copy(const data_unset *s) {
- data_string *src = (data_string *)s;
- data_string *ds = data_string_init();
-
- buffer_copy_string_buffer(ds->key, src->key);
- buffer_copy_string_buffer(ds->value, src->value);
- ds->is_index_key = src->is_index_key;
- return (data_unset *)ds;
-}
-
-static void data_string_free(data_unset *d) {
- data_string *ds = (data_string *)d;
-
- buffer_free(ds->key);
- buffer_free(ds->value);
-
- free(d);
-}
-
-static void data_string_reset(data_unset *d) {
- data_string *ds = (data_string *)d;
-
- /* reused array elements */
- buffer_reset(ds->key);
- buffer_reset(ds->value);
-}
-
-static int data_string_insert_dup(data_unset *dst, data_unset *src) {
- data_string *ds_dst = (data_string *)dst;
- data_string *ds_src = (data_string *)src;
-
- if (ds_dst->value->used) {
- buffer_append_string_len(ds_dst->value, CONST_STR_LEN(", "));
- buffer_append_string_buffer(ds_dst->value, ds_src->value);
- } else {
- buffer_copy_string_buffer(ds_dst->value, ds_src->value);
- }
-
- src->free(src);
-
- return 0;
-}
-
-static int data_response_insert_dup(data_unset *dst, data_unset *src) {
- data_string *ds_dst = (data_string *)dst;
- data_string *ds_src = (data_string *)src;
-
- if (ds_dst->value->used) {
- buffer_append_string_len(ds_dst->value, CONST_STR_LEN("\r\n"));
- buffer_append_string_buffer(ds_dst->value, ds_dst->key);
- buffer_append_string_len(ds_dst->value, CONST_STR_LEN(": "));
- buffer_append_string_buffer(ds_dst->value, ds_src->value);
- } else {
- buffer_copy_string_buffer(ds_dst->value, ds_src->value);
- }
-
- src->free(src);
-
- return 0;
-}
-
-
-static void data_string_print(const data_unset *d, int depth) {
- data_string *ds = (data_string *)d;
- unsigned int i = 0;
- UNUSED(depth);
-
- // empty and uninitialized strings
- if (ds->value->used < 1) {
- fputs("\"\"", stdout);
- return;
- }
-
- // print out the string as is, except prepend " with backslash
- putc('"', stdout);
- for (i = 0; i < ds->value->used - 1; i++) {
- unsigned char c = ds->value->ptr[i];
- if (c == '"') {
- fputs("\\\"", stdout);
- } else {
- putc(c, stdout);
- }
- }
- putc('"', stdout);
-}
-
-
-data_string *data_string_init(void) {
- data_string *ds;
-
- ds = calloc(1, sizeof(*ds));
- assert(ds);
-
- ds->key = buffer_init();
- ds->value = buffer_init();
-
- ds->copy = data_string_copy;
- ds->free = data_string_free;
- ds->reset = data_string_reset;
- ds->insert_dup = data_string_insert_dup;
- ds->print = data_string_print;
- ds->type = TYPE_STRING;
-
- return ds;
-}
-
-data_string *data_response_init(void) {
- data_string *ds;
-
- ds = data_string_init();
- ds->insert_dup = data_response_insert_dup;
-
- return ds;
-}
diff --git a/src/etag.c b/src/etag.c
deleted file mode 100644
index 0e16c598..00000000
--- a/src/etag.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#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"
-
-int etag_is_equal(buffer *etag, const char *matches) {
- if (buffer_is_equal_string(etag, matches, strlen(matches))) return 1;
- return 0;
-}
-
-int etag_create(buffer *etag, struct stat *st, etag_flags_t flags) {
-
- if (0 == flags) return 0;
-
- buffer_reset(etag);
-
- if (flags & ETAG_USE_INODE) {
- buffer_append_off_t(etag, st->st_ino);
- buffer_append_string_len(etag, CONST_STR_LEN("-"));
- }
- if (flags & ETAG_USE_SIZE) {
- buffer_append_off_t(etag, st->st_size);
- buffer_append_string_len(etag, CONST_STR_LEN("-"));
- }
- if (flags & ETAG_USE_MTIME) {
- buffer_append_long(etag, st->st_mtime);
- }
- return 0;
-}
-
-int etag_mutate(buffer *mut, buffer *etag) {
- size_t i;
- uint32_t h;
-
- for (h=0, i=0; i < etag->used-1; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
-
- buffer_reset(mut);
- buffer_copy_string_len(mut, CONST_STR_LEN("\""));
- buffer_append_long(mut, h);
- buffer_append_string_len(mut, CONST_STR_LEN("\""));
-
- return 0;
-}
diff --git a/src/etag.h b/src/etag.h
deleted file mode 100644
index 80e9ab9c..00000000
--- a/src/etag.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef ETAG_H
-#define ETAG_H
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "buffer.h"
-
-typedef enum { ETAG_USE_INODE = 1, ETAG_USE_MTIME = 2, ETAG_USE_SIZE = 4 } etag_flags_t;
-
-LI_API int etag_is_equal(buffer *etag, const char *matches);
-LI_API int etag_create(buffer *etag, struct stat *st, etag_flags_t flags);
-LI_API int etag_mutate(buffer *mut, buffer *etag);
-
-
-#endif
diff --git a/src/fastcgi.h b/src/fastcgi.h
deleted file mode 100644
index 31c00ad6..00000000
--- a/src/fastcgi.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * fastcgi.h --
- *
- * Defines for the FastCGI protocol.
- *
- *
- * Copyright (c) 1995-1996 Open Market, Inc.
- *
- * See the file "LICENSE.TERMS" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * $Id: fastcgi.h,v 1.1.1.1 2003/10/18 09:54:10 weigon Exp $
- */
-
-#ifndef _FASTCGI_H
-#define _FASTCGI_H
-
-/*
- * Listening socket file number
- */
-#define FCGI_LISTENSOCK_FILENO 0
-
-typedef struct {
- unsigned char version;
- unsigned char type;
- unsigned char requestIdB1;
- unsigned char requestIdB0;
- unsigned char contentLengthB1;
- unsigned char contentLengthB0;
- unsigned char paddingLength;
- unsigned char reserved;
-} FCGI_Header;
-
-#define FCGI_MAX_LENGTH 0xffff
-
-/*
- * Number of bytes in a FCGI_Header. Future versions of the protocol
- * will not reduce this number.
- */
-#define FCGI_HEADER_LEN 8
-
-/*
- * Value for version component of FCGI_Header
- */
-#define FCGI_VERSION_1 1
-
-/*
- * Values for type component of FCGI_Header
- */
-#define FCGI_BEGIN_REQUEST 1
-#define FCGI_ABORT_REQUEST 2
-#define FCGI_END_REQUEST 3
-#define FCGI_PARAMS 4
-#define FCGI_STDIN 5
-#define FCGI_STDOUT 6
-#define FCGI_STDERR 7
-#define FCGI_DATA 8
-#define FCGI_GET_VALUES 9
-#define FCGI_GET_VALUES_RESULT 10
-#define FCGI_UNKNOWN_TYPE 11
-#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
-
-/*
- * Value for requestId component of FCGI_Header
- */
-#define FCGI_NULL_REQUEST_ID 0
-
-
-typedef struct {
- unsigned char roleB1;
- unsigned char roleB0;
- unsigned char flags;
- unsigned char reserved[5];
-} FCGI_BeginRequestBody;
-
-typedef struct {
- FCGI_Header header;
- FCGI_BeginRequestBody body;
-} FCGI_BeginRequestRecord;
-
-/*
- * Mask for flags component of FCGI_BeginRequestBody
- */
-#define FCGI_KEEP_CONN 1
-
-/*
- * Values for role component of FCGI_BeginRequestBody
- */
-#define FCGI_RESPONDER 1
-#define FCGI_AUTHORIZER 2
-#define FCGI_FILTER 3
-
-
-typedef struct {
- unsigned char appStatusB3;
- unsigned char appStatusB2;
- unsigned char appStatusB1;
- unsigned char appStatusB0;
- unsigned char protocolStatus;
- unsigned char reserved[3];
-} FCGI_EndRequestBody;
-
-typedef struct {
- FCGI_Header header;
- FCGI_EndRequestBody body;
-} FCGI_EndRequestRecord;
-
-/*
- * Values for protocolStatus component of FCGI_EndRequestBody
- */
-#define FCGI_REQUEST_COMPLETE 0
-#define FCGI_CANT_MPX_CONN 1
-#define FCGI_OVERLOADED 2
-#define FCGI_UNKNOWN_ROLE 3
-
-
-/*
- * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT records
- */
-#define FCGI_MAX_CONNS "FCGI_MAX_CONNS"
-#define FCGI_MAX_REQS "FCGI_MAX_REQS"
-#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
-
-
-typedef struct {
- unsigned char type;
- unsigned char reserved[7];
-} FCGI_UnknownTypeBody;
-
-typedef struct {
- FCGI_Header header;
- FCGI_UnknownTypeBody body;
-} FCGI_UnknownTypeRecord;
-
-#endif /* _FASTCGI_H */
-
diff --git a/src/fcgi-stat-accel.c b/src/fcgi-stat-accel.c
deleted file mode 100644
index bae39e6b..00000000
--- a/src/fcgi-stat-accel.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- compile with:
-
- $ gcc -lfcgi -lpthread fcgi-stat-accel.c -o fcgi-stat-accel
-
- fcgi-stat-accel will use the PHP_FCGI_CHILDREN environment variable to set the thread count.
-
- The default value, if spawned from lighttpd, is 20.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <fcntl.h>
-
-#include <stdlib.h>
-#ifdef HAVE_FASTCGI_FASTCGI_H
-#include <fastcgi/fcgiapp.h>
-#elif defined (HAVE_FASTCGI_H)
-#include <fcgiapp.h>
-#endif
-
-#define THREAD_COUNT 20
-
-#define FORBIDDEN(stream) \
- FCGX_FPrintF(stream, "Status: 403 Forbidden\r\nContent-Type: text/html\r\n\r\n<h1>403 Forbidden</h1>\n");
-#define NOTFOUND(stream, filename) \
- FCGX_FPrintF(stream, "Status: 404 Not Found\r\nContent-Type: text/html\r\n\r\n<h1>404 Not Found</h1>\r\n%s", filename);
-#define SENDFILE(stream, filename) \
- FCGX_FPrintF(stream, "X-LIGHTTPD-send-file: %s\r\n\r\n", filename);
-
-#define UNUSED(x) ( (void)(x) )
-
-static void *doit(void *a){
- FCGX_Request request;
- int rc;
- char *filename;
- UNUSED(a);
-
- FCGX_InitRequest(&request, 0, /* FCGI_FAIL_ACCEPT_ON_INTR */ 0);
-
- while(1){
- int fd;
- //Some platforms require accept() serialization, some don't. The documentation claims it to be thread safe
-// static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
-// pthread_mutex_lock(&accept_mutex);
- rc = FCGX_Accept_r(&request);
-// pthread_mutex_unlock(&accept_mutex);
-
- if(rc < 0)
- break;
-
- //get the filename
- if((filename = FCGX_GetParam("SCRIPT_FILENAME", request.envp)) == NULL){
- FORBIDDEN(request.out);
- //don't try to open directories
- }else if(filename[strlen(filename)-1] == '/'){
- FORBIDDEN(request.out);
- //open the file
- }else if((fd = open(filename, O_RDONLY)) == -1){
- NOTFOUND(request.out, filename);
- //no error, serve it
- }else{
- SENDFILE(request.out, filename);
-
- close(fd);
- }
-
- FCGX_Finish_r(&request);
- }
- return NULL;
-}
-
-int main(void){
- int i,j,thread_count;
- pthread_t* id;
- char* env_val;
-
- FCGX_Init();
-
- thread_count = THREAD_COUNT;
- env_val = getenv("PHP_FCGI_CHILDREN");
- if (env_val != NULL) {
- j = atoi(env_val);
- if (j != 0) {
- thread_count = j;
- };
- };
-
- id = malloc(sizeof(*id) * thread_count);
-
- for (i = 0; i < thread_count; i++) {
- pthread_create(&id[i], NULL, doit, NULL);
- }
-
- /* block the current thread by executing one */
- doit(NULL);
-
- for (i = 0; i < thread_count; i++) {
- pthread_join(id[i], NULL);
- }
-
- free(id);
-
- return 0;
-}
-
diff --git a/src/fdevent.c b/src/fdevent.c
deleted file mode 100644
index 9386b1d9..00000000
--- a/src/fdevent.c
+++ /dev/null
@@ -1,390 +0,0 @@
-#include <sys/types.h>
-
-#include "settings.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "fdevent.h"
-#include "buffer.h"
-#include "log.h"
-
-#include "sys-socket.h"
-
-static fdevent_handler_info_t fdevent_handlers[] = {
- /* - poll is most reliable
- * - select works everywhere
- * - linux-* are experimental
- */
- {
- FDEVENT_HANDLER_LINUX_SYSEPOLL,
- "linux-sysepoll",
- "epoll (Linux 2.6)",
-#ifdef USE_LINUX_EPOLL
- fdevent_linux_sysepoll_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_POLL,
- "poll",
- "poll (Unix)",
-#ifdef USE_POLL
- fdevent_poll_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_SELECT,
- "select",
- "select (generic)",
-#ifdef USE_SELECT
- fdevent_select_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_LINUX_RTSIG,
- "linux-rtsig",
- "rt-signals (Linux 2.4+)",
-#ifdef USE_LINUX_SIGIO
- fdevent_linux_rtsig_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll",
- "/dev/poll (Solaris)",
-#ifdef USE_SOLARIS_DEVPOLL
- fdevent_solaris_devpoll_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_FREEBSD_KQUEUE,
- "freebsd-kqueue",
- "kqueue (FreeBSD)",
-#ifdef USE_FREEBSD_KQUEUE
- fdevent_freebsd_kqueue_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_FREEBSD_KQUEUE,
- "kqueue",
- "kqueue (FreeBSD)",
-#ifdef USE_FREEBSD_KQUEUE
- fdevent_freebsd_kqueue_init
-#else
- NULL
-#endif
- },
- {
- FDEVENT_HANDLER_UNSET,
- NULL,
- NULL,
- NULL
- }
-};
-
-
-
-const fdevent_handler_info_t *fdevent_get_handlers() {
- return fdevent_handlers;
-}
-
-const fdevent_handler_info_t *fdevent_get_defaulthandler() {
- const fdevent_handler_info_t *handler = fdevent_get_handlers();
-
- while (handler->name) {
- if (handler->init) {
- return handler;
- }
- handler ++;
- }
-
- return NULL;
-}
-
-const fdevent_handler_info_t *fdevent_get_handler_info_by_type(fdevent_handler_t type) {
- const fdevent_handler_info_t *handler = fdevent_get_handlers();
-
- while (handler->name) {
- if (type == handler->type) {
- return handler;
- }
- handler ++;
- }
-
- return NULL;
-}
-
-const fdevent_handler_info_t *fdevent_get_handler_info_by_name(const char *name) {
- const fdevent_handler_info_t *handler = fdevent_get_handlers();
-
- while (handler->name) {
- if (strcmp(name, handler->name) == 0) {
- return handler;
- }
- handler ++;
- }
-
- return NULL;
-}
-
-fdevent_revent *fdevent_revent_init(void) {
- STRUCT_INIT(fdevent_revent, revent);
-
- return revent;
-}
-
-void fdevent_revent_free(fdevent_revent *revent) {
- if (!revent) return;
-
- free(revent);
-}
-
-fdevent_revents *fdevent_revents_init(void) {
- STRUCT_INIT(fdevent_revents, revents);
-
- return revents;
-}
-
-void fdevent_revents_reset(fdevent_revents *revents) {
- if (!revents) return;
-
- revents->used = 0;
-}
-
-void fdevent_revents_add(fdevent_revents *revents, int fd, int events) {
- fdevent_revent *revent;
-
- if (revents->used == revents->size) {
- /* resize the events-array */
- revents->ptr = realloc(revents->ptr, (revents->size + 1) * sizeof(*(revents->ptr)));
- revents->ptr[revents->size++] = fdevent_revent_init();
- }
-
- revent = revents->ptr[revents->used++];
- revent->fd = fd;
- revent->revents = events;
-}
-
-void fdevent_revents_free(fdevent_revents *revents) {
- size_t i;
-
- if (!revents) return;
-
- if (revents->size) {
- for (i = 0; i < revents->size; i++) {
- fdevent_revent_free(revents->ptr[i]);
- }
-
- free(revents->ptr);
- }
- free(revents);
-}
-
-fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
- fdevents *ev;
- const fdevent_handler_info_t *handler = fdevent_get_handler_info_by_type(type);
-
- ev = calloc(1, sizeof(*ev));
- ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
- ev->maxfds = maxfds;
-
- assert(handler && handler->init);
- if (0 != handler->init(ev)) {
- switch(type) {
- case FDEVENT_HANDLER_POLL:
- ERROR("event-handler poll failed %s", "");
- return NULL;
-
- case FDEVENT_HANDLER_SELECT:
- ERROR("event-handler select failed %s", "");
- return NULL;
-
- default:
- if (0 != fdevent_linux_rtsig_init(ev)) {
- ERROR("event-handler '%s' failed, use 'poll' or 'select' instead", handler->name);
-
- return NULL;
- }
- }
- }
-
- return ev;
-}
-
-void fdevent_free(fdevents *ev) {
- size_t i;
- if (!ev) return;
-
- if (ev->free) ev->free(ev);
-
- for (i = 0; i < ev->maxfds; i++) {
- if (ev->fdarray[i]) free(ev->fdarray[i]);
- }
-
- free(ev->fdarray);
- free(ev);
-}
-
-int fdevent_reset(fdevents *ev) {
- if (ev->reset) return ev->reset(ev);
-
- return 0;
-}
-
-static fdnode *fdnode_init() {
- fdnode *fdn;
-
- fdn = calloc(1, sizeof(*fdn));
- fdn->fd = -1;
-
- return fdn;
-}
-
-static void fdnode_free(fdnode *fdn) {
- free(fdn);
-}
-
-/* Unix file descriptors begin at zero for each process, but not so win32.
-The fdevent system uses the file descriptors as indexers into the fdarray, but we can't
-just do that on windows. Lazily, this is O(n) on the number of file descriptors/sockets, but
-with select's limit of 64 events, this is not really a bottleneck. For the sake of win32,
-it would be nice if all file/socket descriptors were references to IO devices in our own
-global table, instead of just using the system-provided fd directly.
-*/
-#ifdef _WIN32
-
-size_t fdevent_find_free_slot(fdevents *ev, int fd) {
- size_t i;
- for ( i = 0; i < ev->maxfds; i++ )
- {
- if ( ev->fdarray[i] == NULL )
- return i;
- }
- SEGFAULT("no more free fdevent.fdarray slots: %s", "");
- return -1;
-}
-
-size_t fdevent_find_slot(fdevents *ev, int fd) {
- size_t i;
- for ( i = 0; i < ev->maxfds; i++ )
- {
- if ( ev->fdarray[i] && ev->fdarray[i]->fd == fd ) return i;
- }
- DebugBreak();
- return -1;
-}
-
-#else
-
-#define fdevent_find_free_slot( ev, fd ) (fd)
-#define fdevent_find_slot( ev, fd ) (fd)
-
-#endif
-
-int fdevent_register(fdevents *ev, iosocket *sock, fdevent_handler handler, void *ctx) {
- fdnode *fdn;
- size_t fda_ndx;
-
- fda_ndx = fdevent_find_free_slot(ev, sock->fd);
-
- fdn = fdnode_init();
- fdn->handler = handler;
- fdn->fd = sock->fd;
- fdn->ctx = ctx;
-
- ev->fdarray[fda_ndx] = fdn;
-
- return 0;
-}
-
-int fdevent_unregister(fdevents *ev, iosocket *sock) {
- fdnode *fdn;
- size_t fda_ndx;
- if (!ev) return 0;
- fda_ndx = fdevent_find_slot(ev, sock->fd);
-
- fdn = ev->fdarray[fda_ndx];
-
- fdnode_free(fdn);
-
- ev->fdarray[fda_ndx] = NULL;
-
- return 0;
-}
-
-int fdevent_event_del(fdevents *ev, iosocket *sock) {
- if (ev->event_del) ev->event_del(ev, sock);
-
- return 0;
-}
-
-int fdevent_event_add(fdevents *ev, iosocket *sock, int events) {
- if (ev->event_add) ev->event_add(ev, sock, events);
-
- return 0;
-}
-
-int fdevent_poll(fdevents *ev, int timeout_ms) {
- if (ev->poll == NULL) SEGFAULT("ev->poll is %p", (void*) (intptr_t) ev->poll);
- return ev->poll(ev, timeout_ms);
-}
-
-int fdevent_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
- size_t i;
-
- if (ev->get_revents == NULL) SEGFAULT("ev->get_revents is %p", (void*) (intptr_t) ev->get_revents);
-
- fdevent_revents_reset(revents);
-
- ev->get_revents(ev, event_count, revents);
- /* select() reports more events, as it counts per event and per fd (e.g. READ+WRITE on one fd == two events) */
- /* assert(revents->used == event_count); */
-
- /* patch the event handlers */
- for (i = 0; i < revents->used; i++) {
- size_t fda_ndx;
- fdevent_revent *r = revents->ptr[i];
-
- fda_ndx = fdevent_find_slot(ev, r->fd);
-
- r->handler = ev->fdarray[fda_ndx]->handler;
- r->context = ev->fdarray[fda_ndx]->ctx;
- }
-
- return 0;
-}
-
-int fdevent_fcntl_set(fdevents *ev, iosocket *sock) {
-#ifdef _WIN32
- int i = 1;
-#endif
-#ifdef FD_CLOEXEC
- /* close fd on exec (cgi) */
- fcntl(sock->fd, F_SETFD, FD_CLOEXEC);
-#endif
- if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, sock->fd);
-#ifdef O_NONBLOCK
- return fcntl(sock->fd, F_SETFL, O_NONBLOCK | O_RDWR);
-#elif defined _WIN32
- return ioctlsocket(sock->fd, FIONBIO, &i);
-#else
- return 0;
-#endif
-}
-
-
diff --git a/src/fdevent.h b/src/fdevent.h
deleted file mode 100644
index 13ae07f7..00000000
--- a/src/fdevent.h
+++ /dev/null
@@ -1,280 +0,0 @@
-#ifndef _FDEVENT_H_
-#define _FDEVENT_H_
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "settings.h"
-#include "bitset.h"
-
-#include "iosocket.h"
-#include "array-static.h"
-
-/* select event-system */
-
-#if defined(HAVE_EPOLL_CTL) && defined(HAVE_SYS_EPOLL_H)
-# if defined HAVE_STDINT_H
-# include <stdint.h>
-# endif
-# define USE_LINUX_EPOLL
-# include <sys/epoll.h>
-#endif
-
-/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
- * under /usr/include/sys/ */
-#if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
-# define USE_POLL
-# ifdef HAVE_POLL_H
-# include <poll.h>
-# else
-# include <sys/poll.h>
-# endif
-# if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
-# define USE_LINUX_SIGIO
-# include <signal.h>
-# endif
-#endif
-#ifdef _WIN32
-# define HAVE_SELECT
-#endif
-#if defined HAVE_SELECT
-# ifdef _WIN32
-# include <winsock2.h>
-# endif
-# define USE_SELECT
-# ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-# endif
-#endif
-
-#if defined HAVE_SYS_DEVPOLL_H && defined(__sun)
-# define USE_SOLARIS_DEVPOLL
-# include <sys/devpoll.h>
-#endif
-
-#if defined HAVE_SYS_EVENT_H && defined HAVE_KQUEUE
-# define USE_FREEBSD_KQUEUE
-# include <sys/event.h>
-#endif
-
-#if defined HAVE_SYS_PORT_H && defined HAVE_PORT_CREATE
-# define USE_SOLARIS_PORT
-# include <sys/port.h>
-#endif
-
-
-typedef handler_t (*fdevent_handler)(void *srv, void *ctx, int revents);
-
-#define FDEVENT_IN BV(0)
-#define FDEVENT_PRI BV(1)
-#define FDEVENT_OUT BV(2)
-#define FDEVENT_ERR BV(3)
-#define FDEVENT_HUP BV(4)
-#define FDEVENT_NVAL BV(5)
-
-typedef enum { FD_EVENT_TYPE_UNSET = -1,
- FD_EVENT_TYPE_CONNECTION,
- FD_EVENT_TYPE_FCGI_CONNECTION,
- FD_EVENT_TYPE_DIRWATCH,
- FD_EVENT_TYPE_CGI_CONNECTION
-} fd_event_t;
-
-typedef enum { FDEVENT_HANDLER_UNSET,
- FDEVENT_HANDLER_SELECT,
- FDEVENT_HANDLER_POLL,
- FDEVENT_HANDLER_LINUX_RTSIG,
- FDEVENT_HANDLER_LINUX_SYSEPOLL,
- FDEVENT_HANDLER_SOLARIS_DEVPOLL,
- FDEVENT_HANDLER_FREEBSD_KQUEUE,
- FDEVENT_HANDLER_SOLARIS_PORT
-} fdevent_handler_t;
-
-/**
- * a mapping from fd to connection structure
- *
- */
-typedef struct {
- int fd; /**< the fd */
- void *conn; /**< a reference the corresponding data-structure */
- fd_event_t fd_type; /**< type of the fd */
- int events; /**< registered events */
- int revents;
-} fd_conn;
-
-ARRAY_STATIC_DEF(fd_conn_buffer, fd_conn, );
-
-/**
- * revents
- */
-typedef struct {
- int fd;
- int revents;
-
- fdevent_handler handler;
- void *context;
-} fdevent_revent;
-
-ARRAY_STATIC_DEF(fdevent_revents, fdevent_revent, );
-
-/**
- * array of unused fd's
- *
- */
-
-typedef struct _fdnode {
- fdevent_handler handler; /* who handles the events for this fd */
- void *ctx; /* opaque pointer which is passed as 3rd parameter to the handler */
- int fd; /* fd */
-
- struct _fdnode *prev, *next;
-} fdnode;
-
-typedef struct {
- int *ptr;
-
- size_t used;
- size_t size;
-} buffer_int;
-
-/**
- * fd-event handler for select(), poll() and rt-signals on Linux 2.4
- *
- */
-typedef struct fdevents {
- fdevent_handler_t type;
-
- fdnode **fdarray; /* a list of fdnodes */
- size_t maxfds;
-
-#ifdef USE_LINUX_SIGIO
- int in_sigio;
- int signum;
- sigset_t sigset;
- siginfo_t siginfo;
- bitset *sigbset;
-#endif
-#ifdef USE_LINUX_EPOLL
- int epoll_fd;
- struct epoll_event *epoll_events;
-#endif
-#ifdef USE_POLL
- struct pollfd *pollfds;
-
- size_t size;
- size_t used;
-
- buffer_int unused;
-#endif
-#ifdef USE_SELECT
- /* Temporary sets, cloned from permanent sets, and passed to select() */
- fd_set select_read;
- fd_set select_write;
- fd_set select_error;
-
- /* Permanent sets */
- fd_set select_set_read;
- fd_set select_set_write;
- fd_set select_set_error;
-
- /* Since windows socket IDs are as good as unpredictable, we need to keep track of each one.
- *nix socket IDs start at zero for each process and are reused throughout the life of the process. */
-#ifdef _WIN32
- /* We could simply use select_set_error, because that is currently always inclusive,
- but better to keep it separate. */
- fd_set select_set_all;
-#else
- int select_max_fd;
-#endif
-#endif
-
-
-#ifdef USE_SOLARIS_DEVPOLL
- int devpoll_fd;
- struct pollfd *devpollfds;
-#endif
-#ifdef USE_FREEBSD_KQUEUE
- int kq_fd;
- struct kevent *kq_results;
- bitset *kq_read_bevents;
- bitset *kq_write_bevents;
-#endif
-#ifdef USE_SOLARIS_PORT
- int port_fd;
-#endif
- int (*reset)(struct fdevents *ev);
- void (*free)(struct fdevents *ev);
-
- int (*event_add)(struct fdevents *ev, iosocket *sock, int events);
- int (*event_del)(struct fdevents *ev, iosocket *sock);
- int (*get_revents)(struct fdevents *ev, size_t event_count, fdevent_revents *revents);
-
- int (*poll)(struct fdevents *ev, int timeout_ms);
-
- int (*fcntl_set)(struct fdevents *ev, int fd);
-} fdevents;
-
-typedef struct {
- fdevent_handler_t type;
- const char *name;
- const char *description;
- int (*init)(fdevents *ev);
-} fdevent_handler_info_t;
-
-LI_API const fdevent_handler_info_t *fdevent_get_handlers();
-LI_API const fdevent_handler_info_t *fdevent_get_defaulthandler();
-LI_API const fdevent_handler_info_t *fdevent_get_handler_info_by_type(fdevent_handler_t type);
-LI_API const fdevent_handler_info_t *fdevent_get_handler_info_by_name(const char *name);
-
-LI_API fdevents* fdevent_init(size_t maxfds, fdevent_handler_t type);
-LI_API int fdevent_reset(fdevents *ev);
-LI_API void fdevent_free(fdevents *ev);
-
-/**
- * call the plugin for the number of available events
- */
-LI_API int fdevent_poll(fdevents *ev, int timeout_ms);
-/**
- * get all available events
- */
-LI_API int fdevent_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents);
-
-/**
- * add or remove a fd to the handled-pool
- */
-LI_API int fdevent_register(fdevents *ev, iosocket *sock, fdevent_handler handler, void *ctx);
-LI_API int fdevent_unregister(fdevents *ev, iosocket *sock);
-
-/**
- * add a event to a registered fd
- */
-LI_API int fdevent_event_add(fdevents *ev, iosocket *sock, int events);
-LI_API int fdevent_event_del(fdevents *ev, iosocket *sock);
-
-/**
- * set non-blocking
- */
-LI_API int fdevent_fcntl_set(fdevents *ev, iosocket *sock);
-
-LI_API fdevent_revents* fdevent_revents_init(void);
-LI_API void fdevent_revents_reset(fdevent_revents *revents);
-LI_API void fdevent_revents_add(fdevent_revents *revents, int fd, int events);
-LI_API void fdevent_revents_free(fdevent_revents *revents);
-
-LI_API fdevent_revent* fdevent_revent_init(void);
-LI_API void fdevent_revent_free(fdevent_revent *revent);
-
-
-/**
- * plugin init
- */
-LI_API int fdevent_select_init(fdevents *ev);
-LI_API int fdevent_poll_init(fdevents *ev);
-LI_API int fdevent_linux_rtsig_init(fdevents *ev);
-LI_API int fdevent_linux_sysepoll_init(fdevents *ev);
-LI_API int fdevent_solaris_devpoll_init(fdevents *ev);
-LI_API int fdevent_freebsd_kqueue_init(fdevents *ev);
-
-#endif
-
-
-
diff --git a/src/fdevent_freebsd_kqueue.c b/src/fdevent_freebsd_kqueue.c
deleted file mode 100644
index 64af9a91..00000000
--- a/src/fdevent_freebsd_kqueue.c
+++ /dev/null
@@ -1,221 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-
-#include "server.h"
-#include "fdevent.h"
-#include "settings.h"
-#include "buffer.h"
-
-#ifdef USE_FREEBSD_KQUEUE
-#include <sys/event.h>
-#include <sys/time.h>
-
-#include "sys-files.h"
-#include "log.h"
-
-static int fdevent_freebsd_kqueue_event_add(fdevents *ev, iosocket *sock, int events);
-
-static void fdevent_freebsd_kqueue_free(fdevents *ev) {
- close(ev->kq_fd);
- free(ev->kq_results);
- bitset_free(ev->kq_read_bevents);
- bitset_free(ev->kq_write_bevents);
-}
-
-static int fdevent_freebsd_kqueue_event_del(fdevents *ev, iosocket *sock) {
- int ret;
-
- if (sock->fde_ndx < 0) return -1;
-
- /* delete events */
- ret = fdevent_freebsd_kqueue_event_add(ev, sock, 0);
- sock->fde_ndx = -1;
- return 0;
-}
-
-static int fdevent_freebsd_kqueue_event_add(fdevents *ev, iosocket *sock, int events) {
- int ret;
- struct kevent kev[2];
- struct timespec ts;
- int nchanges = 0;
- int changed_events = 0;
-
- if (bitset_test_bit(ev->kq_read_bevents, sock->fd)) {
- changed_events |= FDEVENT_IN;
- }
- if (bitset_test_bit(ev->kq_write_bevents, sock->fd)) {
- changed_events |= FDEVENT_OUT;
- }
- /* use XOR on changed_events and events to see which events changed. */
- changed_events ^= events;
-
- if (changed_events & FDEVENT_IN) {
- /* add/delete FDEVENT_IN */
- if (events & FDEVENT_IN) {
- /* add */
- EV_SET(&(kev[nchanges]), sock->fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
- nchanges++;
- bitset_set_bit(ev->kq_read_bevents, sock->fd);
- } else {
- /* delete */
- EV_SET(&(kev[nchanges]), sock->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
- nchanges++;
- bitset_clear_bit(ev->kq_read_bevents, sock->fd);
- }
- }
-
- if (changed_events & FDEVENT_OUT) {
- /* add/delete FDEVENT_OUT */
- if (events & FDEVENT_OUT) {
- /* add */
- EV_SET(&(kev[nchanges]), sock->fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
- nchanges++;
- bitset_set_bit(ev->kq_write_bevents, sock->fd);
- } else {
- /* delete */
- EV_SET(&(kev[nchanges]), sock->fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
- nchanges++;
- bitset_clear_bit(ev->kq_write_bevents, sock->fd);
- }
- }
-
- if (nchanges == 0) return 0;
-
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
-
- ret = kevent(ev->kq_fd,
- kev, nchanges,
- NULL, 0,
- &ts);
-
- if (ret == -1) {
- ERROR("kqueue failed polling: %s\n", strerror(errno));
-
- return -1;
- }
-
- sock->fde_ndx = sock->fd;
-
- return 0;
-}
-
-static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) {
- int ret;
- struct timespec ts;
-
- ts.tv_sec = timeout_ms / 1000;
- ts.tv_nsec = (timeout_ms % 1000) * 1000000;
-
- ret = kevent(ev->kq_fd,
- NULL, 0,
- ev->kq_results, ev->maxfds,
- &ts);
-
- if (ret == -1) {
- switch(errno) {
- case EINTR:
- /* we got interrupted, perhaps just a SIGCHLD of a CGI script */
- return 0;
- default:
- fprintf(stderr, "%s.%d: kqueue failed polling: %s\n",
- __FILE__, __LINE__, strerror(errno));
- break;
- }
- }
-
- return ret;
-}
-
-static int fdevent_freebsd_kqueue_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
- size_t ndx;
-
- for (ndx = 0; ndx < event_count; ndx++) {
- int events = 0, e;
-
- e = ev->kq_results[ndx].filter;
-
- if (e == EVFILT_READ) {
- events |= FDEVENT_IN;
- } else if (e == EVFILT_WRITE) {
- events |= FDEVENT_OUT;
- }
-
- e = ev->kq_results[ndx].flags;
-
- if (e & EV_EOF) {
- events |= FDEVENT_HUP;
- }
-
- if (e & EV_ERROR) {
- events |= FDEVENT_ERR;
- }
-
- fdevent_revents_add(revents, ev->kq_results[ndx].ident, events);
- }
-
- return 0;
-}
-
-static int fdevent_freebsd_kqueue_reset(fdevents *ev) {
- if (-1 == (ev->kq_fd = kqueue())) {
- fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__, strerror(errno));
-
- return -1;
- }
-
- return 0;
-}
-
-
-int fdevent_freebsd_kqueue_init(fdevents *ev) {
- ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
-#define SET(x) \
- ev->x = fdevent_freebsd_kqueue_##x;
-
- SET(free);
- SET(poll);
- SET(reset);
-
- SET(event_del);
- SET(event_add);
-
- SET(get_revents);
-
- ev->kq_fd = -1;
-
- ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results));
- ev->kq_read_bevents = bitset_init(ev->maxfds);
- ev->kq_write_bevents = bitset_init(ev->maxfds);
-
- /* check that kqueue works */
-
- if (-1 == (ev->kq_fd = kqueue())) {
- fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__, strerror(errno));
-
- return -1;
- }
-
- close(ev->kq_fd);
- ev->kq_fd = -1;
-
- return 0;
-}
-#else
-int fdevent_freebsd_kqueue_init(fdevents *ev) {
- UNUSED(ev);
-
- fprintf(stderr, "%s.%d: kqueue not available, try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__);
-
- return -1;
-}
-#endif
diff --git a/src/fdevent_linux_rtsig.c b/src/fdevent_linux_rtsig.c
deleted file mode 100644
index 95bebf2a..00000000
--- a/src/fdevent_linux_rtsig.c
+++ /dev/null
@@ -1,235 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <limits.h>
-
-#ifndef _GNU_SOURCE
-/* seems we dont need this when using _GNU_SOURCE
- * #define __USE_GNU
- */
-#define __USE_GNU
-#endif
-#include <fcntl.h>
-
-#include "fdevent.h"
-#include "settings.h"
-#include "buffer.h"
-#include "sys-process.h"
-#include "log.h"
-
-#ifdef USE_LINUX_SIGIO
-static void fdevent_linux_rtsig_free(fdevents *ev) {
- free(ev->pollfds);
- if (ev->unused.ptr) free(ev->unused.ptr);
-
- bitset_free(ev->sigbset);
-}
-
-
-static int fdevent_linux_rtsig_event_del(fdevents *ev, iosocket *sock) {
- if (sock->fde_ndx < 0) return -1;
-
- if ((size_t)sock->fde_ndx >= ev->used) {
- SEGFAULT("del! out of range %d %zu", sock->fde_ndx, ev->used);
- }
-
- if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
- size_t k = sock->fde_ndx;
-
- ev->pollfds[k].fd = -1;
-
- bitset_clear_bit(ev->sigbset, sock->fd);
-
- if (ev->unused.size == 0) {
- ev->unused.size = 16;
- ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
- } else if (ev->unused.size == ev->unused.used) {
- ev->unused.size += 16;
- ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
- }
-
- ev->unused.ptr[ev->unused.used++] = k;
- } else {
- SEGFAULT("del! %d %d", ev->pollfds[sock->fde_ndx].fd, sock->fd);
- }
- sock->fde_ndx = -1;
-
- return 0;
-}
-
-#if 0
-static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
- size_t j;
-
- if (ev->used == 0) return 0;
- if (ev->unused.used != 0) return 0;
-
- for (j = ev->used - 1; j + 1 > 0; j--) {
- if (ev->pollfds[j].fd == -1) ev->used--;
- }
-
-
- return 0;
-}
-#endif
-
-static int fdevent_linux_rtsig_event_add(fdevents *ev, iosocket *sock, int events) {
- /* known index */
- if (sock->fde_ndx != -1) {
- if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
- ev->pollfds[sock->fde_ndx].events = events;
-
- return sock->fde_ndx;
- }
- SEGFAULT("add: (%d, %d)", sock->fde_ndx, ev->pollfds[sock->fde_ndx].fd);
- }
-
- if (ev->unused.used > 0) {
- int k = ev->unused.ptr[--ev->unused.used];
-
- ev->pollfds[k].fd = sock->fd;
- ev->pollfds[k].events = events;
-
- bitset_set_bit(ev->sigbset, sock->fd);
-
- return k;
- } else {
- if (ev->size == 0) {
- ev->size = 16;
- ev->pollfds = malloc(sizeof(*ev->pollfds) * ev->size);
- } else if (ev->size == ev->used) {
- ev->size += 16;
- ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
- }
-
- ev->pollfds[ev->used].fd = sock->fd;
- ev->pollfds[ev->used].events = events;
-
- bitset_set_bit(ev->sigbset, sock->fd);
-
- return ev->used++;
- }
-}
-
-static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
- struct timespec ts;
- int r;
-
-#if 0
- fdevent_linux_rtsig_event_compress(ev);
-#endif
-
- ev->in_sigio = 1;
-
- ts.tv_sec = timeout_ms / 1000;
- ts.tv_nsec = (timeout_ms % 1000) * 1000000;
- r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
-
- if (r == -1) {
- if (errno == EAGAIN) return 0;
- return r;
- } else if (r == SIGIO) {
- struct sigaction act;
-
- /* flush the signal queue */
- memset(&act, 0, sizeof(act));
- act.sa_handler = SIG_IGN;
- sigaction(ev->signum, &act, NULL);
-
- /* re-enable the signal queue */
- act.sa_handler = SIG_DFL;
- sigaction(ev->signum, &act, NULL);
-
- ev->in_sigio = 0;
- r = poll(ev->pollfds, ev->used, timeout_ms);
-
- return r;
- } else if (r == ev->signum) {
-# if 0
- fprintf(stderr, "event: %d %02lx\n", ev->siginfo.si_fd, ev->siginfo.si_band);
-# endif
- return bitset_test_bit(ev->sigbset, ev->siginfo.si_fd);
- } else {
- /* ? */
- return -1;
- }
-}
-
-static int fdevent_linux_rtsig_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
- UNUSED(event_count);
-
- if (ev->in_sigio == 1) {
- /* only one event */
-
- fdevent_revents_add(revents, ev->siginfo.si_fd, ev->siginfo.si_band & 0x3f);
- } else {
- size_t ndx;
-
- for (ndx = 0; ndx < ev->used; ndx++) {
- if (ev->pollfds[ndx].revents) {
- fdevent_revents_add(revents, ev->pollfds[ndx].fd, ev->pollfds[ndx].revents);
- }
- }
- }
-
- return 0;
-}
-
-static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
- static pid_t pid = 0;
-
- if (pid == 0) pid = getpid();
-
- if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
-
- if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
-
- return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
-}
-
-
-int fdevent_linux_rtsig_init(fdevents *ev) {
- ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
-#define SET(x) \
- ev->x = fdevent_linux_rtsig_##x;
-
- SET(free);
- SET(poll);
-
- SET(event_del);
- SET(event_add);
-
- SET(fcntl_set);
- SET(get_revents);
-
- ev->signum = SIGRTMIN + 1;
-
- sigemptyset(&(ev->sigset));
- sigaddset(&(ev->sigset), ev->signum);
- sigaddset(&(ev->sigset), SIGIO);
- if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
- fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__, strerror(errno));
-
- return -1;
- }
-
- ev->in_sigio = 1;
-
- ev->sigbset = bitset_init(ev->maxfds);
-
- return 0;
-}
-#else
-int fdevent_linux_rtsig_init(fdevents *ev) {
- UNUSED(ev);
-
- fprintf(stderr, "%s.%d: linux-rtsig not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__);
- return -1;
-}
-#endif
diff --git a/src/fdevent_linux_sysepoll.c b/src/fdevent_linux_sysepoll.c
deleted file mode 100644
index 24a6cc9e..00000000
--- a/src/fdevent_linux_sysepoll.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-
-#include "fdevent.h"
-#include "settings.h"
-#include "buffer.h"
-#include "log.h"
-
-#include "sys-files.h"
-
-#ifdef USE_LINUX_EPOLL
-static void fdevent_linux_sysepoll_free(fdevents *ev) {
- close(ev->epoll_fd);
- free(ev->epoll_events);
-}
-
-static int fdevent_linux_sysepoll_event_del(fdevents *ev, iosocket *sock) {
- struct epoll_event ep;
-
- if (sock->fde_ndx < 0) return -1;
-
- memset(&ep, 0, sizeof(ep));
-
- ep.data.fd = sock->fd;
- ep.data.ptr = NULL;
-
- if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, sock->fd, &ep)) {
- SEGFAULT("epoll_ctl (del) failed on fd=%d: %s", sock->fd, strerror(errno));
-
- return 0;
- }
-
- sock->fde_ndx = -1;
-
- return 0;
-}
-
-static int fdevent_linux_sysepoll_event_add(fdevents *ev, iosocket *sock, int events) {
- struct epoll_event ep;
- int add = 0;
-
- /* a new fd */
- if (sock->fde_ndx == -1) add = 1;
-
- memset(&ep, 0, sizeof(ep));
-
- ep.events = 0;
-
- if (events & FDEVENT_IN) ep.events |= EPOLLIN;
- if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
-
- /**
- *
- * with EPOLLET we don't get a FDEVENT_HUP
- * if the close is delay after everything has
- * sent.
- *
- */
-
- ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
-
- ep.data.ptr = NULL;
- ep.data.fd = sock->fd;
-
- if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, sock->fd, &ep)) {
- SEGFAULT("epoll_ctl (add/mod) failed on fd=%d: %s", sock->fd, strerror(errno));
-
- return 0;
- }
-
- sock->fde_ndx = sock->fd;
-
- return 0;
-}
-
-static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) {
- return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
-}
-
-static int fdevent_linux_sysepoll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
- size_t ndx;
-
- for (ndx = 0; ndx < event_count; ndx++) {
- int events = 0, e;
-
- e = ev->epoll_events[ndx].events;
- if (e & EPOLLIN) events |= FDEVENT_IN;
- if (e & EPOLLOUT) events |= FDEVENT_OUT;
- if (e & EPOLLERR) events |= FDEVENT_ERR;
- if (e & EPOLLHUP) events |= FDEVENT_HUP;
- if (e & EPOLLPRI) events |= FDEVENT_PRI;
-
- fdevent_revents_add(revents, ev->epoll_events[ndx].data.fd, events);
- }
-
- return 0;
-}
-
-int fdevent_linux_sysepoll_init(fdevents *ev) {
- ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
-#define SET(x) \
- ev->x = fdevent_linux_sysepoll_##x;
-
- SET(free);
- SET(poll);
-
- SET(event_del);
- SET(event_add);
-
- SET(get_revents);
-
- if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
- ERROR("epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"",
- strerror(errno));
-
- return -1;
- }
-
- if (-1 == fcntl(ev->epoll_fd, F_SETFD, FD_CLOEXEC)) {
- ERROR("fcntl after epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"",
- strerror(errno));
-
- close(ev->epoll_fd);
-
- return -1;
- }
-
- ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events));
-
- return 0;
-}
-
-#else
-int fdevent_linux_sysepoll_init(fdevents *ev) {
- UNUSED(ev);
-
- ERROR("event-handler 'linux-sysepoll' is not supported, try to set server.event-handler = \"%s\" or \"%s\"", "select", "poll");
-
- return -1;
-}
-#endif
diff --git a/src/fdevent_poll.c b/src/fdevent_poll.c
deleted file mode 100644
index ebf149c7..00000000
--- a/src/fdevent_poll.c
+++ /dev/null
@@ -1,153 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-
-#include "fdevent.h"
-#include "settings.h"
-#include "buffer.h"
-#include "log.h"
-
-#ifdef USE_POLL
-static void fdevent_poll_free(fdevents *ev) {
- free(ev->pollfds);
- if (ev->unused.ptr) free(ev->unused.ptr);
-}
-
-static int fdevent_poll_event_del(fdevents *ev, iosocket *sock) {
- if (sock->fde_ndx < 0) return -1;
-
- if ((size_t)sock->fde_ndx >= ev->used) {
- SEGFAULT("(fdevent-poll-del) out of range %d %zd", sock->fde_ndx, ev->used);
- }
-
- if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
- size_t k = sock->fde_ndx;
-
- ev->pollfds[k].fd = -1;
- /* ev->pollfds[k].events = 0; */
- /* ev->pollfds[k].revents = 0; */
-
- if (ev->unused.size == 0) {
- ev->unused.size = 16;
- ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
- } else if (ev->unused.size == ev->unused.used) {
- ev->unused.size += 16;
- ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
- }
-
- ev->unused.ptr[ev->unused.used++] = k;
- } else {
- SEGFAULT("(fdevent-poll-del) sock->fde_ndx: %d, sock->fd: %d -> stored fd: %d", sock->fde_ndx, sock->fd, ev->pollfds[sock->fde_ndx].fd);
- }
-
- sock->fde_ndx = -1;
-
- return 0;
-}
-
-#if 0
-static int fdevent_poll_event_compress(fdevents *ev) {
- size_t j;
-
- if (ev->used == 0) return 0;
- if (ev->unused.used != 0) return 0;
-
- for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
-
- return 0;
-}
-#endif
-
-static int fdevent_poll_event_add(fdevents *ev, iosocket *sock, int events) {
- if (sock->fde_ndx != -1) {
- /* this fd was already added, just change the requested events */
-
- if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
- ev->pollfds[sock->fde_ndx].events = events;
-
- return sock->fde_ndx;
- }
- SEGFAULT("(fdevent-poll-add) (%d, %d)", sock->fde_ndx, ev->pollfds[sock->fde_ndx].fd);
- }
-
- if (ev->unused.used > 0) {
- int k = ev->unused.ptr[--ev->unused.used];
-
- ev->pollfds[k].fd = sock->fd;
- ev->pollfds[k].events = events;
-
- sock->fde_ndx = k;
-
- } else {
- if (ev->size == 0) {
- ev->size = 16;
- ev->pollfds = malloc(sizeof(*ev->pollfds) * ev->size);
- } else if (ev->size == ev->used) {
- ev->size += 16;
- ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
- }
-
- ev->pollfds[ev->used].fd = sock->fd;
- ev->pollfds[ev->used].events = events;
-
- sock->fde_ndx = ev->used++;
- }
- return 0;
-}
-
-static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
-#if 0
- fdevent_poll_event_compress(ev);
-#endif
- return poll(ev->pollfds, ev->used, timeout_ms);
-}
-
-static int fdevent_poll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
- size_t ndx;
-
- UNUSED(event_count);
-
- for (ndx = 0; ndx < ev->used; ndx++) {
- if (ev->pollfds[ndx].revents) {
- if (ev->pollfds[ndx].revents & POLLNVAL) {
- /* should never happen */
- SEGFAULT("ev->pollfds[%zu].revents has POLLNVAL", ndx);
- }
-
- fdevent_revents_add(revents, ev->pollfds[ndx].fd, ev->pollfds[ndx].revents);
- }
- }
-
- return 0;
-}
-
-int fdevent_poll_init(fdevents *ev) {
- ev->type = FDEVENT_HANDLER_POLL;
-#define SET(x) \
- ev->x = fdevent_poll_##x;
-
- SET(free);
- SET(poll);
-
- SET(event_del);
- SET(event_add);
-
- SET(get_revents);
-
- return 0;
-}
-
-#else
-int fdevent_poll_init(fdevents *ev) {
- UNUSED(ev);
-
- ERROR("event-handler 'poll' is not supported, try to set server.event-handler = \"%s\"", "select");
-
- return -1;
-}
-#endif
diff --git a/src/fdevent_select.c b/src/fdevent_select.c
deleted file mode 100644
index 66997da6..00000000
--- a/src/fdevent_select.c
+++ /dev/null
@@ -1,166 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "fdevent.h"
-#include "settings.h"
-#include "buffer.h"
-
-#include "sys-socket.h"
-
-#ifdef HAVE_SYS_TIME_H
-/* struct timeval tv needs it on IRIX + MIPS pro*/
-#include <sys/time.h>
-#endif
-
-#ifdef USE_SELECT
-
-static int fdevent_select_reset(fdevents *ev) {
- FD_ZERO(&(ev->select_set_read));
- FD_ZERO(&(ev->select_set_write));
- FD_ZERO(&(ev->select_set_error));
-#ifdef _WIN32
- FD_ZERO(&(ev->select_set_all));
-#endif
-#ifndef _WIN32
- ev->select_max_fd = -1;
-#endif
-
- return 0;
-}
-
-static int fdevent_select_event_del(fdevents *ev, iosocket *sock) {
- if (sock->fde_ndx < 0) return -1;
-
- FD_CLR(sock->fd, &(ev->select_set_read));
- FD_CLR(sock->fd, &(ev->select_set_write));
- FD_CLR(sock->fd, &(ev->select_set_error));
-#ifdef _WIN32
- FD_CLR(sock->fd, &(ev->select_set_all));
-#endif
-
- /* mark the fdevent as deleted */
- sock->fde_ndx = -1;
-
- return 0;
-}
-
-static int fdevent_select_event_add(fdevents *ev, iosocket *sock, int events) {
- /* we should be protected by max-fds, but you never know */
-#ifndef _WIN32
- assert(sock->fd < ((int)FD_SETSIZE));
-#endif
-
- if (events & FDEVENT_IN) {
- FD_SET(sock->fd, &(ev->select_set_read));
- FD_CLR(sock->fd, &(ev->select_set_write));
- }
- if (events & FDEVENT_OUT) {
- FD_CLR(sock->fd, &(ev->select_set_read));
- FD_SET(sock->fd, &(ev->select_set_write));
- }
- FD_SET(sock->fd, &(ev->select_set_error));
-
- /* we need this for the poll */
-#ifdef _WIN32
- FD_SET(sock->fd, &(ev->select_set_all));
-#else
- if (sock->fd > ev->select_max_fd) ev->select_max_fd = sock->fd;
-#endif
-
- /* mark fd as added */
- sock->fde_ndx = sock->fd;
-
- return 0;
-}
-
-static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
- struct timeval tv;
-#ifndef _WIN32
- int max_ev = ev->select_max_fd + 1;
-#else
- // windows ignores this
- int max_ev = 0;
-#endif
-
- tv.tv_sec = timeout_ms / 1000;
- tv.tv_usec = (timeout_ms % 1000) * 1000;
-
- ev->select_read = ev->select_set_read;
- ev->select_write = ev->select_set_write;
- ev->select_error = ev->select_set_error;
-
- return select(max_ev, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
-}
-
-/**
- * scan the fdset for events
- */
-static int fdevent_select_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
-
- int ndx = 0;
-#ifndef _WIN32
- int top = ev->select_max_fd + 1;
-#else
- int top = ev->select_set_all.fd_count; // FD_SETSIZE;
-#endif
-
- UNUSED(event_count);
-
- for (ndx = 0; ndx < top; ndx++) {
- int events = 0;
-
-#ifdef _WIN32
- int fdx = ev->select_set_all.fd_array[ndx];
- if ( fdx <= 0 ) continue;
-#else
- int fdx = ndx;
-#endif
-
- if (FD_ISSET(fdx, &(ev->select_read))) {
- events |= FDEVENT_IN;
- }
- if (FD_ISSET(fdx, &(ev->select_write))) {
- events |= FDEVENT_OUT;
- }
- if (FD_ISSET(fdx, &(ev->select_error))) {
- events |= FDEVENT_ERR;
- }
-
- if (events) {
- fdevent_revents_add(revents, fdx, events);
- }
- }
-
- return 0;
-}
-
-int fdevent_select_init(fdevents *ev) {
- ev->type = FDEVENT_HANDLER_SELECT;
-#define SET(x) \
- ev->x = fdevent_select_##x;
-
- SET(reset);
- SET(poll);
-
- SET(event_del);
- SET(event_add);
-
- SET(get_revents);
-
- return 0;
-}
-
-#else
-int fdevent_select_init(fdevents *ev) {
- UNUSED(ev);
-
- return -1;
-}
-#endif
diff --git a/src/fdevent_solaris_devpoll.c b/src/fdevent_solaris_devpoll.c
deleted file mode 100644
index 60364230..00000000
--- a/src/fdevent_solaris_devpoll.c
+++ /dev/null
@@ -1,181 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-
-#include "fdevent.h"
-#include "settings.h"
-#include "buffer.h"
-#include "log.h"
-
-#ifdef USE_SOLARIS_DEVPOLL
-#include <unistd.h>
-
-static void fdevent_solaris_devpoll_free(fdevents *ev) {
- free(ev->devpollfds);
- close(ev->devpoll_fd);
-}
-
-/* return -1 is fine here */
-
-static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
- struct pollfd pfd;
-
- if (fde_ndx < 0) return -1;
-
- pfd.fd = fd;
- pfd.events = POLLREMOVE;
- pfd.revents = 0;
-
- if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
- fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
- __FILE__, __LINE__,
- fd, strerror(errno));
-
- return -1;
- }
-
- return -1;
-}
-
-static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
- struct pollfd pfd;
- int add = 0;
-
- if (fde_ndx == -1) add = 1;
-
- pfd.fd = fd;
- pfd.events = events;
- pfd.revents = 0;
-
- if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
- fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
- __FILE__, __LINE__,
- fd, strerror(errno));
-
- return -1;
- }
-
- return fd;
-}
-
-static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
- struct dvpoll dopoll;
- int ret;
-
- dopoll.dp_timeout = timeout_ms;
- dopoll.dp_nfds = ev->maxfds - 1;
- dopoll.dp_fds = ev->devpollfds;
-
- ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
-
- return ret;
-}
-
-static int fdevent_solaris_devpoll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
- size_t ndx;
-
- for (ndx = 0; ndx < event_count; ndx++) {
- if (ev->devpollfds[ndx].revents) {
- if (ev->devpollfds[ndx].revents & POLLNVAL) {
- /* should never happen */
- SEGFAULT("ev->devpollfds[%d].revents = %d (POLLNVAL)", ndx, ev->devpollfds[ndx].revents);
- }
-
- fdevent_revents_add(revents, ev->devpollfds[ndx].fd, ev->devpollfds[ndx].revents);
- }
- }
-
- return 0;
-}
-
-#if 0
-static int fdevent_solaris_devpoll_event_get_revent(fdevents *ev, size_t ndx) {
- return ev->devpollfds[ndx].revents;
-}
-
-static int fdevent_solaris_devpoll_event_get_fd(fdevents *ev, size_t ndx) {
- return ev->devpollfds[ndx].fd;
-}
-
-static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
- size_t i;
-
- UNUSED(ev);
-
- i = (last_ndx < 0) ? 0 : last_ndx + 1;
-
- return i;
-}
-#endif
-
-int fdevent_solaris_devpoll_reset(fdevents *ev) {
- /* a forked process does only inherit the filedescriptor,
- * but every operation on the device will lead to a EACCES */
- if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
- fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__, strerror(errno));
-
- return -1;
- }
-
- if (fcntl(ev->devpoll_fd, F_SETFD, FD_CLOEXEC) < 0) {
- fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__, strerror(errno));
-
- close(ev->devpoll_fd);
-
- return -1;
- }
- return 0;
-}
-int fdevent_solaris_devpoll_init(fdevents *ev) {
- ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
-#define SET(x) \
- ev->x = fdevent_solaris_devpoll_##x;
-
- SET(free);
- SET(poll);
- SET(reset);
-
- SET(event_del);
- SET(event_add);
-
-#if 0
- SET(event_next_fdndx);
- SET(event_get_fd);
- SET(event_get_revent);
-#endif
- SET(get_revents);
-
- ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
-
- if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
- fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__, strerror(errno));
-
- return -1;
- }
-
- /* we just wanted to check if it works */
- close(ev->devpoll_fd);
-
- ev->devpoll_fd = -1;
-
- return 0;
-}
-
-#else
-int fdevent_solaris_devpoll_init(fdevents *ev) {
- UNUSED(ev);
-
- fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
- __FILE__, __LINE__);
-
- return -1;
-}
-#endif
diff --git a/src/filter.c b/src/filter.c
deleted file mode 100644
index efb5eb65..00000000
--- a/src/filter.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * the network filter-API
- *
- *
- */
-
-#include <stdlib.h>
-
-#include <string.h>
-#include <assert.h>
-
-#include "filter.h"
-
-/**
- * create the filter
- *
- * each filter has a chunkqueue with content and
- * a prev and a next pointer
- */
-static filter *filter_init(void) {
- filter *fl;
-
- fl = calloc(1, sizeof(*fl));
-
- fl->next = NULL;
- fl->prev = NULL;
-
- fl->cq = chunkqueue_init();
-
- return fl;
-}
-
-/**
- * free the filter
- */
-static void filter_free(filter *fl) {
- filter *next, *prev;
-
- /* free chunkqueue */
- if(fl->cq) {
- chunkqueue_free(fl->cq);
- }
-
- /* remove this filter from chain. */
- next = fl->next;
- prev = fl->prev;
-
- if(next) {
- next->prev = prev;
- }
- if(prev) {
- prev->next = next;
- }
-
- free(fl);
-}
-
-/**
- * reset the filter
- */
-static void filter_reset(filter *fl) {
- /* reset chunkqueue */
- if(fl->cq) {
- chunkqueue_reset(fl->cq);
- } else {
- fl->cq = chunkqueue_init();
- }
-}
-
-/**
- * create a filter chain
- */
-filter_chain *filter_chain_init(void) {
- filter_chain *chain;
-
- chain = calloc(1, sizeof(*chain));
-
- chain->first = NULL;
- chain->last = NULL;
- filter_chain_create_filter(chain, FILTER_ID_INPUT);
-
- return chain;
-}
-
-void filter_chain_free(filter_chain *chain) {
- filter *first;
- if (!chain) return;
-
- /* free all filters, after the first filter */
- first = chain->first;
- while(first->next) {
- filter_free(first->next);
- }
- /* free first filter */
- filter_free(first);
-
- free(chain);
-}
-
-void filter_chain_reset(filter_chain *chain) {
- filter *first;
- if (!chain) return;
-
- /* free all filters, except first filter */
- first = chain->first;
- while(first->next) {
- filter_free(first->next);
- }
- /* reset first filter */
- filter_reset(first);
- chain->last = first;
-}
-
-filter *filter_chain_create_filter(filter_chain *chain, int id) {
- filter *fl;
- if (!chain) return NULL;
-
- fl = filter_init();
- fl->id = id;
- /* add filter to end of chain. */
- if (chain->last != NULL) {
- chain->last->next = fl;
- }
- fl->prev = chain->last;
- chain->last = fl;
- if (chain->first == NULL) {
- chain->first = fl;
- }
-
- return fl;
-}
-
-filter *filter_chain_get_filter(filter_chain *chain, int id) {
- filter *fl;
- if (!chain) return NULL;
-
- /* find filter with id */
- fl = chain->first;
- while(fl) {
- if (fl->id == id) break;
- fl = fl->next;
- }
-
- return fl;
-}
-
-void filter_chain_remove_filter(filter_chain *chain, filter *fl) {
- if (!chain || !fl) return;
-
- if (chain->first == fl) {
- chain->first = fl->next;
- }
- if (chain->last == fl) {
- chain->last = fl->prev;
- }
- filter_free(fl);
-}
-
-/**
- * move all the content of the last filter to the chunk queue
- */
-off_t filter_chain_copy_output(filter_chain *chain, chunkqueue *out) {
- off_t total;
- chunkqueue *in;
-
- if (!chain || !out) return 0;
- if (out->is_closed) return 0;
-
- in = chain->last->cq;
- total = chunkqueue_steal_all_chunks(out, in);
- in->bytes_out += total;
- out->bytes_in += total;
-
- chunkqueue_remove_finished_chunks(in);
-
- if (in->is_closed) {
- out->is_closed = 1;
- }
-
- return total;
-}
-
diff --git a/src/filter.h b/src/filter.h
deleted file mode 100644
index 91749d42..00000000
--- a/src/filter.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _FILTER_H_
-#define _FILTER_H_
-
-#include "chunk.h"
-
-#define FILTER_ID_INPUT -1
-
-/*
- * The filter chain will always have an input filter to hold
- * the pre-filtered content. All other filters are added after
- * the last filter.
- *
- * Each filter uses the chunkqueue from the previous filter as
- * input and outputs to it's own chunkqueue.
- *
- */
-
-typedef struct filter {
- struct filter *prev;
- struct filter *next;
-
- int id; /* use plugin id */
- chunkqueue *cq; /* this filters output */
-} filter;
-
-typedef struct {
- filter *first;
- filter *last;
-
-} filter_chain;
-
-LI_API filter_chain * filter_chain_init(void);
-LI_API void filter_chain_free(filter_chain *chain);
-LI_API void filter_chain_reset(filter_chain *chain);
-
-LI_API filter * filter_chain_create_filter(filter_chain *chain, int id);
-LI_API filter * filter_chain_get_filter(filter_chain *chain, int id);
-LI_API void filter_chain_remove_filter(filter_chain *chain, filter *fl);
-
-LI_API off_t filter_chain_copy_output(filter_chain *chain, chunkqueue *out);
-
-#endif
diff --git a/src/http-header-glue.c b/src/http-header-glue.c
deleted file mode 100644
index a16eec49..00000000
--- a/src/http-header-glue.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-
-#include "base.h"
-#include "array.h"
-#include "buffer.h"
-#include "log.h"
-#include "etag.h"
-#include "response.h"
-
-/*
- * This was 'borrowed' from tcpdump.
- *
- *
- * This is fun.
- *
- * In older BSD systems, socket addresses were fixed-length, and
- * "sizeof (struct sockaddr)" gave the size of the structure.
- * All addresses fit within a "struct sockaddr".
- *
- * In newer BSD systems, the socket address is variable-length, and
- * there's an "sa_len" field giving the length of the structure;
- * this allows socket addresses to be longer than 2 bytes of family
- * and 14 bytes of data.
- *
- * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
- * variant of the old BSD scheme (with "struct sockaddr_storage" rather
- * than "struct sockaddr"), and some use the new BSD scheme.
- *
- * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
- * macro that determines the size based on the address family. Other
- * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
- * but not in the final version). On the latter systems, we explicitly
- * check the AF_ type to determine the length; we assume that on
- * all those systems we have "struct sockaddr_storage".
- */
-
-#ifdef HAVE_IPV6
-# ifndef SA_LEN
-# ifdef HAVE_SOCKADDR_SA_LEN
-# define SA_LEN(addr) ((addr)->sa_len)
-# else /* HAVE_SOCKADDR_SA_LEN */
-# ifdef HAVE_STRUCT_SOCKADDR_STORAGE
-static size_t get_sa_len(const struct sockaddr *addr) {
- switch (addr->sa_family) {
-
-# ifdef AF_INET
- case AF_INET:
- return (sizeof (struct sockaddr_in));
-# endif
-
-# ifdef AF_INET6
- case AF_INET6:
- return (sizeof (struct sockaddr_in6));
-# endif
-
- default:
- return (sizeof (struct sockaddr));
-
- }
-}
-# define SA_LEN(addr) (get_sa_len(addr))
-# else /* HAVE_SOCKADDR_STORAGE */
-# define SA_LEN(addr) (sizeof (struct sockaddr))
-# endif /* HAVE_SOCKADDR_STORAGE */
-# endif /* HAVE_SOCKADDR_SA_LEN */
-# endif /* SA_LEN */
-#endif
-
-
-
-
-int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
- data_string *ds;
-
- UNUSED(srv);
-
- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
- ds = data_response_init();
- }
- buffer_copy_string_len(ds->key, key, keylen);
- buffer_copy_string_len(ds->value, value, vallen);
-
- array_insert_unique(con->response.headers, (data_unset *)ds);
-
- return 0;
-}
-
-int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
- data_string *ds;
-
- UNUSED(srv);
-
- /* if there already is a key by this name overwrite the value */
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key, keylen))) {
- buffer_copy_string(ds->value, value);
-
- return 0;
- }
-
- return response_header_insert(srv, con, key, keylen, value, vallen);
-}
-
-
-int response_header_append(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
- data_string *ds;
-
- UNUSED(srv);
-
- /* if there already is a key by this name append the value */
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key, keylen))) {
- buffer_append_string_len(ds->value, CONST_STR_LEN(", "));
- buffer_append_string_len(ds->value, value, vallen);
- return 0;
- }
-
- return response_header_insert(srv, con, key, keylen, value, vallen);
-}
-
-int http_response_redirect_to_directory(server *srv, connection *con) {
- buffer *o;
-
- o = buffer_init();
-
- if (con->conf.is_ssl) {
- buffer_copy_string_len(o, CONST_STR_LEN("https://"));
- } else {
- buffer_copy_string_len(o, CONST_STR_LEN("http://"));
- }
- if (con->uri.authority->used) {
- buffer_append_string_buffer(o, con->uri.authority);
- } else {
- /* get the name of the currently connected socket */
- struct hostent *he;
-#ifdef HAVE_IPV6
- char hbuf[256];
-#endif
- sock_addr our_addr;
- socklen_t our_addr_len;
-
- our_addr_len = sizeof(our_addr);
-
- if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) {
- con->http_status = 500;
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "can't get sockname", strerror(errno));
-
- buffer_free(o);
- return 0;
- }
-
-
- /* Lookup name: secondly try to get hostname for bind address */
- switch(our_addr.plain.sa_family) {
-#ifdef HAVE_IPV6
- case AF_INET6:
- if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
- SA_LEN((const struct sockaddr *)&our_addr.ipv6),
- hbuf, sizeof(hbuf), NULL, 0, 0)) {
-
- char dst[INET6_ADDRSTRLEN];
-
- ERROR("NOTICE: getnameinfo() failed: %s, using ip-address instead",
- strerror(errno));
-
- buffer_append_string(o,
- inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
- dst, sizeof(dst)));
- } else {
- buffer_append_string(o, hbuf);
- }
- break;
-#endif
- case AF_INET:
- if (NULL == (he = gethostbyaddr((char *)&our_addr.ipv4.sin_addr, sizeof(struct in_addr), AF_INET))) {
- ERROR("NOTICE: gethostbyaddr() failed: %d, using ip-address instead",
- h_errno);
-
- buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
- } else {
- buffer_append_string(o, he->h_name);
- }
- break;
- default:
- ERROR("ERROR: unsupported address-type, %d", our_addr.plain.sa_family);
-
- buffer_free(o);
- return -1;
- }
-
- if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
- (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
- buffer_append_string_len(o, CONST_STR_LEN(":"));
- buffer_append_long(o, srv->srvconf.port);
- }
- }
- buffer_append_string_buffer(o, con->uri.path);
- buffer_append_string_len(o, CONST_STR_LEN("/"));
- if (!buffer_is_empty(con->uri.query)) {
- buffer_append_string_len(o, CONST_STR_LEN("?"));
- buffer_append_string_buffer(o, con->uri.query);
- }
-
- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
-
- con->http_status = 301;
- con->send->is_closed = 1; /* no content */
-
- buffer_free(o);
-
- return 0;
-}
-
-buffer * strftime_cache_get(server *srv, time_t last_mod) {
- struct tm *tm;
- size_t i;
-
- for (i = 0; i < FILE_CACHE_MAX; i++) {
- /* found cache-entry */
- if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
-
- /* found empty slot */
- if (srv->mtime_cache[i].mtime == 0) break;
- }
-
- if (i == FILE_CACHE_MAX) {
- i = 0;
- }
-
- srv->mtime_cache[i].mtime = last_mod;
- buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
- tm = gmtime(&(srv->mtime_cache[i].mtime));
- srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
- srv->mtime_cache[i].str->size - 1,
- "%a, %d %b %Y %H:%M:%S GMT", tm);
- srv->mtime_cache[i].str->used++;
-
- return srv->mtime_cache[i].str;
-}
-
-
-int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) {
- data_string *http_if_none_match;
- data_string *http_if_modified_since;
-
- UNUSED(srv);
-
- /*
- * 14.26 If-None-Match
- * [...]
- * If none of the entity tags match, then the server MAY perform the
- * requested method as if the If-None-Match header field did not exist,
- * but MUST also ignore any If-Modified-Since header field(s) in the
- * request. That is, if no entity tags match, then the server MUST NOT
- * return a 304 (Not Modified) response.
- */
-
- http_if_none_match = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("if-none-match"));
- http_if_modified_since = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("if-modified-since"));
-
- /* last-modified handling */
- if (http_if_none_match) {
- if (etag_is_equal(con->physical.etag, BUF_STR(http_if_none_match->value))) {
- if (con->request.http_method == HTTP_METHOD_GET ||
- con->request.http_method == HTTP_METHOD_HEAD) {
-
- /* check if etag + last-modified */
- if (http_if_modified_since) {
- size_t used_len;
- char *semicolon;
-
- if (NULL == (semicolon = strchr(BUF_STR(http_if_modified_since->value), ';'))) {
- used_len = http_if_modified_since->value->used - 1;
- } else {
- used_len = semicolon - BUF_STR(http_if_modified_since->value);
- }
-
- if (0 == strncmp(BUF_STR(http_if_modified_since->value), mtime->ptr, used_len)) {
- if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
- return HANDLER_FINISHED;
- } else {
-#ifdef HAVE_STRPTIME
- char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
- time_t t_header, t_file;
- struct tm tm;
-
- /* check if we can safely copy the string */
- if (used_len >= sizeof(buf)) {
- TRACE("last-mod check failed as timestamp was too long: %s: %zu, %zu",
- SAFE_BUF_STR(http_if_modified_since->value),
- used_len, sizeof(buf) - 1);
-
- con->http_status = 412;
- return HANDLER_FINISHED;
- }
-
-
- strncpy(buf, BUF_STR(http_if_modified_since->value), used_len);
- buf[used_len] = '\0';
-
- if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
- con->http_status = 412;
- return HANDLER_FINISHED;
- }
- tm.tm_isdst = 0;
- t_header = mktime(&tm);
-
- strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
- tm.tm_isdst = 0;
- t_file = mktime(&tm);
-
- if (t_file > t_header) return HANDLER_GO_ON;
-
- con->http_status = 304;
- return HANDLER_FINISHED;
-#else
- return HANDLER_GO_ON;
-#endif
- }
- } else {
- con->http_status = 304;
- return HANDLER_FINISHED;
- }
- } else {
- con->http_status = 412;
- return HANDLER_FINISHED;
- }
- }
- } else if (http_if_modified_since) {
- size_t used_len;
- char *semicolon;
-
- if (NULL == (semicolon = strchr(BUF_STR(http_if_modified_since->value), ';'))) {
- used_len = http_if_modified_since->value->used - 1;
- } else {
- used_len = semicolon - BUF_STR(http_if_modified_since->value);
- }
-
- if (0 == strncmp(BUF_STR(http_if_modified_since->value), mtime->ptr, used_len)) {
- if ('\0' == mtime->ptr[used_len]) con->http_status = 304;
- return HANDLER_FINISHED;
- } else {
-#ifdef HAVE_STRPTIME
- char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
- time_t t_header, t_file;
- struct tm tm;
-
- /* convert to timestamp */
- if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
-
- strncpy(buf, BUF_STR(http_if_modified_since->value), used_len);
- buf[used_len] = '\0';
-
- if (NULL == strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm)) {
- return HANDLER_GO_ON;
- }
- tm.tm_isdst = 0;
- t_header = mktime(&tm);
-
- strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
- tm.tm_isdst = 0;
- t_file = mktime(&tm);
-
- if (t_file > t_header) return HANDLER_GO_ON;
-
- con->http_status = 304;
- return HANDLER_FINISHED;
-#else
- return HANDLER_GO_ON;
-#endif
- }
- }
-
- return HANDLER_GO_ON;
-}
diff --git a/src/http_auth.c b/src/http_auth.c
deleted file mode 100644
index 357f4a1b..00000000
--- a/src/http_auth.c
+++ /dev/null
@@ -1,1252 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_CRYPT_H
-# include <crypt.h>
-#elif defined(__linux__)
-/* linux needs _XOPEN_SOURCE */
-#endif
-
-#ifdef HAVE_LIBCRYPT
-# define HAVE_CRYPT
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "server.h"
-#include "log.h"
-#include "http_auth.h"
-#include "http_auth_digest.h"
-#include "stream.h"
-
-#include "inet_ntop_cache.h"
-
-#include "sys-strings.h"
-#include "sys-files.h"
-
-#ifdef USE_OPENSSL
-# include <openssl/md5.h>
-#else
-# include "md5.h"
-
-typedef li_MD5_CTX MD5_CTX;
-#define MD5_Init li_MD5_Init
-#define MD5_Update li_MD5_Update
-#define MD5_Final li_MD5_Final
-
-#endif
-
-/**
- * the $apr1$ handling is taken from apache 1.3.x
- */
-
-/*
- * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
- * MD5 crypt() function, which is licenced as follows:
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- */
-
-handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
-#ifdef USE_LDAP
-void auth_ldap_cleanup(ldap_plugin_config *p);
-#endif
-
-static const char base64_pad = '=';
-
-/* "A-Z a-z 0-9 + /" maps to 0-63 */
-static const short base64_reverse_table[256] = {
-/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 - 0x0F */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 - 0x1F */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 - 0x2F */
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 - 0x3F */
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 - 0x4F */
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 - 0x5F */
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 - 0x6F */
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70 - 0x7F */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80 - 0x8F */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90 - 0x9F */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xA0 - 0xAF */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xB0 - 0xBF */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xC0 - 0xCF */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xD0 - 0xDF */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xE0 - 0xEF */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xF0 - 0xFF */
-};
-
-
-static unsigned char * base64_decode(buffer *out, const char *in) {
- unsigned char *result;
- int ch, j = 0, k;
- size_t i;
-
- size_t in_len = strlen(in);
-
- buffer_prepare_copy(out, in_len);
-
- result = (unsigned char *)out->ptr;
-
- ch = in[0];
- /* run through the whole string, converting as we go */
- for (i = 0; i < in_len; i++) {
- ch = (unsigned char) in[i];
-
- if (ch == '\0') break;
-
- if (ch == base64_pad) break;
-
- ch = base64_reverse_table[ch];
- if (ch < 0) continue;
-
- switch(i % 4) {
- case 0:
- result[j] = ch << 2;
- break;
- case 1:
- result[j++] |= ch >> 4;
- result[j] = (ch & 0x0f) << 4;
- break;
- case 2:
- result[j++] |= ch >>2;
- result[j] = (ch & 0x03) << 6;
- break;
- case 3:
- result[j++] |= ch;
- break;
- }
- }
- k = j;
- /* mop things up if we ended on a boundary */
- if (ch == base64_pad) {
- switch(i % 4) {
- case 0:
- case 1:
- return NULL;
- case 2:
- k++;
- case 3:
- result[k++] = 0;
- }
- }
- result[k] = '\0';
-
- out->used = k;
-
- return result;
-}
-
-static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
- int ret = -1;
-
- if (!username->used|| !realm->used) return -1;
-
- if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
- stream f;
- char * f_line;
-
- if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
-
- if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
-
- return -1;
- }
-
- f_line = f.start;
-
- while (f_line - f.start != f.size) {
- char *f_user, *f_pwd, *e, *f_realm;
- size_t u_len, pwd_len, r_len;
-
- f_user = f_line;
-
- /*
- * htdigest format
- *
- * user:realm:md5(user:realm:password)
- */
-
- if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "parsed error in", p->conf.auth_htdigest_userfile,
- "expected 'username:realm:hashed password'");
-
- stream_close(&f);
-
- return -1;
- }
-
- if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "parsed error in", p->conf.auth_plain_userfile,
- "expected 'username:realm:hashed password'");
-
- stream_close(&f);
-
- return -1;
- }
-
- /* get pointers to the fields */
- u_len = f_realm - f_user;
- f_realm++;
- r_len = f_pwd - f_realm;
- f_pwd++;
-
- if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
- pwd_len = e - f_pwd;
- } else {
- pwd_len = f.size - (f_pwd - f.start);
- }
-
- if (username->used - 1 == u_len &&
- (realm->used - 1 == r_len) &&
- (0 == strncmp(username->ptr, f_user, u_len)) &&
- (0 == strncmp(realm->ptr, f_realm, r_len))) {
- /* found */
-
- buffer_copy_string_len(password, f_pwd, pwd_len);
-
- ret = 0;
- break;
- }
-
- /* EOL */
- if (!e) break;
-
- f_line = e + 1;
- }
-
- stream_close(&f);
- } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
- p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
- stream f;
- char * f_line;
- buffer *auth_fn;
-
- auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
-
- if (buffer_is_empty(auth_fn)) return -1;
-
- if (0 != stream_open(&f, auth_fn)) {
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "opening plain-userfile", auth_fn, "failed:", strerror(errno));
-
- return -1;
- }
-
- f_line = f.start;
-
- while (f_line - f.start != f.size) {
- char *f_user, *f_pwd, *e;
- size_t u_len, pwd_len;
-
- f_user = f_line;
-
- /*
- * htpasswd format
- *
- * user:crypted passwd
- */
-
- if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "parsed error in", auth_fn,
- "expected 'username:hashed password'");
-
- stream_close(&f);
-
- return -1;
- }
-
- /* get pointers to the fields */
- u_len = f_pwd - f_user;
- f_pwd++;
-
- if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
- pwd_len = e - f_pwd;
- } else {
- pwd_len = f.size - (f_pwd - f.start);
- }
-
- if (username->used - 1 == u_len &&
- (0 == strncmp(username->ptr, f_user, u_len))) {
- /* found */
-
- buffer_copy_string_len(password, f_pwd, pwd_len);
-
- ret = 0;
- break;
- }
-
- /* EOL */
- if (!e) break;
-
- f_line = e + 1;
- }
-
- stream_close(&f);
- } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
- ret = 0;
- } else {
- return -1;
- }
-
- return ret;
-}
-
-static int http_auth_match_rules(server *srv, mod_auth_plugin_data *p, const char *url, const char *username, const char *group, const char *host) {
- const char *r = NULL, *rules = NULL;
- size_t i;
- int username_len;
- data_string *require;
- array *req;
-
- UNUSED(group);
- UNUSED(host);
-
- /* check what has to be match to fullfil the request */
- /* search auth-directives for path */
- for (i = 0; i < p->conf.auth_require->used; i++) {
- if (p->conf.auth_require->data[i]->key->used == 0) continue;
-
- if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
- break;
- }
- }
-
- if (i == p->conf.auth_require->used) {
- return -1;
- }
-
- req = ((data_array *)(p->conf.auth_require->data[i]))->value;
-
- require = (data_string *)array_get_element(req, CONST_STR_LEN("require"));
-
- /* if we get here, the user we got a authed user */
- if (buffer_is_equal_string(require->value, CONST_STR_LEN("valid-user"))) {
- return 0;
- }
-
- /* user=name1|group=name3|host=name4 */
-
- /* seperate the string by | */
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
-#endif
-
- username_len = username ? strlen(username) : 0;
-
- r = rules = require->value->ptr;
-
- while (1) {
- const char *eq;
- const char *k, *v, *e;
- int k_len, v_len, r_len;
-
- e = strchr(r, '|');
-
- if (e) {
- r_len = e - r;
- } else {
- r_len = strlen(rules) - (r - rules);
- }
-
- /* from r to r + r_len is a rule */
-
- if (0 == strncmp(r, "valid-user", r_len)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
- require->value);
- return -1;
- }
-
- /* search for = in the rules */
- if (NULL == (eq = strchr(r, '='))) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "parsing the 'require' section in 'auth.require' failed: a = is missing",
- require->value);
- return -1;
- }
-
- /* = out of range */
- if (eq > r + r_len) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "parsing the 'require' section in 'auth.require' failed: = out of range",
- require->value);
-
- return -1;
- }
-
- /* the part before the = is user|group|host */
-
- k = r;
- k_len = eq - r;
- v = eq + 1;
- v_len = r_len - k_len - 1;
-
- if (k_len == 4) {
- if (0 == strncmp(k, "user", k_len)) {
- if (username &&
- username_len == v_len &&
- 0 == strncmp(username, v, v_len)) {
- return 0;
- }
- } else if (0 == strncmp(k, "host", k_len)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "host ... (not implemented)");
- } else {
- log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
- return -1;
- }
- } else if (k_len == 5) {
- if (0 == strncmp(k, "group", k_len)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "group ... (not implemented)");
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ss", "unknown key", k);
- return -1;
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
- return -1;
- }
-
- if (!e) break;
- r = e + 1;
- }
-
- log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
-
- return -1;
-}
-
-#define APR_MD5_DIGESTSIZE 16
-#define APR1_ID "$apr1$"
-
-/*
- * The following MD5 password encryption code was largely borrowed from
- * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
- * licenced as stated at the top of this file.
- */
-
-static void to64(char *s, unsigned long v, int n)
-{
- static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */
- "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
- while (--n >= 0) {
- *s++ = itoa64[v&0x3f];
- v >>= 6;
- }
-}
-
-static void apr_md5_encode(const char *pw, const char *salt, char *result, size_t nbytes) {
- /*
- * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
- * plus 4 for the '$' separators, plus the password hash itself.
- * Let's leave a goodly amount of leeway.
- */
-
- char passwd[120], *p;
- const char *sp, *ep;
- unsigned char final[APR_MD5_DIGESTSIZE];
- ssize_t sl, pl, i;
- MD5_CTX ctx, ctx1;
- unsigned long l;
-
- /*
- * Refine the salt first. It's possible we were given an already-hashed
- * string as the salt argument, so extract the actual salt value from it
- * if so. Otherwise just use the string up to the first '$' as the salt.
- */
- sp = salt;
-
- /*
- * If it starts with the magic string, then skip that.
- */
- if (!strncmp(sp, APR1_ID, strlen(APR1_ID))) {
- sp += strlen(APR1_ID);
- }
-
- /*
- * It stops at the first '$' or 8 chars, whichever comes first
- */
- for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
- continue;
- }
-
- /*
- * Get the length of the true salt
- */
- sl = ep - sp;
-
- /*
- * 'Time to make the doughnuts..'
- */
- MD5_Init(&ctx);
-
- /*
- * The password first, since that is what is most unknown
- */
- MD5_Update(&ctx, (const unsigned char*) pw, strlen(pw));
-
- /*
- * Then our magic string
- */
- MD5_Update(&ctx, (const unsigned char*) APR1_ID, strlen(APR1_ID));
-
- /*
- * Then the raw salt
- */
- MD5_Update(&ctx, (const unsigned char*) sp, sl);
-
- /*
- * Then just as many characters of the MD5(pw, salt, pw)
- */
- MD5_Init(&ctx1);
- MD5_Update(&ctx1, (const unsigned char*) pw, strlen(pw));
- MD5_Update(&ctx1, (const unsigned char*) sp, sl);
- MD5_Update(&ctx1, (const unsigned char*) pw, strlen(pw));
- MD5_Final(final, &ctx1);
- for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
- MD5_Update(&ctx, final,
- (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl);
- }
-
- /*
- * Don't leave anything around in vm they could use.
- */
- memset(final, 0, sizeof(final));
-
- /*
- * Then something really weird...
- */
- for (i = strlen(pw); i != 0; i >>= 1) {
- if (i & 1) {
- MD5_Update(&ctx, final, 1);
- }
- else {
- MD5_Update(&ctx, (const unsigned char*) pw, 1);
- }
- }
-
- /*
- * Now make the output string. We know our limitations, so we
- * can use the string routines without bounds checking.
- */
- strcpy(passwd, APR1_ID);
- strncat(passwd, sp, sl);
- strcat(passwd, "$");
-
- MD5_Final(final, &ctx);
-
- /*
- * And now, just to make sure things don't run too fast..
- * On a 60 Mhz Pentium this takes 34 msec, so you would
- * need 30 seconds to build a 1000 entry dictionary...
- */
- for (i = 0; i < 1000; i++) {
- MD5_Init(&ctx1);
- if (i & 1) {
- MD5_Update(&ctx1, (const unsigned char*) pw, strlen(pw));
- }
- else {
- MD5_Update(&ctx1, final, APR_MD5_DIGESTSIZE);
- }
- if (i % 3) {
- MD5_Update(&ctx1, (const unsigned char*) sp, sl);
- }
-
- if (i % 7) {
- MD5_Update(&ctx1, (const unsigned char*) pw, strlen(pw));
- }
-
- if (i & 1) {
- MD5_Update(&ctx1, final, APR_MD5_DIGESTSIZE);
- }
- else {
- MD5_Update(&ctx1, (const unsigned char*) pw, strlen(pw));
- }
- MD5_Final(final,&ctx1);
- }
-
- p = passwd + strlen(passwd);
-
- l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
- l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
- l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
- l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
- l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
- l = final[11] ; to64(p, l, 2); p += 2;
- *p = '\0';
-
- /*
- * Don't leave anything around in vm they could use.
- */
- memset(final, 0, sizeof(final));
-
- /* FIXME
- */
-#define apr_cpystrn strncpy
- apr_cpystrn(result, passwd, nbytes - 1);
-}
-
-
-/**
- *
- *
- * @param password password-string from the auth-backend
- * @param pw password-string from the client
- */
-
-static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p, array *req, buffer *username, buffer *realm, buffer *password, const char *pw) {
- UNUSED(srv);
- UNUSED(req);
-
- if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
- /*
- * htdigest format
- *
- * user:realm:md5(user:realm:password)
- */
-
- MD5_CTX Md5Ctx;
- HASH HA1;
- char a1[256];
-
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)realm->ptr, realm->used - 1);
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
- MD5_Final(HA1, &Md5Ctx);
-
- CvtHex(HA1, a1);
-
- if (buffer_is_equal_string(password, a1, strlen(a1))) {
- return 0;
- }
- } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
- char sample[120];
- if (!strncmp(password->ptr, APR1_ID, strlen(APR1_ID))) {
- /*
- * The hash was created using $apr1$ custom algorithm.
- */
- apr_md5_encode(pw, password->ptr, sample, sizeof(sample));
- return (strcmp(sample, password->ptr) == 0) ? 0 : 1;
- } else {
-#ifdef HAVE_CRYPT
- char salt[32];
- char *crypted;
- size_t salt_len = 0;
- /*
- * htpasswd format
- *
- * user:crypted password
- */
-
- /*
- * Algorithm Salt
- * CRYPT_STD_DES 2-character (Default)
- * CRYPT_EXT_DES 9-character
- * CRYPT_MD5 12-character beginning with $1$
- * CRYPT_BLOWFISH 16-character beginning with $2$
- */
-
- if (password->used < 13 + 1) {
- fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
- return -1;
- }
-
- if (password->used == 13 + 1) {
- /* a simple DES password is 2 + 11 characters */
- salt_len = 2;
- } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
- char *dollar = NULL;
-
- if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
- fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
- return -1;
- }
-
- salt_len = dollar - password->ptr;
- }
-
- if (salt_len > sizeof(salt) - 1) {
- fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
- return -1;
- }
-
- strncpy(salt, password->ptr, salt_len);
-
- salt[salt_len] = '\0';
-
- crypted = crypt(pw, salt);
-
- if (buffer_is_equal_string(password, crypted, strlen(crypted))) {
- return 0;
- } else {
- fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
- }
-
-#endif
- }
- } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
- if (buffer_is_equal_string(password, pw, strlen(pw))) {
- return 0;
- }
- } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
-#ifdef USE_LDAP
- LDAP *ldap = NULL;
- LDAPMessage *lm = NULL, *first = NULL;
- struct berval credentials;
- char *dn = NULL;
- int ret = 0;
- char *attrs[] = { LDAP_NO_ATTRS, NULL };
- size_t i = 0;
-
- /* for now we stay synchronous */
-
- /*
- * 1. connect anonymously (done in plugin init)
- * 2. get DN for uid = username
- * 3. auth against ldap server
- * 4. (optional) check a field
- * 5. disconnect
- *
- */
-
- /* check username
- *
- * we have to protect us againt username which modifies out filter in
- * a unpleasant way
- */
-
- for (i = 0; i < username->used - 1; i++) {
- char c = username->ptr[i];
-
- if (!isalpha(c) &&
- !isdigit(c) &&
- (c != ' ') &&
- (c != '@') &&
- (c != '-') &&
- (c != '_') &&
- (c != '.') ) {
-
- log_error_write(srv, __FILE__, __LINE__, "sbd",
- "ldap: invalid character (- _.@a-zA-Z0-9 allowed) in username:", username, i);
-
- return -1;
- }
- }
-
- if (p->conf.auth_ldap_allow_empty_pw != 1 && pw[0] == '\0')
- return -1;
-
- /* 2. */
-
- if (p->conf.ldap->ldap == NULL) {
- if(auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON)
- return -1;
- }
-
- /* build filter */
- buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap->ldap_filter_pre);
- buffer_append_string_buffer(p->ldap_filter, username);
- buffer_append_string_buffer(p->ldap_filter, p->conf.ldap->ldap_filter_post);
-
- ret = ldap_search_ext_s(p->conf.ldap->ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, NULL, NULL, NULL, 0, &lm);
-
- if (ret == LDAP_SERVER_DOWN) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "ldap: server down, try to reconnect");
-
- auth_ldap_cleanup(p->conf.ldap);
-
- if(auth_ldap_init(srv, &p->conf) != HANDLER_GO_ON)
- return -1;
-
- log_error_write(srv, __FILE__, __LINE__, "s",
- "ldap: successfully reconnected");
- }
-
- if (ret != LDAP_SUCCESS) {
- log_error_write(srv, __FILE__, __LINE__, "sssb",
- "ldap:", ldap_err2string(ret), ", filter:", p->ldap_filter);
-
- return -1;
- }
-
- if (ldap_count_entries(p->conf.ldap->ldap, lm) > 1) {
- log_error_write(srv, __FILE__, __LINE__, "ssb",
- "ldap:", "more than one record returned, you might have to refine the filter:", p->ldap_filter);
- }
-
- first = ldap_first_entry(p->conf.ldap->ldap, lm);
- if (first == NULL) {
- ldap_get_option(p->conf.ldap->ldap, LDAP_OPT_ERROR_NUMBER, &ret);
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_msgfree(lm);
-
- return -1;
- }
-
- dn = ldap_get_dn(p->conf.ldap->ldap, first);
- if (dn == NULL) {
- ldap_get_option(p->conf.ldap->ldap, LDAP_OPT_ERROR_NUMBER, &ret);
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_msgfree(lm);
-
- return -1;
- }
-
- ldap_msgfree(lm);
-
- /* 3. */
- ret = ldap_initialize(&ldap, p->conf.auth_ldap_url->ptr);
- if (ret) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_memfree(dn);
-
- return -1;
- }
-
- {
- const int ldap_version = LDAP_VERSION3;
- ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
- }
- if (ret != LDAP_OPT_SUCCESS) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_memfree(ldap);
- ldap_memfree(dn);
-
- return -1;
- }
-
- if (p->conf.auth_ldap_starttls == 1) {
- ret = ldap_start_tls_s(ldap, NULL, NULL);
- if (ret != LDAP_OPT_SUCCESS) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
-
- ldap_memfree(ldap);
- ldap_memfree(dn);
-
- return -1;
- }
- }
-
- /* Don't initialize it using " = {...}" since upstream doesn't
- * guarantee an order and the compiler only issues a warning when
- * passing an int as the pointer and vice-versa.
- * We have to cast away the const since berval is a general struct,
- * but ldap_sasl_bind_s doesn't write to the *pw location
- */
- credentials.bv_val = (char*)pw;
- credentials.bv_len = strlen(pw);
-
- /* TODO: add funtionality to specify LDAP_SASL_EXTERNAL (or GSS-SPNEGO, etc.) */
- ret = ldap_sasl_bind_s(ldap, dn, LDAP_SASL_SIMPLE, &credentials, NULL, NULL, NULL);
- if (ret != LDAP_SUCCESS) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_memfree(ldap);
- ldap_memfree(dn);
-
- return -1;
- }
-
- /* 5. */
- ldap_unbind_ext_s(ldap, NULL, NULL);
- ldap_memfree(dn);
-
- /* everything worked, good, access granted */
-
- return 0;
-#endif
- }
- return -1;
-}
-
-int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
- buffer *username, *password;
- char *pw;
-
- data_string *realm;
-
- realm = (data_string *)array_get_element(req, CONST_STR_LEN("realm"));
-
- username = buffer_init();
-
- if (!base64_decode(username, realm_str)) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", username);
-
- buffer_free(username);
- return 0;
- }
-
- /* r2 == user:password */
- if (NULL == (pw = strchr(username->ptr, ':'))) {
- log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
-
- buffer_free(username);
- return 0;
- }
-
- *pw++ = '\0';
-
- username->used = pw - username->ptr;
-
- password = buffer_init();
-
- /* copy password to r1 */
- if (http_auth_get_password(srv, p, username, realm->value, password)) {
- buffer_free(username);
- buffer_free(password);
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "get_password failed, IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
-
- return 0;
- }
-
- /* password doesn't match */
- if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
- log_error_write(srv, __FILE__, __LINE__, "sbsBss", "password doesn't match for", con->uri.path, "username:", username, ", IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
-
- buffer_free(username);
- buffer_free(password);
-
- return 0;
- }
-
- /* value is our allow-rules */
- if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
- buffer_free(username);
- buffer_free(password);
-
- log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
-
- return 0;
- }
-
- /* remember the username */
- buffer_copy_string_buffer(p->auth_user, username);
-
- buffer_free(username);
- buffer_free(password);
-
- return 1;
-}
-
-typedef struct {
- const char *key;
- int key_len;
- char **ptr;
-} digest_kv;
-
-int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
- char a1[256];
- char a2[256];
-
- char *username;
- char *realm;
- char *nonce;
- char *uri;
- char *algorithm;
- char *qop;
- char *cnonce;
- char *nc;
- char *respons;
-
- char *e, *c;
- const char *m = NULL;
- int i;
- buffer *password, *b, *username_buf, *realm_buf;
-
- MD5_CTX Md5Ctx;
- HASH HA1;
- HASH HA2;
- HASH RespHash;
- HASHHEX HA2Hex;
-
-
- /* init pointers */
-#define S(x) \
- x, sizeof(x)-1, NULL
- digest_kv dkv[10] = {
- { S("username=") },
- { S("realm=") },
- { S("nonce=") },
- { S("uri=") },
- { S("algorithm=") },
- { S("qop=") },
- { S("cnonce=") },
- { S("nc=") },
- { S("response=") },
-
- { NULL, 0, NULL }
- };
-#undef S
-
- dkv[0].ptr = &username;
- dkv[1].ptr = &realm;
- dkv[2].ptr = &nonce;
- dkv[3].ptr = &uri;
- dkv[4].ptr = &algorithm;
- dkv[5].ptr = &qop;
- dkv[6].ptr = &cnonce;
- dkv[7].ptr = &nc;
- dkv[8].ptr = &respons;
- dkv[9].ptr = NULL;
-
- UNUSED(req);
-
- for (i = 0; dkv[i].key; i++) {
- *(dkv[i].ptr) = NULL;
- }
-
-
- if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
- p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "digest: unsupported backend (only htdigest or plain)");
-
- return -1;
- }
-
- b = buffer_init_string(realm_str);
-
- /* parse credentials from client */
- for (c = b->ptr; *c; c++) {
- /* skip whitespaces */
- while (*c == ' ' || *c == '\t') c++;
- if (!*c) break;
-
- for (i = 0; dkv[i].key; i++) {
- if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
- if ((c[dkv[i].key_len] == '"') &&
- (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
- /* value with "..." */
- *(dkv[i].ptr) = c + dkv[i].key_len + 1;
- c = e;
-
- *e = '\0';
- } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
- /* value without "...", terminated by ',' */
- *(dkv[i].ptr) = c + dkv[i].key_len;
- c = e;
-
- *e = '\0';
- } else {
- /* value without "...", terminated by EOL */
- *(dkv[i].ptr) = c + dkv[i].key_len;
- c += strlen(c) - 1;
- }
- }
- }
- }
-
- if (p->conf.auth_debug > 1) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
- log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
- log_error_write(srv, __FILE__, __LINE__, "ss", "nonce", nonce);
- log_error_write(srv, __FILE__, __LINE__, "ss", "uri", uri);
- log_error_write(srv, __FILE__, __LINE__, "ss", "algorigthm", algorithm);
- log_error_write(srv, __FILE__, __LINE__, "ss", "qop", qop);
- log_error_write(srv, __FILE__, __LINE__, "ss", "cnonce", cnonce);
- log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
- log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
- }
-
- /* check if everything is transmitted */
- if (!username ||
- !realm ||
- !nonce ||
- !uri ||
- (qop && (!nc || !cnonce)) ||
- !respons ) {
- /* missing field */
-
- log_error_write(srv, __FILE__, __LINE__, "s",
- "digest: missing field");
-
- buffer_free(b);
- return -1;
- }
-
- /**
- * protect the md5-sess against missing cnonce and nonce
- */
- if (algorithm &&
- 0 == strcasecmp(algorithm, "md5-sess") &&
- (!nonce || !cnonce)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "digest: (md5-sess: missing field");
-
- buffer_free(b);
- return -1;
- }
-
- m = get_http_method_name(con->request.http_method);
-
- /* password-string == HA1 */
- password = buffer_init();
- username_buf = buffer_init_string(username);
- realm_buf = buffer_init_string(realm);
- if (http_auth_get_password(srv, p, username_buf, realm_buf, password)) {
- buffer_free(password);
- buffer_free(b);
- buffer_free(username_buf);
- buffer_free(realm_buf);
- return 0;
- }
-
- buffer_free(username_buf);
- buffer_free(realm_buf);
-
- if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
- /* generate password from plain-text */
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)username, strlen(username));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)realm, strlen(realm));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)password->ptr, password->used - 1);
- MD5_Final(HA1, &Md5Ctx);
- } else if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
- /* HA1 */
- /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
- for (i = 0; i < HASHLEN; i++) {
- HA1[i] = hex2int(password->ptr[i*2]) << 4;
- HA1[i] |= hex2int(password->ptr[i*2+1]);
- }
- } else {
- /* we already check that above */
- SEGFAULT("p->conf.auth_backend is %d", p->conf.auth_backend);
- }
-
- buffer_free(password);
-
- if (algorithm &&
- strcasecmp(algorithm, "md5-sess") == 0) {
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)HA1, 16);
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)nonce, strlen(nonce));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
- MD5_Final(HA1, &Md5Ctx);
- }
-
- CvtHex(HA1, a1);
-
- /* calculate H(A2) */
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)uri, strlen(uri));
- if (qop && strcasecmp(qop, "auth-int") == 0) {
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)"", HASHHEXLEN);
- }
- MD5_Final(HA2, &Md5Ctx);
- CvtHex(HA2, HA2Hex);
-
- /* calculate response */
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)nonce, strlen(nonce));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- if (qop && *qop) {
- MD5_Update(&Md5Ctx, (unsigned char *)nc, strlen(nc));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- MD5_Update(&Md5Ctx, (unsigned char *)qop, strlen(qop));
- MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
- };
- MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
- MD5_Final(RespHash, &Md5Ctx);
- CvtHex(RespHash, a2);
-
- if (0 != strcmp(a2, respons)) {
- /* digest not ok */
-
- if (p->conf.auth_debug) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "digest: digest mismatch", a2, respons);
- }
-
- log_error_write(srv, __FILE__, __LINE__, "ssss",
- "digest: auth failed for ", username, ": wrong password, IP:", inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
-
- buffer_free(b);
- return 0;
- }
-
- /* value is our allow-rules */
- if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
- buffer_free(b);
-
- log_error_write(srv, __FILE__, __LINE__, "s",
- "digest: rules did match");
-
- return 0;
- }
-
- /* remember the username */
- buffer_copy_string(p->auth_user, username);
-
- buffer_free(b);
-
- if (p->conf.auth_debug) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "digest: auth ok");
- }
- return 1;
-}
-
-
-int http_auth_digest_generate_nonce(server *srv, mod_auth_plugin_data *p, buffer *fn, char out[33]) {
- HASH h;
- MD5_CTX Md5Ctx;
- char hh[32];
-
- UNUSED(p);
-
- /* generate shared-secret */
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
- MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
-
- /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
- LI_ltostr(hh, srv->cur_ts);
- MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
- MD5_Update(&Md5Ctx, (unsigned char *)srv->entropy, sizeof(srv->entropy));
- LI_ltostr(hh, rand());
- MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
-
- MD5_Final(h, &Md5Ctx);
-
- CvtHex(h, out);
-
- return 0;
-}
diff --git a/src/http_auth.h b/src/http_auth.h
deleted file mode 100644
index 84674fdb..00000000
--- a/src/http_auth.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef _HTTP_AUTH_H_
-#define _HTTP_AUTH_H_
-
-#include "server.h"
-#include "plugin.h"
-
-#if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
-# define USE_LDAP
-# include <ldap.h>
-#endif
-
-typedef enum {
- AUTH_BACKEND_UNSET,
- AUTH_BACKEND_PLAIN,
- AUTH_BACKEND_LDAP,
- AUTH_BACKEND_HTPASSWD,
- AUTH_BACKEND_HTDIGEST
-} auth_backend_t;
-
-#ifdef USE_LDAP
-typedef struct {
- LDAP *ldap;
-
- buffer *ldap_filter_pre;
- buffer *ldap_filter_post;
-} ldap_plugin_config;
-#endif
-
-typedef struct {
- /* auth */
- array *auth_require;
-
- buffer *auth_plain_groupfile;
- buffer *auth_plain_userfile;
-
- buffer *auth_htdigest_userfile;
- buffer *auth_htpasswd_userfile;
-
- buffer *auth_backend_conf;
-
- buffer *auth_ldap_url;
- buffer *auth_ldap_basedn;
- buffer *auth_ldap_binddn;
- buffer *auth_ldap_bindpw;
- buffer *auth_ldap_filter;
- buffer *auth_ldap_cafile;
- buffer *auth_ldap_cert;
- buffer *auth_ldap_key;
- unsigned short auth_ldap_starttls;
- unsigned short auth_ldap_allow_empty_pw;
-
- unsigned short auth_debug;
-
- /* generated */
- auth_backend_t auth_backend;
-
-#ifdef USE_LDAP
- ldap_plugin_config *ldap;
-#endif
-} mod_auth_plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
- buffer *tmp_buf;
-
- buffer *auth_user;
-
-#ifdef USE_LDAP
- buffer *ldap_filter;
-#endif
-
- mod_auth_plugin_config **config_storage;
-
- mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
-} mod_auth_plugin_data;
-
-int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str);
-int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str);
-int http_auth_digest_generate_nonce(server *srv, mod_auth_plugin_data *p, buffer *fn, char hh[33]);
-
-#endif
diff --git a/src/http_auth_digest.c b/src/http_auth_digest.c
deleted file mode 100644
index 27b933ae..00000000
--- a/src/http_auth_digest.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <string.h>
-#include "http_auth_digest.h"
-
-#include "buffer.h"
-
-#ifndef USE_OPENSSL
-# include "md5.h"
-
-typedef li_MD5_CTX MD5_CTX;
-#define MD5_Init li_MD5_Init
-#define MD5_Update li_MD5_Update
-#define MD5_Final li_MD5_Final
-
-#endif
-
-void CvtHex(IN HASH Bin, OUT HASHHEX Hex) {
- unsigned short i;
-
- for (i = 0; i < HASHLEN; i++) {
- Hex[i*2] = int2hex((Bin[i] >> 4) & 0xf);
- Hex[i*2+1] = int2hex(Bin[i] & 0xf);
- }
- Hex[HASHHEXLEN] = '\0';
-}
-
diff --git a/src/http_auth_digest.h b/src/http_auth_digest.h
deleted file mode 100644
index 25d95ee4..00000000
--- a/src/http_auth_digest.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _DIGCALC_H_
-#define _DIGCALC_H_
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define HASHLEN 16
-typedef unsigned char HASH[HASHLEN];
-#define HASHHEXLEN 32
-typedef char HASHHEX[HASHHEXLEN+1];
-#ifdef USE_OPENSSL
-#define IN const
-#else
-#define IN
-#endif
-#define OUT
-
-void CvtHex(
- IN HASH Bin,
- OUT HASHHEX Hex
- );
-
-#endif
diff --git a/src/http_parser.h b/src/http_parser.h
deleted file mode 100644
index ba86f16a..00000000
--- a/src/http_parser.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _HTTP_PARSER_H_
-#define _HTTP_PARSER_H_
-
-typedef enum {
- PARSE_UNSET,
- PARSE_SUCCESS,
- PARSE_ERROR,
- PARSE_NEED_MORE
-} parse_status_t;
-
-#endif
diff --git a/src/http_req.c b/src/http_req.c
deleted file mode 100644
index 004ca303..00000000
--- a/src/http_req.c
+++ /dev/null
@@ -1,323 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "log.h"
-#include "http_req.h"
-#include "http_req_parser.h"
-
-typedef struct {
- chunkqueue *cq;
-
- chunk *c; /* current chunk in the chunkqueue */
- size_t offset; /* current offset in current chunk */
-
- chunk *lookup_c;
- size_t lookup_offset;
-
- int last_token_id;
-
- int is_key;
- int is_statusline;
-} http_req_tokenizer_t;
-
-http_req *http_request_init(void) {
- http_req *req = calloc(1, sizeof(*req));
-
- req->uri_raw = buffer_init();
- req->headers = array_init();
-
- return req;
-}
-
-void http_request_reset(http_req *req) {
- if (!req) return;
-
- buffer_reset(req->uri_raw);
- array_reset(req->headers);
-
-}
-
-void http_request_free(http_req *req) {
- if (!req) return;
-
- buffer_free(req->uri_raw);
- array_free(req->headers);
-
- free(req);
-}
-
-static int http_req_get_next_char(http_req_tokenizer_t *t, unsigned char *c) {
- if (t->c->mem->used == 0) {
- TRACE("chunk-len: %zd", t->c->mem->used);
- }
-
- if (t->offset == t->c->mem->used - 1) {
- /* end of chunk, open next chunk */
-
- if (!t->c->next) return -1;
-
- t->c = t->c->next;
- /* skip empty chunks */
- while (t->c && t->c->mem->used == 0) t->c = t->c->next;
- if (!t->c) return -1;
-
- t->offset = 0;
- }
-
- *c = t->c->mem->ptr[t->offset++];
-
- t->lookup_offset = t->offset;
- t->lookup_c = t->c;
-
-#if 0
- fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
-#endif
-
- return 0;
-}
-
-static int http_req_lookup_next_char(http_req_tokenizer_t *t, unsigned char *c) {
- if (t->lookup_c->mem->used == 0) {
- TRACE("chunk-len: %zd", t->lookup_c->mem->used);
- }
- if (t->lookup_offset == t->lookup_c->mem->used - 1) {
- /* end of chunk, open next chunk */
-
- if (!t->lookup_c->next) return -1;
-
- t->lookup_c = t->lookup_c->next;
-
- /* skip empty chunks */
- while (t->lookup_c && t->lookup_c->mem->used == 0) t->lookup_c = t->lookup_c->next;
- if (!t->lookup_c) return -1;
-
- t->lookup_offset = 0;
- }
-
- *c = t->lookup_c->mem->ptr[t->lookup_offset++];
-#if 0
- fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
-#endif
-
- return 0;
-}
-
-typedef enum {
- PARSER_UNSET,
- PARSER_OK,
- PARSER_ERROR,
- PARSER_EOF
-} http_req_parser_t;
-
-static http_req_parser_t http_req_tokenizer(
- http_req_tokenizer_t *t,
- int *token_id,
- buffer *token
-) {
- unsigned char c;
- int tid = 0;
-
- /* push the token to the parser */
-
- while (tid == 0 && 0 == http_req_get_next_char(t, &c)) {
- switch (c) {
- case ':':
- tid = TK_COLON;
-
- t->is_key = 0;
-
- break;
- case ' ':
- case '\t':
- if (t->last_token_id == TK_CRLF) {
- /* WS as the start of a line */
-
- tid = TK_TAB;
- t->is_key = 0;
- }
- /* ignore the rest of the WS-chars */
- break;
- case '\r':
- if (0 != http_req_lookup_next_char(t, &c)) return PARSER_EOF;
-
- if (c == '\n') {
- tid = TK_CRLF;
-
- t->c = t->lookup_c;
- t->offset = t->lookup_offset;
-
- t->is_statusline = 0;
- t->is_key = 1;
- } else {
- ERROR("CR with out LF at pos: %zu", t->offset);
- return PARSER_ERROR;
- }
- break;
- case '\n':
- tid = TK_CRLF;
-
- t->is_statusline = 0;
- t->is_key = 1;
-
- break;
- default:
- while (c >= 32 && c != 127 && c != 255) {
- if (t->is_statusline) {
- if (c == 32) break; /* the space is a splitter in the statusline */
- } else {
- if (t->is_key) {
- if (c == ':') break; /* the : is the splitter between key and value */
- if (c == ' ') break; /* no spaces in keys */
- }
- }
- if (0 != http_req_lookup_next_char(t, &c)) return PARSER_EOF;
- }
-
- if (t->c == t->lookup_c &&
- t->offset == t->lookup_offset + 1) {
-
- ERROR("invalid char (%d) at pos: %zu", c, t->offset);
- return PARSER_ERROR;
- }
-
- tid = TK_STRING;
-
- /* the lookup points to the first invalid char */
- t->lookup_offset--;
-
- /* no overlapping string */
- if (t->c == t->lookup_c) {
- buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
- } else {
- /* first chunk */
- buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
-
- /* chunks in the middle */
- for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
- buffer_append_string_buffer(token, t->c->mem);
- t->offset = t->c->mem->used - 1;
- }
-
- /* last chunk */
- buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
- }
-
- t->offset = t->lookup_offset;
-
- break;
- }
- }
-
- if (tid) {
- *token_id = tid;
-
- return PARSER_OK;
- }
-
- return PARSER_EOF;
-}
-
-parse_status_t http_request_parse_cq(chunkqueue *cq, http_req *req) {
- http_req_tokenizer_t t;
- void *pParser = NULL;
- int token_id = 0;
- buffer *token = NULL;
- http_req_ctx_t context;
- parse_status_t ret = PARSE_UNSET;
- http_req_parser_t parser_ret;
-
- t.cq = cq;
- t.c = cq->first;
- t.offset = t.c->offset;
- t.is_key = 0;
- t.is_statusline = 1;
- t.last_token_id = 0;
-
- context.ok = 1;
- context.errmsg = buffer_init();
- context.req = req;
- context.unused_buffers = buffer_pool_init();
-
- pParser = http_req_parserAlloc( malloc );
- token = buffer_init();
-
- array_reset(req->headers);
-
- while((PARSER_OK == (parser_ret = http_req_tokenizer(&t, &token_id, token))) && context.ok) {
- http_req_parser(pParser, token_id, token, &context);
-
- token = buffer_pool_get(context.unused_buffers);
-
- /* CRLF CRLF ... the header end sequence */
- if (t.last_token_id == TK_CRLF &&
- token_id == TK_CRLF) break;
-
- t.last_token_id = token_id;
- }
-
- // Tokenizer failed
- if (parser_ret == PARSER_ERROR) {
- ret = PARSE_ERROR;
- }
-
- /* oops, the parser failed */
- if (context.ok == 0) {
- ret = PARSE_ERROR;
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- } else {
- chunk *c;
- buffer *hdr = buffer_init();
-
- for (c = cq->first; c; c = c->next) {
- if (c == cq->first) {
- buffer_append_string_len(hdr, c->mem->ptr + c->offset, c->mem->used - 1 - c->offset);
- } else {
- buffer_append_string_buffer(hdr, c->mem);
- }
- }
-
- TRACE("parsing failed at token (%s [%d]), header: %s", SAFE_BUF_STR(token), token_id, SAFE_BUF_STR(hdr));
-
- buffer_free(hdr);
- }
- }
-
- http_req_parser(pParser, 0, token, &context);
- http_req_parserFree(pParser, free);
-
- if (context.ok == 0) {
- /* we are missing the some tokens */
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- }
-
- if (ret == PARSE_UNSET) {
- ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
- }
- } else if (parser_ret == PARSER_EOF) { // didn't see CRLF CRLF, no other error till now
- ret = PARSE_NEED_MORE;
- } else {
- chunk *c;
-
- for (c = cq->first; c != t.c; c = c->next) {
- c->offset = c->mem->used - 1;
- }
-
- c->offset = t.offset;
-
- ret = PARSE_SUCCESS;
- }
-
- buffer_pool_append(context.unused_buffers, token);
- buffer_pool_free(context.unused_buffers);
- buffer_free(context.errmsg);
-
- return ret;
-}
-
-
diff --git a/src/http_req.h b/src/http_req.h
deleted file mode 100644
index 54b4a087..00000000
--- a/src/http_req.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _HTTP_REQ_H_
-#define _HTTP_REQ_H_
-
-#include <stdio.h>
-
-#include "array.h"
-#include "chunk.h"
-#include "http_parser.h"
-
-typedef struct {
- int protocol; /* http/1.0, http/1.1 */
- int method; /* e.g. GET */
- buffer *uri_raw; /* e.g. /foobar/ */
- array *headers;
-} http_req;
-
-typedef struct {
- int ok;
- buffer *errmsg;
-
- http_req *req;
- buffer_pool *unused_buffers;
-} http_req_ctx_t;
-
-LI_API http_req * http_request_init(void);
-LI_API void http_request_free(http_req *req);
-LI_API void http_request_reset(http_req *req);
-
-LI_API parse_status_t http_request_parse_cq(chunkqueue *cq, http_req *http_request);
-
-/* declare prototypes for the parser */
-void *http_req_parserAlloc(void *(*mallocProc)(size_t));
-void http_req_parserFree(void *p, void (*freeProc)(void*));
-void http_req_parserTrace(FILE *TraceFILE, char *zTracePrompt);
-void http_req_parser(void *, int, buffer *, http_req_ctx_t *);
-
-#endif
diff --git a/src/http_req_parser.y b/src/http_req_parser.y
deleted file mode 100644
index 54c2673a..00000000
--- a/src/http_req_parser.y
+++ /dev/null
@@ -1,160 +0,0 @@
-%token_prefix TK_
-%token_type {buffer *}
-%extra_argument {http_req_ctx_t *ctx}
-%name http_req_parser
-
-%include {
-#include <assert.h>
-#include <string.h>
-#include "http_req.h"
-#include "keyvalue.h"
-#include "array.h"
-#include "log.h"
-}
-
-%parse_failure {
- ctx->ok = 0;
-}
-
-%type protocol { http_version_t }
-%type method { http_method_t }
-%type request_hdr { http_req * }
-%type headers { array * }
-%type header { data_string * }
-%type multiline { buffer * }
-%token_destructor { buffer_free($$); }
-
-/**
-* GET ... HTTP/1.0
-* Host: ...
-*/
-request_hdr ::= method(B) STRING(C) protocol(D) CRLF headers CRLF . {
- http_req *req = ctx->req;
-
- req->method = B;
- req->protocol = D;
- buffer_copy_string_buffer(req->uri_raw, C);
- buffer_pool_append(ctx->unused_buffers, C);
-}
-
-/**
-* \r\n
-* GET ... HTTP/1.0\r\n
-* Host: ...\r\n
-* \r\n
-*/
-request_hdr ::= CRLF method(B) STRING(C) protocol(D) CRLF headers CRLF . {
- http_req *req = ctx->req;
-
- req->method = B;
- req->protocol = D;
- buffer_copy_string_buffer(req->uri_raw, C);
- buffer_pool_append(ctx->unused_buffers, C);
-}
-
-
-/**
-* GET ... HTTP/1.0\r\n
-* \r\n
-*
-*/
-request_hdr ::= method(B) STRING(C) protocol(D) CRLF CRLF . {
- http_req *req = ctx->req;
-
- req->method = B;
- req->protocol = D;
- buffer_copy_string_buffer(req->uri_raw, C);
- buffer_pool_append(ctx->unused_buffers, C);
-}
-
-/**
-* \r\n
-* GET ... HTTP/1.0\r\n
-* \r\n
-*
-*/
-request_hdr ::= CRLF method(B) STRING(C) protocol(D) CRLF CRLF . {
- http_req *req = ctx->req;
-
- req->method = B;
- req->protocol = D;
- buffer_copy_string_buffer(req->uri_raw, C);
- buffer_pool_append(ctx->unused_buffers, C);
-}
-
-
-method(A) ::= STRING(B) . {
- A = get_http_method_key(BUF_STR(B));
-
- buffer_pool_append(ctx->unused_buffers, B);
-}
-
-protocol(A) ::= STRING(B). {
- /* the protocol might be HTTP/1.0 or HTTP/1.1
- * the version string is allowed to have leading zeros
- */
- A = HTTP_VERSION_UNSET;
-
- if (0 == strncmp(BUF_STR(B), "HTTP/", 5)) {
- char *err = NULL;
- /* is there a dot */
- char *major, *minor;
-
- major = BUF_STR(B) + 5;
- minor = strchr(major, '.');
- if (minor) {
- int hi, lo;
- hi = strtol(major, &err, 10);
- minor++;
- if (*err == '.' && *minor != '\0') {
- lo = strtol(minor, &err, 10);
- if (*err == '\0') {
- if (hi == 1 && lo == 1) {
- A = HTTP_VERSION_1_1;
- } else if (hi == 1 && lo == 0) {
- A = HTTP_VERSION_1_0;
- }
- }
- }
- }
- }
-
- buffer_pool_append(ctx->unused_buffers, B);
-}
-
-headers ::= headers header.
-headers ::= header.
-
-header(HDR) ::= STRING(A) COLON multiline(B). {
- http_req *req = ctx->req;
-
- if (NULL == (HDR = (data_string *)array_get_unused_element(req->headers, TYPE_STRING))) {
- HDR = data_string_init();
- }
-
- buffer_copy_string_buffer(HDR->key, A);
- buffer_copy_string_buffer(HDR->value, B);
- buffer_pool_append(ctx->unused_buffers, A);
- buffer_pool_append(ctx->unused_buffers, B);
-
- array_insert_unique(req->headers, (data_unset *)HDR);
-}
-
-header ::= STRING COLON CRLF .
-
-multiline(A) ::= STRING(B) CRLF TAB multiline(C). {
- buffer_append_string_buffer(B, C);
- A = B;
-
- B = NULL;
- buffer_pool_append(ctx->unused_buffers, C);
-}
-
-/* the simple form */
-multiline(A) ::= STRING(B) CRLF. {
- A = B;
-
- B = NULL;
-}
-
-
diff --git a/src/http_req_range.c b/src/http_req_range.c
deleted file mode 100644
index 434959bb..00000000
--- a/src/http_req_range.c
+++ /dev/null
@@ -1,188 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "log.h"
-#include "http_req_range.h"
-#include "http_req_range_parser.h"
-
-typedef struct {
- buffer *hdr;
- size_t ndx;
-
- chunk *lookup_c;
- size_t lookup_offset;
-} http_req_range_tokenizer_t;
-
-http_req_range *http_request_range_init(void) {
- http_req_range *range = calloc(1, sizeof(*range));
-
- range->start = -1;
- range->end = -1;
-
- return range;
-}
-
-void http_request_range_reset(http_req_range *range) {
- if (!range) return;
-
- http_request_range_free(range->next);
-
- range->next = NULL;
-
- range->start = -1;
- range->end = -1;
-}
-
-void http_request_range_free(http_req_range *range) {
- if (!range) return;
-
- http_request_range_free(range->next);
-
- free(range);
-}
-
-static int http_req_range_tokenizer(
- http_req_range_tokenizer_t *t,
- int *token_id,
- buffer *token
-) {
- int tid = 0;
-
- /* push the token to the parser */
-
- while (tid == 0) {
- char c = t->hdr->ptr[t->ndx];
-
- switch (c) {
- case '-':
- tid = TK_MINUS;
- t->ndx++;
-
- break;
- case '=':
- tid = TK_EQUAL;
- t->ndx++;
-
- break;
- case ',':
- tid = TK_COMMA;
- t->ndx++;
-
- break;
-
- case ' ':
- case '\t':
- /* ignore WS */
- t->ndx++;
- break;
- case '\0':
- return 0;
- default:
- /* 'bytes' or a number */
- if (0 == strncmp(t->hdr->ptr + t->ndx, "bytes", 5)) {
- tid = TK_BYTES;
-
- t->ndx += 5;
- } else {
- size_t d;
- /* */
- for (d = t->ndx; d < t->hdr->used; d++) {
- char dc = t->hdr->ptr[d];
- if (dc < '0' || dc > '9') {
- break;
- }
- }
-
- if (d == t->ndx) {
- /* no digit found */
-
- TRACE("%s", "no digit found");
-
- return -1;
- }
-
- tid = TK_NUMBER;
-
- buffer_copy_string_len(token, t->hdr->ptr + t->ndx, d - t->ndx);
-
- t->ndx = d;
- }
-
- break;
- }
- }
-
- if (tid) {
- *token_id = tid;
-
- return 1;
- }
-
- return -1;
-}
-
-parse_status_t http_request_range_parse(buffer *hdr, http_req_range *ranges) {
- http_req_range_tokenizer_t t;
- void *pParser = NULL;
- int token_id = 0;
- buffer *token = NULL;
- http_req_range_ctx_t context;
- parse_status_t ret = PARSE_UNSET;
-
- t.hdr = hdr;
- t.ndx = 0;
-
- context.ok = 1;
- context.errmsg = buffer_init();
- context.ranges = ranges;
- context.unused_buffers = buffer_pool_init();
-
- pParser = http_req_range_parserAlloc( malloc );
- token = buffer_pool_get(context.unused_buffers);
-#if 0
- http_req_range_parserTrace(stderr, "range: ");
-#endif
-
- while((1 == http_req_range_tokenizer(&t, &token_id, token)) && context.ok) {
- http_req_range_parser(pParser, token_id, token, &context);
-
- token = buffer_pool_get(context.unused_buffers);
- }
-
- /* oops, the parser failed */
- if (context.ok == 0) {
- ret = PARSE_ERROR;
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- } else {
- TRACE("%s", "parsing failed ...");
- }
- }
-
- http_req_range_parser(pParser, 0, token, &context);
- http_req_range_parserFree(pParser, free);
-
- if (context.ok == 0) {
- /* we are missing the some tokens */
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- }
-
- if (ret == PARSE_UNSET) {
- ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
- }
- } else {
- ret = PARSE_SUCCESS;
- }
-
- buffer_pool_append(context.unused_buffers, token);
- buffer_pool_free(context.unused_buffers);
- buffer_free(context.errmsg);
-
- return ret;
-}
-
diff --git a/src/http_req_range.h b/src/http_req_range.h
deleted file mode 100644
index 32a862aa..00000000
--- a/src/http_req_range.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _HTTP_REQ_RANGE_H_
-#define _HTTP_REQ_RANGE_H_
-
-#include <stdio.h>
-
-#include "array.h"
-#include "chunk.h"
-#include "http_parser.h"
-
-typedef struct _http_req_range {
- off_t start;
- off_t end;
- struct _http_req_range *next;
-} http_req_range;
-
-typedef struct {
- int ok;
- buffer *errmsg;
-
- http_req_range *ranges;
-
- buffer_pool *unused_buffers;
-} http_req_range_ctx_t;
-
-LI_API http_req_range * http_request_range_init(void);
-LI_API void http_request_range_free(http_req_range *range);
-LI_API void http_request_range_reset(http_req_range *range);
-
-LI_API parse_status_t http_request_range_parse(buffer *range_hdr, http_req_range *ranges);
-
-/* declare prototypes for the parser */
-void *http_req_range_parserAlloc(void *(*mallocProc)(size_t));
-void http_req_range_parserFree(void *p, void (*freeProc)(void*));
-void http_req_range_parserTrace(FILE *TraceFILE, char *zTracePrompt);
-void http_req_range_parser(void *, int, buffer *, http_req_range_ctx_t *);
-
-#endif
diff --git a/src/http_req_range_parser.y b/src/http_req_range_parser.y
deleted file mode 100644
index 62241fb3..00000000
--- a/src/http_req_range_parser.y
+++ /dev/null
@@ -1,76 +0,0 @@
-%token_prefix TK_
-%token_type {buffer *}
-%extra_argument {http_req_range_ctx_t *ctx}
-%name http_req_range_parser
-
-%include {
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <sys/types.h>
-#include <string.h>
-#include "http_req_range.h"
-#include "log.h"
-#include "sys-strings.h"
-}
-
-%parse_failure {
- ctx->ok = 0;
-}
-
-%type num { off_t }
-%type range { http_req_range * }
-%type ranges { http_req_range * }
-%token_destructor { buffer_free($$); }
-
-
-range_hdr ::= BYTES EQUAL ranges(A) . {
- ctx->ranges->start = A->start;
- ctx->ranges->end = A->end;
- ctx->ranges->next = A->next;
-
- A->next = NULL;
- http_request_range_free(A);
-}
-
-ranges(A) ::= ranges(B) COMMA range(C) . {
- for (A = B; A->next; A = A->next);
-
- A->next = C;
-
- A = B;
-}
-ranges(A) ::= range(B) . {
- A = B;
-}
-range(A) ::= num(B) MINUS . {
- http_req_range *r = http_request_range_init();
-
- r->start = B;
- r->end = -1;
-
- A = r;
-}
-
-range(A) ::= num(B) MINUS num(C) . {
- http_req_range *r = http_request_range_init();
-
- r->start = B;
- r->end = C;
-
- A = r;
-}
-
-range(A) ::= MINUS num(B) . {
- http_req_range *r = http_request_range_init();
-
- r->start = -1;
- r->end = B;
-
- A = r;
-}
-
-num(A) ::= NUMBER(B) . {
- A = strtoull(BUF_STR(B), NULL, 10);
- buffer_pool_append(ctx->unused_buffers, B);
-}
diff --git a/src/http_req_range_test.c b/src/http_req_range_test.c
deleted file mode 100644
index 3532582c..00000000
--- a/src/http_req_range_test.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <stdint.h>
-
-#include <tap.h>
-
-#include "http_req_range.h"
-#include "log.h"
-
-int main(void) {
- http_req_range *r, *ranges = http_request_range_init();
- buffer *b = buffer_init();
-
- log_init();
- plan_tests(7);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=0-0"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "0-0");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
- http_request_range_reset(ranges);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=1-2,3-4"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "1-2,3-4");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
- http_request_range_reset(ranges);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=-0"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "-0");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
- http_request_range_reset(ranges);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=0-"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "0-");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
- http_request_range_reset(ranges);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=0-0,0-"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "0-0,0-");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
- http_request_range_reset(ranges);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=0-0,-0"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "0-0,-0");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
- http_request_range_reset(ranges);
-
- buffer_copy_string_len(b, CONST_STR_LEN("bytes=1-2,3-4,5-"));
- ok(PARSE_SUCCESS == http_request_range_parse(b, ranges), "1-2,3-4,5-");
- for (r = ranges; r; r = r->next) {
- diag(".. %jd - %jd", (intmax_t) r->start, (intmax_t) r->end);
- }
-
- http_request_range_free(ranges);
-
- buffer_free(b);
- log_free();
-
- return exit_status();
-}
diff --git a/src/http_req_test.c b/src/http_req_test.c
deleted file mode 100644
index d53c0b85..00000000
--- a/src/http_req_test.c
+++ /dev/null
@@ -1,141 +0,0 @@
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-#include <tap.h>
-
-#include "http_req.h"
-#include "log.h"
-
-const char* chunkqueue_to_buffer(chunkqueue *cq, buffer *b) {
- chunk *c;
-
- buffer_reset(b);
-
- for (c = cq->first; c; c = c->next) {
- buffer_append_string(b, c->mem->ptr + c->offset);
- }
-
- return b->ptr;
-}
-
-int main(void) {
- http_req *req = http_request_init();
- chunkqueue *cq = chunkqueue_init();
- buffer *b, *content = buffer_init();
- const char *body;
-
- log_init();
- plan_tests(8);
-
- /* basic request header + CRLF */
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "GET / HTTP/1.0\r\n"
- "Location: foobar\r\n"
- "Content-Lenght: 24\r\n"
- "\r\nABC"
- );
-
- ok(PARSE_SUCCESS == http_request_parse_cq(cq, req), "basic GET header");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- http_request_free(req);
-
- /* line-wrapping */
-
- chunkqueue_reset(cq);
- req = http_request_init();
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string(b,
- "GET /server-status HTTP/1.0\r\n"
- "User-Agent: Wget/1.9.1\r\n"
- "Authorization: Digest username=\"jan\", realm=\"jan\", nonce=\"9a5428ccc05b086a08d918e73b01fc6f\",\r\n"
- " uri=\"/server-status\", response=\"ea5f7d9a30b8b762f9610ccb87dea74f\"\r\n"
- "\r\n"
- );
-
- ok(PARSE_SUCCESS == http_request_parse_cq(cq, req), "POST request with line-wrapping");
-
- chunkqueue_remove_finished_chunks(cq);
-
- http_request_free(req);
-
- /* no request line */
-
- chunkqueue_reset(cq);
- req = http_request_init();
-
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "Location: foobar\r\n"
- "Content-Lenght: 24\r\n"
- "\r\nABC"
- );
-
- ok(PARSE_ERROR == http_request_parse_cq(cq, req), "missing request-line");
-
- http_request_free(req);
-
- /* LF as line-ending */
-
- chunkqueue_reset(cq);
- req = http_request_init();
-
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "GET / HTTP/1.0\n"
- "\nABC"
- );
- ok(PARSE_SUCCESS == http_request_parse_cq(cq, req), "no request key-value pairs");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- /* LF as line-ending */
-
- chunkqueue_reset(cq);
- req = http_request_init();
-
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "GE");
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string_len(b, CONST_STR_LEN("T "));
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string_len(b, CONST_STR_LEN("/foo"));
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string_len(b, CONST_STR_LEN("bar HTTP/1.0\r"));
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string(b, "\n"
- "Locati");
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string(b, "on: foobar\r\n"
- "Content-Lenght: 24\r\n"
- "\r\nABC"
- );
- ok(PARSE_SUCCESS == http_request_parse_cq(cq, req), "POST request with line-wrapping");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- http_request_free(req);
- chunkqueue_free(cq);
- buffer_free(content);
- log_free();
-
- return exit_status();
-}
diff --git a/src/http_resp.c b/src/http_resp.c
deleted file mode 100644
index 23b2e58c..00000000
--- a/src/http_resp.c
+++ /dev/null
@@ -1,303 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "log.h"
-#include "http_resp.h"
-#include "http_resp_parser.h"
-
-typedef struct {
- chunkqueue *cq;
-
- chunk *c; /* current chunk in the chunkqueue */
- size_t offset; /* current offset in current chunk */
-
- chunk *lookup_c;
- size_t lookup_offset;
-
- int is_key;
- int is_statusline;
-} http_resp_tokenizer_t;
-
-http_resp *http_response_init(void) {
- http_resp *resp = calloc(1, sizeof(*resp));
-
- resp->reason = buffer_init();
- resp->headers = array_init();
- resp->status = -1;
-
- return resp;
-}
-
-void http_response_reset(http_resp *resp) {
- if (!resp) return;
-
- buffer_reset(resp->reason);
- array_reset(resp->headers);
- resp->status = -1;
-
-}
-
-void http_response_free(http_resp *resp) {
- if (!resp) return;
-
- buffer_free(resp->reason);
- array_free(resp->headers);
-
- free(resp);
-}
-
-static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
- if (t->offset == t->c->mem->used - 1) {
- /* end of chunk, open next chunk */
-
- if (!t->c->next) return -1;
-
- t->c = t->c->next;
- t->offset = 0;
- }
-
- *c = t->c->mem->ptr[t->offset++];
-
- t->lookup_offset = t->offset;
- t->lookup_c = t->c;
-
-#if 0
- fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
-#endif
-
- return 0;
-}
-
-static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
- if (t->lookup_offset == t->lookup_c->mem->used - 1) {
- /* end of chunk, open next chunk */
-
- if (!t->lookup_c->next) return -1;
-
- t->lookup_c = t->lookup_c->next;
- t->lookup_offset = 0;
- }
-
- *c = t->lookup_c->mem->ptr[t->lookup_offset++];
-#if 0
- fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
-#endif
-
- return 0;
-}
-
-typedef enum {
- PARSER_UNSET,
- PARSER_OK,
- PARSER_ERROR,
- PARSER_EOF
-} http_resp_parser_t;
-
-static http_resp_parser_t http_resp_tokenizer(
- http_resp_tokenizer_t *t,
- int *token_id,
- buffer *token
-) {
- unsigned char c;
- int tid = 0;
-
- /* push the token to the parser */
-
- while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
- switch (c) {
- case ':':
- tid = TK_COLON;
-
- t->is_key = 0;
-
- break;
- case ' ':
- case '\t':
- /* ignore WS */
-
- break;
- case '\r':
- if (0 != http_resp_lookup_next_char(t, &c)) return -1;
-
- if (c == '\n') {
- tid = TK_CRLF;
-
- t->c = t->lookup_c;
- t->offset = t->lookup_offset;
-
- t->is_statusline = 0;
- t->is_key = 1;
- } else {
- ERROR("CR with out LF at pos: %zu", t->offset);
- return PARSER_ERROR;
- }
- break;
- case '\n':
- tid = TK_CRLF;
-
- t->is_statusline = 0;
- t->is_key = 1;
-
- break;
- default:
- while (c >= 32 && c != 127 && c != 255) {
- if (t->is_statusline) {
- if (t->is_key && c == ':') { t->is_statusline = 0; break; } /* this is not a status line by a real header */
- if (c == 32) { t->is_key = 0; break; } /* the space is a splitter in the statusline */
- } else {
- if (t->is_key) {
- if (c == ':') break; /* the : is the splitter between key and value */
- }
- }
- if (0 != http_resp_lookup_next_char(t, &c)) return PARSER_EOF;
- }
-
- if (t->c == t->lookup_c &&
- t->offset == t->lookup_offset + 1) {
-
- ERROR("invalid char (%d) at pos: %zu", c, t->offset);
- return PARSER_ERROR;
- }
-
- tid = TK_STRING;
-
- /* the lookup points to the first invalid char */
- t->lookup_offset--;
-
- /* no overlapping string */
- if (t->c == t->lookup_c) {
- buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
- } else {
- /* first chunk */
- buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
-
- /* chunks in the middle */
- for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
- buffer_append_string_buffer(token, t->c->mem);
- t->offset = t->c->mem->used - 1;
- }
-
- /* last chunk */
- buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
- }
-
- t->offset = t->lookup_offset;
-
- break;
- }
- }
-
- if (tid) {
- *token_id = tid;
-
- return PARSER_OK;
- }
-
- return PARSER_EOF;
-}
-
-parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
- http_resp_tokenizer_t t;
- void *pParser = NULL;
- int token_id = 0;
- buffer *token = NULL;
- http_resp_ctx_t context;
- parse_status_t ret = PARSE_UNSET;
- http_resp_parser_t parser_ret;
- int last_token_id = 0;
-
- if(!cq->first) return PARSE_NEED_MORE;
- t.cq = cq;
- t.c = cq->first;
- t.offset = t.c->offset;
- t.is_key = 1;
- t.is_statusline = 1;
-
- context.ok = 1;
- context.errmsg = buffer_init();
- context.resp = resp;
- context.unused_buffers = buffer_pool_init();
-
- array_reset(resp->headers);
- resp->status = 0;
-
- pParser = http_resp_parserAlloc( malloc );
- token = buffer_pool_get(context.unused_buffers);
-#if 0
- http_resp_parserTrace(stderr, "http-response: ");
-#endif
-
- while((PARSER_OK == (parser_ret = http_resp_tokenizer(&t, &token_id, token))) && context.ok) {
- http_resp_parser(pParser, token_id, token, &context);
-
- token = buffer_pool_get(context.unused_buffers);
-
- /* CRLF CRLF ... the header end sequence */
- if (last_token_id == TK_CRLF &&
- token_id == TK_CRLF) break;
-
- last_token_id = token_id;
- }
-
- // Tokenizer failed
- if (parser_ret == PARSER_ERROR) {
- ret = PARSE_ERROR;
- }
-
- /* oops, the parser failed */
- if (context.ok == 0) {
- ret = PARSE_ERROR;
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- } else {
- TRACE("%s", "parsing failed ...");
- }
- }
-
- http_resp_parser(pParser, 0, token, &context);
- http_resp_parserFree(pParser, free);
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- }
- if (context.ok == 0) {
- /* we are missing the some tokens */
-
- if (!buffer_is_empty(context.errmsg)) {
- TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg));
- }
-
- if (ret == PARSE_UNSET) {
- ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
- }
- } else if (parser_ret == PARSER_EOF) { // didn't see CRLF CRLF, no other error till now
- ret = PARSE_NEED_MORE;
- } else {
- chunk *c;
-
- for (c = cq->first; c != t.c; c = c->next) {
- c->offset = c->mem->used - 1;
- cq->bytes_out += c->mem->used - 1;
- }
-
- c->offset = t.offset;
- cq->bytes_out += t.offset;
-
- ret = PARSE_SUCCESS;
- }
-
- buffer_pool_append(context.unused_buffers, token);
- buffer_pool_free(context.unused_buffers);
- buffer_free(context.errmsg);
-
- if (resp->status && (resp->status < 100 || resp->status > 999)) {
- ERROR("invalid status code %i", resp->status);
- return PARSE_ERROR;
- }
-
- return ret;
-}
-
diff --git a/src/http_resp.h b/src/http_resp.h
deleted file mode 100644
index ccc67f94..00000000
--- a/src/http_resp.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _HTTP_RESP_H_
-#define _HTTP_RESP_H_
-
-#include <stdio.h>
-
-#include "buffer.h"
-#include "array.h"
-#include "array-static.h"
-#include "chunk.h"
-#include "http_parser.h"
-
-typedef struct {
- int protocol; /* http/1.0, http/1.1 */
- int status; /* e.g. 200 */
- buffer *reason; /* e.g. Ok */
- array *headers;
-} http_resp;
-
-typedef struct {
- int ok;
- buffer *errmsg;
-
- http_resp *resp;
-
- buffer_pool *unused_buffers;
-} http_resp_ctx_t;
-
-LI_API http_resp * http_response_init(void);
-LI_API void http_response_free(http_resp *resp);
-LI_API void http_response_reset(http_resp *resp);
-
-LI_API parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
-
-/* declare prototypes for the parser */
-void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
-void http_resp_parserFree(void *p, void (*freeProc)(void*));
-void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
-void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
-
-#endif
diff --git a/src/http_resp_parser.y b/src/http_resp_parser.y
deleted file mode 100644
index 7305f682..00000000
--- a/src/http_resp_parser.y
+++ /dev/null
@@ -1,143 +0,0 @@
-%token_prefix TK_
-%token_type {buffer *}
-%extra_argument {http_resp_ctx_t *ctx}
-%name http_resp_parser
-
-%include {
-#include <assert.h>
-#include <string.h>
-#include "http_resp.h"
-#include "keyvalue.h"
-#include "array.h"
-#include "log.h"
-}
-
-%parse_failure {
- ctx->ok = 0;
-}
-
-%type protocol { int }
-%type response_hdr { http_resp * }
-%type number { int }
-%type headers { array * }
-%type header { data_string * }
-%destructor reason { buffer_free($$); }
-%token_destructor { buffer_free($$); }
-
-/* just headers + Status: ... */
-response_hdr ::= header headers CRLF . {
- http_resp *resp = ctx->resp;
- data_string *ds;
-
- resp->protocol = HTTP_VERSION_UNSET;
-
- buffer_copy_string(resp->reason, ""); /* no reason */
-
- if (NULL == (ds = (data_string *)array_get_element(resp->headers, CONST_STR_LEN("Status")))) {
- resp->status = 0;
- } else {
- char *err;
- resp->status = strtol(ds->value->ptr, &err, 10);
-
- if (*err != '\0' && *err != ' ' && *err != '\r') {
- buffer_copy_string(ctx->errmsg, "expected a number: ");
- buffer_append_string_buffer(ctx->errmsg, ds->value);
- buffer_append_string(ctx->errmsg, err);
-
- ctx->ok = 0;
- }
- }
-}
-
-/* HTTP-Version SP Status-Code SP Reason-Phrase CRLF ... */
-response_hdr ::= protocol(B) number(C) reason(D) CRLF headers CRLF . {
- http_resp *resp = ctx->resp;
-
- resp->status = C;
- resp->protocol = B;
- buffer_copy_string_buffer(resp->reason, D);
- buffer_pool_append(ctx->unused_buffers, D);
-}
-
-/* HTTP-Version SP Status-Code CRLF ... */
-response_hdr ::= protocol(B) number(C) CRLF headers CRLF . {
- http_resp *resp = ctx->resp;
-
- resp->status = C;
- resp->protocol = B;
- buffer_reset(resp->reason);
-}
-
-protocol(A) ::= STRING(B). {
- if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.0"))) {
- A = HTTP_VERSION_1_0;
- } else if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.1"))) {
- A = HTTP_VERSION_1_1;
- } else {
- buffer_copy_string(ctx->errmsg, "unknown protocol: ");
- buffer_append_string_buffer(ctx->errmsg, B);
-
- ctx->ok = 0;
- }
- buffer_pool_append(ctx->unused_buffers, B);
-}
-
-number(A) ::= STRING(B). {
- char *err;
- A = strtol(B->ptr, &err, 10);
-
- if (*err != '\0') {
- buffer_copy_string(ctx->errmsg, "expected a number, got: ");
- buffer_append_string_buffer(ctx->errmsg, B);
-
- ctx->ok = 0;
- }
- buffer_pool_append(ctx->unused_buffers, B);
-}
-
-reason(A) ::= STRING(B). {
- A = B;
-}
-
-reason(A) ::= reason(C) STRING(B). {
- A = C;
-
- buffer_append_string(A, " ");
- buffer_append_string_buffer(A, B);
-
- buffer_pool_append(ctx->unused_buffers, B);
-}
-
-headers ::= headers header.
-headers ::= .
-
-header(HDR) ::= STRING(A) COLON STRING(B) CRLF. {
- http_resp *resp = ctx->resp;
-
- if (NULL == (HDR = (data_string *)array_get_unused_element(resp->headers, TYPE_STRING))) {
- HDR = data_response_init();
- }
-
- buffer_copy_string_buffer(HDR->key, A);
- buffer_copy_string_buffer(HDR->value, B);
- buffer_pool_append(ctx->unused_buffers, A);
- buffer_pool_append(ctx->unused_buffers, B);
-
- array_insert_unique(resp->headers, (data_unset *)HDR);
-}
-
-/* empty headers */
-header(HDR) ::= STRING(A) COLON CRLF. {
- http_resp *resp = ctx->resp;
-
- if (NULL == (HDR = (data_string *)array_get_unused_element(resp->headers, TYPE_STRING))) {
- HDR = data_response_init();
- }
-
- buffer_copy_string_buffer(HDR->key, A);
- buffer_copy_string(HDR->value, "");
- buffer_pool_append(ctx->unused_buffers, A);
-
- array_insert_unique(resp->headers, (data_unset *)HDR);
-}
-
diff --git a/src/http_resp_test.c b/src/http_resp_test.c
deleted file mode 100644
index 2d91034d..00000000
--- a/src/http_resp_test.c
+++ /dev/null
@@ -1,141 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <tap.h>
-
-#include "http_resp.h"
-#include "log.h"
-
-const char* chunkqueue_to_buffer(chunkqueue *cq, buffer *b) {
- chunk *c;
-
- buffer_reset(b);
-
- for (c = cq->first; c; c = c->next) {
- buffer_append_string(b, c->mem->ptr + c->offset);
- }
-
- return b->ptr;
-}
-
-int main(void) {
- http_resp *resp = http_response_init();
- chunkqueue *cq = chunkqueue_init();
- buffer *b, *content = buffer_init();
- const char *body;
-
- log_init();
- plan_tests(9);
-
- /* basic response header + CRLF */
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "HTTP/1.0 304 Not Modified\r\n"
- "Location: foobar\r\n"
- "Content-Lenght: 24\r\n"
- "\r\nABC"
- );
-
- ok(PARSE_SUCCESS == http_response_parse_cq(cq, resp), "good 304 response with CRLF");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- http_response_free(resp);
-
- /* line-wrapping */
-
- chunkqueue_reset(cq);
- resp = http_response_init();
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string(b,
- "HTTP/1.0 304 Not Modified\n"
- "Location: foobar\n"
- "Content-Lenght: 24\n"
- "\nABC"
- );
-
- ok(PARSE_SUCCESS == http_response_parse_cq(cq, resp), "good response with LF");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- http_response_free(resp);
-
- /* no request line */
-
- chunkqueue_reset(cq);
- resp = http_response_init();
-
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "Status: 200 Foobar\r\n"
- "Location: foobar\r\n"
- "Content-Lenght: 24\r\n"
- "\r\nABC"
- );
-
- ok(PARSE_SUCCESS == http_response_parse_cq(cq, resp), "Status: 200 ...");
-
- http_response_free(resp);
-
- /* LF as line-ending */
-
- chunkqueue_reset(cq);
- resp = http_response_init();
-
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "Location: foobar\n"
- "\nABC"
- );
- ok(PARSE_SUCCESS == http_response_parse_cq(cq, resp), "no Status at all");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- /* LF as line-ending */
-
- chunkqueue_reset(cq);
- resp = http_response_init();
-
- b = chunkqueue_get_append_buffer(cq);
-
- buffer_copy_string(b,
- "HTTP");
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string_len(b, CONST_STR_LEN("/1.0 "));
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string_len(b, CONST_STR_LEN("30"));
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string_len(b, CONST_STR_LEN("4 Not Modified\r"));
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string(b, "\n"
- "Locati");
-
- b = chunkqueue_get_append_buffer(cq);
- buffer_copy_string(b, "on: foobar\r\n"
- "Content-Lenght: 24\r\n"
- "\r\nABC"
- );
- ok(PARSE_SUCCESS == http_response_parse_cq(cq, resp), "chunked response");
-
- chunkqueue_remove_finished_chunks(cq);
- body = chunkqueue_to_buffer(cq, content);
- ok(0 == strcmp("ABC", body), "content is ABC, got %s", body);
-
- http_response_free(resp);
- chunkqueue_free(cq);
- buffer_free(content);
- log_free();
-
- return exit_status();
-}
diff --git a/src/inet_ntop_cache.c b/src/inet_ntop_cache.c
deleted file mode 100644
index 51755df3..00000000
--- a/src/inet_ntop_cache.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <sys/types.h>
-
-#include <string.h>
-
-
-#include "base.h"
-#include "inet_ntop_cache.h"
-#include "sys-socket.h"
-
-const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
-#ifdef HAVE_IPV6
- size_t ndx = 0, i;
- for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
- if (srv->inet_ntop_cache[i].ts != 0 && srv->inet_ntop_cache[i].family == addr->plain.sa_family) {
- if (srv->inet_ntop_cache[i].family == AF_INET6 &&
- 0 == memcmp(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16)) {
- /* IPv6 found in cache */
- break;
- } else if (srv->inet_ntop_cache[i].family == AF_INET &&
- srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
- /* IPv4 found in cache */
- break;
-
- }
- }
- }
-
- if (i == INET_NTOP_CACHE_MAX) {
- /* not found in cache */
-
- i = ndx;
- inet_ntop(addr->plain.sa_family,
- addr->plain.sa_family == AF_INET6 ?
- (const void *) &(addr->ipv6.sin6_addr) :
- (const void *) &(addr->ipv4.sin_addr),
- srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
-
- srv->inet_ntop_cache[i].ts = srv->cur_ts;
- srv->inet_ntop_cache[i].family = addr->plain.sa_family;
-
- if (srv->inet_ntop_cache[i].family == AF_INET) {
- srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
- } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
- memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
- }
- }
-
- return srv->inet_ntop_cache[i].b2;
-#else
- UNUSED(srv);
- return inet_ntoa(addr->ipv4.sin_addr);
-#endif
-}
diff --git a/src/inet_ntop_cache.h b/src/inet_ntop_cache.h
deleted file mode 100644
index b2a769f2..00000000
--- a/src/inet_ntop_cache.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _INET_NTOP_CACHE_H_
-#define _INET_NTOP_CACHE_H_
-
-#include "base.h"
-LI_API const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr);
-
-#endif
diff --git a/src/iosocket.c b/src/iosocket.c
deleted file mode 100644
index 25d477ff..00000000
--- a/src/iosocket.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include <stdlib.h>
-
-#include "iosocket.h"
-#include "sys-socket.h"
-#include "sys-files.h"
-#include "array-static.h"
-
-iosocket *iosocket_init(void) {
- STRUCT_INIT(iosocket, sock);
-
- sock->fde_ndx = -1;
- sock->fd = -1;
-
- sock->type = IOSOCKET_TYPE_SOCKET;
-
-#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
- sock->tlsext_server_name = buffer_init();
-#endif
-
- return sock;
-}
-
-void iosocket_free(iosocket *sock) {
- if (!sock) return;
-
- if (sock->fd != -1) {
- switch (sock->type) {
- case IOSOCKET_TYPE_SOCKET:
- closesocket(sock->fd);
- break;
- case IOSOCKET_TYPE_PIPE:
- close(sock->fd);
- break;
- default:
- break;
- }
- }
-
-#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
- buffer_free(sock->tlsext_server_name);
-#endif
-
- free(sock);
-}
diff --git a/src/iosocket.h b/src/iosocket.h
deleted file mode 100644
index a11dbfe0..00000000
--- a/src/iosocket.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _IOSOCKET_H_
-#define _IOSOCKET_H_
-
-/**
- * make sure we know about OPENSSL all the time
- *
- * if we don't include config.h here we run into different sizes
- * for the iosocket-struct depending on config.h include before
- * iosocket.h or not
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
-# define USE_OPENSSL
-# include <openssl/ssl.h>
-#endif
-
-#include "settings.h"
-#include "buffer.h"
-
-typedef enum {
- IOSOCKET_TYPE_UNSET,
- IOSOCKET_TYPE_SOCKET,
- IOSOCKET_TYPE_PIPE
-} iosocket_t;
-
-/**
- * a non-blocking fd
- */
-typedef struct {
- int fd;
- int fde_ndx;
-
-#ifdef USE_OPENSSL
- SSL *ssl;
-#ifndef OPENSSL_NO_TLSEXT
- buffer *tlsext_server_name;
-#endif
-#endif
-
- iosocket_t type; /**< sendfile on solaris doesn't work on pipes */
-} iosocket;
-
-LI_API iosocket * iosocket_init(void);
-LI_API void iosocket_free(iosocket *sock);
-
-#endif
diff --git a/src/joblist.c b/src/joblist.c
deleted file mode 100644
index 8f68f496..00000000
--- a/src/joblist.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "base.h"
-#include "joblist.h"
-#include "log.h"
-
-void joblist_append(server *srv, connection *con) {
- if (con->in_joblist) return;
- con->in_joblist = 1;
-
- if (srv->joblist->size == 0) {
- srv->joblist->size = 16;
- srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
- } else if (srv->joblist->used == srv->joblist->size) {
- srv->joblist->size += 16;
- srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
- }
-
- srv->joblist->ptr[srv->joblist->used++] = con;
-}
-
-void joblist_free(server *srv, connections *joblist) {
- UNUSED(srv);
-
- free(joblist->ptr);
- free(joblist);
-}
-
-#ifdef USE_GTHREAD
-void joblist_async_append(server *srv, connection *con) {
- g_async_queue_push(srv->joblist_queue, con);
-
- server_wakeup(srv);
-}
-
-void server_wakeup(server *srv) {
- if (g_atomic_int_compare_and_exchange(&srv->did_wakeup, 0, 1)) {
- write(srv->wakeup_pipe[1], " ", 1);
- }
-}
-#endif
-
-connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
- connection *con;
- UNUSED(srv);
-
-
- if (fdwaitqueue->used == 0) return NULL;
-
- con = fdwaitqueue->ptr[0];
-
- memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
-
- return con;
-}
-
-int fdwaitqueue_append(server *srv, connection *con) {
- if (srv->fdwaitqueue->size == 0) {
- srv->fdwaitqueue->size = 16;
- srv->fdwaitqueue->ptr = malloc(sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
- } else if (srv->fdwaitqueue->used == srv->fdwaitqueue->size) {
- srv->fdwaitqueue->size += 16;
- srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
- }
-
- srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
-
- return 0;
-}
-
-void fdwaitqueue_free(server *srv, connections *fdwaitqueue) {
- UNUSED(srv);
- free(fdwaitqueue->ptr);
- free(fdwaitqueue);
-}
diff --git a/src/joblist.h b/src/joblist.h
deleted file mode 100644
index 2f6bb236..00000000
--- a/src/joblist.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _JOB_LIST_H_
-#define _JOB_LIST_H_
-
-#include "base.h"
-
-LI_API void joblist_append(server *srv, connection *con);
-LI_API void joblist_free(server *srv, connections *joblist);
-
-#ifdef USE_GTHREAD
-LI_API void joblist_async_append(server *srv, connection *con);
-
-LI_API void server_wakeup(server *srv);
-#endif
-
-LI_API int fdwaitqueue_append(server *srv, connection *con);
-LI_API void fdwaitqueue_free(server *srv, connections *fdwaitqueue);
-LI_API connection* fdwaitqueue_unshift(server *srv, connections *fdwaitqueue);
-
-#endif
diff --git a/src/keyvalue.c b/src/keyvalue.c
deleted file mode 100644
index a615116d..00000000
--- a/src/keyvalue.c
+++ /dev/null
@@ -1,390 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "base.h"
-#include "server.h"
-#include "keyvalue.h"
-
-static keyvalue http_versions[] = {
- { HTTP_VERSION_1_1, "HTTP/1.1" },
- { HTTP_VERSION_1_0, "HTTP/1.0" },
- { HTTP_VERSION_UNSET, NULL }
-};
-
-static keyvalue http_methods[] = {
- { HTTP_METHOD_GET, "GET" },
- { HTTP_METHOD_POST, "POST" },
- { HTTP_METHOD_HEAD, "HEAD" },
- { HTTP_METHOD_PROPFIND, "PROPFIND" },
- { HTTP_METHOD_PROPPATCH, "PROPPATCH" },
- { HTTP_METHOD_REPORT, "REPORT" },
- { HTTP_METHOD_OPTIONS, "OPTIONS" },
- { HTTP_METHOD_MKCOL, "MKCOL" },
- { HTTP_METHOD_PUT, "PUT" },
- { HTTP_METHOD_DELETE, "DELETE" },
- { HTTP_METHOD_COPY, "COPY" },
- { HTTP_METHOD_MOVE, "MOVE" },
- { HTTP_METHOD_LABEL, "LABEL" },
- { HTTP_METHOD_CHECKOUT, "CHECKOUT" },
- { HTTP_METHOD_CHECKIN, "CHECKIN" },
- { HTTP_METHOD_MERGE, "MERGE" },
- { HTTP_METHOD_LOCK, "LOCK" },
- { HTTP_METHOD_UNLOCK, "UNLOCK" },
- { HTTP_METHOD_MKACTIVITY, "MKACTIVITY" },
- { HTTP_METHOD_UNCHECKOUT, "UNCHECKOUT" },
- { HTTP_METHOD_VERSION_CONTROL, "VERSION-CONTROL" },
- { HTTP_METHOD_CONNECT, "CONNECT" },
-
- { HTTP_METHOD_UNSET, NULL }
-};
-
-static keyvalue http_status[] = {
- { 100, "Continue" },
- { 101, "Switching Protocols" },
- { 102, "Processing" }, /* WebDAV */
- { 200, "OK" },
- { 201, "Created" },
- { 202, "Accepted" },
- { 203, "Non-Authoritative Information" },
- { 204, "No Content" },
- { 205, "Reset Content" },
- { 206, "Partial Content" },
- { 207, "Multi-status" }, /* WebDAV */
- { 300, "Multiple Choices" },
- { 301, "Moved Permanently" },
- { 302, "Found" },
- { 303, "See Other" },
- { 304, "Not Modified" },
- { 305, "Use Proxy" },
- { 306, "(Unused)" },
- { 307, "Temporary Redirect" },
- { 400, "Bad Request" },
- { 401, "Unauthorized" },
- { 402, "Payment Required" },
- { 403, "Forbidden" },
- { 404, "Not Found" },
- { 405, "Method Not Allowed" },
- { 406, "Not Acceptable" },
- { 407, "Proxy Authentication Required" },
- { 408, "Request Timeout" },
- { 409, "Conflict" },
- { 410, "Gone" },
- { 411, "Length Required" },
- { 412, "Precondition Failed" },
- { 413, "Request Entity Too Large" },
- { 414, "Request-URI Too Long" },
- { 415, "Unsupported Media Type" },
- { 416, "Requested Range Not Satisfiable" },
- { 417, "Expectation Failed" },
- { 422, "Unprocessable Entity" }, /* WebDAV */
- { 423, "Locked" }, /* WebDAV */
- { 424, "Failed Dependency" }, /* WebDAV */
- { 426, "Upgrade Required" }, /* TLS */
- { 500, "Internal Server Error" },
- { 501, "Not Implemented" },
- { 502, "Bad Gateway" },
- { 503, "Service Not Available" },
- { 504, "Gateway Timeout" },
- { 505, "HTTP Version Not Supported" },
- { 507, "Insufficient Storage" }, /* WebDAV */
- { 509, "Bandwidth Limit exceeded" },
-
- { -1, NULL }
-};
-
-static keyvalue http_status_body[] = {
- { 400, "400.html" },
- { 401, "401.html" },
- { 403, "403.html" },
- { 404, "404.html" },
- { 411, "411.html" },
- { 416, "416.html" },
- { 500, "500.html" },
- { 501, "501.html" },
- { 503, "503.html" },
- { 505, "505.html" },
-
- { -1, NULL }
-};
-
-
-const char *keyvalue_get_value(keyvalue *kv, int k) {
- int i;
- for (i = 0; kv[i].value; i++) {
- if (kv[i].key == k) return kv[i].value;
- }
- return NULL;
-}
-
-int keyvalue_get_key(keyvalue *kv, const char *s) {
- int i;
- for (i = 0; kv[i].value; i++) {
- if (0 == strcmp(kv[i].value, s)) return kv[i].key;
- }
- return -1;
-}
-
-keyvalue_buffer *keyvalue_buffer_init(void) {
- keyvalue_buffer *kvb;
-
- kvb = calloc(1, sizeof(*kvb));
-
- return kvb;
-}
-
-int keyvalue_buffer_append(keyvalue_buffer *kvb, int key, const char *value) {
- size_t i;
- if (kvb->size == 0) {
- kvb->size = 4;
-
- kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
-
- for(i = 0; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- } else if (kvb->used == kvb->size) {
- kvb->size += 4;
-
- kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
-
- for(i = kvb->used; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- }
-
- kvb->kv[kvb->used]->key = key;
- kvb->kv[kvb->used]->value = strdup(value);
-
- kvb->used++;
-
- return 0;
-}
-
-void keyvalue_buffer_free(keyvalue_buffer *kvb) {
- size_t i;
-
- for (i = 0; i < kvb->size; i++) {
- if (kvb->kv[i]->value) free(kvb->kv[i]->value);
- free(kvb->kv[i]);
- }
-
- if (kvb->kv) free(kvb->kv);
-
- free(kvb);
-}
-
-
-s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
- s_keyvalue_buffer *kvb;
-
- kvb = calloc(1, sizeof(*kvb));
-
- return kvb;
-}
-
-int s_keyvalue_buffer_append(s_keyvalue_buffer *kvb, const char *key, const char *value) {
- size_t i;
- if (kvb->size == 0) {
- kvb->size = 4;
- kvb->used = 0;
-
- kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
-
- for(i = 0; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- } else if (kvb->used == kvb->size) {
- kvb->size += 4;
-
- kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
-
- for(i = kvb->used; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- }
-
- kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
- kvb->kv[kvb->used]->value = strdup(value);
-
- kvb->used++;
-
- return 0;
-}
-
-void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
- size_t i;
-
- for (i = 0; i < kvb->size; i++) {
- if (kvb->kv[i]->key) free(kvb->kv[i]->key);
- if (kvb->kv[i]->value) free(kvb->kv[i]->value);
- free(kvb->kv[i]);
- }
-
- if (kvb->kv) free(kvb->kv);
-
- free(kvb);
-}
-
-
-httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
- httpauth_keyvalue_buffer *kvb;
-
- kvb = calloc(1, sizeof(*kvb));
-
- return kvb;
-}
-
-int httpauth_keyvalue_buffer_append(httpauth_keyvalue_buffer *kvb, const char *key, const char *realm, httpauth_type type) {
- size_t i;
- if (kvb->size == 0) {
- kvb->size = 4;
-
- kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
-
- for(i = 0; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- } else if (kvb->used == kvb->size) {
- kvb->size += 4;
-
- kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
-
- for(i = kvb->used; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- }
-
- kvb->kv[kvb->used]->key = strdup(key);
- kvb->kv[kvb->used]->realm = strdup(realm);
- kvb->kv[kvb->used]->type = type;
-
- kvb->used++;
-
- return 0;
-}
-
-void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
- size_t i;
-
- for (i = 0; i < kvb->size; i++) {
- if (kvb->kv[i]->key) free(kvb->kv[i]->key);
- if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
- free(kvb->kv[i]);
- }
-
- if (kvb->kv) free(kvb->kv);
-
- free(kvb);
-}
-
-
-const char *get_http_version_name(int i) {
- return keyvalue_get_value(http_versions, i);
-}
-
-const char *get_http_status_name(int i) {
- return keyvalue_get_value(http_status, i);
-}
-
-const char *get_http_method_name(http_method_t i) {
- return keyvalue_get_value(http_methods, i);
-}
-
-const char *get_http_status_body_name(int i) {
- return keyvalue_get_value(http_status_body, i);
-}
-
-int get_http_version_key(const char *s) {
- return keyvalue_get_key(http_versions, s);
-}
-
-http_method_t get_http_method_key(const char *s) {
- return (http_method_t)keyvalue_get_key(http_methods, s);
-}
-
-
-
-
-pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
- pcre_keyvalue_buffer *kvb;
-
- kvb = calloc(1, sizeof(*kvb));
-
- return kvb;
-}
-
-int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, const char *value) {
-#ifdef HAVE_PCRE_H
- size_t i;
- const char *errptr;
- int erroff;
- pcre_keyvalue *kv;
-#endif
-
- if (!key) return -1;
-
-#ifdef HAVE_PCRE_H
- if (kvb->size == 0) {
- kvb->size = 4;
- kvb->used = 0;
-
- kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
-
- for(i = 0; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- } else if (kvb->used == kvb->size) {
- kvb->size += 4;
-
- kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
-
- for(i = kvb->used; i < kvb->size; i++) {
- kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
- }
- }
-
- kv = kvb->kv[kvb->used];
- if (NULL == (kv->key = pcre_compile(key,
- 0, &errptr, &erroff, NULL))) {
-
- fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
- return -1;
- }
-
- if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
- errptr != NULL) {
- return -1;
- }
-
- kv->value = buffer_init_string(value);
-
- kvb->used++;
-
- return 0;
-#else
- UNUSED(kvb);
- UNUSED(value);
-
- return -1;
-#endif
-}
-
-void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) {
-#ifdef HAVE_PCRE_H
- size_t i;
- pcre_keyvalue *kv;
-
- for (i = 0; i < kvb->size; i++) {
- kv = kvb->kv[i];
- if (kv->key) pcre_free(kv->key);
- if (kv->key_extra) pcre_free(kv->key_extra);
- if (kv->value) buffer_free(kv->value);
- free(kv);
- }
-
- if (kvb->kv) free(kvb->kv);
-#endif
-
- free(kvb);
-}
diff --git a/src/keyvalue.h b/src/keyvalue.h
deleted file mode 100644
index e3b65c38..00000000
--- a/src/keyvalue.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef _KEY_VALUE_H_
-#define _KEY_VALUE_H_
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_PCRE_H
-# include <pcre.h>
-#endif
-
-typedef enum {
- HTTP_METHOD_UNSET = -1,
- HTTP_METHOD_GET,
- HTTP_METHOD_POST,
- HTTP_METHOD_HEAD,
- HTTP_METHOD_OPTIONS,
- HTTP_METHOD_PROPFIND, /* WebDAV */
- HTTP_METHOD_MKCOL,
- HTTP_METHOD_PUT,
- HTTP_METHOD_DELETE,
- HTTP_METHOD_COPY,
- HTTP_METHOD_MOVE,
- HTTP_METHOD_PROPPATCH,
- HTTP_METHOD_REPORT, /* DeltaV */
- HTTP_METHOD_CHECKOUT,
- HTTP_METHOD_CHECKIN,
- HTTP_METHOD_VERSION_CONTROL,
- HTTP_METHOD_UNCHECKOUT,
- HTTP_METHOD_MKACTIVITY,
- HTTP_METHOD_MERGE,
- HTTP_METHOD_LOCK,
- HTTP_METHOD_UNLOCK,
- HTTP_METHOD_LABEL,
- HTTP_METHOD_CONNECT
-} http_method_t;
-
-typedef enum {
- HTTP_VERSION_UNSET = -1,
- HTTP_VERSION_1_0,
- HTTP_VERSION_1_1
-} http_version_t;
-
-typedef struct {
- int key;
-
- char *value;
-} keyvalue;
-
-typedef struct {
- char *key;
-
- char *value;
-} s_keyvalue;
-
-typedef struct {
-#ifdef HAVE_PCRE_H
- pcre *key;
- pcre_extra *key_extra;
-#endif
-
- buffer *value;
-} pcre_keyvalue;
-
-typedef enum { HTTP_AUTH_BASIC, HTTP_AUTH_DIGEST } httpauth_type;
-
-typedef struct {
- char *key;
-
- char *realm;
- httpauth_type type;
-} httpauth_keyvalue;
-
-#define KVB(x) \
-typedef struct {\
- x **kv; \
- size_t used;\
- size_t size;\
-} x ## _buffer
-
-KVB(keyvalue);
-KVB(s_keyvalue);
-KVB(httpauth_keyvalue);
-KVB(pcre_keyvalue);
-
-LI_API const char * get_http_status_name(int i);
-LI_API const char * get_http_version_name(int i);
-LI_API const char * get_http_method_name(http_method_t i);
-LI_API const char * get_http_status_body_name(int i);
-LI_API int get_http_version_key(const char *s);
-LI_API http_method_t get_http_method_key(const char *s);
-
-LI_API const char * keyvalue_get_value(keyvalue *kv, int k);
-LI_API int keyvalue_get_key(keyvalue *kv, const char *s);
-
-LI_API keyvalue_buffer * keyvalue_buffer_init(void);
-LI_API int keyvalue_buffer_append(keyvalue_buffer *kvb, int k, const char *value);
-LI_API void keyvalue_buffer_free(keyvalue_buffer *kvb);
-
-LI_API s_keyvalue_buffer * s_keyvalue_buffer_init(void);
-LI_API int s_keyvalue_buffer_append(s_keyvalue_buffer *kvb, const char *key, const char *value);
-LI_API void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb);
-
-LI_API httpauth_keyvalue_buffer * httpauth_keyvalue_buffer_init(void);
-LI_API int httpauth_keyvalue_buffer_append(httpauth_keyvalue_buffer *kvb, const char *key, const char *realm, httpauth_type type);
-LI_API void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb);
-
-LI_API pcre_keyvalue_buffer * pcre_keyvalue_buffer_init(void);
-LI_API int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, const char *value);
-LI_API void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb);
-
-#endif
diff --git a/src/lemon.c b/src/lemon.c
deleted file mode 100644
index ac37f907..00000000
--- a/src/lemon.c
+++ /dev/null
@@ -1,4400 +0,0 @@
-/*
-** This file contains all sources (including headers) to the LEMON
-** LALR(1) parser generator. The sources have been combined into a
-** single file to make it easy to include LEMON in the source tree
-** and Makefile of another program.
-**
-** The author of this program disclaims copyright.
-*/
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-extern void qsort();
-extern double strtod();
-extern long strtol();
-extern void free();
-extern int access();
-extern int atoi();
-extern char *getenv();
-
-#ifndef __WIN32__
-# if defined(_WIN32) || defined(WIN32)
-# define __WIN32__
-# endif
-#endif
-
-#define PRIVATE static
-/* #define PRIVATE */
-
-#ifdef TEST
-#define MAXRHS 5 /* Set low to exercise exception code */
-#else
-#define MAXRHS 1000
-#endif
-
-char *msort();
-extern void *malloc();
-
-extern void memory_error();
-
-/******** From the file "action.h" *************************************/
-struct action *Action_new();
-struct action *Action_sort();
-void Action_add();
-
-/********* From the file "assert.h" ************************************/
-void myassert();
-#ifndef NDEBUG
-# define assert(X) if(!(X))myassert(__FILE__,__LINE__)
-#else
-# define assert(X)
-#endif
-
-/********** From the file "build.h" ************************************/
-void FindRulePrecedences();
-void FindFirstSets();
-void FindStates();
-void FindLinks();
-void FindFollowSets();
-void FindActions();
-
-/********* From the file "configlist.h" *********************************/
-void Configlist_init(/* void */);
-struct config *Configlist_add(/* struct rule *, int */);
-struct config *Configlist_addbasis(/* struct rule *, int */);
-void Configlist_closure(/* void */);
-void Configlist_sort(/* void */);
-void Configlist_sortbasis(/* void */);
-struct config *Configlist_return(/* void */);
-struct config *Configlist_basis(/* void */);
-void Configlist_eat(/* struct config * */);
-void Configlist_reset(/* void */);
-
-/********* From the file "error.h" ***************************************/
-void ErrorMsg(const char *, int,const char *, ...);
-
-/****** From the file "option.h" ******************************************/
-struct s_options {
- enum { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
- OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
- char *label;
- char *arg;
- char *message;
-};
-int OptInit(/* char**,struct s_options*,FILE* */);
-int OptNArgs(/* void */);
-char *OptArg(/* int */);
-void OptErr(/* int */);
-void OptPrint(/* void */);
-
-/******** From the file "parse.h" *****************************************/
-void Parse(/* struct lemon *lemp */);
-
-/********* From the file "plink.h" ***************************************/
-struct plink *Plink_new(/* void */);
-void Plink_add(/* struct plink **, struct config * */);
-void Plink_copy(/* struct plink **, struct plink * */);
-void Plink_delete(/* struct plink * */);
-
-/********** From the file "report.h" *************************************/
-void Reprint(/* struct lemon * */);
-void ReportOutput(/* struct lemon * */);
-void ReportTable(/* struct lemon * */);
-void ReportHeader(/* struct lemon * */);
-void CompressTables(/* struct lemon * */);
-
-/********** From the file "set.h" ****************************************/
-void SetSize(/* int N */); /* All sets will be of size N */
-char *SetNew(/* void */); /* A new set for element 0..N */
-void SetFree(/* char* */); /* Deallocate a set */
-
-int SetAdd(/* char*,int */); /* Add element to a set */
-int SetUnion(/* char *A,char *B */); /* A <- A U B, thru element N */
-
-#define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
-
-/********** From the file "struct.h" *************************************/
-/*
-** Principal data structures for the LEMON parser generator.
-*/
-
-typedef enum {Bo_FALSE=0, Bo_TRUE} Boolean;
-
-/* Symbols (terminals and nonterminals) of the grammar are stored
-** in the following: */
-struct symbol {
- char *name; /* Name of the symbol */
- int index; /* Index number for this symbol */
- enum {
- TERMINAL,
- NONTERMINAL
- } type; /* Symbols are all either TERMINALS or NTs */
- struct rule *rule; /* Linked list of rules of this (if an NT) */
- struct symbol *fallback; /* fallback token in case this token doesn't parse */
- int prec; /* Precedence if defined (-1 otherwise) */
- enum e_assoc {
- LEFT,
- RIGHT,
- NONE,
- UNK
- } assoc; /* Associativity if predecence is defined */
- char *firstset; /* First-set for all rules of this symbol */
- Boolean lambda; /* True if NT and can generate an empty string */
- char *destructor; /* Code which executes whenever this symbol is
- ** popped from the stack during error processing */
- int destructorln; /* Line number of destructor code */
- char *datatype; /* The data type of information held by this
- ** object. Only used if type==NONTERMINAL */
- int dtnum; /* The data type number. In the parser, the value
- ** stack is a union. The .yy%d element of this
- ** union is the correct data type for this object */
-};
-
-/* Each production rule in the grammar is stored in the following
-** structure. */
-struct rule {
- struct symbol *lhs; /* Left-hand side of the rule */
- char *lhsalias; /* Alias for the LHS (NULL if none) */
- int ruleline; /* Line number for the rule */
- int nrhs; /* Number of RHS symbols */
- struct symbol **rhs; /* The RHS symbols */
- char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
- int line; /* Line number at which code begins */
- char *code; /* The code executed when this rule is reduced */
- struct symbol *precsym; /* Precedence symbol for this rule */
- int index; /* An index number for this rule */
- Boolean canReduce; /* True if this rule is ever reduced */
- struct rule *nextlhs; /* Next rule with the same LHS */
- struct rule *next; /* Next rule in the global list */
-};
-
-/* A configuration is a production rule of the grammar together with
-** a mark (dot) showing how much of that rule has been processed so far.
-** Configurations also contain a follow-set which is a list of terminal
-** symbols which are allowed to immediately follow the end of the rule.
-** Every configuration is recorded as an instance of the following: */
-struct config {
- struct rule *rp; /* The rule upon which the configuration is based */
- int dot; /* The parse point */
- char *fws; /* Follow-set for this configuration only */
- struct plink *fplp; /* Follow-set forward propagation links */
- struct plink *bplp; /* Follow-set backwards propagation links */
- struct state *stp; /* Pointer to state which contains this */
- enum {
- COMPLETE, /* The status is used during followset and */
- INCOMPLETE /* shift computations */
- } status;
- struct config *next; /* Next configuration in the state */
- struct config *bp; /* The next basis configuration */
-};
-
-/* Every shift or reduce operation is stored as one of the following */
-struct action {
- struct symbol *sp; /* The look-ahead symbol */
- enum e_action {
- SHIFT,
- ACCEPT,
- REDUCE,
- ERROR,
- CONFLICT, /* Was a reduce, but part of a conflict */
- SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
- RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
- NOT_USED /* Deleted by compression */
- } type;
- union {
- struct state *stp; /* The new state, if a shift */
- struct rule *rp; /* The rule, if a reduce */
- } x;
- struct action *next; /* Next action for this state */
- struct action *collide; /* Next action with the same hash */
-};
-
-/* Each state of the generated parser's finite state machine
-** is encoded as an instance of the following structure. */
-struct state {
- struct config *bp; /* The basis configurations for this state */
- struct config *cfp; /* All configurations in this set */
- int index; /* Sequencial number for this state */
- struct action *ap; /* Array of actions for this state */
- int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
- int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
- int iDflt; /* Default action */
-};
-#define NO_OFFSET (-2147483647)
-
-/* A followset propagation link indicates that the contents of one
-** configuration followset should be propagated to another whenever
-** the first changes. */
-struct plink {
- struct config *cfp; /* The configuration to which linked */
- struct plink *next; /* The next propagate link */
-};
-
-/* The state vector for the entire parser generator is recorded as
-** follows. (LEMON uses no global variables and makes little use of
-** static variables. Fields in the following structure can be thought
-** of as begin global variables in the program.) */
-struct lemon {
- struct state **sorted; /* Table of states sorted by state number */
- struct rule *rule; /* List of all rules */
- int nstate; /* Number of states */
- int nrule; /* Number of rules */
- int nsymbol; /* Number of terminal and nonterminal symbols */
- int nterminal; /* Number of terminal symbols */
- struct symbol **symbols; /* Sorted array of pointers to symbols */
- int errorcnt; /* Number of errors */
- struct symbol *errsym; /* The error symbol */
- char *name; /* Name of the generated parser */
- char *arg; /* Declaration of the 3th argument to parser */
- char *tokentype; /* Type of terminal symbols in the parser stack */
- char *vartype; /* The default type of non-terminal symbols */
- char *start; /* Name of the start symbol for the grammar */
- char *stacksize; /* Size of the parser stack */
- char *include; /* Code to put at the start of the C file */
- int includeln; /* Line number for start of include code */
- char *error; /* Code to execute when an error is seen */
- int errorln; /* Line number for start of error code */
- char *overflow; /* Code to execute on a stack overflow */
- int overflowln; /* Line number for start of overflow code */
- char *failure; /* Code to execute on parser failure */
- int failureln; /* Line number for start of failure code */
- char *accept; /* Code to execute when the parser excepts */
- int acceptln; /* Line number for the start of accept code */
- char *extracode; /* Code appended to the generated file */
- int extracodeln; /* Line number for the start of the extra code */
- char *tokendest; /* Code to execute to destroy token data */
- int tokendestln; /* Line number for token destroyer code */
- char *vardest; /* Code for the default non-terminal destructor */
- int vardestln; /* Line number for default non-term destructor code*/
- char *filename; /* Name of the input file */
- char *tmplname; /* Name of the template file */
- char *outname; /* Name of the current output file */
- char *tokenprefix; /* A prefix added to token names in the .h file */
- int nconflict; /* Number of parsing conflicts */
- int tablesize; /* Size of the parse tables */
- int basisflag; /* Print only basis configurations */
- int has_fallback; /* True if any %fallback is seen in the grammer */
- char *argv0; /* Name of the program */
-};
-
-#define MemoryCheck(X) if((X)==0){ \
- memory_error(); \
-}
-
-/**************** From the file "table.h" *********************************/
-/*
-** All code in this file has been automatically generated
-** from a specification in the file
-** "table.q"
-** by the associative array code building program "aagen".
-** Do not edit this file! Instead, edit the specification
-** file, then rerun aagen.
-*/
-/*
-** Code for processing tables in the LEMON parser generator.
-*/
-
-/* Routines for handling a strings */
-
-char *Strsafe();
-
-void Strsafe_init(/* void */);
-int Strsafe_insert(/* char * */);
-char *Strsafe_find(/* char * */);
-
-/* Routines for handling symbols of the grammar */
-
-struct symbol *Symbol_new();
-int Symbolcmpp(/* struct symbol **, struct symbol ** */);
-void Symbol_init(/* void */);
-int Symbol_insert(/* struct symbol *, char * */);
-struct symbol *Symbol_find(/* char * */);
-struct symbol *Symbol_Nth(/* int */);
-int Symbol_count(/* */);
-struct symbol **Symbol_arrayof(/* */);
-
-/* Routines to manage the state table */
-
-int Configcmp(/* struct config *, struct config * */);
-struct state *State_new();
-void State_init(/* void */);
-int State_insert(/* struct state *, struct config * */);
-struct state *State_find(/* struct config * */);
-struct state **State_arrayof(/* */);
-
-/* Routines used for efficiency in Configlist_add */
-
-void Configtable_init(/* void */);
-int Configtable_insert(/* struct config * */);
-struct config *Configtable_find(/* struct config * */);
-void Configtable_clear(/* int(*)(struct config *) */);
-/****************** From the file "action.c" *******************************/
-/*
-** Routines processing parser actions in the LEMON parser generator.
-*/
-
-/* Allocate a new parser action */
-struct action *Action_new(){
- static struct action *freelist = 0;
- struct action *new;
-
- if( freelist==0 ){
- int i;
- int amt = 100;
- freelist = (struct action *)malloc( sizeof(struct action)*amt );
- if( freelist==0 ){
- fprintf(stderr,"Unable to allocate memory for a new parser action.");
- exit(1);
- }
- for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
- freelist[amt-1].next = 0;
- }
- new = freelist;
- freelist = freelist->next;
- return new;
-}
-
-/* Compare two actions */
-static int actioncmp(ap1,ap2)
-struct action *ap1;
-struct action *ap2;
-{
- int rc;
- rc = ap1->sp->index - ap2->sp->index;
- if( rc==0 ) rc = (int)ap1->type - (int)ap2->type;
- if( rc==0 ){
- assert( ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
- assert( ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
- rc = ap1->x.rp->index - ap2->x.rp->index;
- }
- return rc;
-}
-
-/* Sort parser actions */
-struct action *Action_sort(ap)
-struct action *ap;
-{
- ap = (struct action *)msort(ap,&ap->next,actioncmp);
- return ap;
-}
-
-void Action_add(app,type,sp,arg)
-struct action **app;
-enum e_action type;
-struct symbol *sp;
-char *arg;
-{
- struct action *new;
- new = Action_new();
- new->next = *app;
- *app = new;
- new->type = type;
- new->sp = sp;
- if( type==SHIFT ){
- new->x.stp = (struct state *)arg;
- }else{
- new->x.rp = (struct rule *)arg;
- }
-}
-/********************** New code to implement the "acttab" module ***********/
-/*
-** This module implements routines use to construct the yy_action[] table.
-*/
-
-/*
-** The state of the yy_action table under construction is an instance of
-** the following structure
-*/
-typedef struct acttab acttab;
-struct acttab {
- int nAction; /* Number of used slots in aAction[] */
- int nActionAlloc; /* Slots allocated for aAction[] */
- struct {
- int lookahead; /* Value of the lookahead token */
- int action; /* Action to take on the given lookahead */
- } *aAction, /* The yy_action[] table under construction */
- *aLookahead; /* A single new transaction set */
- int mnLookahead; /* Minimum aLookahead[].lookahead */
- int mnAction; /* Action associated with mnLookahead */
- int mxLookahead; /* Maximum aLookahead[].lookahead */
- int nLookahead; /* Used slots in aLookahead[] */
- int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
-};
-
-/* Return the number of entries in the yy_action table */
-#define acttab_size(X) ((X)->nAction)
-
-/* The value for the N-th entry in yy_action */
-#define acttab_yyaction(X,N) ((X)->aAction[N].action)
-
-/* The value for the N-th entry in yy_lookahead */
-#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
-
-/* Free all memory associated with the given acttab */
-/*
-PRIVATE void acttab_free(acttab *p){
- free( p->aAction );
- free( p->aLookahead );
- free( p );
-}
-*/
-
-/* Allocate a new acttab structure */
-PRIVATE acttab *acttab_alloc(void){
- acttab *p = malloc( sizeof(*p) );
- if( p==0 ){
- fprintf(stderr,"Unable to allocate memory for a new acttab.");
- exit(1);
- }
- memset(p, 0, sizeof(*p));
- return p;
-}
-
-/* Add a new action to the current transaction set
-*/
-PRIVATE void acttab_action(acttab *p, int lookahead, int action){
- if( p->nLookahead>=p->nLookaheadAlloc ){
- p->nLookaheadAlloc += 25;
- p->aLookahead = realloc( p->aLookahead,
- sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
- if( p->aLookahead==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- }
- if( p->nLookahead==0 ){
- p->mxLookahead = lookahead;
- p->mnLookahead = lookahead;
- p->mnAction = action;
- }else{
- if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
- if( p->mnLookahead>lookahead ){
- p->mnLookahead = lookahead;
- p->mnAction = action;
- }
- }
- p->aLookahead[p->nLookahead].lookahead = lookahead;
- p->aLookahead[p->nLookahead].action = action;
- p->nLookahead++;
-}
-
-/*
-** Add the transaction set built up with prior calls to acttab_action()
-** into the current action table. Then reset the transaction set back
-** to an empty set in preparation for a new round of acttab_action() calls.
-**
-** Return the offset into the action table of the new transaction.
-*/
-PRIVATE int acttab_insert(acttab *p){
- int i, j, k, n;
- assert( p->nLookahead>0 );
-
- /* Make sure we have enough space to hold the expanded action table
- ** in the worst case. The worst case occurs if the transaction set
- ** must be appended to the current action table
- */
- n = p->mxLookahead + 1;
- if( p->nAction + n >= p->nActionAlloc ){
- int oldAlloc = p->nActionAlloc;
- p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
- p->aAction = realloc( p->aAction,
- sizeof(p->aAction[0])*p->nActionAlloc);
- if( p->aAction==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- for(i=oldAlloc; i<p->nActionAlloc; i++){
- p->aAction[i].lookahead = -1;
- p->aAction[i].action = -1;
- }
- }
-
- /* Scan the existing action table looking for an offset where we can
- ** insert the current transaction set. Fall out of the loop when that
- ** offset is found. In the worst case, we fall out of the loop when
- ** i reaches p->nAction, which means we append the new transaction set.
- **
- ** i is the index in p->aAction[] where p->mnLookahead is inserted.
- */
- for(i=0; i<p->nAction+p->mnLookahead; i++){
- if( p->aAction[i].lookahead<0 ){
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- if( k<0 ) break;
- if( p->aAction[k].lookahead>=0 ) break;
- }
- if( j<p->nLookahead ) continue;
- for(j=0; j<p->nAction; j++){
- if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
- }
- if( j==p->nAction ){
- break; /* Fits in empty slots */
- }
- }else if( p->aAction[i].lookahead==p->mnLookahead ){
- if( p->aAction[i].action!=p->mnAction ) continue;
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- if( k<0 || k>=p->nAction ) break;
- if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
- if( p->aLookahead[j].action!=p->aAction[k].action ) break;
- }
- if( j<p->nLookahead ) continue;
- n = 0;
- for(j=0; j<p->nAction; j++){
- if( p->aAction[j].lookahead<0 ) continue;
- if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
- }
- if( n==p->nLookahead ){
- break; /* Same as a prior transaction set */
- }
- }
- }
- /* Insert transaction set at index i. */
- for(j=0; j<p->nLookahead; j++){
- k = p->aLookahead[j].lookahead - p->mnLookahead + i;
- p->aAction[k] = p->aLookahead[j];
- if( k>=p->nAction ) p->nAction = k+1;
- }
- p->nLookahead = 0;
-
- /* Return the offset that is added to the lookahead in order to get the
- ** index into yy_action of the action */
- return i - p->mnLookahead;
-}
-
-/********************** From the file "assert.c" ****************************/
-/*
-** A more efficient way of handling assertions.
-*/
-void myassert(file,line)
-char *file;
-int line;
-{
- fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file);
- exit(1);
-}
-/********************** From the file "build.c" *****************************/
-/*
-** Routines to construction the finite state machine for the LEMON
-** parser generator.
-*/
-
-/* Find a precedence symbol of every rule in the grammar.
-**
-** Those rules which have a precedence symbol coded in the input
-** grammar using the "[symbol]" construct will already have the
-** rp->precsym field filled. Other rules take as their precedence
-** symbol the first RHS symbol with a defined precedence. If there
-** are not RHS symbols with a defined precedence, the precedence
-** symbol field is left blank.
-*/
-void FindRulePrecedences(xp)
-struct lemon *xp;
-{
- struct rule *rp;
- for(rp=xp->rule; rp; rp=rp->next){
- if( rp->precsym==0 ){
- int i;
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]->prec>=0 ){
- rp->precsym = rp->rhs[i];
- break;
- }
- }
- }
- }
- return;
-}
-
-/* Find all nonterminals which will generate the empty string.
-** Then go back and compute the first sets of every nonterminal.
-** The first set is the set of all terminal symbols which can begin
-** a string generated by that nonterminal.
-*/
-void FindFirstSets(lemp)
-struct lemon *lemp;
-{
- int i;
- struct rule *rp;
- int progress;
-
- for(i=0; i<lemp->nsymbol; i++){
- lemp->symbols[i]->lambda = Bo_FALSE;
- }
- for(i=lemp->nterminal; i<lemp->nsymbol; i++){
- lemp->symbols[i]->firstset = SetNew();
- }
-
- /* First compute all lambdas */
- do{
- progress = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->lhs->lambda ) continue;
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]->lambda==Bo_FALSE ) break;
- }
- if( i==rp->nrhs ){
- rp->lhs->lambda = Bo_TRUE;
- progress = 1;
- }
- }
- }while( progress );
-
- /* Now compute all first sets */
- do{
- struct symbol *s1, *s2;
- progress = 0;
- for(rp=lemp->rule; rp; rp=rp->next){
- s1 = rp->lhs;
- for(i=0; i<rp->nrhs; i++){
- s2 = rp->rhs[i];
- if( s2->type==TERMINAL ){
- progress += SetAdd(s1->firstset,s2->index);
- break;
- }else if( s1==s2 ){
- if( s1->lambda==Bo_FALSE ) break;
- }else{
- progress += SetUnion(s1->firstset,s2->firstset);
- if( s2->lambda==Bo_FALSE ) break;
- }
- }
- }
- }while( progress );
- return;
-}
-
-/* Compute all LR(0) states for the grammar. Links
-** are added to between some states so that the LR(1) follow sets
-** can be computed later.
-*/
-PRIVATE struct state *getstate(/* struct lemon * */); /* forward reference */
-void FindStates(lemp)
-struct lemon *lemp;
-{
- struct symbol *sp;
- struct rule *rp;
-
- Configlist_init();
-
- /* Find the start symbol */
- if( lemp->start ){
- sp = Symbol_find(lemp->start);
- if( sp==0 ){
- ErrorMsg(lemp->filename,0,
-"The specified start symbol \"%s\" is not \
-in a nonterminal of the grammar. \"%s\" will be used as the start \
-symbol instead.",lemp->start,lemp->rule->lhs->name);
- lemp->errorcnt++;
- sp = lemp->rule->lhs;
- }
- }else{
- sp = lemp->rule->lhs;
- }
-
- /* Make sure the start symbol doesn't occur on the right-hand side of
- ** any rule. Report an error if it does. (YACC would generate a new
- ** start symbol in this case.) */
- for(rp=lemp->rule; rp; rp=rp->next){
- int i;
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhs[i]==sp ){
- ErrorMsg(lemp->filename,0,
-"The start symbol \"%s\" occurs on the \
-right-hand side of a rule. This will result in a parser which \
-does not work properly.",sp->name);
- lemp->errorcnt++;
- }
- }
- }
-
- /* The basis configuration set for the first state
- ** is all rules which have the start symbol as their
- ** left-hand side */
- for(rp=sp->rule; rp; rp=rp->nextlhs){
- struct config *newcfp;
- newcfp = Configlist_addbasis(rp,0);
- SetAdd(newcfp->fws,0);
- }
-
- /* Compute the first state. All other states will be
- ** computed automatically during the computation of the first one.
- ** The returned pointer to the first state is not used. */
- (void)getstate(lemp);
- return;
-}
-
-/* Return a pointer to a state which is described by the configuration
-** list which has been built from calls to Configlist_add.
-*/
-PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
-PRIVATE struct state *getstate(lemp)
-struct lemon *lemp;
-{
- struct config *cfp, *bp;
- struct state *stp;
-
- /* Extract the sorted basis of the new state. The basis was constructed
- ** by prior calls to "Configlist_addbasis()". */
- Configlist_sortbasis();
- bp = Configlist_basis();
-
- /* Get a state with the same basis */
- stp = State_find(bp);
- if( stp ){
- /* A state with the same basis already exists! Copy all the follow-set
- ** propagation links from the state under construction into the
- ** preexisting state, then return a pointer to the preexisting state */
- struct config *x, *y;
- for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
- Plink_copy(&y->bplp,x->bplp);
- Plink_delete(x->fplp);
- x->fplp = x->bplp = 0;
- }
- cfp = Configlist_return();
- Configlist_eat(cfp);
- }else{
- /* This really is a new state. Construct all the details */
- Configlist_closure(lemp); /* Compute the configuration closure */
- Configlist_sort(); /* Sort the configuration closure */
- cfp = Configlist_return(); /* Get a pointer to the config list */
- stp = State_new(); /* A new state structure */
- MemoryCheck(stp);
- stp->bp = bp; /* Remember the configuration basis */
- stp->cfp = cfp; /* Remember the configuration closure */
- stp->index = lemp->nstate++; /* Every state gets a sequence number */
- stp->ap = 0; /* No actions, yet. */
- State_insert(stp,stp->bp); /* Add to the state table */
- buildshifts(lemp,stp); /* Recursively compute successor states */
- }
- return stp;
-}
-
-/* Construct all successor states to the given state. A "successor"
-** state is any state which can be reached by a shift action.
-*/
-PRIVATE void buildshifts(lemp,stp)
-struct lemon *lemp;
-struct state *stp; /* The state from which successors are computed */
-{
- struct config *cfp; /* For looping thru the config closure of "stp" */
- struct config *bcfp; /* For the inner loop on config closure of "stp" */
- struct config *new; /* */
- struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
- struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
- struct state *newstp; /* A pointer to a successor state */
-
- /* Each configuration becomes complete after it contibutes to a successor
- ** state. Initially, all configurations are incomplete */
- for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
-
- /* Loop through all configurations of the state "stp" */
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
- if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
- Configlist_reset(); /* Reset the new config set */
- sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */
-
- /* For every configuration in the state "stp" which has the symbol "sp"
- ** following its dot, add the same configuration to the basis set under
- ** construction but with the dot shifted one symbol to the right. */
- for(bcfp=cfp; bcfp; bcfp=bcfp->next){
- if( bcfp->status==COMPLETE ) continue; /* Already used */
- if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
- bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
- if( bsp!=sp ) continue; /* Must be same as for "cfp" */
- bcfp->status = COMPLETE; /* Mark this config as used */
- new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
- Plink_add(&new->bplp,bcfp);
- }
-
- /* Get a pointer to the state described by the basis configuration set
- ** constructed in the preceding loop */
- newstp = getstate(lemp);
-
- /* The state "newstp" is reached from the state "stp" by a shift action
- ** on the symbol "sp" */
- Action_add(&stp->ap,SHIFT,sp,newstp);
- }
-}
-
-/*
-** Construct the propagation links
-*/
-void FindLinks(lemp)
-struct lemon *lemp;
-{
- int i;
- struct config *cfp, *other;
- struct state *stp;
- struct plink *plp;
-
- /* Housekeeping detail:
- ** Add to every propagate link a pointer back to the state to
- ** which the link is attached. */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- cfp->stp = stp;
- }
- }
-
- /* Convert all backlinks into forward links. Only the forward
- ** links are used in the follow-set computation. */
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- for(plp=cfp->bplp; plp; plp=plp->next){
- other = plp->cfp;
- Plink_add(&other->fplp,cfp);
- }
- }
- }
-}
-
-/* Compute all followsets.
-**
-** A followset is the set of all symbols which can come immediately
-** after a configuration.
-*/
-void FindFollowSets(lemp)
-struct lemon *lemp;
-{
- int i;
- struct config *cfp;
- struct plink *plp;
- int progress;
- int change;
-
- for(i=0; i<lemp->nstate; i++){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- cfp->status = INCOMPLETE;
- }
- }
-
- do{
- progress = 0;
- for(i=0; i<lemp->nstate; i++){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue;
- for(plp=cfp->fplp; plp; plp=plp->next){
- change = SetUnion(plp->cfp->fws,cfp->fws);
- if( change ){
- plp->cfp->status = INCOMPLETE;
- progress = 1;
- }
- }
- cfp->status = COMPLETE;
- }
- }
- }while( progress );
-}
-
-static int resolve_conflict();
-
-/* Compute the reduce actions, and resolve conflicts.
-*/
-void FindActions(lemp)
-struct lemon *lemp;
-{
- int i,j;
- struct config *cfp;
- struct symbol *sp;
- struct rule *rp;
-
- /* Add all of the reduce actions
- ** A reduce action is added for each element of the followset of
- ** a configuration which has its dot at the extreme right.
- */
- for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
- struct state *stp;
- stp = lemp->sorted[i];
- for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
- if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
- for(j=0; j<lemp->nterminal; j++){
- if( SetFind(cfp->fws,j) ){
- /* Add a reduce action to the state "stp" which will reduce by the
- ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
- Action_add(&stp->ap,REDUCE,lemp->symbols[j],cfp->rp);
- }
- }
- }
- }
- }
-
- /* Add the accepting token */
- if( lemp->start ){
- sp = Symbol_find(lemp->start);
- if( sp==0 ) sp = lemp->rule->lhs;
- }else{
- sp = lemp->rule->lhs;
- }
- /* Add to the first state (which is always the starting state of the
- ** finite state machine) an action to ACCEPT if the lookahead is the
- ** start nonterminal. */
- Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
-
- /* Resolve conflicts */
- for(i=0; i<lemp->nstate; i++){
- struct action *ap, *nap;
- struct state *stp;
- stp = lemp->sorted[i];
- assert( stp->ap );
- stp->ap = Action_sort(stp->ap);
- for(ap=stp->ap; ap && ap->next; ap=ap->next){
- for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
- /* The two actions "ap" and "nap" have the same lookahead.
- ** Figure out which one should be used */
- lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
- }
- }
- }
-
- /* Report an error for each rule that can never be reduced. */
- for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = Bo_FALSE;
- for(i=0; i<lemp->nstate; i++){
- struct action *ap;
- for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
- if( ap->type==REDUCE ) ap->x.rp->canReduce = Bo_TRUE;
- }
- }
- for(rp=lemp->rule; rp; rp=rp->next){
- if( rp->canReduce ) continue;
- ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
- lemp->errorcnt++;
- }
-}
-
-/* Resolve a conflict between the two given actions. If the
-** conflict can't be resolve, return non-zero.
-**
-** NO LONGER TRUE:
-** To resolve a conflict, first look to see if either action
-** is on an error rule. In that case, take the action which
-** is not associated with the error rule. If neither or both
-** actions are associated with an error rule, then try to
-** use precedence to resolve the conflict.
-**
-** If either action is a SHIFT, then it must be apx. This
-** function won't work if apx->type==REDUCE and apy->type==SHIFT.
-*/
-static int resolve_conflict(apx,apy)
-struct action *apx;
-struct action *apy;
-{
- struct symbol *spx, *spy;
- int errcnt = 0;
- assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
- if( apx->type==SHIFT && apy->type==REDUCE ){
- spx = apx->sp;
- spy = apy->x.rp->precsym;
- if( spy==0 || spx->prec<0 || spy->prec<0 ){
- /* Not enough precedence information. */
- apy->type = CONFLICT;
- errcnt++;
- }else if( spx->prec>spy->prec ){ /* Lower precedence wins */
- apy->type = RD_RESOLVED;
- }else if( spx->prec<spy->prec ){
- apx->type = SH_RESOLVED;
- }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
- apy->type = RD_RESOLVED; /* associativity */
- }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */
- apx->type = SH_RESOLVED;
- }else{
- assert( spx->prec==spy->prec && spx->assoc==NONE );
- apy->type = CONFLICT;
- errcnt++;
- }
- }else if( apx->type==REDUCE && apy->type==REDUCE ){
- spx = apx->x.rp->precsym;
- spy = apy->x.rp->precsym;
- if( spx==0 || spy==0 || spx->prec<0 ||
- spy->prec<0 || spx->prec==spy->prec ){
- apy->type = CONFLICT;
- errcnt++;
- }else if( spx->prec>spy->prec ){
- apy->type = RD_RESOLVED;
- }else if( spx->prec<spy->prec ){
- apx->type = RD_RESOLVED;
- }
- }else{
- assert(
- apx->type==SH_RESOLVED ||
- apx->type==RD_RESOLVED ||
- apx->type==CONFLICT ||
- apy->type==SH_RESOLVED ||
- apy->type==RD_RESOLVED ||
- apy->type==CONFLICT
- );
- /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
- ** REDUCEs on the list. If we reach this point it must be because
- ** the parser conflict had already been resolved. */
- }
- return errcnt;
-}
-/********************* From the file "configlist.c" *************************/
-/*
-** Routines to processing a configuration list and building a state
-** in the LEMON parser generator.
-*/
-
-static struct config *freelist = 0; /* List of free configurations */
-static struct config *current = 0; /* Top of list of configurations */
-static struct config **currentend = 0; /* Last on list of configs */
-static struct config *basis = 0; /* Top of list of basis configs */
-static struct config **basisend = 0; /* End of list of basis configs */
-
-/* Return a pointer to a new configuration */
-PRIVATE struct config *newconfig(){
- struct config *new;
- if( freelist==0 ){
- int i;
- int amt = 3;
- freelist = (struct config *)malloc( sizeof(struct config)*amt );
- if( freelist==0 ){
- fprintf(stderr,"Unable to allocate memory for a new configuration.");
- exit(1);
- }
- for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
- freelist[amt-1].next = 0;
- }
- new = freelist;
- freelist = freelist->next;
- return new;
-}
-
-/* The configuration "old" is no longer used */
-PRIVATE void deleteconfig(old)
-struct config *old;
-{
- old->next = freelist;
- freelist = old;
-}
-
-/* Initialized the configuration list builder */
-void Configlist_init(){
- current = 0;
- currentend = &current;
- basis = 0;
- basisend = &basis;
- Configtable_init();
- return;
-}
-
-/* Initialized the configuration list builder */
-void Configlist_reset(){
- current = 0;
- currentend = &current;
- basis = 0;
- basisend = &basis;
- Configtable_clear(0);
- return;
-}
-
-/* Add another configuration to the configuration list */
-struct config *Configlist_add(rp,dot)
-struct rule *rp; /* The rule */
-int dot; /* Index into the RHS of the rule where the dot goes */
-{
- struct config *cfp, model;
-
- assert( currentend!=0 );
- model.rp = rp;
- model.dot = dot;
- cfp = Configtable_find(&model);
- if( cfp==0 ){
- cfp = newconfig();
- cfp->rp = rp;
- cfp->dot = dot;
- cfp->fws = SetNew();
- cfp->stp = 0;
- cfp->fplp = cfp->bplp = 0;
- cfp->next = 0;
- cfp->bp = 0;
- *currentend = cfp;
- currentend = &cfp->next;
- Configtable_insert(cfp);
- }
- return cfp;
-}
-
-/* Add a basis configuration to the configuration list */
-struct config *Configlist_addbasis(rp,dot)
-struct rule *rp;
-int dot;
-{
- struct config *cfp, model;
-
- assert( basisend!=0 );
- assert( currentend!=0 );
- model.rp = rp;
- model.dot = dot;
- cfp = Configtable_find(&model);
- if( cfp==0 ){
- cfp = newconfig();
- cfp->rp = rp;
- cfp->dot = dot;
- cfp->fws = SetNew();
- cfp->stp = 0;
- cfp->fplp = cfp->bplp = 0;
- cfp->next = 0;
- cfp->bp = 0;
- *currentend = cfp;
- currentend = &cfp->next;
- *basisend = cfp;
- basisend = &cfp->bp;
- Configtable_insert(cfp);
- }
- return cfp;
-}
-
-/* Compute the closure of the configuration list */
-void Configlist_closure(lemp)
-struct lemon *lemp;
-{
- struct config *cfp, *newcfp;
- struct rule *rp, *newrp;
- struct symbol *sp, *xsp;
- int i, dot;
-
- assert( currentend!=0 );
- for(cfp=current; cfp; cfp=cfp->next){
- rp = cfp->rp;
- dot = cfp->dot;
- if( dot>=rp->nrhs ) continue;
- sp = rp->rhs[dot];
- if( sp->type==NONTERMINAL ){
- if( sp->rule==0 && sp!=lemp->errsym ){
- ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
- sp->name);
- lemp->errorcnt++;
- }
- for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
- newcfp = Configlist_add(newrp,0);
- for(i=dot+1; i<rp->nrhs; i++){
- xsp = rp->rhs[i];
- if( xsp->type==TERMINAL ){
- SetAdd(newcfp->fws,xsp->index);
- break;
- }else{
- SetUnion(newcfp->fws,xsp->firstset);
- if( xsp->lambda==Bo_FALSE ) break;
- }
- }
- if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
- }
- }
- }
- return;
-}
-
-/* Sort the configuration list */
-void Configlist_sort(){
- current = (struct config *)msort(current,&(current->next),Configcmp);
- currentend = 0;
- return;
-}
-
-/* Sort the basis configuration list */
-void Configlist_sortbasis(){
- basis = (struct config *)msort(current,&(current->bp),Configcmp);
- basisend = 0;
- return;
-}
-
-/* Return a pointer to the head of the configuration list and
-** reset the list */
-struct config *Configlist_return(){
- struct config *old;
- old = current;
- current = 0;
- currentend = 0;
- return old;
-}
-
-/* Return a pointer to the head of the configuration list and
-** reset the list */
-struct config *Configlist_basis(){
- struct config *old;
- old = basis;
- basis = 0;
- basisend = 0;
- return old;
-}
-
-/* Free all elements of the given configuration list */
-void Configlist_eat(cfp)
-struct config *cfp;
-{
- struct config *nextcfp;
- for(; cfp; cfp=nextcfp){
- nextcfp = cfp->next;
- assert( cfp->fplp==0 );
- assert( cfp->bplp==0 );
- if( cfp->fws ) SetFree(cfp->fws);
- deleteconfig(cfp);
- }
- return;
-}
-/***************** From the file "error.c" *********************************/
-/*
-** Code for printing error message.
-*/
-
-/* Find a good place to break "msg" so that its length is at least "min"
-** but no more than "max". Make the point as close to max as possible.
-*/
-static int findbreak(msg,min,max)
-char *msg;
-int min;
-int max;
-{
- int i,spot;
- char c;
- for(i=spot=min; i<=max; i++){
- c = msg[i];
- if( c=='\t' ) msg[i] = ' ';
- if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
- if( c==0 ){ spot = i; break; }
- if( c=='-' && i<max-1 ) spot = i+1;
- if( c==' ' ) spot = i;
- }
- return spot;
-}
-
-/*
-** The error message is split across multiple lines if necessary. The
-** splits occur at a space, if there is a space available near the end
-** of the line.
-*/
-#define ERRMSGSIZE 10000 /* Hope this is big enough. No way to error check */
-#define LINEWIDTH 79 /* Max width of any output line */
-#define PREFIXLIMIT 30 /* Max width of the prefix on each line */
-void ErrorMsg(const char *filename, int lineno, const char *format, ...){
- char errmsg[ERRMSGSIZE];
- char prefix[PREFIXLIMIT+10];
- int errmsgsize;
- int prefixsize;
- int availablewidth;
- va_list ap;
- int end, restart, base;
-
- va_start(ap, format);
- /* Prepare a prefix to be prepended to every output line */
- if( lineno>0 ){
- sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
- }else{
- sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
- }
- prefixsize = strlen(prefix);
- availablewidth = LINEWIDTH - prefixsize;
-
- /* Generate the error message */
- vsprintf(errmsg,format,ap);
- va_end(ap);
- errmsgsize = strlen(errmsg);
- /* Remove trailing '\n's from the error message. */
- while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
- errmsg[--errmsgsize] = 0;
- }
-
- /* Print the error message */
- base = 0;
- while( errmsg[base]!=0 ){
- end = restart = findbreak(&errmsg[base],0,availablewidth);
- restart += base;
- while( errmsg[restart]==' ' ) restart++;
- fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
- base = restart;
- }
-}
-/**************** From the file "main.c" ************************************/
-/*
-** Main program file for the LEMON parser generator.
-*/
-
-/* Report an out-of-memory condition and abort. This function
-** is used mostly by the "MemoryCheck" macro in struct.h
-*/
-void memory_error(){
- fprintf(stderr,"Out of memory. Aborting...\n");
- exit(1);
-}
-
-
-/* The main program. Parse the command line and do it... */
-int main(argc,argv)
-int argc;
-char **argv;
-{
- static int version = 0;
- static int rpflag = 0;
- static int basisflag = 0;
- static int compress = 0;
- static int quiet = 0;
- static int statistics = 0;
- static int mhflag = 0;
- static struct s_options options[] = {
- {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
- {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
- {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
- {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
- {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
- {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."},
- {OPT_FLAG, "x", (char*)&version, "Print the version number."},
- {OPT_FLAG,0,0,0}
- };
- int i;
- struct lemon lem;
- char *def_tmpl_name = "lempar.c";
- ( (void) argc ); // UNUSED(argc)
-
- OptInit(argv,options,stderr);
- if( version ){
- printf("Lemon version 1.0\n");
- exit(0);
- }
- if( OptNArgs() < 1 ){
- fprintf(stderr,"Exactly one filename argument is required.\n");
- exit(1);
- }
- lem.errorcnt = 0;
-
- /* Initialize the machine */
- Strsafe_init();
- Symbol_init();
- State_init();
- lem.argv0 = argv[0];
- lem.filename = OptArg(0);
- lem.tmplname = (OptNArgs() == 2) ? OptArg(1) : def_tmpl_name;
- lem.basisflag = basisflag;
- lem.has_fallback = 0;
- lem.nconflict = 0;
- lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
- lem.vartype = 0;
- lem.stacksize = 0;
- lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
- lem.tokenprefix = lem.outname = lem.extracode = 0;
- lem.vardest = 0;
- lem.tablesize = 0;
- Symbol_new("$");
- lem.errsym = Symbol_new("error");
-
- /* Parse the input file */
- Parse(&lem);
- if( lem.errorcnt ) exit(lem.errorcnt);
- if( lem.rule==0 ){
- fprintf(stderr,"Empty grammar.\n");
- exit(1);
- }
-
- /* Count and index the symbols of the grammar */
- lem.nsymbol = Symbol_count();
- Symbol_new("{default}");
- lem.symbols = Symbol_arrayof();
- for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
- qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
- (int(*)())Symbolcmpp);
- for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
- for(i=1; isupper(lem.symbols[i]->name[0]); i++);
- lem.nterminal = i;
-
- /* Generate a reprint of the grammar, if requested on the command line */
- if( rpflag ){
- Reprint(&lem);
- }else{
- /* Initialize the size for all follow and first sets */
- SetSize(lem.nterminal);
-
- /* Find the precedence for every production rule (that has one) */
- FindRulePrecedences(&lem);
-
- /* Compute the lambda-nonterminals and the first-sets for every
- ** nonterminal */
- FindFirstSets(&lem);
-
- /* Compute all LR(0) states. Also record follow-set propagation
- ** links so that the follow-set can be computed later */
- lem.nstate = 0;
- FindStates(&lem);
- lem.sorted = State_arrayof();
-
- /* Tie up loose ends on the propagation links */
- FindLinks(&lem);
-
- /* Compute the follow set of every reducible configuration */
- FindFollowSets(&lem);
-
- /* Compute the action tables */
- FindActions(&lem);
-
- /* Compress the action tables */
- if( compress==0 ) CompressTables(&lem);
-
- /* Generate a report of the parser generated. (the "y.output" file) */
- if( !quiet ) ReportOutput(&lem);
-
- /* Generate the source code for the parser */
- ReportTable(&lem, mhflag);
-
- /* Produce a header file for use by the scanner. (This step is
- ** omitted if the "-m" option is used because makeheaders will
- ** generate the file for us.) */
- if( !mhflag ) ReportHeader(&lem);
- }
- if( statistics ){
- printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
- lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
- printf(" %d states, %d parser table entries, %d conflicts\n",
- lem.nstate, lem.tablesize, lem.nconflict);
- }
- if( lem.nconflict ){
- fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
- }
- exit(lem.errorcnt + lem.nconflict);
-}
-/******************** From the file "msort.c" *******************************/
-/*
-** A generic merge-sort program.
-**
-** USAGE:
-** Let "ptr" be a pointer to some structure which is at the head of
-** a null-terminated list. Then to sort the list call:
-**
-** ptr = msort(ptr,&(ptr->next),cmpfnc);
-**
-** In the above, "cmpfnc" is a pointer to a function which compares
-** two instances of the structure and returns an integer, as in
-** strcmp. The second argument is a pointer to the pointer to the
-** second element of the linked list. This address is used to compute
-** the offset to the "next" field within the structure. The offset to
-** the "next" field must be constant for all structures in the list.
-**
-** The function returns a new pointer which is the head of the list
-** after sorting.
-**
-** ALGORITHM:
-** Merge-sort.
-*/
-
-/*
-** Return a pointer to the next structure in the linked list.
-*/
-#define NEXT(A) (*(char**)(((unsigned long)A)+offset))
-
-/*
-** Inputs:
-** a: A sorted, null-terminated linked list. (May be null).
-** b: A sorted, null-terminated linked list. (May be null).
-** cmp: A pointer to the comparison function.
-** offset: Offset in the structure to the "next" field.
-**
-** Return Value:
-** A pointer to the head of a sorted list containing the elements
-** of both a and b.
-**
-** Side effects:
-** The "next" pointers for elements in the lists a and b are
-** changed.
-*/
-static char *merge(a,b,cmp,offset)
-char *a;
-char *b;
-int (*cmp)();
-int offset;
-{
- char *ptr, *head;
-
- if( a==0 ){
- head = b;
- }else if( b==0 ){
- head = a;
- }else{
- if( (*cmp)(a,b)<0 ){
- ptr = a;
- a = NEXT(a);
- }else{
- ptr = b;
- b = NEXT(b);
- }
- head = ptr;
- while( a && b ){
- if( (*cmp)(a,b)<0 ){
- NEXT(ptr) = a;
- ptr = a;
- a = NEXT(a);
- }else{
- NEXT(ptr) = b;
- ptr = b;
- b = NEXT(b);
- }
- }
- if( a ) NEXT(ptr) = a;
- else NEXT(ptr) = b;
- }
- return head;
-}
-
-/*
-** Inputs:
-** list: Pointer to a singly-linked list of structures.
-** next: Pointer to pointer to the second element of the list.
-** cmp: A comparison function.
-**
-** Return Value:
-** A pointer to the head of a sorted list containing the elements
-** orginally in list.
-**
-** Side effects:
-** The "next" pointers for elements in list are changed.
-*/
-#define LISTSIZE 30
-char *msort(list,next,cmp)
-char *list;
-char **next;
-int (*cmp)();
-{
- unsigned long offset;
- char *ep;
- char *set[LISTSIZE];
- int i;
- offset = (unsigned long)next - (unsigned long)list;
- for(i=0; i<LISTSIZE; i++) set[i] = 0;
- while( list ){
- ep = list;
- list = NEXT(list);
- NEXT(ep) = 0;
- for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
- ep = merge(ep,set[i],cmp,offset);
- set[i] = 0;
- }
- set[i] = ep;
- }
- ep = 0;
- for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
- return ep;
-}
-/************************ From the file "option.c" **************************/
-static char **argv;
-static struct s_options *op;
-static FILE *errstream;
-
-#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
-
-/*
-** Print the command line with a carrot pointing to the k-th character
-** of the n-th field.
-*/
-static void errline(n,k,err)
-int n;
-int k;
-FILE *err;
-{
- int spcnt, i;
- spcnt = 0;
- if( argv[0] ) fprintf(err,"%s",argv[0]);
- spcnt = strlen(argv[0]) + 1;
- for(i=1; i<n && argv[i]; i++){
- fprintf(err," %s",argv[i]);
- spcnt += strlen(argv[i]+1);
- }
- spcnt += k;
- for(; argv[i]; i++) fprintf(err," %s",argv[i]);
- if( spcnt<20 ){
- fprintf(err,"\n%*s^-- here\n",spcnt,"");
- }else{
- fprintf(err,"\n%*shere --^\n",spcnt-7,"");
- }
-}
-
-/*
-** Return the index of the N-th non-switch argument. Return -1
-** if N is out of range.
-*/
-static int argindex(n)
-int n;
-{
- int i;
- int dashdash = 0;
- if( argv!=0 && *argv!=0 ){
- for(i=1; argv[i]; i++){
- if( dashdash || !ISOPT(argv[i]) ){
- if( n==0 ) return i;
- n--;
- }
- if( strcmp(argv[i],"--")==0 ) dashdash = 1;
- }
- }
- return -1;
-}
-
-static char emsg[] = "Command line syntax error: ";
-
-/*
-** Process a flag command line argument.
-*/
-static int handleflags(i,err)
-int i;
-FILE *err;
-{
- int v;
- int errcnt = 0;
- int j;
- for(j=0; op[j].label; j++){
- if( strcmp(&argv[i][1],op[j].label)==0 ) break;
- }
- v = argv[i][0]=='-' ? 1 : 0;
- if( op[j].label==0 ){
- if( err ){
- fprintf(err,"%sundefined option.\n",emsg);
- errline(i,1,err);
- }
- errcnt++;
- }else if( op[j].type==OPT_FLAG ){
- *((int*)op[j].arg) = v;
- }else if( op[j].type==OPT_FFLAG ){
- (*(void(*)())((intptr_t)op[j].arg))(v);
- }else{
- if( err ){
- fprintf(err,"%smissing argument on switch.\n",emsg);
- errline(i,1,err);
- }
- errcnt++;
- }
- return errcnt;
-}
-
-/*
-** Process a command line switch which has an argument.
-*/
-static int handleswitch(i,err)
-int i;
-FILE *err;
-{
- int lv = 0;
- double dv = 0.0;
- char *sv = 0, *end;
- char *cp;
- int j;
- int errcnt = 0;
- cp = strchr(argv[i],'=');
- *cp = 0;
- for(j=0; op[j].label; j++){
- if( strcmp(argv[i],op[j].label)==0 ) break;
- }
- *cp = '=';
- if( op[j].label==0 ){
- if( err ){
- fprintf(err,"%sundefined option.\n",emsg);
- errline(i,0,err);
- }
- errcnt++;
- }else{
- cp++;
- switch( op[j].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- if( err ){
- fprintf(err,"%soption requires an argument.\n",emsg);
- errline(i,0,err);
- }
- errcnt++;
- break;
- case OPT_DBL:
- case OPT_FDBL:
- dv = strtod(cp,&end);
- if( *end ){
- if( err ){
- fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
- errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
- }
- errcnt++;
- }
- break;
- case OPT_INT:
- case OPT_FINT:
- lv = strtol(cp,&end,0);
- if( *end ){
- if( err ){
- fprintf(err,"%sillegal character in integer argument.\n",emsg);
- errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
- }
- errcnt++;
- }
- break;
- case OPT_STR:
- case OPT_FSTR:
- sv = cp;
- break;
- }
- switch( op[j].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- break;
- case OPT_DBL:
- *(double*)(op[j].arg) = dv;
- break;
- case OPT_FDBL:
- (*(void(*)())((intptr_t)op[j].arg))(dv);
- break;
- case OPT_INT:
- *(int*)(op[j].arg) = lv;
- break;
- case OPT_FINT:
- (*(void(*)())((intptr_t)op[j].arg))((int)lv);
- break;
- case OPT_STR:
- *(char**)(op[j].arg) = sv;
- break;
- case OPT_FSTR:
- (*(void(*)())((intptr_t)op[j].arg))(sv);
- break;
- }
- }
- return errcnt;
-}
-
-int OptInit(a,o,err)
-char **a;
-struct s_options *o;
-FILE *err;
-{
- int errcnt = 0;
- argv = a;
- op = o;
- errstream = err;
- if( argv && *argv && op ){
- int i;
- for(i=1; argv[i]; i++){
- if( argv[i][0]=='+' || argv[i][0]=='-' ){
- errcnt += handleflags(i,err);
- }else if( strchr(argv[i],'=') ){
- errcnt += handleswitch(i,err);
- }
- }
- }
- if( errcnt>0 ){
- fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
- OptPrint();
- exit(1);
- }
- return 0;
-}
-
-int OptNArgs(){
- int cnt = 0;
- int dashdash = 0;
- int i;
- if( argv!=0 && argv[0]!=0 ){
- for(i=1; argv[i]; i++){
- if( dashdash || !ISOPT(argv[i]) ) cnt++;
- if( strcmp(argv[i],"--")==0 ) dashdash = 1;
- }
- }
- return cnt;
-}
-
-char *OptArg(n)
-int n;
-{
- int i;
- i = argindex(n);
- return i>=0 ? argv[i] : 0;
-}
-
-void OptErr(n)
-int n;
-{
- int i;
- i = argindex(n);
- if( i>=0 ) errline(i,0,errstream);
-}
-
-void OptPrint(){
- int i;
- int max, len;
- max = 0;
- for(i=0; op[i].label; i++){
- len = strlen(op[i].label) + 1;
- switch( op[i].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- break;
- case OPT_INT:
- case OPT_FINT:
- len += 9; /* length of "<integer>" */
- break;
- case OPT_DBL:
- case OPT_FDBL:
- len += 6; /* length of "<real>" */
- break;
- case OPT_STR:
- case OPT_FSTR:
- len += 8; /* length of "<string>" */
- break;
- }
- if( len>max ) max = len;
- }
- for(i=0; op[i].label; i++){
- switch( op[i].type ){
- case OPT_FLAG:
- case OPT_FFLAG:
- fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
- break;
- case OPT_INT:
- case OPT_FINT:
- fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
- (int)(max-strlen(op[i].label)-9),"",op[i].message);
- break;
- case OPT_DBL:
- case OPT_FDBL:
- fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
- (int)(max-strlen(op[i].label)-6),"",op[i].message);
- break;
- case OPT_STR:
- case OPT_FSTR:
- fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
- (int)(max-strlen(op[i].label)-8),"",op[i].message);
- break;
- }
- }
-}
-/*********************** From the file "parse.c" ****************************/
-/*
-** Input file parser for the LEMON parser generator.
-*/
-
-/* The state of the parser */
-struct pstate {
- char *filename; /* Name of the input file */
- int tokenlineno; /* Linenumber at which current token starts */
- int errorcnt; /* Number of errors so far */
- char *tokenstart; /* Text of current token */
- struct lemon *gp; /* Global state vector */
- enum e_state {
- INITIALIZE,
- WAITING_FOR_DECL_OR_RULE,
- WAITING_FOR_DECL_KEYWORD,
- WAITING_FOR_DECL_ARG,
- WAITING_FOR_PRECEDENCE_SYMBOL,
- WAITING_FOR_ARROW,
- IN_RHS,
- LHS_ALIAS_1,
- LHS_ALIAS_2,
- LHS_ALIAS_3,
- RHS_ALIAS_1,
- RHS_ALIAS_2,
- PRECEDENCE_MARK_1,
- PRECEDENCE_MARK_2,
- RESYNC_AFTER_RULE_ERROR,
- RESYNC_AFTER_DECL_ERROR,
- WAITING_FOR_DESTRUCTOR_SYMBOL,
- WAITING_FOR_DATATYPE_SYMBOL,
- WAITING_FOR_FALLBACK_ID
- } state; /* The state of the parser */
- struct symbol *fallback; /* The fallback token */
- struct symbol *lhs; /* Left-hand side of current rule */
- char *lhsalias; /* Alias for the LHS */
- int nrhs; /* Number of right-hand side symbols seen */
- struct symbol *rhs[MAXRHS]; /* RHS symbols */
- char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
- struct rule *prevrule; /* Previous rule parsed */
- char *declkeyword; /* Keyword of a declaration */
- char **declargslot; /* Where the declaration argument should be put */
- int *decllnslot; /* Where the declaration linenumber is put */
- enum e_assoc declassoc; /* Assign this association to decl arguments */
- int preccounter; /* Assign this precedence to decl arguments */
- struct rule *firstrule; /* Pointer to first rule in the grammar */
- struct rule *lastrule; /* Pointer to the most recently parsed rule */
-};
-
-/* Parse a single token */
-static void parseonetoken(psp)
-struct pstate *psp;
-{
- char *x;
- x = Strsafe(psp->tokenstart); /* Save the token permanently */
-#if 0
- printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
- x,psp->state);
-#endif
- switch( psp->state ){
- case INITIALIZE:
- psp->prevrule = 0;
- psp->preccounter = 0;
- psp->firstrule = psp->lastrule = 0;
- psp->gp->nrule = 0;
- /* Fall thru to next case */
- case WAITING_FOR_DECL_OR_RULE:
- if( x[0]=='%' ){
- psp->state = WAITING_FOR_DECL_KEYWORD;
- }else if( islower(x[0]) ){
- psp->lhs = Symbol_new(x);
- psp->nrhs = 0;
- psp->lhsalias = 0;
- psp->state = WAITING_FOR_ARROW;
- }else if( x[0]=='{' ){
- if( psp->prevrule==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"There is not prior rule opon which to attach the code \
-fragment which begins on this line.");
- psp->errorcnt++;
- }else if( psp->prevrule->code!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"Code fragment beginning on this line is not the first \
-to follow the previous rule.");
- psp->errorcnt++;
- }else{
- psp->prevrule->line = psp->tokenlineno;
- psp->prevrule->code = &x[1];
- }
- }else if( x[0]=='[' ){
- psp->state = PRECEDENCE_MARK_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Token \"%s\" should be either \"%%\" or a nonterminal name.",
- x);
- psp->errorcnt++;
- }
- break;
- case PRECEDENCE_MARK_1:
- if( !isupper(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "The precedence symbol must be a terminal.");
- psp->errorcnt++;
- }else if( psp->prevrule==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "There is no prior rule to assign precedence \"[%s]\".",x);
- psp->errorcnt++;
- }else if( psp->prevrule->precsym!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
-"Precedence mark on this line is not the first \
-to follow the previous rule.");
- psp->errorcnt++;
- }else{
- psp->prevrule->precsym = Symbol_new(x);
- }
- psp->state = PRECEDENCE_MARK_2;
- break;
- case PRECEDENCE_MARK_2:
- if( x[0]!=']' ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \"]\" on precedence mark.");
- psp->errorcnt++;
- }
- psp->state = WAITING_FOR_DECL_OR_RULE;
- break;
- case WAITING_FOR_ARROW:
- if( x[0]==':' && x[1]==':' && x[2]=='=' ){
- psp->state = IN_RHS;
- }else if( x[0]=='(' ){
- psp->state = LHS_ALIAS_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Expected to see a \":\" following the LHS symbol \"%s\".",
- psp->lhs->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_1:
- if( isalpha(x[0]) ){
- psp->lhsalias = x;
- psp->state = LHS_ALIAS_2;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "\"%s\" is not a valid alias for the LHS \"%s\"\n",
- x,psp->lhs->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_2:
- if( x[0]==')' ){
- psp->state = LHS_ALIAS_3;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case LHS_ALIAS_3:
- if( x[0]==':' && x[1]==':' && x[2]=='=' ){
- psp->state = IN_RHS;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \"->\" following: \"%s(%s)\".",
- psp->lhs->name,psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case IN_RHS:
- if( x[0]=='.' ){
- struct rule *rp;
- rp = (struct rule *)malloc( sizeof(struct rule) +
- sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
- if( rp==0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Can't allocate enough memory for this rule.");
- psp->errorcnt++;
- psp->prevrule = 0;
- }else{
- int i;
- rp->ruleline = psp->tokenlineno;
- rp->rhs = (struct symbol**)&rp[1];
- rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
- for(i=0; i<psp->nrhs; i++){
- rp->rhs[i] = psp->rhs[i];
- rp->rhsalias[i] = psp->alias[i];
- }
- rp->lhs = psp->lhs;
- rp->lhsalias = psp->lhsalias;
- rp->nrhs = psp->nrhs;
- rp->code = 0;
- rp->precsym = 0;
- rp->index = psp->gp->nrule++;
- rp->nextlhs = rp->lhs->rule;
- rp->lhs->rule = rp;
- rp->next = 0;
- if( psp->firstrule==0 ){
- psp->firstrule = psp->lastrule = rp;
- }else{
- psp->lastrule->next = rp;
- psp->lastrule = rp;
- }
- psp->prevrule = rp;
- }
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( isalpha(x[0]) ){
- if( psp->nrhs>=MAXRHS ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Too many symbol on RHS or rule beginning at \"%s\".",
- x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }else{
- psp->rhs[psp->nrhs] = Symbol_new(x);
- psp->alias[psp->nrhs] = 0;
- psp->nrhs++;
- }
- }else if( x[0]=='(' && psp->nrhs>0 ){
- psp->state = RHS_ALIAS_1;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal character on RHS of rule: \"%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case RHS_ALIAS_1:
- if( isalpha(x[0]) ){
- psp->alias[psp->nrhs-1] = x;
- psp->state = RHS_ALIAS_2;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
- x,psp->rhs[psp->nrhs-1]->name);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case RHS_ALIAS_2:
- if( x[0]==')' ){
- psp->state = IN_RHS;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_RULE_ERROR;
- }
- break;
- case WAITING_FOR_DECL_KEYWORD:
- if( isalpha(x[0]) ){
- psp->declkeyword = x;
- psp->declargslot = 0;
- psp->decllnslot = 0;
- psp->state = WAITING_FOR_DECL_ARG;
- if( strcmp(x,"name")==0 ){
- psp->declargslot = &(psp->gp->name);
- }else if( strcmp(x,"include")==0 ){
- psp->declargslot = &(psp->gp->include);
- psp->decllnslot = &psp->gp->includeln;
- }else if( strcmp(x,"code")==0 ){
- psp->declargslot = &(psp->gp->extracode);
- psp->decllnslot = &psp->gp->extracodeln;
- }else if( strcmp(x,"token_destructor")==0 ){
- psp->declargslot = &psp->gp->tokendest;
- psp->decllnslot = &psp->gp->tokendestln;
- }else if( strcmp(x,"default_destructor")==0 ){
- psp->declargslot = &psp->gp->vardest;
- psp->decllnslot = &psp->gp->vardestln;
- }else if( strcmp(x,"token_prefix")==0 ){
- psp->declargslot = &psp->gp->tokenprefix;
- }else if( strcmp(x,"syntax_error")==0 ){
- psp->declargslot = &(psp->gp->error);
- psp->decllnslot = &psp->gp->errorln;
- }else if( strcmp(x,"parse_accept")==0 ){
- psp->declargslot = &(psp->gp->accept);
- psp->decllnslot = &psp->gp->acceptln;
- }else if( strcmp(x,"parse_failure")==0 ){
- psp->declargslot = &(psp->gp->failure);
- psp->decllnslot = &psp->gp->failureln;
- }else if( strcmp(x,"stack_overflow")==0 ){
- psp->declargslot = &(psp->gp->overflow);
- psp->decllnslot = &psp->gp->overflowln;
- }else if( strcmp(x,"extra_argument")==0 ){
- psp->declargslot = &(psp->gp->arg);
- }else if( strcmp(x,"token_type")==0 ){
- psp->declargslot = &(psp->gp->tokentype);
- }else if( strcmp(x,"default_type")==0 ){
- psp->declargslot = &(psp->gp->vartype);
- }else if( strcmp(x,"stack_size")==0 ){
- psp->declargslot = &(psp->gp->stacksize);
- }else if( strcmp(x,"start_symbol")==0 ){
- psp->declargslot = &(psp->gp->start);
- }else if( strcmp(x,"left")==0 ){
- psp->preccounter++;
- psp->declassoc = LEFT;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"right")==0 ){
- psp->preccounter++;
- psp->declassoc = RIGHT;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"nonassoc")==0 ){
- psp->preccounter++;
- psp->declassoc = NONE;
- psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
- }else if( strcmp(x,"destructor")==0 ){
- psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
- }else if( strcmp(x,"type")==0 ){
- psp->state = WAITING_FOR_DATATYPE_SYMBOL;
- }else if( strcmp(x,"fallback")==0 ){
- psp->fallback = 0;
- psp->state = WAITING_FOR_FALLBACK_ID;
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Unknown declaration keyword: \"%%%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal declaration keyword: \"%s\".",x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case WAITING_FOR_DESTRUCTOR_SYMBOL:
- if( !isalpha(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol name missing after %destructor keyword");
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- struct symbol *sp = Symbol_new(x);
- psp->declargslot = &sp->destructor;
- psp->decllnslot = &sp->destructorln;
- psp->state = WAITING_FOR_DECL_ARG;
- }
- break;
- case WAITING_FOR_DATATYPE_SYMBOL:
- if( !isalpha(x[0]) ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol name missing after %destructor keyword");
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- struct symbol *sp = Symbol_new(x);
- psp->declargslot = &sp->datatype;
- psp->decllnslot = 0;
- psp->state = WAITING_FOR_DECL_ARG;
- }
- break;
- case WAITING_FOR_PRECEDENCE_SYMBOL:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( isupper(x[0]) ){
- struct symbol *sp;
- sp = Symbol_new(x);
- if( sp->prec>=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Symbol \"%s\" has already be given a precedence.",x);
- psp->errorcnt++;
- }else{
- sp->prec = psp->preccounter;
- sp->assoc = psp->declassoc;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Can't assign a precedence to \"%s\".",x);
- psp->errorcnt++;
- }
- break;
- case WAITING_FOR_DECL_ARG:
- if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
- if( *(psp->declargslot)!=0 ){
- ErrorMsg(psp->filename,psp->tokenlineno,
- "The argument \"%s\" to declaration \"%%%s\" is not the first.",
- x[0]=='\"' ? &x[1] : x,psp->declkeyword);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }else{
- *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
- if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }
- }else{
- ErrorMsg(psp->filename,psp->tokenlineno,
- "Illegal argument to %%%s: %s",psp->declkeyword,x);
- psp->errorcnt++;
- psp->state = RESYNC_AFTER_DECL_ERROR;
- }
- break;
- case WAITING_FOR_FALLBACK_ID:
- if( x[0]=='.' ){
- psp->state = WAITING_FOR_DECL_OR_RULE;
- }else if( !isupper(x[0]) ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%fallback argument \"%s\" should be a token", x);
- psp->errorcnt++;
- }else{
- struct symbol *sp = Symbol_new(x);
- if( psp->fallback==0 ){
- psp->fallback = sp;
- }else if( sp->fallback ){
- ErrorMsg(psp->filename, psp->tokenlineno,
- "More than one fallback assigned to token %s", x);
- psp->errorcnt++;
- }else{
- sp->fallback = psp->fallback;
- psp->gp->has_fallback = 1;
- }
- }
- break;
- case RESYNC_AFTER_RULE_ERROR:
-/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
-** break; */
- case RESYNC_AFTER_DECL_ERROR:
- if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
- if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
- break;
- }
-}
-
-/* In spite of its name, this function is really a scanner. It read
-** in the entire input file (all at once) then tokenizes it. Each
-** token is passed to the function "parseonetoken" which builds all
-** the appropriate data structures in the global state vector "gp".
-*/
-struct pstate ps;
-void Parse(gp)
-struct lemon *gp;
-{
- FILE *fp;
- char *filebuf;
- size_t filesize;
- int lineno;
- int c;
- char *cp, *nextcp;
- int startline = 0;
-
- ps.gp = gp;
- ps.filename = gp->filename;
- ps.errorcnt = 0;
- ps.state = INITIALIZE;
-
- /* Begin by reading the input file */
- fp = fopen(ps.filename,"rb");
- if( fp==0 ){
- ErrorMsg(ps.filename,0,"Can't open this file for reading.");
- gp->errorcnt++;
- return;
- }
- fseek(fp,0,2);
- filesize = ftell(fp);
- rewind(fp);
- filebuf = (char *)malloc( filesize+1 );
- if( filebuf==0 ){
- ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
- filesize+1);
- fclose(fp);
- gp->errorcnt++;
- return;
- }
- if( fread(filebuf,1,filesize,fp)!=filesize ){
- ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
- filesize);
- free(filebuf);
- fclose(fp);
- gp->errorcnt++;
- return;
- }
- fclose(fp);
- filebuf[filesize] = 0;
-
- /* Now scan the text of the input file */
- lineno = 1;
- for(cp=filebuf; (c= *cp)!=0; ){
- if( c=='\n' ) lineno++; /* Keep track of the line number */
- if( isspace(c) ){ cp++; continue; } /* Skip all white space */
- if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
- cp+=2;
- while( (c= *cp)!=0 && c!='\n' ) cp++;
- continue;
- }
- if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
- cp+=2;
- while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
- if( c=='\n' ) lineno++;
- cp++;
- }
- if( c ) cp++;
- continue;
- }
- ps.tokenstart = cp; /* Mark the beginning of the token */
- ps.tokenlineno = lineno; /* Linenumber on which token begins */
- if( c=='\"' ){ /* String literals */
- cp++;
- while( (c= *cp)!=0 && c!='\"' ){
- if( c=='\n' ) lineno++;
- cp++;
- }
- if( c==0 ){
- ErrorMsg(ps.filename,startline,
-"String starting on this line is not terminated before the end of the file.");
- ps.errorcnt++;
- nextcp = cp;
- }else{
- nextcp = cp+1;
- }
- }else if( c=='{' ){ /* A block of C code */
- int level;
- cp++;
- for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
- if( c=='\n' ) lineno++;
- else if( c=='{' ) level++;
- else if( c=='}' ) level--;
- else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
- int prevc;
- cp = &cp[2];
- prevc = 0;
- while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
- if( c=='\n' ) lineno++;
- prevc = c;
- cp++;
- }
- }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
- cp = &cp[2];
- while( (c= *cp)!=0 && c!='\n' ) cp++;
- if( c ) lineno++;
- }else if( c=='\'' || c=='\"' ){ /* String a character literals */
- int startchar, prevc;
- startchar = c;
- prevc = 0;
- for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
- if( c=='\n' ) lineno++;
- if( prevc=='\\' ) prevc = 0;
- else prevc = c;
- }
- }
- }
- if( c==0 ){
- ErrorMsg(ps.filename,ps.tokenlineno,
-"C code starting on this line is not terminated before the end of the file.");
- ps.errorcnt++;
- nextcp = cp;
- }else{
- nextcp = cp+1;
- }
- }else if( isalnum(c) ){ /* Identifiers */
- while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
- nextcp = cp;
- }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
- cp += 3;
- nextcp = cp;
- }else{ /* All other (one character) operators */
- cp++;
- nextcp = cp;
- }
- c = *cp;
- *cp = 0; /* Null terminate the token */
- parseonetoken(&ps); /* Parse the token */
- *cp = c; /* Restore the buffer */
- cp = nextcp;
- }
- free(filebuf); /* Release the buffer after parsing */
- gp->rule = ps.firstrule;
- gp->errorcnt = ps.errorcnt;
-}
-/*************************** From the file "plink.c" *********************/
-/*
-** Routines processing configuration follow-set propagation links
-** in the LEMON parser generator.
-*/
-static struct plink *plink_freelist = 0;
-
-/* Allocate a new plink */
-struct plink *Plink_new(){
- struct plink *new;
-
- if( plink_freelist==0 ){
- int i;
- int amt = 100;
- plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
- if( plink_freelist==0 ){
- fprintf(stderr,
- "Unable to allocate memory for a new follow-set propagation link.\n");
- exit(1);
- }
- for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
- plink_freelist[amt-1].next = 0;
- }
- new = plink_freelist;
- plink_freelist = plink_freelist->next;
- return new;
-}
-
-/* Add a plink to a plink list */
-void Plink_add(plpp,cfp)
-struct plink **plpp;
-struct config *cfp;
-{
- struct plink *new;
- new = Plink_new();
- new->next = *plpp;
- *plpp = new;
- new->cfp = cfp;
-}
-
-/* Transfer every plink on the list "from" to the list "to" */
-void Plink_copy(to,from)
-struct plink **to;
-struct plink *from;
-{
- struct plink *nextpl;
- while( from ){
- nextpl = from->next;
- from->next = *to;
- *to = from;
- from = nextpl;
- }
-}
-
-/* Delete every plink on the list */
-void Plink_delete(plp)
-struct plink *plp;
-{
- struct plink *nextpl;
-
- while( plp ){
- nextpl = plp->next;
- plp->next = plink_freelist;
- plink_freelist = plp;
- plp = nextpl;
- }
-}
-/*********************** From the file "report.c" **************************/
-/*
-** Procedures for generating reports and tables in the LEMON parser generator.
-*/
-
-/* Generate a filename with the given suffix. Space to hold the
-** name comes from malloc() and must be freed by the calling
-** function.
-*/
-PRIVATE char *file_makename(lemp,suffix)
-struct lemon *lemp;
-char *suffix;
-{
- char *name;
- char *cp;
-
- name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
- if( name==0 ){
- fprintf(stderr,"Can't allocate space for a filename.\n");
- exit(1);
- }
- /* skip directory, JK */
- if (NULL == (cp = strrchr(lemp->filename, '/'))) {
- cp = lemp->filename;
- } else {
- cp++;
- }
- strcpy(name,cp);
- cp = strrchr(name,'.');
- if( cp ) *cp = 0;
- strcat(name,suffix);
- return name;
-}
-
-/* Open a file with a name based on the name of the input file,
-** but with a different (specified) suffix, and return a pointer
-** to the stream */
-PRIVATE FILE *file_open(lemp,suffix,mode)
-struct lemon *lemp;
-char *suffix;
-char *mode;
-{
- FILE *fp;
-
- if( lemp->outname ) free(lemp->outname);
- lemp->outname = file_makename(lemp, suffix);
- fp = fopen(lemp->outname,mode);
- if( fp==0 && *mode=='w' ){
- fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
- lemp->errorcnt++;
- return 0;
- }
- return fp;
-}
-
-/* Duplicate the input file without comments and without actions
-** on rules */
-void Reprint(lemp)
-struct lemon *lemp;
-{
- struct rule *rp;
- struct symbol *sp;
- int i, j, maxlen, len, ncolumns, skip;
- printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
- maxlen = 10;
- for(i=0; i<lemp->nsymbol; i++){
- sp = lemp->symbols[i];
- len = strlen(sp->name);
- if( len>maxlen ) maxlen = len;
- }
- ncolumns = 76/(maxlen+5);
- if( ncolumns<1 ) ncolumns = 1;
- skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
- for(i=0; i<skip; i++){
- printf("//");
- for(j=i; j<lemp->nsymbol; j+=skip){
- sp = lemp->symbols[j];
- assert( sp->index==j );
- printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
- }
- printf("\n");
- }
- for(rp=lemp->rule; rp; rp=rp->next){
- printf("%s",rp->lhs->name);
-/* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
- printf(" ::=");
- for(i=0; i<rp->nrhs; i++){
- printf(" %s",rp->rhs[i]->name);
-/* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
- }
- printf(".");
- if( rp->precsym ) printf(" [%s]",rp->precsym->name);
-/* if( rp->code ) printf("\n %s",rp->code); */
- printf("\n");
- }
-}
-
-PRIVATE void ConfigPrint(fp,cfp)
-FILE *fp;
-struct config *cfp;
-{
- struct rule *rp;
- int i;
- rp = cfp->rp;
- fprintf(fp,"%s ::=",rp->lhs->name);
- for(i=0; i<=rp->nrhs; i++){
- if( i==cfp->dot ) fprintf(fp," *");
- if( i==rp->nrhs ) break;
- fprintf(fp," %s",rp->rhs[i]->name);
- }
-}
-
-/* #define TEST */
-#ifdef TEST
-/* Print a set */
-PRIVATE void SetPrint(out,set,lemp)
-FILE *out;
-char *set;
-struct lemon *lemp;
-{
- int i;
- char *spacer;
- spacer = "";
- fprintf(out,"%12s[","");
- for(i=0; i<lemp->nterminal; i++){
- if( SetFind(set,i) ){
- fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
- spacer = " ";
- }
- }
- fprintf(out,"]\n");
-}
-
-/* Print a plink chain */
-PRIVATE void PlinkPrint(out,plp,tag)
-FILE *out;
-struct plink *plp;
-char *tag;
-{
- while( plp ){
- fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index);
- ConfigPrint(out,plp->cfp);
- fprintf(out,"\n");
- plp = plp->next;
- }
-}
-#endif
-
-/* Print an action to the given file descriptor. Return FALSE if
-** nothing was actually printed.
-*/
-PRIVATE int PrintAction(struct action *ap, FILE *fp, int indent){
- int result = 1;
- switch( ap->type ){
- case SHIFT:
- fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->index);
- break;
- case REDUCE:
- fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
- break;
- case ACCEPT:
- fprintf(fp,"%*s accept",indent,ap->sp->name);
- break;
- case ERROR:
- fprintf(fp,"%*s error",indent,ap->sp->name);
- break;
- case CONFLICT:
- fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
- indent,ap->sp->name,ap->x.rp->index);
- break;
- case SH_RESOLVED:
- case RD_RESOLVED:
- case NOT_USED:
- result = 0;
- break;
- }
- return result;
-}
-
-/* Generate the "y.output" log file */
-void ReportOutput(lemp)
-struct lemon *lemp;
-{
- int i;
- struct state *stp;
- struct config *cfp;
- struct action *ap;
- FILE *fp;
-
- fp = file_open(lemp,".out","w");
- if( fp==0 ) return;
- fprintf(fp," \b");
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- fprintf(fp,"State %d:\n",stp->index);
- if( lemp->basisflag ) cfp=stp->bp;
- else cfp=stp->cfp;
- while( cfp ){
- char buf[20];
- if( cfp->dot==cfp->rp->nrhs ){
- sprintf(buf,"(%d)",cfp->rp->index);
- fprintf(fp," %5s ",buf);
- }else{
- fprintf(fp," ");
- }
- ConfigPrint(fp,cfp);
- fprintf(fp,"\n");
-#ifdef TEST
- SetPrint(fp,cfp->fws,lemp);
- PlinkPrint(fp,cfp->fplp,"To ");
- PlinkPrint(fp,cfp->bplp,"From");
-#endif
- if( lemp->basisflag ) cfp=cfp->bp;
- else cfp=cfp->next;
- }
- fprintf(fp,"\n");
- for(ap=stp->ap; ap; ap=ap->next){
- if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
- }
- fprintf(fp,"\n");
- }
- fclose(fp);
- return;
-}
-
-/* Search for the file "name" which is in the same directory as
-** the exacutable */
-PRIVATE char *pathsearch(argv0,name,modemask)
-char *argv0;
-char *name;
-int modemask;
-{
- char *pathlist;
- char *path,*cp;
- char c;
-
-#ifdef __WIN32__
- cp = strrchr(argv0,'\\');
-#else
- cp = strrchr(argv0,'/');
-#endif
- if( cp ){
- c = *cp;
- *cp = 0;
- path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
- if( path ) sprintf(path,"%s/%s",argv0,name);
- *cp = c;
- }else{
- pathlist = getenv("PATH");
- if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
- path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
- if( path!=0 ){
- while( *pathlist ){
- cp = strchr(pathlist,':');
- if( cp==0 ) cp = &pathlist[strlen(pathlist)];
- c = *cp;
- *cp = 0;
- sprintf(path,"%s/%s",pathlist,name);
- *cp = c;
- if( c==0 ) pathlist = "";
- else pathlist = &cp[1];
- if( access(path,modemask)==0 ) break;
- }
- }
- }
- return path;
-}
-
-/* Given an action, compute the integer value for that action
-** which is to be put in the action table of the generated machine.
-** Return negative if no action should be generated.
-*/
-PRIVATE int compute_action(lemp,ap)
-struct lemon *lemp;
-struct action *ap;
-{
- int act;
- switch( ap->type ){
- case SHIFT: act = ap->x.stp->index; break;
- case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
- case ERROR: act = lemp->nstate + lemp->nrule; break;
- case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
- default: act = -1; break;
- }
- return act;
-}
-
-#define LINESIZE 1000
-/* The next cluster of routines are for reading the template file
-** and writing the results to the generated parser */
-/* The first function transfers data from "in" to "out" until
-** a line is seen which begins with "%%". The line number is
-** tracked.
-**
-** if name!=0, then any word that begin with "Parse" is changed to
-** begin with *name instead.
-*/
-PRIVATE void tplt_xfer(name,in,out,lineno)
-char *name;
-FILE *in;
-FILE *out;
-int *lineno;
-{
- int i, iStart;
- char line[LINESIZE];
- while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
- (*lineno)++;
- iStart = 0;
- if( name ){
- for(i=0; line[i]; i++){
- if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
- && (i==0 || !isalpha(line[i-1]))
- ){
- if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
- fprintf(out,"%s",name);
- i += 4;
- iStart = i+1;
- }
- }
- }
- fprintf(out,"%s",&line[iStart]);
- }
-}
-
-/* The next function finds the template file and opens it, returning
-** a pointer to the opened file. */
-PRIVATE FILE *tplt_open(lemp)
-struct lemon *lemp;
-{
-
- char buf[1000];
- FILE *in;
- char *tpltname;
- char *cp;
-
- cp = strrchr(lemp->filename,'.');
- if( cp ){
- sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
- }else{
- sprintf(buf,"%s.lt",lemp->filename);
- }
- if( access(buf,004)==0 ){
- tpltname = buf;
- }else if( access(lemp->tmplname,004)==0 ){
- tpltname = lemp->tmplname;
- }else{
- tpltname = pathsearch(lemp->argv0,lemp->tmplname,0);
- }
- if( tpltname==0 ){
- fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
- lemp->tmplname);
- lemp->errorcnt++;
- return 0;
- }
- in = fopen(tpltname,"r");
- if( in==0 ){
- fprintf(stderr,"Can't open the template file \"%s\".\n",lemp->tmplname);
- lemp->errorcnt++;
- return 0;
- }
- return in;
-}
-
-/* Print a string to the file and keep the linenumber up to date */
-PRIVATE void tplt_print(out,lemp,str,strln,lineno)
-FILE *out;
-struct lemon *lemp;
-char *str;
-int strln;
-int *lineno;
-{
- if( str==0 ) return;
- fprintf(out,"#line %d \"%s\"\n",strln,lemp->filename); (*lineno)++;
- while( *str ){
- if( *str=='\n' ) (*lineno)++;
- putc(*str,out);
- str++;
- }
- fprintf(out,"\n#line %d \"%s\"\n",*lineno+2,lemp->outname); (*lineno)+=2;
- return;
-}
-
-/*
-** The following routine emits code for the destructor for the
-** symbol sp
-*/
-PRIVATE void emit_destructor_code(out,sp,lemp,lineno)
-FILE *out;
-struct symbol *sp;
-struct lemon *lemp;
-int *lineno;
-{
- char *cp = 0;
-
- int linecnt = 0;
- if( sp->type==TERMINAL ){
- cp = lemp->tokendest;
- if( cp==0 ) return;
- fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
- }else if( sp->destructor ){
- cp = sp->destructor;
- fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
- }else if( lemp->vardest ){
- cp = lemp->vardest;
- if( cp==0 ) return;
- fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
- }
- for(; *cp; cp++){
- if( *cp=='$' && cp[1]=='$' ){
- fprintf(out,"(yypminor->yy%d)",sp->dtnum);
- cp++;
- continue;
- }
- if( *cp=='\n' ) linecnt++;
- fputc(*cp,out);
- }
- (*lineno) += 3 + linecnt;
- fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
- return;
-}
-
-/*
-** Return TRUE (non-zero) if the given symbol has a destructor.
-*/
-PRIVATE int has_destructor(sp, lemp)
-struct symbol *sp;
-struct lemon *lemp;
-{
- int ret;
- if( sp->type==TERMINAL ){
- ret = lemp->tokendest!=0;
- }else{
- ret = lemp->vardest!=0 || sp->destructor!=0;
- }
- return ret;
-}
-
-/*
-** Generate code which executes when the rule "rp" is reduced. Write
-** the code to "out". Make sure lineno stays up-to-date.
-*/
-PRIVATE void emit_code(out,rp,lemp,lineno)
-FILE *out;
-struct rule *rp;
-struct lemon *lemp;
-int *lineno;
-{
- char *cp, *xp;
- int linecnt = 0;
- int i;
- char lhsused = 0; /* True if the LHS element has been used */
- char used[MAXRHS]; /* True for each RHS element which is used */
-
- for(i=0; i<rp->nrhs; i++) used[i] = 0;
- lhsused = 0;
-
- /* Generate code to do the reduce action */
- if( rp->code ){
- fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename);
- for(cp=rp->code; *cp; cp++){
- if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
- char saved;
- for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
- saved = *xp;
- *xp = 0;
- if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
- fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum);
- cp = xp;
- lhsused = 1;
- }else{
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
- fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum);
- cp = xp;
- used[i] = 1;
- break;
- }
- }
- }
- *xp = saved;
- }
- if( *cp=='\n' ) linecnt++;
- fputc(*cp,out);
- } /* End loop */
- (*lineno) += 3 + linecnt;
- fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
- } /* End if( rp->code ) */
-
- /* Check to make sure the LHS has been used */
- if( rp->lhsalias && !lhsused ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label \"%s\" for \"%s(%s)\" is never used.",
- rp->lhsalias,rp->lhs->name,rp->lhsalias);
- lemp->errorcnt++;
- }
-
- /* Generate destructor code for RHS symbols which are not used in the
- ** reduce code */
- for(i=0; i<rp->nrhs; i++){
- if( rp->rhsalias[i] && !used[i] ){
- ErrorMsg(lemp->filename,rp->ruleline,
- "Label %s for \"%s(%s)\" is never used.",
- rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
- lemp->errorcnt++;
- }else if( rp->rhsalias[i]==0 ){
- if( has_destructor(rp->rhs[i],lemp) ){
- fprintf(out," yy_destructor(%d,&yymsp[%d].minor);\n",
- rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
- }else{
- fprintf(out," /* No destructor defined for %s */\n",
- rp->rhs[i]->name);
- (*lineno)++;
- }
- }
- }
- return;
-}
-
-/*
-** Print the definition of the union used for the parser's data stack.
-** This union contains fields for every possible data type for tokens
-** and nonterminals. In the process of computing and printing this
-** union, also set the ".dtnum" field of every terminal and nonterminal
-** symbol.
-*/
-PRIVATE void print_stack_union(out,lemp,plineno,mhflag)
-FILE *out; /* The output stream */
-struct lemon *lemp; /* The main info structure for this parser */
-int *plineno; /* Pointer to the line number */
-int mhflag; /* True if generating makeheaders output */
-{
- int lineno = *plineno; /* The line number of the output */
- char **types; /* A hash table of datatypes */
- int arraysize; /* Size of the "types" array */
- int maxdtlength; /* Maximum length of any ".datatype" field. */
- char *stddt; /* Standardized name for a datatype */
- int i,j; /* Loop counters */
- int hash; /* For hashing the name of a type */
- char *name; /* Name of the parser */
-
- /* Allocate and initialize types[] and allocate stddt[] */
- arraysize = lemp->nsymbol * 2;
- types = (char**)malloc( arraysize * sizeof(char*) );
- for(i=0; i<arraysize; i++) types[i] = 0;
- maxdtlength = 0;
- if( lemp->vartype ){
- maxdtlength = strlen(lemp->vartype);
- }
- for(i=0; i<lemp->nsymbol; i++){
- int len;
- struct symbol *sp = lemp->symbols[i];
- if( sp->datatype==0 ) continue;
- len = strlen(sp->datatype);
- if( len>maxdtlength ) maxdtlength = len;
- }
- stddt = (char*)malloc( maxdtlength*2 + 1 );
- if( types==0 || stddt==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
-
- /* Build a hash table of datatypes. The ".dtnum" field of each symbol
- ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
- ** used for terminal symbols. If there is no %default_type defined then
- ** 0 is also used as the .dtnum value for nonterminals which do not specify
- ** a datatype using the %type directive.
- */
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- char *cp;
- if( sp==lemp->errsym ){
- sp->dtnum = arraysize+1;
- continue;
- }
- if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
- sp->dtnum = 0;
- continue;
- }
- cp = sp->datatype;
- if( cp==0 ) cp = lemp->vartype;
- j = 0;
- while( isspace(*cp) ) cp++;
- while( *cp ) stddt[j++] = *cp++;
- while( j>0 && isspace(stddt[j-1]) ) j--;
- stddt[j] = 0;
- hash = 0;
- for(j=0; stddt[j]; j++){
- hash = hash*53 + stddt[j];
- }
- hash = (hash & 0x7fffffff)%arraysize;
- while( types[hash] ){
- if( strcmp(types[hash],stddt)==0 ){
- sp->dtnum = hash + 1;
- break;
- }
- hash++;
- if( hash>=arraysize ) hash = 0;
- }
- if( types[hash]==0 ){
- sp->dtnum = hash + 1;
- types[hash] = (char*)malloc( strlen(stddt)+1 );
- if( types[hash]==0 ){
- fprintf(stderr,"Out of memory.\n");
- exit(1);
- }
- strcpy(types[hash],stddt);
- }
- }
-
- /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
- name = lemp->name ? lemp->name : "Parse";
- lineno = *plineno;
- if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
- fprintf(out,"#define %sTOKENTYPE %s\n",name,
- lemp->tokentype?lemp->tokentype:"void*"); lineno++;
- if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
- fprintf(out,"typedef union {\n"); lineno++;
- fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
- for(i=0; i<arraysize; i++){
- if( types[i]==0 ) continue;
- fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
- free(types[i]);
- }
- fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
- free(stddt);
- free(types);
- fprintf(out,"} YYMINORTYPE;\n"); lineno++;
- *plineno = lineno;
-}
-
-/*
-** Return the name of a C datatype able to represent values between
-** lwr and upr, inclusive.
-*/
-static const char *minimum_size_type(int lwr, int upr){
- if( lwr>=0 ){
- if( upr<=255 ){
- return "unsigned char";
- }else if( upr<65535 ){
- return "unsigned short int";
- }else{
- return "unsigned int";
- }
- }else if( lwr>=-127 && upr<=127 ){
- return "signed char";
- }else if( lwr>=-32767 && upr<32767 ){
- return "short";
- }else{
- return "int";
- }
-}
-
-/*
-** Each state contains a set of token transaction and a set of
-** nonterminal transactions. Each of these sets makes an instance
-** of the following structure. An array of these structures is used
-** to order the creation of entries in the yy_action[] table.
-*/
-struct axset {
- struct state *stp; /* A pointer to a state */
- int isTkn; /* True to use tokens. False for non-terminals */
- int nAction; /* Number of actions */
-};
-
-/*
-** Compare to axset structures for sorting purposes
-*/
-static int axset_compare(const void *a, const void *b){
- struct axset *p1 = (struct axset*)a;
- struct axset *p2 = (struct axset*)b;
- return p2->nAction - p1->nAction;
-}
-
-/* Generate C source code for the parser */
-void ReportTable(lemp, mhflag)
-struct lemon *lemp;
-int mhflag; /* Output in makeheaders format if true */
-{
- FILE *out, *in;
- char line[LINESIZE];
- int lineno;
- struct state *stp;
- struct action *ap;
- struct rule *rp;
- struct acttab *pActtab;
- int i, j, n;
- int mnTknOfst, mxTknOfst;
- int mnNtOfst, mxNtOfst;
- struct axset *ax;
- char *name;
-
- in = tplt_open(lemp);
- if( in==0 ) return;
- out = file_open(lemp,".c","w");
- if( out==0 ){
- fclose(in);
- return;
- }
- lineno = 1;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the include code, if any */
- tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
- if( mhflag ){
- name = file_makename(lemp, ".h");
- fprintf(out,"#include \"%s\"\n", name); lineno++;
- free(name);
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate #defines for all tokens */
- if( mhflag ){
- char *prefix;
- fprintf(out,"#if INTERFACE\n"); lineno++;
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
- lineno++;
- }
- fprintf(out,"#endif\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the defines */
- fprintf(out,"/* \001 */\n");
- fprintf(out,"#define YYCODETYPE %s\n",
- minimum_size_type(0, lemp->nsymbol+5)); lineno++;
- fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
- fprintf(out,"#define YYACTIONTYPE %s\n",
- minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++;
- print_stack_union(out,lemp,&lineno,mhflag);
- if( lemp->stacksize ){
- if( atoi(lemp->stacksize)<=0 ){
- ErrorMsg(lemp->filename,0,
-"Illegal stack size: [%s]. The stack size should be an integer constant.",
- lemp->stacksize);
- lemp->errorcnt++;
- lemp->stacksize = "100";
- }
- fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
- }else{
- fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
- }
- if( mhflag ){
- fprintf(out,"#if INTERFACE\n"); lineno++;
- }
- name = lemp->name ? lemp->name : "Parse";
- if( lemp->arg && lemp->arg[0] ){
- i = strlen(lemp->arg);
- while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
- while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
- fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
- name,lemp->arg,&lemp->arg[i]); lineno++;
- fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
- name,&lemp->arg[i],&lemp->arg[i]); lineno++;
- }else{
- fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
- fprintf(out,"#define %sARG_STORE\n",name); lineno++;
- }
- if( mhflag ){
- fprintf(out,"#endif\n"); lineno++;
- }
- fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
- fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
- fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
- fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
- if( lemp->has_fallback ){
- fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the action table and its associates:
- **
- ** yy_action[] A single table containing all actions.
- ** yy_lookahead[] A table containing the lookahead for each entry in
- ** yy_action. Used to detect hash collisions.
- ** yy_shift_ofst[] For each state, the offset into yy_action for
- ** shifting terminals.
- ** yy_reduce_ofst[] For each state, the offset into yy_action for
- ** shifting non-terminals after a reduce.
- ** yy_default[] Default action for each state.
- */
-
- /* Compute the actions on all states and count them up */
- ax = malloc( sizeof(ax[0])*lemp->nstate*2 );
- if( ax==0 ){
- fprintf(stderr,"malloc failed\n");
- exit(1);
- }
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- stp->nTknAct = stp->nNtAct = 0;
- stp->iDflt = lemp->nstate + lemp->nrule;
- stp->iTknOfst = NO_OFFSET;
- stp->iNtOfst = NO_OFFSET;
- for(ap=stp->ap; ap; ap=ap->next){
- if( compute_action(lemp,ap)>=0 ){
- if( ap->sp->index<lemp->nterminal ){
- stp->nTknAct++;
- }else if( ap->sp->index<lemp->nsymbol ){
- stp->nNtAct++;
- }else{
- stp->iDflt = compute_action(lemp, ap);
- }
- }
- }
- ax[i*2].stp = stp;
- ax[i*2].isTkn = 1;
- ax[i*2].nAction = stp->nTknAct;
- ax[i*2+1].stp = stp;
- ax[i*2+1].isTkn = 0;
- ax[i*2+1].nAction = stp->nNtAct;
- }
- mxTknOfst = mnTknOfst = 0;
- mxNtOfst = mnNtOfst = 0;
-
- /* Compute the action table. In order to try to keep the size of the
- ** action table to a minimum, the heuristic of placing the largest action
- ** sets first is used.
- */
- qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
- pActtab = acttab_alloc();
- for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
- stp = ax[i].stp;
- if( ax[i].isTkn ){
- for(ap=stp->ap; ap; ap=ap->next){
- int action;
- if( ap->sp->index>=lemp->nterminal ) continue;
- action = compute_action(lemp, ap);
- if( action<0 ) continue;
- acttab_action(pActtab, ap->sp->index, action);
- }
- stp->iTknOfst = acttab_insert(pActtab);
- if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
- if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
- }else{
- for(ap=stp->ap; ap; ap=ap->next){
- int action;
- if( ap->sp->index<lemp->nterminal ) continue;
- if( ap->sp->index==lemp->nsymbol ) continue;
- action = compute_action(lemp, ap);
- if( action<0 ) continue;
- acttab_action(pActtab, ap->sp->index, action);
- }
- stp->iNtOfst = acttab_insert(pActtab);
- if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
- if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
- }
- }
- free(ax);
-
- /* Output the yy_action table */
- fprintf(out,"static YYACTIONTYPE yy_action[] = {\n"); lineno++;
- n = acttab_size(pActtab);
- for(i=j=0; i<n; i++){
- int action = acttab_yyaction(pActtab, i);
- if( action<0 ) action = lemp->nsymbol + lemp->nrule + 2;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", action);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_lookahead table */
- fprintf(out,"static YYCODETYPE yy_lookahead[] = {\n"); lineno++;
- for(i=j=0; i<n; i++){
- int la = acttab_yylookahead(pActtab, i);
- if( la<0 ) la = lemp->nsymbol;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", la);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_shift_ofst[] table */
- fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
- fprintf(out, "static %s yy_shift_ofst[] = {\n",
- minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
- n = lemp->nstate;
- for(i=j=0; i<n; i++){
- int ofst;
- stp = lemp->sorted[i];
- ofst = stp->iTknOfst;
- if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", ofst);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the yy_reduce_ofst[] table */
- fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
- fprintf(out, "static %s yy_reduce_ofst[] = {\n",
- minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
- n = lemp->nstate;
- for(i=j=0; i<n; i++){
- int ofst;
- stp = lemp->sorted[i];
- ofst = stp->iNtOfst;
- if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", ofst);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
-
- /* Output the default action table */
- fprintf(out, "static YYACTIONTYPE yy_default[] = {\n"); lineno++;
- n = lemp->nstate;
- for(i=j=0; i<n; i++){
- stp = lemp->sorted[i];
- if( j==0 ) fprintf(out," /* %5d */ ", i);
- fprintf(out, " %4d,", stp->iDflt);
- if( j==9 || i==n-1 ){
- fprintf(out, "\n"); lineno++;
- j = 0;
- }else{
- j++;
- }
- }
- fprintf(out, "};\n"); lineno++;
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the table of fallback tokens.
- */
- if( lemp->has_fallback ){
- for(i=0; i<lemp->nterminal; i++){
- struct symbol *p = lemp->symbols[i];
- if( p->fallback==0 ){
- fprintf(out, " 0, /* %10s => nothing */\n", p->name);
- }else{
- fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
- p->name, p->fallback->name);
- }
- lineno++;
- }
- }
- tplt_xfer(lemp->name, in, out, &lineno);
-
- /* Generate a table containing the symbolic name of every symbol
- */
- for(i=0; i<lemp->nsymbol; i++){
- sprintf(line,"\"%s\",",lemp->symbols[i]->name);
- fprintf(out," %-15s",line);
- if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
- }
- if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate a table containing a text string that describes every
- ** rule in the rule set of the grammer. This information is used
- ** when tracing REDUCE actions.
- */
- for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
- assert( rp->index==i );
- fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
- for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
- fprintf(out,"\",\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes every time a symbol is popped from
- ** the stack while processing errors or while destroying the parser.
- ** (In other words, generate the %destructor actions)
- */
- if( lemp->tokendest ){
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type!=TERMINAL ) continue;
- fprintf(out," case %d:\n",sp->index); lineno++;
- }
- for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
- if( i<lemp->nsymbol ){
- emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- }
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
- fprintf(out," case %d:\n",sp->index); lineno++;
- emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- if( lemp->vardest ){
- struct symbol *dflt_sp = 0;
- for(i=0; i<lemp->nsymbol; i++){
- struct symbol *sp = lemp->symbols[i];
- if( sp==0 || sp->type==TERMINAL ||
- sp->index<=0 || sp->destructor!=0 ) continue;
- fprintf(out," case %d:\n",sp->index); lineno++;
- dflt_sp = sp;
- }
- if( dflt_sp!=0 ){
- emit_destructor_code(out,dflt_sp,lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes whenever the parser stack overflows */
- tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate the table of rule information
- **
- ** Note: This code depends on the fact that rules are number
- ** sequentually beginning with 0.
- */
- for(rp=lemp->rule; rp; rp=rp->next){
- fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which execution during each REDUCE action */
- for(rp=lemp->rule; rp; rp=rp->next){
- fprintf(out," case %d:\n",rp->index); lineno++;
- emit_code(out,rp,lemp,&lineno);
- fprintf(out," break;\n"); lineno++;
- }
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes if a parse fails */
- tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes when a syntax error occurs */
- tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Generate code which executes when the parser accepts its input */
- tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
- tplt_xfer(lemp->name,in,out,&lineno);
-
- /* Append any addition code the user desires */
- tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
-
- fclose(in);
- fclose(out);
- return;
-}
-
-/* Generate a header file for the parser */
-void ReportHeader(lemp)
-struct lemon *lemp;
-{
- FILE *out, *in;
- char *prefix;
- char line[LINESIZE];
- char pattern[LINESIZE];
- int i;
-
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- in = file_open(lemp,".h","r");
- if( in ){
- for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
- sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
- if( strcmp(line,pattern) ) break;
- }
- fclose(in);
- if( i==lemp->nterminal ){
- /* No change in the file. Don't rewrite it. */
- return;
- }
- }
- out = file_open(lemp,".h","w");
- if( out ){
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
- }
- fclose(out);
- }
- return;
-}
-
-/* Reduce the size of the action tables, if possible, by making use
-** of defaults.
-**
-** In this version, we take the most frequent REDUCE action and make
-** it the default. Only default a reduce if there are more than one.
-*/
-void CompressTables(lemp)
-struct lemon *lemp;
-{
- struct state *stp;
- struct action *ap, *ap2;
- struct rule *rp, *rp2, *rbest;
- int nbest, n;
- int i;
-
- for(i=0; i<lemp->nstate; i++){
- stp = lemp->sorted[i];
- nbest = 0;
- rbest = 0;
-
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type!=REDUCE ) continue;
- rp = ap->x.rp;
- if( rp==rbest ) continue;
- n = 1;
- for(ap2=ap->next; ap2; ap2=ap2->next){
- if( ap2->type!=REDUCE ) continue;
- rp2 = ap2->x.rp;
- if( rp2==rbest ) continue;
- if( rp2==rp ) n++;
- }
- if( n>nbest ){
- nbest = n;
- rbest = rp;
- }
- }
-
- /* Do not make a default if the number of rules to default
- ** is not at least 2 */
- if( nbest<2 ) continue;
-
-
- /* Combine matching REDUCE actions into a single default */
- for(ap=stp->ap; ap; ap=ap->next){
- if( ap->type==REDUCE && ap->x.rp==rbest ) break;
- }
- assert( ap );
- ap->sp = Symbol_new("{default}");
- for(ap=ap->next; ap; ap=ap->next){
- if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
- }
- stp->ap = Action_sort(stp->ap);
- }
-}
-
-/***************** From the file "set.c" ************************************/
-/*
-** Set manipulation routines for the LEMON parser generator.
-*/
-
-static int global_size = 0;
-
-/* Set the set size */
-void SetSize(n)
-int n;
-{
- global_size = n+1;
-}
-
-/* Allocate a new set */
-char *SetNew(){
- char *s;
- int i;
- s = (char*)malloc( global_size );
- if( s==0 ){
- memory_error();
- }
- for(i=0; i<global_size; i++) s[i] = 0;
- return s;
-}
-
-/* Deallocate a set */
-void SetFree(s)
-char *s;
-{
- free(s);
-}
-
-/* Add a new element to the set. Return TRUE if the element was added
-** and FALSE if it was already there. */
-int SetAdd(s,e)
-char *s;
-int e;
-{
- int rv;
- rv = s[e];
- s[e] = 1;
- return !rv;
-}
-
-/* Add every element of s2 to s1. Return TRUE if s1 changes. */
-int SetUnion(s1,s2)
-char *s1;
-char *s2;
-{
- int i, progress;
- progress = 0;
- for(i=0; i<global_size; i++){
- if( s2[i]==0 ) continue;
- if( s1[i]==0 ){
- progress = 1;
- s1[i] = 1;
- }
- }
- return progress;
-}
-/********************** From the file "table.c" ****************************/
-/*
-** All code in this file has been automatically generated
-** from a specification in the file
-** "table.q"
-** by the associative array code building program "aagen".
-** Do not edit this file! Instead, edit the specification
-** file, then rerun aagen.
-*/
-/*
-** Code for processing tables in the LEMON parser generator.
-*/
-
-PRIVATE int strhash(x)
-char *x;
-{
- int h = 0;
- while( *x) h = h*13 + *(x++);
- return h;
-}
-
-/* Works like strdup, sort of. Save a string in malloced memory, but
-** keep strings in a table so that the same string is not in more
-** than one place.
-*/
-char *Strsafe(y)
-char *y;
-{
- char *z;
-
- z = Strsafe_find(y);
- if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
- strcpy(z,y);
- Strsafe_insert(z);
- }
- MemoryCheck(z);
- return z;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x1".
-*/
-struct s_x1 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x1node *tbl; /* The data stored here */
- struct s_x1node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x1".
-*/
-typedef struct s_x1node {
- char *data; /* The data */
- struct s_x1node *next; /* Next entry with the same hash */
- struct s_x1node **from; /* Previous link */
-} x1node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x1 *x1a;
-
-/* Allocate a new associative array */
-void Strsafe_init(){
- if( x1a ) return;
- x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
- if( x1a ){
- x1a->size = 1024;
- x1a->count = 0;
- x1a->tbl = (x1node*)malloc(
- (sizeof(x1node) + sizeof(x1node*))*1024 );
- if( x1a->tbl==0 ){
- free(x1a);
- x1a = 0;
- }else{
- int i;
- x1a->ht = (x1node**)&(x1a->tbl[1024]);
- for(i=0; i<1024; i++) x1a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Strsafe_insert(data)
-char *data;
-{
- x1node *np;
- int h;
- int ph;
-
- if( x1a==0 ) return 0;
- ph = strhash(data);
- h = ph & (x1a->size-1);
- np = x1a->ht[h];
- while( np ){
- if( strcmp(np->data,data)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x1a->count>=x1a->size ){
- /* Need to make the hash table bigger */
- int i,size;
- struct s_x1 array;
- array.size = size = x1a->size*2;
- array.count = x1a->count;
- array.tbl = (x1node*)malloc(
- (sizeof(x1node) + sizeof(x1node*))*size );
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x1node**)&(array.tbl[size]);
- for(i=0; i<size; i++) array.ht[i] = 0;
- for(i=0; i<x1a->count; i++){
- x1node *oldnp, *newnp;
- oldnp = &(x1a->tbl[i]);
- h = strhash(oldnp->data) & (size-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x1a->tbl);
- *x1a = array;
- }
- /* Insert the new data */
- h = ph & (x1a->size-1);
- np = &(x1a->tbl[x1a->count++]);
- np->data = data;
- if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
- np->next = x1a->ht[h];
- x1a->ht[h] = np;
- np->from = &(x1a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-char *Strsafe_find(key)
-char *key;
-{
- int h;
- x1node *np;
-
- if( x1a==0 ) return 0;
- h = strhash(key) & (x1a->size-1);
- np = x1a->ht[h];
- while( np ){
- if( strcmp(np->data,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return a pointer to the (terminal or nonterminal) symbol "x".
-** Create a new symbol if this is the first time "x" has been seen.
-*/
-struct symbol *Symbol_new(x)
-char *x;
-{
- struct symbol *sp;
-
- sp = Symbol_find(x);
- if( sp==0 ){
- sp = (struct symbol *)malloc( sizeof(struct symbol) );
- MemoryCheck(sp);
- sp->name = Strsafe(x);
- sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
- sp->rule = 0;
- sp->fallback = 0;
- sp->prec = -1;
- sp->assoc = UNK;
- sp->firstset = 0;
- sp->lambda = Bo_FALSE;
- sp->destructor = 0;
- sp->datatype = 0;
- Symbol_insert(sp,sp->name);
- }
- return sp;
-}
-
-/* Compare two symbols for working purposes
-**
-** Symbols that begin with upper case letters (terminals or tokens)
-** must sort before symbols that begin with lower case letters
-** (non-terminals). Other than that, the order does not matter.
-**
-** We find experimentally that leaving the symbols in their original
-** order (the order they appeared in the grammar file) gives the
-** smallest parser tables in SQLite.
-*/
-int Symbolcmpp(struct symbol **a, struct symbol **b){
- int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
- int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
- return i1-i2;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x2".
-*/
-struct s_x2 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x2node *tbl; /* The data stored here */
- struct s_x2node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x2".
-*/
-typedef struct s_x2node {
- struct symbol *data; /* The data */
- char *key; /* The key */
- struct s_x2node *next; /* Next entry with the same hash */
- struct s_x2node **from; /* Previous link */
-} x2node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x2 *x2a;
-
-/* Allocate a new associative array */
-void Symbol_init(){
- if( x2a ) return;
- x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
- if( x2a ){
- x2a->size = 128;
- x2a->count = 0;
- x2a->tbl = (x2node*)malloc(
- (sizeof(x2node) + sizeof(x2node*))*128 );
- if( x2a->tbl==0 ){
- free(x2a);
- x2a = 0;
- }else{
- int i;
- x2a->ht = (x2node**)&(x2a->tbl[128]);
- for(i=0; i<128; i++) x2a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Symbol_insert(data,key)
-struct symbol *data;
-char *key;
-{
- x2node *np;
- int h;
- int ph;
-
- if( x2a==0 ) return 0;
- ph = strhash(key);
- h = ph & (x2a->size-1);
- np = x2a->ht[h];
- while( np ){
- if( strcmp(np->key,key)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x2a->count>=x2a->size ){
- /* Need to make the hash table bigger */
- int i,size;
- struct s_x2 array;
- array.size = size = x2a->size*2;
- array.count = x2a->count;
- array.tbl = (x2node*)malloc(
- (sizeof(x2node) + sizeof(x2node*))*size );
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x2node**)&(array.tbl[size]);
- for(i=0; i<size; i++) array.ht[i] = 0;
- for(i=0; i<x2a->count; i++){
- x2node *oldnp, *newnp;
- oldnp = &(x2a->tbl[i]);
- h = strhash(oldnp->key) & (size-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->key = oldnp->key;
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x2a->tbl);
- *x2a = array;
- }
- /* Insert the new data */
- h = ph & (x2a->size-1);
- np = &(x2a->tbl[x2a->count++]);
- np->key = key;
- np->data = data;
- if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
- np->next = x2a->ht[h];
- x2a->ht[h] = np;
- np->from = &(x2a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct symbol *Symbol_find(key)
-char *key;
-{
- int h;
- x2node *np;
-
- if( x2a==0 ) return 0;
- h = strhash(key) & (x2a->size-1);
- np = x2a->ht[h];
- while( np ){
- if( strcmp(np->key,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return the n-th data. Return NULL if n is out of range. */
-struct symbol *Symbol_Nth(n)
-int n;
-{
- struct symbol *data;
- if( x2a && n>0 && n<=x2a->count ){
- data = x2a->tbl[n-1].data;
- }else{
- data = 0;
- }
- return data;
-}
-
-/* Return the size of the array */
-int Symbol_count()
-{
- return x2a ? x2a->count : 0;
-}
-
-/* Return an array of pointers to all data in the table.
-** The array is obtained from malloc. Return NULL if memory allocation
-** problems, or if the array is empty. */
-struct symbol **Symbol_arrayof()
-{
- struct symbol **array;
- int i,size;
- if( x2a==0 ) return 0;
- size = x2a->count;
- array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
- if( array ){
- for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
- }
- return array;
-}
-
-/* Compare two configurations */
-int Configcmp(a,b)
-struct config *a;
-struct config *b;
-{
- int x;
- x = a->rp->index - b->rp->index;
- if( x==0 ) x = a->dot - b->dot;
- return x;
-}
-
-/* Compare two states */
-PRIVATE int statecmp(a,b)
-struct config *a;
-struct config *b;
-{
- int rc;
- for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
- rc = a->rp->index - b->rp->index;
- if( rc==0 ) rc = a->dot - b->dot;
- }
- if( rc==0 ){
- if( a ) rc = 1;
- if( b ) rc = -1;
- }
- return rc;
-}
-
-/* Hash a state */
-PRIVATE int statehash(a)
-struct config *a;
-{
- int h=0;
- while( a ){
- h = h*571 + a->rp->index*37 + a->dot;
- a = a->bp;
- }
- return h;
-}
-
-/* Allocate a new state structure */
-struct state *State_new()
-{
- struct state *new;
- new = (struct state *)malloc( sizeof(struct state) );
- MemoryCheck(new);
- return new;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x3".
-*/
-struct s_x3 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x3node *tbl; /* The data stored here */
- struct s_x3node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x3".
-*/
-typedef struct s_x3node {
- struct state *data; /* The data */
- struct config *key; /* The key */
- struct s_x3node *next; /* Next entry with the same hash */
- struct s_x3node **from; /* Previous link */
-} x3node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x3 *x3a;
-
-/* Allocate a new associative array */
-void State_init(){
- if( x3a ) return;
- x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
- if( x3a ){
- x3a->size = 128;
- x3a->count = 0;
- x3a->tbl = (x3node*)malloc(
- (sizeof(x3node) + sizeof(x3node*))*128 );
- if( x3a->tbl==0 ){
- free(x3a);
- x3a = 0;
- }else{
- int i;
- x3a->ht = (x3node**)&(x3a->tbl[128]);
- for(i=0; i<128; i++) x3a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int State_insert(data,key)
-struct state *data;
-struct config *key;
-{
- x3node *np;
- int h;
- int ph;
-
- if( x3a==0 ) return 0;
- ph = statehash(key);
- h = ph & (x3a->size-1);
- np = x3a->ht[h];
- while( np ){
- if( statecmp(np->key,key)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x3a->count>=x3a->size ){
- /* Need to make the hash table bigger */
- int i,size;
- struct s_x3 array;
- array.size = size = x3a->size*2;
- array.count = x3a->count;
- array.tbl = (x3node*)malloc(
- (sizeof(x3node) + sizeof(x3node*))*size );
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x3node**)&(array.tbl[size]);
- for(i=0; i<size; i++) array.ht[i] = 0;
- for(i=0; i<x3a->count; i++){
- x3node *oldnp, *newnp;
- oldnp = &(x3a->tbl[i]);
- h = statehash(oldnp->key) & (size-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->key = oldnp->key;
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x3a->tbl);
- *x3a = array;
- }
- /* Insert the new data */
- h = ph & (x3a->size-1);
- np = &(x3a->tbl[x3a->count++]);
- np->key = key;
- np->data = data;
- if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
- np->next = x3a->ht[h];
- x3a->ht[h] = np;
- np->from = &(x3a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct state *State_find(key)
-struct config *key;
-{
- int h;
- x3node *np;
-
- if( x3a==0 ) return 0;
- h = statehash(key) & (x3a->size-1);
- np = x3a->ht[h];
- while( np ){
- if( statecmp(np->key,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Return an array of pointers to all data in the table.
-** The array is obtained from malloc. Return NULL if memory allocation
-** problems, or if the array is empty. */
-struct state **State_arrayof()
-{
- struct state **array;
- int i,size;
- if( x3a==0 ) return 0;
- size = x3a->count;
- array = (struct state **)malloc( sizeof(struct state *)*size );
- if( array ){
- for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
- }
- return array;
-}
-
-/* Hash a configuration */
-PRIVATE int confighash(a)
-struct config *a;
-{
- int h=0;
- h = h*571 + a->rp->index*37 + a->dot;
- return h;
-}
-
-/* There is one instance of the following structure for each
-** associative array of type "x4".
-*/
-struct s_x4 {
- int size; /* The number of available slots. */
- /* Must be a power of 2 greater than or */
- /* equal to 1 */
- int count; /* Number of currently slots filled */
- struct s_x4node *tbl; /* The data stored here */
- struct s_x4node **ht; /* Hash table for lookups */
-};
-
-/* There is one instance of this structure for every data element
-** in an associative array of type "x4".
-*/
-typedef struct s_x4node {
- struct config *data; /* The data */
- struct s_x4node *next; /* Next entry with the same hash */
- struct s_x4node **from; /* Previous link */
-} x4node;
-
-/* There is only one instance of the array, which is the following */
-static struct s_x4 *x4a;
-
-/* Allocate a new associative array */
-void Configtable_init(){
- if( x4a ) return;
- x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
- if( x4a ){
- x4a->size = 64;
- x4a->count = 0;
- x4a->tbl = (x4node*)malloc(
- (sizeof(x4node) + sizeof(x4node*))*64 );
- if( x4a->tbl==0 ){
- free(x4a);
- x4a = 0;
- }else{
- int i;
- x4a->ht = (x4node**)&(x4a->tbl[64]);
- for(i=0; i<64; i++) x4a->ht[i] = 0;
- }
- }
-}
-/* Insert a new record into the array. Return TRUE if successful.
-** Prior data with the same key is NOT overwritten */
-int Configtable_insert(data)
-struct config *data;
-{
- x4node *np;
- int h;
- int ph;
-
- if( x4a==0 ) return 0;
- ph = confighash(data);
- h = ph & (x4a->size-1);
- np = x4a->ht[h];
- while( np ){
- if( Configcmp(np->data,data)==0 ){
- /* An existing entry with the same key is found. */
- /* Fail because overwrite is not allows. */
- return 0;
- }
- np = np->next;
- }
- if( x4a->count>=x4a->size ){
- /* Need to make the hash table bigger */
- int i,size;
- struct s_x4 array;
- array.size = size = x4a->size*2;
- array.count = x4a->count;
- array.tbl = (x4node*)malloc(
- (sizeof(x4node) + sizeof(x4node*))*size );
- if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
- array.ht = (x4node**)&(array.tbl[size]);
- for(i=0; i<size; i++) array.ht[i] = 0;
- for(i=0; i<x4a->count; i++){
- x4node *oldnp, *newnp;
- oldnp = &(x4a->tbl[i]);
- h = confighash(oldnp->data) & (size-1);
- newnp = &(array.tbl[i]);
- if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
- newnp->next = array.ht[h];
- newnp->data = oldnp->data;
- newnp->from = &(array.ht[h]);
- array.ht[h] = newnp;
- }
- free(x4a->tbl);
- *x4a = array;
- }
- /* Insert the new data */
- h = ph & (x4a->size-1);
- np = &(x4a->tbl[x4a->count++]);
- np->data = data;
- if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
- np->next = x4a->ht[h];
- x4a->ht[h] = np;
- np->from = &(x4a->ht[h]);
- return 1;
-}
-
-/* Return a pointer to data assigned to the given key. Return NULL
-** if no such key. */
-struct config *Configtable_find(key)
-struct config *key;
-{
- int h;
- x4node *np;
-
- if( x4a==0 ) return 0;
- h = confighash(key) & (x4a->size-1);
- np = x4a->ht[h];
- while( np ){
- if( Configcmp(np->data,key)==0 ) break;
- np = np->next;
- }
- return np ? np->data : 0;
-}
-
-/* Remove all data from the table. Pass each data to the function "f"
-** as it is removed. ("f" may be null to avoid this step.) */
-void Configtable_clear(f)
-int(*f)(/* struct config * */);
-{
- int i;
- if( x4a==0 || x4a->count==0 ) return;
- if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
- for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
- x4a->count = 0;
- return;
-}
diff --git a/src/lempar.c b/src/lempar.c
deleted file mode 100644
index c98720a6..00000000
--- a/src/lempar.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/* Driver template for the LEMON parser generator.
-** The author disclaims copyright to this source code.
-*/
-/* First off, code is include which follows the "include" declaration
-** in the input file. */
-#include <stdio.h>
-%%
-/* 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.
-*/
-/*
-** These constants (all generated automatically by the parser generator)
-** specify the various kinds of tokens (terminals) that the parser
-** understands.
-**
-** Each symbol here is a terminal symbol in the grammar.
-*/
-%%
-/* Make sure the INTERFACE macro is defined.
-*/
-#ifndef INTERFACE
-# define INTERFACE 1
-#endif
-/* The next thing included is series of defines which control
-** various aspects of the generated parser.
-** YYCODETYPE is the data type used for storing terminal
-** and nonterminal numbers. "unsigned char" is
-** used if there are fewer than 250 terminals
-** and nonterminals. "int" is used otherwise.
-** YYNOCODE is a number of type YYCODETYPE which corresponds
-** to no legal terminal or nonterminal number. This
-** number is used to fill in empty slots of the hash
-** table.
-** YYFALLBACK If defined, this indicates that one or more tokens
-** have fall-back values which should be used if the
-** original value of the token will not parse.
-** YYACTIONTYPE is the data type used for storing terminal
-** and nonterminal numbers. "unsigned char" is
-** used if there are fewer than 250 rules and
-** states combined. "int" is used otherwise.
-** ParseTOKENTYPE is the data type used for minor tokens given
-** directly to the parser from the tokenizer.
-** YYMINORTYPE is the data type used for all minor tokens.
-** This is typically a union of many types, one of
-** which is ParseTOKENTYPE. The entry in the union
-** for base tokens is called "yy0".
-** YYSTACKDEPTH is the maximum depth of the parser's stack.
-** ParseARG_SDECL A static variable declaration for the %extra_argument
-** ParseARG_PDECL A parameter declaration for the %extra_argument
-** ParseARG_STORE Code to store %extra_argument into yypParser
-** ParseARG_FETCH Code to extract %extra_argument from yypParser
-** YYNSTATE the combined number of states.
-** YYNRULE the number of rules in the grammar
-** YYERRORSYMBOL is the code number of the error symbol. If not
-** defined, then do no error processing.
-*/
-%%
-#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
-#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
-#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
-
-/* Next are that tables used to determine what action to take based on the
-** current state and lookahead token. These tables are used to implement
-** functions that take a state number and lookahead value and return an
-** action integer.
-**
-** Suppose the action integer is N. Then the action is determined as
-** follows
-**
-** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
-** token onto the stack and goto state N.
-**
-** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
-**
-** N == YYNSTATE+YYNRULE A syntax error has occurred.
-**
-** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
-**
-** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
-** slots in the yy_action[] table.
-**
-** The action table is constructed as a single large table named yy_action[].
-** Given state S and lookahead X, the action is computed as
-**
-** yy_action[ yy_shift_ofst[S] + X ]
-**
-** If the index value yy_shift_ofst[S]+X is out of range or if the value
-** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
-** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
-** and that yy_default[S] should be used instead.
-**
-** The formula above is for computing the action when the lookahead is
-** a terminal symbol. If the lookahead is a non-terminal (as occurs after
-** a reduce action) then the yy_reduce_ofst[] array is used in place of
-** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
-** YY_SHIFT_USE_DFLT.
-**
-** The following are the tables generated in this section:
-**
-** yy_action[] A single table containing all actions.
-** yy_lookahead[] A table containing the lookahead for each entry in
-** yy_action. Used to detect hash collisions.
-** yy_shift_ofst[] For each state, the offset into yy_action for
-** shifting terminals.
-** yy_reduce_ofst[] For each state, the offset into yy_action for
-** shifting non-terminals after a reduce.
-** yy_default[] Default action for each state.
-*/
-%%
-#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
-
-/* The next table maps tokens into fallback tokens. If a construct
-** like the following:
-**
-** %fallback ID X Y Z.
-**
-** appears in the grammer, then ID becomes a fallback token for X, Y,
-** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
-** but it does not parse, the type of the token is changed to ID and
-** the parse is retried before an error is thrown.
-*/
-#ifdef YYFALLBACK
-static const YYCODETYPE yyFallback[] = {
-%%
-};
-#endif /* YYFALLBACK */
-
-/* The following structure represents a single element of the
-** parser's stack. Information stored includes:
-**
-** + The state number for the parser at this level of the stack.
-**
-** + The value of the token stored at this level of the stack.
-** (In other words, the "major" token.)
-**
-** + The semantic value stored at this level of the stack. This is
-** the information used by the action routines in the grammar.
-** It is sometimes called the "minor" token.
-*/
-struct yyStackEntry {
- int stateno; /* The state-number */
- int major; /* The major token value. This is the code
- ** number for the token at this stack level */
- YYMINORTYPE minor; /* The user-supplied minor token value. This
- ** is the value of the token */
-};
-typedef struct yyStackEntry yyStackEntry;
-
-/* The state of the parser is completely contained in an instance of
-** the following structure */
-struct yyParser {
- int yyidx; /* Index of top element in stack */
- int yyerrcnt; /* Shifts left before out of the error */
- ParseARG_SDECL /* A place to hold %extra_argument */
- yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
-};
-typedef struct yyParser yyParser;
-
-#ifndef NDEBUG
-#include <stdio.h>
-static FILE *yyTraceFILE = 0;
-static char *yyTracePrompt = 0;
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/*
-** Turn parser tracing on by giving a stream to which to write the trace
-** and a prompt to preface each trace message. Tracing is turned off
-** by making either argument NULL
-**
-** Inputs:
-** <ul>
-** <li> A FILE* to which trace output should be written.
-** If NULL, then tracing is turned off.
-** <li> A prefix string written at the beginning of every
-** line of trace output. If NULL, then tracing is
-** turned off.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-#if 0
-void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
- yyTraceFILE = TraceFILE;
- yyTracePrompt = zTracePrompt;
- if( yyTraceFILE==0 ) yyTracePrompt = 0;
- else if( yyTracePrompt==0 ) yyTraceFILE = 0;
-}
-#endif
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/* For tracing shifts, the names of all terminals and nonterminals
-** are required. The following table supplies these names */
-static const char *yyTokenName[] = {
-%%
-};
-#endif /* NDEBUG */
-
-#ifndef NDEBUG
-/* For tracing reduce actions, the names of all rules are required.
-*/
-static const char *yyRuleName[] = {
-%%
-};
-#endif /* NDEBUG */
-
-/*
-** This function returns the symbolic name associated with a token
-** value.
-*/
-#if 0
-const char *ParseTokenName(int tokenType){
-#ifndef NDEBUG
- if( tokenType>0 && ((size_t)tokenType)<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
- return yyTokenName[tokenType];
- }else{
- return "Unknown";
- }
-#else
- return "";
-#endif
-}
-#endif
-
-/*
-** This function allocates a new parser.
-** The only argument is a pointer to a function which works like
-** malloc.
-**
-** Inputs:
-** A pointer to the function used to allocate memory.
-**
-** Outputs:
-** A pointer to a parser. This pointer is used in subsequent calls
-** to Parse and ParseFree.
-*/
-void *ParseAlloc(void *(*mallocProc)(size_t)){
- yyParser *pParser;
- pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
- if( pParser ){
- pParser->yyidx = -1;
- }
- return pParser;
-}
-
-/* The following function deletes the value associated with a
-** symbol. The symbol can be either a terminal or nonterminal.
-** "yymajor" is the symbol code, and "yypminor" is a pointer to
-** the value.
-*/
-static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
- switch( yymajor ){
- /* Here is inserted the actions which take place when a
- ** terminal or non-terminal is destroyed. This can happen
- ** when the symbol is popped from the stack during a
- ** reduce or during error processing or when a parser is
- ** being destroyed before it is finished parsing.
- **
- ** Note: during a reduce, the only symbols destroyed are those
- ** which appear on the RHS of the rule, but which are not used
- ** inside the C code.
- */
-%%
- default: break; /* If no destructor action specified: do nothing */
- }
-}
-
-/*
-** Pop the parser's stack once.
-**
-** If there is a destructor routine associated with the token which
-** is popped from the stack, then call it.
-**
-** Return the major token number for the symbol popped.
-*/
-static int yy_pop_parser_stack(yyParser *pParser){
- YYCODETYPE yymajor;
- yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
-
- if( pParser->yyidx<0 ) return 0;
-#ifndef NDEBUG
- if( yyTraceFILE && pParser->yyidx>=0 ){
- fprintf(yyTraceFILE,"%sPopping %s\n",
- yyTracePrompt,
- yyTokenName[yytos->major]);
- }
-#endif
- yymajor = yytos->major;
- yy_destructor( yymajor, &yytos->minor);
- pParser->yyidx--;
- return yymajor;
-}
-
-/*
-** Deallocate and destroy a parser. Destructors are all called for
-** all stack elements before shutting the parser down.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser. This should be a pointer
-** obtained from ParseAlloc.
-** <li> A pointer to a function used to reclaim memory obtained
-** from malloc.
-** </ul>
-*/
-void ParseFree(
- void *p, /* The parser to be deleted */
- void (*freeProc)(void*) /* Function used to reclaim memory */
-){
- yyParser *pParser = (yyParser*)p;
- if( pParser==0 ) return;
- while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
- (*freeProc)((void*)pParser);
-}
-
-/*
-** Find the appropriate action for a parser given the terminal
-** look-ahead token iLookAhead.
-**
-** If the look-ahead token is YYNOCODE, then check to see if the action is
-** independent of the look-ahead. If it is, return the action, otherwise
-** return YY_NO_ACTION.
-*/
-static int yy_find_shift_action(
- yyParser *pParser, /* The parser */
- int iLookAhead /* The look-ahead token */
-){
- int i;
- int stateno = pParser->yystack[pParser->yyidx].stateno;
-
- /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
- i = yy_shift_ofst[stateno];
- if( i==YY_SHIFT_USE_DFLT ){
- return yy_default[stateno];
- }
- if( iLookAhead==YYNOCODE ){
- return YY_NO_ACTION;
- }
- i += iLookAhead;
- if( i<0 || (size_t)i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
-#ifdef YYFALLBACK
- int iFallback; /* Fallback token */
- if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
- && (iFallback = yyFallback[iLookAhead])!=0 ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
- }
-#endif
- return yy_find_shift_action(pParser, iFallback);
- }
-#endif
- return yy_default[stateno];
- }else{
- return yy_action[i];
- }
-}
-
-/*
-** Find the appropriate action for a parser given the non-terminal
-** look-ahead token iLookAhead.
-**
-** If the look-ahead token is YYNOCODE, then check to see if the action is
-** independent of the look-ahead. If it is, return the action, otherwise
-** return YY_NO_ACTION.
-*/
-static int yy_find_reduce_action(
- yyParser *pParser, /* The parser */
- int iLookAhead /* The look-ahead token */
-){
- int i;
- int stateno = pParser->yystack[pParser->yyidx].stateno;
-
- i = yy_reduce_ofst[stateno];
- if( i==YY_REDUCE_USE_DFLT ){
- return yy_default[stateno];
- }
- if( iLookAhead==YYNOCODE ){
- return YY_NO_ACTION;
- }
- i += iLookAhead;
- if( i<0 || (size_t)i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
- return yy_default[stateno];
- }else{
- return yy_action[i];
- }
-}
-
-/*
-** Perform a shift action.
-*/
-static void yy_shift(
- yyParser *yypParser, /* The parser to be shifted */
- int yyNewState, /* The new state to shift in */
- int yyMajor, /* The major token to shift in */
- YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
-){
- yyStackEntry *yytos;
- yypParser->yyidx++;
- if( yypParser->yyidx>=YYSTACKDEPTH ){
- ParseARG_FETCH;
- yypParser->yyidx--;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will execute if the parser
- ** stack every overflows */
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
- return;
- }
- yytos = &yypParser->yystack[yypParser->yyidx];
- yytos->stateno = yyNewState;
- yytos->major = yyMajor;
- yytos->minor = *yypMinor;
-#ifndef NDEBUG
- if( yyTraceFILE && yypParser->yyidx>0 ){
- int i;
- fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
- fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
- for(i=1; i<=yypParser->yyidx; i++)
- fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
- fprintf(yyTraceFILE,"\n");
- }
-#endif
-}
-
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- unsigned char nrhs; /* Number of right-hand side symbols in the rule */
-} yyRuleInfo[] = {
-%%
-};
-
-static void yy_accept(yyParser*); /* Forward Declaration */
-
-/*
-** Perform a reduce action and the shift that must immediately
-** follow the reduce.
-*/
-static void yy_reduce(
- yyParser *yypParser, /* The parser */
- int yyruleno /* Number of the rule by which to reduce */
-){
- int yygoto; /* The next state */
- int yyact; /* The next action */
- YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
- yyStackEntry *yymsp; /* The top of the parser's stack */
- int yysize; /* Amount to pop the stack */
- ParseARG_FETCH;
- yymsp = &yypParser->yystack[yypParser->yyidx];
-#ifndef NDEBUG
- if( yyTraceFILE && yyruleno>=0
- && (size_t) yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
- fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
- yyRuleName[yyruleno]);
- }
-#endif /* NDEBUG */
-
- switch( yyruleno ){
- /* Beginning here are the reduction cases. A typical example
- ** follows:
- ** case 0:
- ** #line <lineno> <grammarfile>
- ** { ... } // User supplied code
- ** #line <lineno> <thisfile>
- ** break;
- */
-%%
- };
- yygoto = yyRuleInfo[yyruleno].lhs;
- yysize = yyRuleInfo[yyruleno].nrhs;
- yypParser->yyidx -= yysize;
- yyact = yy_find_reduce_action(yypParser,yygoto);
- if( yyact < YYNSTATE ){
- yy_shift(yypParser,yyact,yygoto,&yygotominor);
- }else if( yyact == YYNSTATE + YYNRULE + 1 ){
- yy_accept(yypParser);
- }
-}
-
-/*
-** The following code executes when the parse fails
-*/
-static void yy_parse_failed(
- yyParser *yypParser /* The parser */
-){
- ParseARG_FETCH;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser fails */
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/*
-** The following code executes when a syntax error first occurs.
-*/
-static void yy_syntax_error(
- yyParser *yypParser, /* The parser */
- int yymajor, /* The major type of the error token */
- YYMINORTYPE yyminor /* The minor type of the error token */
-){
- ParseARG_FETCH;
- ( (void) yymajor );
- ( (void) yyminor );
-#define TOKEN (yyminor.yy0)
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/*
-** The following is executed when the parser accepts
-*/
-static void yy_accept(
- yyParser *yypParser /* The parser */
-){
- ParseARG_FETCH;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
- }
-#endif
- while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
- /* Here code is inserted which will be executed whenever the
- ** parser accepts */
-%%
- ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
-}
-
-/* The main parser program.
-** The first argument is a pointer to a structure obtained from
-** "ParseAlloc" which describes the current state of the parser.
-** The second argument is the major token number. The third is
-** the minor token. The fourth optional argument is whatever the
-** user wants (and specified in the grammar) and is available for
-** use by the action routines.
-**
-** Inputs:
-** <ul>
-** <li> A pointer to the parser (an opaque structure.)
-** <li> The major token number.
-** <li> The minor token number.
-** <li> An option argument of a grammar-specified type.
-** </ul>
-**
-** Outputs:
-** None.
-*/
-void Parse(
- void *yyp, /* The parser */
- int yymajor, /* The major token code number */
- ParseTOKENTYPE yyminor /* The value for the token */
- ParseARG_PDECL /* Optional %extra_argument parameter */
-){
- YYMINORTYPE yyminorunion;
- int yyact; /* The parser action. */
- int yyendofinput; /* True if we are at the end of input */
- int yyerrorhit = 0; /* True if yymajor has invoked an error */
- yyParser *yypParser; /* The parser */
-
- /* (re)initialize the parser, if necessary */
- yypParser = (yyParser*)yyp;
- if( yypParser->yyidx<0 ){
- if( yymajor==0 ) return; /* Accept empty input */
- yypParser->yyidx = 0;
- yypParser->yyerrcnt = -1;
- yypParser->yystack[0].stateno = 0;
- yypParser->yystack[0].major = 0;
- }
- yyminorunion.yy0 = yyminor;
- yyendofinput = (yymajor==0);
- ParseARG_STORE;
-
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
-
- do{
- yyact = yy_find_shift_action(yypParser,yymajor);
- if( yyact<YYNSTATE ){
- yy_shift(yypParser,yyact,yymajor,&yyminorunion);
- yypParser->yyerrcnt--;
- if( yyendofinput && yypParser->yyidx>=0 ){
- yymajor = 0;
- }else{
- yymajor = YYNOCODE;
- }
- }else if( yyact < YYNSTATE + YYNRULE ){
- yy_reduce(yypParser,yyact-YYNSTATE);
- }else if( yyact == YY_ERROR_ACTION ){
- int yymx;
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
- }
-#endif
-#ifdef YYERRORSYMBOL
- /* A syntax error has occurred.
- ** The response to an error depends upon whether or not the
- ** grammar defines an error token "ERROR".
- **
- ** This is what we do if the grammar does define ERROR:
- **
- ** * Call the %syntax_error function.
- **
- ** * Begin popping the stack until we enter a state where
- ** it is legal to shift the error symbol, then shift
- ** the error symbol.
- **
- ** * Set the error count to three.
- **
- ** * Begin accepting and shifting new tokens. No new error
- ** processing will occur until three tokens have been
- ** shifted successfully.
- **
- */
- if( yypParser->yyerrcnt<0 ){
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- }
- yymx = yypParser->yystack[yypParser->yyidx].major;
- if( yymx==YYERRORSYMBOL || yyerrorhit ){
-#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sDiscard input token %s\n",
- yyTracePrompt,yyTokenName[yymajor]);
- }
-#endif
- yy_destructor(yymajor,&yyminorunion);
- yymajor = YYNOCODE;
- }else{
- while(
- yypParser->yyidx >= 0 &&
- yymx != YYERRORSYMBOL &&
- (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
- ){
- yy_pop_parser_stack(yypParser);
- }
- if( yypParser->yyidx < 0 || yymajor==0 ){
- yy_destructor(yymajor,&yyminorunion);
- yy_parse_failed(yypParser);
- yymajor = YYNOCODE;
- }else if( yymx!=YYERRORSYMBOL ){
- YYMINORTYPE u2;
- u2.YYERRSYMDT = 0;
- yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
- }
- }
- yypParser->yyerrcnt = 3;
- yyerrorhit = 1;
-#else /* YYERRORSYMBOL is not defined */
- /* This is what we do if the grammar does not define ERROR:
- **
- ** * Report an error message, and throw away the input token.
- **
- ** * If the input token is $, then fail the parse.
- **
- ** As before, subsequent error messages are suppressed until
- ** three input tokens have been successfully shifted.
- */
- if( yypParser->yyerrcnt<=0 ){
- yy_syntax_error(yypParser,yymajor,yyminorunion);
- }
- yypParser->yyerrcnt = 3;
- yy_destructor(yymajor,&yyminorunion);
- if( yyendofinput ){
- yy_parse_failed(yypParser);
- }
- yymajor = YYNOCODE;
-#endif
- }else{
- yy_accept(yypParser);
- yymajor = YYNOCODE;
- }
- }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
- return;
-}
diff --git a/src/log.c b/src/log.c
deleted file mode 100644
index 401ab50d..00000000
--- a/src/log.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef _WIN32
-#undef HAVE_SYSLOG_H
-#endif
-
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-
-#include "log.h"
-#include "array.h"
-
-#include "sys-files.h"
-
-#ifdef _WIN32
-#define STDERR_FILENO 2
-#endif
-
-#ifndef O_LARGEFILE
-# define O_LARGEFILE 0
-#endif
-
-/* Close fd and _try_ to get a /dev/null for it instead.
- * close() alone may trigger some bugs when a
- * process opens another file and gets fd = STDOUT_FILENO or STDERR_FILENO
- * and later tries to just print on stdout/stderr
- *
- * Returns 0 on success and -1 on failure (fd gets closed in all cases)
- */
-int openDevNull(int fd) {
- int tmpfd;
- close(fd);
-#if defined(__WIN32)
- /* Cygwin should work with /dev/null */
- tmpfd = open("nul", O_RDWR);
-#else
- tmpfd = open("/dev/null", O_RDWR);
-#endif
- if (tmpfd != -1 && tmpfd != fd) {
- dup2(tmpfd, fd);
- close(tmpfd);
- }
- return (tmpfd != -1) ? 0 : -1;
-}
-
-/**
- * open the errorlog
- *
- * we have 3 possibilities:
- * - stderr (default)
- * - syslog
- * - logfile
- *
- * if the open failed, report to the user and die
- *
- */
-
-
-typedef struct {
- buffer *file;
- unsigned short use_syslog;
-
- /* the errorlog */
- int fd;
- enum { ERRORLOG_FILE, ERRORLOG_FD, ERRORLOG_SYSLOG } mode;
- buffer *buf;
-
- time_t cached_ts;
- buffer *cached_ts_str;
-} errorlog;
-
-errorlog *myconfig = NULL;
-
-void log_init(void) {
- /* use syslog */
- errorlog *err;
-
- err = calloc(1, sizeof(*err));
-
- err->fd = STDERR_FILENO;
- err->mode = ERRORLOG_FD;
- err->buf = buffer_init();
- err->cached_ts_str = buffer_init();
-
- myconfig = err;
-}
-
-void log_free(void) {
- errorlog *err = myconfig;
-
- if (!err) return;
-
- switch(err->mode) {
- case ERRORLOG_FILE:
- case ERRORLOG_FD:
- if (-1 != err->fd) {
- if (STDERR_FILENO != err->fd)
- close(err->fd);
- err->fd = -1;
- }
- break;
- case ERRORLOG_SYSLOG:
-#ifdef HAVE_SYSLOG_H
- closelog();
-#endif
- break;
- }
-
- buffer_free(err->buf);
- buffer_free(err->cached_ts_str);
-
- free(err);
-
- myconfig = NULL;
-}
-
-int log_error_open(buffer *file, buffer *breakage_file, int use_syslog, int dont_daemonize) {
- errorlog *err = myconfig;
-
-#ifdef HAVE_SYSLOG_H
- /* perhaps someone wants to use syslog() */
- openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
-#endif
- err->mode = ERRORLOG_FD;
- err->fd = STDERR_FILENO;
-
- if (use_syslog) {
- err->mode = ERRORLOG_SYSLOG;
- } else if (!buffer_is_empty(file)) {
- if (-1 == (err->fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
- log_error_write(NULL, __FILE__, __LINE__, "SBSS",
- "opening errorlog '", file,
- "' failed: ", strerror(errno));
-
- return -1;
- }
-#ifdef FD_CLOEXEC
- /* close fd on exec (cgi) */
- fcntl(err->fd, F_SETFD, FD_CLOEXEC);
-#endif
- err->mode = ERRORLOG_FILE;
- err->file = file;
- }
-
- TRACE("%s", "server started");
-
- if (err->mode == ERRORLOG_FD && !dont_daemonize) {
- /* We can only log to stderr in dont-daemonize mode */
- err->fd = -1;
- }
-
- if (!buffer_is_empty(breakage_file)) {
- int breakage_fd;
-
- if (err->mode == ERRORLOG_FD) {
- err->fd = dup(STDERR_FILENO);
-#ifdef FD_CLOEXEC
- fcntl(err->fd, F_SETFD, FD_CLOEXEC);
-#endif
- }
-
- if (-1 == (breakage_fd = open(breakage_file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
- log_error_write(NULL, __FILE__, __LINE__, "SBSS",
- "opening breakagelog '", breakage_file,
- "' failed: ", strerror(errno));
-
- return -1;
- }
-
- if (STDERR_FILENO != breakage_fd) {
- dup2(breakage_fd, STDERR_FILENO);
- close(breakage_fd);
- }
- } else if (!dont_daemonize) {
- /* move stderr to /dev/null */
- openDevNull(STDERR_FILENO);
- }
-
-
- return 0;
-}
-
-/**
- * open the errorlog
- *
- * if the open failed, report to the user and die
- * if no filename is given, use syslog instead
- *
- */
-
-int log_error_cycle(void) {
- /* only cycle if we are not in syslog-mode */
-
- errorlog *err = myconfig;
-
- if (err->mode == ERRORLOG_FILE) {
- buffer *file = err->file;
- /* already check of opening time */
-
- int new_fd;
-
- if (-1 == (new_fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
- /* write to old log */
- log_error_write(NULL, __FILE__, __LINE__, "SBSSS",
- "cycling errorlog '", file,
- "' failed: ", strerror(errno),
- ", falling back to syslog()");
-
- close(err->fd);
- err->fd = -1;
-#ifdef HAVE_SYSLOG_H
- err->mode = ERRORLOG_SYSLOG;
-#endif
- } else {
- /* ok, new log is open, close the old one */
- close(err->fd);
- err->fd = new_fd;
- }
- }
-
- return 0;
-}
-
-int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...) {
- va_list ap;
- time_t t;
-
- errorlog *err = myconfig;
-
- UNUSED(srv);
-
- switch(err->mode) {
- case ERRORLOG_FILE:
- case ERRORLOG_FD:
- if (-1 == err->fd) return 0;
- /* cache the generated timestamp */
- t = time(NULL);
-
- if (t != err->cached_ts) {
- buffer_prepare_copy(err->cached_ts_str, 255);
- strftime(err->cached_ts_str->ptr, err->cached_ts_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(t)));
- err->cached_ts_str->used = strlen(err->cached_ts_str->ptr) + 1;
- err->cached_ts = t;
- }
-
- buffer_copy_string_buffer(err->buf, err->cached_ts_str);
- buffer_append_string_len(err->buf, CONST_STR_LEN(" ("));
- break;
- case ERRORLOG_SYSLOG:
- /* syslog is generating its own timestamps */
- buffer_copy_string_len(err->buf, CONST_STR_LEN("("));
- break;
- }
-
- buffer_append_string(err->buf, REMOVE_PATH(filename));
- buffer_append_string_len(err->buf, CONST_STR_LEN(":"));
- buffer_append_long(err->buf, line);
- buffer_append_string_len(err->buf, CONST_STR_LEN(") "));
-
- for(va_start(ap, fmt); *fmt; fmt++) {
- int d;
- char *s;
- buffer *b;
- off_t o;
-
- switch(*fmt) {
- case 's': /* string */
- s = va_arg(ap, char *);
- buffer_append_string(err->buf, s);
- buffer_append_string_len(err->buf, CONST_STR_LEN(" "));
- break;
- case 'b': /* buffer */
- b = va_arg(ap, buffer *);
- buffer_append_string_buffer(err->buf, b);
- buffer_append_string_len(err->buf, CONST_STR_LEN(" "));
- break;
- case 'd': /* int */
- d = va_arg(ap, int);
- buffer_append_long(err->buf, d);
- buffer_append_string_len(err->buf, CONST_STR_LEN(" "));
- break;
- case 'o': /* off_t */
- o = va_arg(ap, off_t);
- buffer_append_off_t(err->buf, o);
- buffer_append_string_len(err->buf, CONST_STR_LEN(" "));
- break;
- case 'x': /* int (hex) */
- d = va_arg(ap, int);
- buffer_append_string_len(err->buf, CONST_STR_LEN("0x"));
- buffer_append_long_hex(err->buf, d);
- buffer_append_string_len(err->buf, CONST_STR_LEN(" "));
- break;
- case 'S': /* string */
- s = va_arg(ap, char *);
- buffer_append_string(err->buf, s);
- break;
- case 'B': /* buffer */
- b = va_arg(ap, buffer *);
- buffer_append_string_buffer(err->buf, b);
- break;
- case 'D': /* int */
- d = va_arg(ap, int);
- buffer_append_long(err->buf, d);
- break;
- case '(':
- case ')':
- case '<':
- case '>':
- case ',':
- case ' ':
- buffer_append_string_len(err->buf, fmt, 1);
- break;
- }
- }
- va_end(ap);
-
- switch(err->mode) {
- case ERRORLOG_FILE:
- case ERRORLOG_FD:
- buffer_append_string_len(err->buf, CONST_STR_LEN("\n"));
- write(err->fd, err->buf->ptr, err->buf->used - 1);
- break;
-#ifdef HAVE_SYSLOG_H
- case ERRORLOG_SYSLOG:
- syslog(LOG_ERR, "%s", err->buf->ptr);
- break;
-#endif
- }
-
- return 0;
-}
-
-int log_trace(const char *fmt, ...) {
- buffer *b;
- int l, tries = 0;
- errorlog *err = myconfig;
- va_list ap;
- time_t t;
- int timestrsize = 0;
-
- b = buffer_init();
- buffer_prepare_copy(b, 4096);
-
- switch(err->mode) {
- case ERRORLOG_FILE:
- case ERRORLOG_FD:
- if (-1 == err->fd) return 0;
- /* cache the generated timestamp */
- t = time(NULL);
-
- if (t != err->cached_ts) {
- buffer_prepare_copy(err->cached_ts_str, 255);
- strftime(err->cached_ts_str->ptr, err->cached_ts_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(t)));
- err->cached_ts_str->used = strlen(err->cached_ts_str->ptr) + 1;
- err->cached_ts = t;
- }
-
- buffer_copy_string_buffer(b, err->cached_ts_str);
- buffer_append_string_len(b, CONST_STR_LEN(" "));
- timestrsize = b->used - 1;
- break;
- case ERRORLOG_SYSLOG:
- /* syslog is generating its own timestamps */
- buffer_copy_string_len(b, CONST_STR_LEN(""));
- timestrsize = b->used - 1;
- break;
- }
-
- do {
- errno = 0;
- va_start(ap, fmt);
- l = vsnprintf(b->ptr+timestrsize, b->size-timestrsize, fmt, ap);
- va_end(ap);
-
- /* if 'l' is between -1 and size we are good,
- * otherwise we have to resize to size
- */
-
- if (l > -1 && ((unsigned int) l) < (b->size-timestrsize)) {
- b->used += l;
-
- break;
- }
-
- if (l > -1) {
- /* C99: l is the mem-size we need */
- buffer_prepare_append(b, l + 1); /* allocate a bit more than we need */
- } else if (tries++ >= 3) {
- int e = errno;
- /* glibc 2.0.6 and earlier return -1 if the output was truncated
- * so we try to increase the buffer size 3 times - so you cannot
- * print error messages longer than 8 * 4096 = 32k with glib <= 2.0.6
- */
- buffer_copy_string_len(b, CONST_STR_LEN("log_trace: vsnprintf error: l = "));
- buffer_append_long(b, l);
- if (e) {
- buffer_append_string_len(b, CONST_STR_LEN(", errno = "));
- buffer_append_long(b, errno);
- buffer_append_string_len(b, CONST_STR_LEN(": "));
- buffer_append_string(b, strerror(e));
- }
- break;
- } else {
- buffer_prepare_append(b, 2*b->size);
- }
- } while(1);
-
- /* write b */
- switch(err->mode) {
- case ERRORLOG_FILE:
- case ERRORLOG_FD:
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
- write(err->fd, b->ptr, b->used - 1);
- break;
-#ifdef HAVE_SYSLOG_H
- case ERRORLOG_SYSLOG:
- syslog(LOG_ERR, "%s", b->ptr);
- break;
-#endif
- }
-
- buffer_free(b);
-
- return 0;
-}
-
-#if REMOVE_PATH_FROM_FILE
-const char *remove_path(const char *path) {
- char *p = strrchr(path, DIR_SEPERATOR);
- if (NULL != p && *(p) != '\0') {
- return (p + 1);
- }
- return path;
-}
-#endif
-
diff --git a/src/log.h b/src/log.h
deleted file mode 100644
index 616e6274..00000000
--- a/src/log.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _LOG_H_
-#define _LOG_H_
-
-#include "valgrind/valgrind.h"
-#include "buffer.h"
-
-/* Close fd and _try_ to get a /dev/null for it instead.
- * Returns 0 on success and -1 on failure (fd gets closed in all cases)
- */
-LI_API int openDevNull(int fd);
-
-LI_API void log_init(void);
-LI_API void log_free(void);
-
-LI_API int log_error_open(buffer* file, buffer* breakage_file, int use_syslog, int dont_daemonize);
-LI_API int log_error_close();
-LI_API int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...);
-LI_API int log_error_cycle();
-#define REMOVE_PATH_FROM_FILE 1
-#if REMOVE_PATH_FROM_FILE
-LI_API const char *remove_path(const char *path);
-#define REMOVE_PATH(file) remove_path(file)
-#else
-#define REMOVE_PATH(file) file
-#endif
-
-// TODO: perhaps make portable (detect if cc supports)
-#define __ATTRIBUTE_PRINTF_FORMAT(fmt, arg) __attribute__ ((__format__ (__printf__, fmt, arg)))
-
-#define ERROR(fmt, ...) \
- log_trace("(error) (%s:%d) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
-
-#define TRACE(fmt, ...) \
- log_trace("(trace) (%s:%d) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
-
-#define SEGFAULT(fmt, ...) \
- do { \
- log_trace("(crashing) (%s:%d) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__); \
- VALGRIND_PRINTF_BACKTRACE(fmt, __VA_ARGS__);\
- abort();\
- } while(0)
-LI_API int log_trace(const char *fmt, ...) __ATTRIBUTE_PRINTF_FORMAT(1, 2);
-#endif
diff --git a/src/md5.c b/src/md5.c
deleted file mode 100644
index b365fc41..00000000
--- a/src/md5.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef USE_OPENSSL
-#include <string.h>
-
-#include "md5.h"
-
-/* Constants for MD5Transform routine.
- */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-static void li_MD5Transform (UINT4 [4], const unsigned char [64]);
-static void Encode (unsigned char *, UINT4 *, unsigned int);
-static void Decode (UINT4 *, const unsigned char *, unsigned int);
-
-#ifdef HAVE_MEMCPY
-#define MD5_memcpy(output, input, len) memcpy((output), (input), (len))
-#else
-static void MD5_memcpy (POINTER, POINTER, unsigned int);
-#endif
-#ifdef HAVE_MEMSET
-#define MD5_memset(output, value, len) memset((output), (value), (len))
-#else
-static void MD5_memset (POINTER, int, unsigned int);
-#endif
-
-static unsigned char PADDING[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-void li_MD5_Init (context)
-li_MD5_CTX *context; /* context */
-{
- context->count[0] = context->count[1] = 0;
- /* Load magic initialization constants.
-*/
- context->state[0] = 0x67452301;
- context->state[1] = 0xefcdab89;
- context->state[2] = 0x98badcfe;
- context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
- operation, processing another message block, and updating the
- context.
- */
-void li_MD5_Update (context, input, inputLen)
-li_MD5_CTX *context; /* context */
-const unsigned char *input; /* input block */
-unsigned int inputLen; /* length of input block */
-{
- unsigned int i, ndx, partLen;
-
- /* Compute number of bytes mod 64 */
- ndx = (unsigned int)((context->count[0] >> 3) & 0x3F);
-
- /* Update number of bits */
- if ((context->count[0] += ((UINT4)inputLen << 3))
-
- < ((UINT4)inputLen << 3))
- context->count[1]++;
- context->count[1] += ((UINT4)inputLen >> 29);
-
- partLen = 64 - ndx;
-
- /* Transform as many times as possible.
-*/
- if (inputLen >= partLen) {
- MD5_memcpy
- ((POINTER)&context->buffer[ndx], (POINTER)input, partLen);
- li_MD5Transform (context->state, context->buffer);
-
- for (i = partLen; i + 63 < inputLen; i += 64)
- li_MD5Transform (context->state, &input[i]);
-
- ndx = 0;
- }
- else
- i = 0;
-
- /* Buffer remaining input */
- MD5_memcpy
- ((POINTER)&context->buffer[ndx], (POINTER)&input[i],
- inputLen-i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
- the message digest and zeroizing the context.
- */
-void li_MD5_Final (digest, context)
-unsigned char digest[16]; /* message digest */
-li_MD5_CTX *context; /* context */
-{
- unsigned char bits[8];
- unsigned int ndx, padLen;
-
- /* Save number of bits */
- Encode (bits, context->count, 8);
-
- /* Pad out to 56 mod 64.
-*/
- ndx = (unsigned int)((context->count[0] >> 3) & 0x3f);
- padLen = (ndx < 56) ? (56 - ndx) : (120 - ndx);
- li_MD5_Update (context, PADDING, padLen);
-
- /* Append length (before padding) */
- li_MD5_Update (context, bits, 8);
-
- /* Store state in digest */
- Encode (digest, context->state, 16);
-
- /* Zeroize sensitive information.
-*/
- MD5_memset ((POINTER)context, 0, sizeof (*context));
-}
-
-/* MD5 basic transformation. Transforms state based on block.
- */
-static void li_MD5Transform (state, block)
-UINT4 state[4];
-const unsigned char block[64];
-{
- UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
- Decode (x, block, 64);
-
- /* Round 1 */
- FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
-
- GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
- HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-
- /* Zeroize sensitive information.
-
-*/
- MD5_memset ((POINTER)x, 0, sizeof (x));
-}
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
- a multiple of 4.
- */
-static void Encode (output, input, len)
-unsigned char *output;
-UINT4 *input;
-unsigned int len;
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
- }
-}
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
- a multiple of 4.
- */
-static void Decode (output, input, len)
-UINT4 *output;
-const unsigned char *input;
-unsigned int len;
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
- (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
-}
-
-/* Note: Replace "for loop" with standard memcpy if possible.
- */
-#ifndef HAVE_MEMCPY
-static void MD5_memcpy (output, input, len)
-POINTER output;
-POINTER input;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
-
- output[i] = input[i];
-}
-#endif
-/* Note: Replace "for loop" with standard memset if possible.
- */
-#ifndef HAVE_MEMSET
-static void MD5_memset (output, value, len)
-POINTER output;
-int value;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
- ((char *)output)[i] = (char)value;
-}
-#endif
-#endif
diff --git a/src/md5.h b/src/md5.h
deleted file mode 100644
index fbcada0f..00000000
--- a/src/md5.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* MD5.H - header file for MD5C.C
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-#include <limits.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-#ifdef _WIN32
-#define UINT4 unsigned __int32
-#define UINT2 unsigned __int16
-#define POINTER unsigned char *
-#else
-#define UINT4 uint32_t
-#define UINT2 uint16_t
-#define POINTER unsigned char *
-#endif
-
-#include "settings.h"
-
-/* MD5 context. */
-typedef struct {
- UINT4 state[4]; /* state (ABCD) */
- UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
- unsigned char buffer[64]; /* input buffer */
-} li_MD5_CTX;
-
-LI_API void li_MD5_Init (li_MD5_CTX *);
-LI_API void li_MD5_Update (li_MD5_CTX *, const unsigned char *, unsigned int);
-LI_API void li_MD5_Final (unsigned char [16], li_MD5_CTX *);
-
-
-
diff --git a/src/mod_access.c b/src/mod_access.c
deleted file mode 100644
index 03eee6da..00000000
--- a/src/mod_access.c
+++ /dev/null
@@ -1,230 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "sys-strings.h"
-
-#define PLUGIN_NAME "access"
-
-#define CONFIG_URL_ACCESS_DENY "url.access-deny"
-#define CONFIG_ACCESS_DENY_ALL PLUGIN_NAME ".deny-all"
-
-typedef struct {
- array *access_deny;
-
- unsigned short deny_all;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_access_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-FREE_FUNC(mod_access_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- array_free(s->access_deny);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_access_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { CONFIG_URL_ACCESS_DENY, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_ACCESS_DENY_ALL, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->access_deny = array_init();
- s->deny_all = 0;
-
- cv[0].destination = s->access_deny;
- cv[1].destination = &(s->deny_all);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(access_deny);
- PATCH_OPTION(deny_all);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_URL_ACCESS_DENY))) {
- PATCH_OPTION(access_deny);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_ACCESS_DENY_ALL))) {
- PATCH_OPTION(deny_all);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_access_uri_handler) {
- plugin_data *p = p_d;
- int s_len;
- size_t k;
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_access_patch_connection(srv, con, p);
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "handling file in mod_access");
- }
-
- s_len = con->uri.path->used - 1;
-
- for (k = 0; k < p->conf.access_deny->used; k++) {
- data_string *ds = (data_string *)p->conf.access_deny->data[k];
- int ct_len = ds->value->used - 1;
-
- if (ct_len > s_len) continue;
- if (ds->value->used == 0) continue;
-
- /* if we have a case-insensitive FS we have to lower-case the URI here too */
-
- if (con->conf.force_lowercase_filenames) {
- if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("access denied, sending %d", con->http_status);
- }
-
- return HANDLER_FINISHED;
- }
- } else {
- if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("access denied for %s as %s matched %d chars, sending %d",
- SAFE_BUF_STR(con->uri.path),
- SAFE_BUF_STR(ds->value),
- ct_len,
- con->http_status);
- }
-
- return HANDLER_FINISHED;
- }
- }
- }
-
- if (p->conf.deny_all) {
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("access.deny-all triggered, sending %d", con->http_status);
- }
-
- return HANDLER_FINISHED;
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-URIHANDLER_FUNC(mod_access_path_handler) {
- plugin_data *p = p_d;
-
- mod_access_patch_connection(srv, con, p);
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "handling file in mod_access");
- }
-
- if (p->conf.deny_all) {
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("access denied, sending %d", con->http_status);
- }
-
- return HANDLER_FINISHED;
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_access_plugin_init(plugin *p);
-LI_EXPORT int mod_access_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string(PLUGIN_NAME);
-
- p->init = mod_access_init;
- p->set_defaults = mod_access_set_defaults;
- p->handle_uri_clean = mod_access_uri_handler;
- p->handle_start_backend = mod_access_path_handler;
- p->cleanup = mod_access_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_accesslog.c b/src/mod_accesslog.c
deleted file mode 100644
index 419fc463..00000000
--- a/src/mod_accesslog.c
+++ /dev/null
@@ -1,911 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h> /* only the defines on windows */
-#include <errno.h>
-#include <time.h>
-
-#include <stdio.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "inet_ntop_cache.h"
-
-#include "sys-socket.h"
-#include "sys-files.h"
-
-#ifdef HAVE_SYSLOG_H
-# include <syslog.h>
-#endif
-
-typedef struct {
- char key;
- enum {
- FORMAT_UNSET,
- FORMAT_UNSUPPORTED,
- FORMAT_PERCENT,
- FORMAT_REMOTE_HOST,
- FORMAT_REMOTE_IDENT,
- FORMAT_REMOTE_USER,
- FORMAT_TIMESTAMP,
- FORMAT_REQUEST_LINE,
- FORMAT_STATUS,
- FORMAT_BYTES_OUT_NO_HEADER,
- FORMAT_HEADER,
-
- FORMAT_REMOTE_ADDR,
- FORMAT_LOCAL_ADDR,
- FORMAT_COOKIE,
- FORMAT_TIME_USED_MS,
- FORMAT_ENV,
- FORMAT_FILENAME,
- FORMAT_REQUEST_PROTOCOL,
- FORMAT_REQUEST_METHOD,
- FORMAT_SERVER_PORT,
- FORMAT_QUERY_STRING,
- FORMAT_TIME_USED,
- FORMAT_URL,
- FORMAT_SERVER_NAME,
- FORMAT_HTTP_HOST,
- FORMAT_CONNECTION_STATUS,
- FORMAT_BYTES_IN,
- FORMAT_BYTES_OUT,
-
- FORMAT_RESPONSE_HEADER
- } type;
-} format_mapping;
-
-/**
- *
- *
- * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
- *
- */
-
-const format_mapping fmap[] =
-{
- { '%', FORMAT_PERCENT },
- { 'h', FORMAT_REMOTE_HOST },
- { 'l', FORMAT_REMOTE_IDENT },
- { 'u', FORMAT_REMOTE_USER },
- { 't', FORMAT_TIMESTAMP },
- { 'r', FORMAT_REQUEST_LINE },
- { 's', FORMAT_STATUS },
- { 'b', FORMAT_BYTES_OUT_NO_HEADER },
- { 'i', FORMAT_HEADER },
-
- { 'a', FORMAT_REMOTE_ADDR },
- { 'A', FORMAT_LOCAL_ADDR },
- { 'B', FORMAT_BYTES_OUT_NO_HEADER },
- { 'C', FORMAT_COOKIE },
- { 'D', FORMAT_TIME_USED_MS },
- { 'e', FORMAT_ENV },
- { 'f', FORMAT_FILENAME },
- { 'H', FORMAT_REQUEST_PROTOCOL },
- { 'm', FORMAT_REQUEST_METHOD },
- { 'n', FORMAT_UNSUPPORTED }, /* we have no notes */
- { 'p', FORMAT_SERVER_PORT },
- { 'P', FORMAT_UNSUPPORTED }, /* we are only one process */
- { 'q', FORMAT_QUERY_STRING },
- { 'T', FORMAT_TIME_USED },
- { 'U', FORMAT_URL }, /* w/o querystring */
- { 'v', FORMAT_SERVER_NAME },
- { 'V', FORMAT_HTTP_HOST },
- { 'X', FORMAT_CONNECTION_STATUS },
- { 'I', FORMAT_BYTES_IN },
- { 'O', FORMAT_BYTES_OUT },
-
- { 'o', FORMAT_RESPONSE_HEADER },
-
- { '\0', FORMAT_UNSET }
-};
-
-
-typedef struct {
- enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
-
- buffer *string;
- int field;
-} format_field;
-
-typedef struct {
- format_field **ptr;
-
- size_t used;
- size_t size;
-} format_fields;
-
-typedef struct {
- buffer *access_logfile;
- buffer *format;
- unsigned short use_syslog;
-
-
- int log_access_fd;
- time_t last_generated_accesslog_ts;
- time_t *last_generated_accesslog_ts_ptr;
-
-
- buffer *access_logbuffer;
- buffer *ts_accesslog_str;
-
- format_fields *parsed_format;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_accesslog_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-static void accesslog_append_escaped(buffer *dest, buffer *str) {
- /* replaces non-printable chars with \xHH where HH is the hex representation of the byte */
- /* exceptions: " => \", \ => \\, whitespace chars => \n \t etc. */
- if (str->used == 0) return;
- buffer_prepare_append(dest, str->used - 1);
-
- for (unsigned int i = 0; i < str->used - 1; i++) {
- if (str->ptr[i] >= ' ' && str->ptr[i] <= '~') {
- /* printable chars */
- buffer_append_string_len(dest, &str->ptr[i], 1);
- } else switch (str->ptr[i]) {
- case '"':
- BUFFER_APPEND_STRING_CONST(dest, "\\\"");
- break;
- case '\\':
- BUFFER_APPEND_STRING_CONST(dest, "\\\\");
- break;
- case '\b':
- BUFFER_APPEND_STRING_CONST(dest, "\\b");
- break;
- case '\n':
- BUFFER_APPEND_STRING_CONST(dest, "\\n");
- break;
- case '\r':
- BUFFER_APPEND_STRING_CONST(dest, "\\r");
- break;
- case '\t':
- BUFFER_APPEND_STRING_CONST(dest, "\\t");
- break;
- case '\v':
- BUFFER_APPEND_STRING_CONST(dest, "\\v");
- break;
- default: {
- /* non printable char => \xHH */
- char hh[5] = {'\\','x',0,0,0};
- char h = str->ptr[i] / 16;
- hh[2] = (h > 9) ? (h - 10 + 'A') : (h + '0');
- h = str->ptr[i] % 16;
- hh[3] = (h > 9) ? (h - 10 + 'A') : (h + '0');
- buffer_append_string_len(dest, &hh[0], 4);
- }
- break;
- }
- }
-}
-
-static int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
- size_t i, j, k = 0, start = 0;
-
- for (i = 0; i < format->used - 1; i++) {
-
- switch(format->ptr[i]) {
- case '%':
- if (start != i) {
- /* copy the string */
- if (fields->size == 0) {
- fields->size = 16;
- fields->used = 0;
- fields->ptr = malloc(fields->size * sizeof(format_field * ));
- } else if (fields->used == fields->size) {
- fields->size += 16;
- fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_field * ));
- }
-
- fields->ptr[fields->used] = malloc(sizeof(format_field));
- fields->ptr[fields->used]->type = FIELD_STRING;
- fields->ptr[fields->used]->string = buffer_init();
-
- buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
-
- fields->used++;
- }
-
-
- /* we need a new field */
-
- if (fields->size == 0) {
- fields->size = 16;
- fields->used = 0;
- fields->ptr = malloc(fields->size * sizeof(format_field * ));
- } else if (fields->used == fields->size) {
- fields->size += 16;
- fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_field * ));
- }
-
- /* search for the terminating command */
- switch (format->ptr[i+1]) {
- case '>':
- case '<':
- /* only for s */
-
- for (j = 0; fmap[j].key != '\0'; j++) {
- if (fmap[j].key != format->ptr[i+2]) continue;
-
- /* found key */
-
- fields->ptr[fields->used] = malloc(sizeof(format_field));
- fields->ptr[fields->used]->type = FIELD_FORMAT;
- fields->ptr[fields->used]->field = fmap[j].type;
- fields->ptr[fields->used]->string = NULL;
-
- fields->used++;
-
- break;
- }
-
- if (fmap[j].key == '\0') {
- log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
- return -1;
- }
-
- start = i + 3;
-
- break;
- case '{':
- /* go forward to } */
-
- for (k = i+2; k < format->used - 1; k++) {
- if (format->ptr[k] == '}') break;
- }
-
- if (k == format->used - 1) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
- return -1;
- }
- if (format->ptr[k+1] == '\0') {
- log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
- return -1;
- }
-
- for (j = 0; fmap[j].key != '\0'; j++) {
- if (fmap[j].key != format->ptr[k+1]) continue;
-
- /* found key */
-
- fields->ptr[fields->used] = malloc(sizeof(format_field));
- fields->ptr[fields->used]->type = FIELD_FORMAT;
- fields->ptr[fields->used]->field = fmap[j].type;
- fields->ptr[fields->used]->string = buffer_init();
-
- buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
-
- fields->used++;
-
- break;
- }
-
- if (fmap[j].key == '\0') {
- log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
- return -1;
- }
-
- start = k + 2;
-
- break;
- default:
- for (j = 0; fmap[j].key != '\0'; j++) {
- if (fmap[j].key != format->ptr[i+1]) continue;
-
- /* found key */
-
- fields->ptr[fields->used] = malloc(sizeof(format_field));
- fields->ptr[fields->used]->type = FIELD_FORMAT;
- fields->ptr[fields->used]->field = fmap[j].type;
- fields->ptr[fields->used]->string = NULL;
-
- fields->used++;
-
- break;
- }
-
- if (fmap[j].key == '\0') {
- log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
- return -1;
- }
-
- start = i + 2;
-
- break;
- }
-
- break;
- }
- }
-
- if (start < i) {
- /* copy the string */
- if (fields->size == 0) {
- fields->size = 16;
- fields->used = 0;
- fields->ptr = malloc(fields->size * sizeof(format_field * ));
- } else if (fields->used == fields->size) {
- fields->size += 16;
- fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_field * ));
- }
-
- fields->ptr[fields->used] = malloc(sizeof(format_field));
- fields->ptr[fields->used]->type = FIELD_STRING;
- fields->ptr[fields->used]->string = buffer_init();
-
- buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
-
- fields->used++;
- }
-
- return 0;
-}
-
-FREE_FUNC(mod_accesslog_free) {
- plugin_data *p = p_d;
- size_t i;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- if (s->access_logbuffer->used) {
- if (s->use_syslog) {
-# ifdef HAVE_SYSLOG_H
- if (s->access_logbuffer->used > 2) {
- syslog(LOG_INFO, "%*s", (int) s->access_logbuffer->used - 2, s->access_logbuffer->ptr);
- }
-# endif
- } else if (s->log_access_fd != -1) {
- write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
- }
- }
-
- if (s->log_access_fd != -1) close(s->log_access_fd);
-
- buffer_free(s->ts_accesslog_str);
- buffer_free(s->access_logbuffer);
- buffer_free(s->format);
- buffer_free(s->access_logfile);
-
- if (s->parsed_format) {
- size_t j;
- for (j = 0; j < s->parsed_format->used; j++) {
- if (s->parsed_format->ptr[j]->string) buffer_free(s->parsed_format->ptr[j]->string);
- free(s->parsed_format->ptr[j]);
- }
- free(s->parsed_format->ptr);
- free(s->parsed_format);
- }
-
- free(s);
- }
-
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(log_access_open) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
- { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->access_logfile = buffer_init();
- s->format = buffer_init();
- s->access_logbuffer = buffer_init();
- s->ts_accesslog_str = buffer_init();
- s->log_access_fd = -1;
- s->last_generated_accesslog_ts = 0;
- s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
-
-
- cv[0].destination = s->access_logfile;
- cv[1].destination = &(s->use_syslog);
- cv[2].destination = s->format;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (i == 0 && buffer_is_empty(s->format)) {
- /* set a default logfile string */
-
- buffer_copy_string_len(s->format, CONST_STR_LEN("%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""));
- }
-
- /* parse */
-
- if (s->format->used) {
- s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
-
- if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
-
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "parsing accesslog-definition failed:", s->format);
-
- return HANDLER_ERROR;
- }
-#if 0
- /* debugging */
- for (j = 0; j < s->parsed_format->used; j++) {
- switch (s->parsed_format->ptr[j]->type) {
- case FIELD_FORMAT:
- log_error_write(srv, __FILE__, __LINE__, "ssds",
- "config:", "format", s->parsed_format->ptr[j]->field,
- s->parsed_format->ptr[j]->string ?
- s->parsed_format->ptr[j]->string->ptr : "" );
- break;
- case FIELD_STRING:
- log_error_write(srv, __FILE__, __LINE__, "ssbs", "config:", "string '", s->parsed_format->ptr[j]->string, "'");
- break;
- default:
- break;
- }
- }
-#endif
- }
-
- if (s->use_syslog) {
- /* ignore the next checks */
- continue;
- }
-
- if (buffer_is_empty(s->access_logfile)) continue;
-
- if (s->access_logfile->ptr[0] == '|') {
-#ifdef HAVE_FORK
- /* create write pipe and spawn process */
-
- int to_log_fds[2];
- pid_t pid;
-
- if (pipe(to_log_fds)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
- return HANDLER_ERROR;
- }
-
- /* fork, execve */
- switch (pid = fork()) {
- case 0:
- /* child */
-
- close(STDIN_FILENO);
- dup2(to_log_fds[0], STDIN_FILENO);
- close(to_log_fds[0]);
- /* not needed */
- close(to_log_fds[1]);
-
- /* we don't need the client socket */
- for (i = 3; i < 256; i++) {
- close(i);
- }
-
- /* exec the log-process (skip the | )
- *
- */
-
- execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, (char *)NULL);
-
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "spawning log-process failed: ", strerror(errno),
- s->access_logfile->ptr + 1);
-
- exit(-1);
- break;
- case -1:
- /* error */
- log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed: ", strerror(errno));
- break;
- default:
- close(to_log_fds[0]);
-
- s->log_access_fd = to_log_fds[1];
-
- break;
- }
-#else
- return -1;
-#endif
- } else if (-1 == (s->log_access_fd =
- open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
-
- log_error_write(srv, __FILE__, __LINE__, "ssb",
- "opening access-log failed:",
- strerror(errno), s->access_logfile);
-
- return HANDLER_ERROR;
- }
-#ifndef _WIN32
- fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
-#endif
- }
-
- return HANDLER_GO_ON;
-}
-
-SIGHUP_FUNC(log_access_cycle) {
- plugin_data *p = p_d;
- size_t i;
-
- if (!p->config_storage) return HANDLER_GO_ON;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (s->access_logbuffer->used) {
- if (s->use_syslog) {
-#ifdef HAVE_SYSLOG_H
- if (s->access_logbuffer->used > 2) {
- /* syslog appends a \n on its own */
- syslog(LOG_INFO, "%*s", (int) s->access_logbuffer->used - 2, s->access_logbuffer->ptr);
- }
-#endif
- } else if (s->log_access_fd != -1) {
- write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
- }
-
- buffer_reset(s->access_logbuffer);
- }
-
- if (s->use_syslog == 0 &&
- !buffer_is_empty(s->access_logfile) &&
- s->access_logfile->ptr[0] != '|') {
-
- close(s->log_access_fd);
-
- if (-1 == (s->log_access_fd =
- open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
-
- return HANDLER_ERROR;
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(access_logfile);
- PATCH_OPTION(format);
- PATCH_OPTION(log_access_fd);
- PATCH_OPTION(last_generated_accesslog_ts_ptr);
- PATCH_OPTION(access_logbuffer);
- PATCH_OPTION(ts_accesslog_str);
- PATCH_OPTION(parsed_format);
- PATCH_OPTION(use_syslog);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
- PATCH_OPTION(access_logfile);
- PATCH_OPTION(log_access_fd);
- PATCH_OPTION(last_generated_accesslog_ts_ptr);
- PATCH_OPTION(access_logbuffer);
- PATCH_OPTION(ts_accesslog_str);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
- PATCH_OPTION(format);
- PATCH_OPTION(parsed_format);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
- PATCH_OPTION(use_syslog);
- }
- }
- }
-
- return 0;
-}
-
-REQUESTDONE_FUNC(log_access_write) {
- plugin_data *p = p_d;
- buffer *b;
- size_t j;
-
- int newts = 0;
- data_string *ds;
-
- mod_accesslog_patch_connection(srv, con, p);
-
- b = p->conf.access_logbuffer;
- if (b->used == 0) {
- buffer_copy_string_len(b, CONST_STR_LEN(""));
- }
-
- for (j = 0; j < p->conf.parsed_format->used; j++) {
- switch(p->conf.parsed_format->ptr[j]->type) {
- case FIELD_STRING:
- buffer_append_string_buffer(b, p->conf.parsed_format->ptr[j]->string);
- break;
- case FIELD_FORMAT:
- switch(p->conf.parsed_format->ptr[j]->field) {
- case FORMAT_TIMESTAMP:
-
- /* cache the generated timestamp */
- if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
- struct tm tm;
-#if defined(HAVE_STRUCT_TM_GMTOFF)
- long scd, hrs, min;
-#endif
-
- buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
-#if defined(HAVE_STRUCT_TM_GMTOFF)
-# ifdef HAVE_LOCALTIME_R
- localtime_r(&(srv->cur_ts), &tm);
- strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", &tm);
-# else
- strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", localtime(&(srv->cur_ts)));
-# endif
- p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
-
- buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
-
- scd = abs(tm.tm_gmtoff);
- hrs = scd / 3600;
- min = (scd % 3600) / 60;
-
- /* hours */
- if (hrs < 10) buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("0"));
- buffer_append_long(p->conf.ts_accesslog_str, hrs);
-
- if (min < 10) buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("0"));
- buffer_append_long(p->conf.ts_accesslog_str, min);
- buffer_append_string_len(p->conf.ts_accesslog_str, CONST_STR_LEN("]"));
-#else
-#ifdef HAVE_GMTIME_R
- gmtime_r(&(srv->cur_ts), &tm);
- strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S +0000]", &tm);
-#else
- strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S +0000]", gmtime(&(srv->cur_ts)));
-#endif
- p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
-#endif
-
- *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
- newts = 1;
- }
-
- buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
-
- break;
- case FORMAT_REMOTE_HOST:
-
- /* handle inet_ntop cache */
-
- buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
-
- break;
- case FORMAT_REMOTE_IDENT:
- /* ident */
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- break;
- case FORMAT_REMOTE_USER:
- if (con->authed_user->used > 1) {
- buffer_append_string_buffer(b, con->authed_user);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_REQUEST_LINE:
- buffer_append_string(b, get_http_method_name(con->request.http_method));
- buffer_append_string_len(b, CONST_STR_LEN(" "));
- accesslog_append_escaped(b, con->request.orig_uri);
- buffer_append_string_len(b, CONST_STR_LEN(" "));
- buffer_append_string(b, get_http_version_name(con->request.http_version));
-
- break;
- case FORMAT_STATUS:
- buffer_append_long(b, con->http_status);
- break;
-
- case FORMAT_BYTES_OUT_NO_HEADER:
- if (con->bytes_written > 0) {
- buffer_append_off_t(b,
- con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_HEADER:
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_BUF_LEN(p->conf.parsed_format->ptr[j]->string)))) {
- accesslog_append_escaped(b, ds->value);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_RESPONSE_HEADER:
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, CONST_BUF_LEN(p->conf.parsed_format->ptr[j]->string)))) {
- accesslog_append_escaped(b, ds->value);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_ENV:
- if (NULL != (ds = (data_string *)array_get_element(con->environment, CONST_BUF_LEN(p->conf.parsed_format->ptr[j]->string)))) {
- accesslog_append_escaped(b, ds->value);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_FILENAME:
- if (con->physical.path->used > 1) {
- buffer_append_string_buffer(b, con->physical.path);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_BYTES_OUT:
- if (con->bytes_written > 0) {
- buffer_append_off_t(b, con->bytes_written);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_BYTES_IN:
- if (con->bytes_read > 0) {
- buffer_append_off_t(b, con->bytes_read);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_TIME_USED:
- buffer_append_long(b, srv->cur_ts - con->request_start);
- break;
- case FORMAT_SERVER_NAME:
- if (con->server_name->used > 1) {
- buffer_append_string_buffer(b, con->server_name);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_HTTP_HOST:
- if (con->uri.authority->used > 1) {
- accesslog_append_escaped(b, con->uri.authority);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- }
- break;
- case FORMAT_REQUEST_PROTOCOL:
- buffer_append_string(b,
- con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
- break;
- case FORMAT_REQUEST_METHOD:
- buffer_append_string(b, get_http_method_name(con->request.http_method));
- break;
- case FORMAT_SERVER_PORT:
- buffer_append_long(b, srv->srvconf.port);
- break;
- case FORMAT_QUERY_STRING:
- accesslog_append_escaped(b, con->uri.query);
- break;
- case FORMAT_URL:
- accesslog_append_escaped(b, con->uri.path_raw);
- break;
- case FORMAT_CONNECTION_STATUS:
- switch(con->keep_alive) {
- case 0: buffer_append_string_len(b, CONST_STR_LEN("-")); break;
- default: buffer_append_string_len(b, CONST_STR_LEN("+")); break;
- }
- break;
- default:
- /*
- { 'a', FORMAT_REMOTE_ADDR },
- { 'A', FORMAT_LOCAL_ADDR },
- { 'C', FORMAT_COOKIE },
- { 'D', FORMAT_TIME_USED_MS },
- */
-
- break;
- }
- break;
- default:
- break;
- }
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- if (p->conf.use_syslog || /* syslog doesn't cache */
- (p->conf.access_logfile->used && p->conf.access_logfile->ptr[0] != '|') || /* pipes don't cache */
- newts ||
- b->used > BUFFER_MAX_REUSE_SIZE) {
- if (p->conf.use_syslog) {
-#ifdef HAVE_SYSLOG_H
- if (b->used > 2) {
- /* syslog appends a \n on its own */
- syslog(LOG_INFO, "%*s", (int) b->used - 2, b->ptr);
- }
-#endif
- } else if (p->conf.log_access_fd != -1) {
- write(p->conf.log_access_fd, b->ptr, b->used - 1);
- }
- buffer_reset(b);
- }
-
- return HANDLER_GO_ON;
-}
-
-
-LI_EXPORT int mod_accesslog_plugin_init(plugin *p);
-LI_EXPORT int mod_accesslog_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("accesslog");
-
- p->init = mod_accesslog_init;
- p->set_defaults= log_access_open;
- p->cleanup = mod_accesslog_free;
-
- p->handle_response_done = log_access_write;
- p->handle_sighup = log_access_cycle;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_alias.c b/src/mod_alias.c
deleted file mode 100644
index c03fb7cb..00000000
--- a/src/mod_alias.c
+++ /dev/null
@@ -1,204 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-#include "sys-strings.h"
-
-/* plugin config for all request/connections */
-typedef struct {
- array *alias;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_alias_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
-
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_alias_free) {
- plugin_data *p = p_d;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->alias);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_alias_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->alias = array_init();
- cv[0].destination = s->alias;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- if (s->alias->used >= 2) {
- const array *a = s->alias;
- size_t j, k;
-
- for (j = 0; j < a->used; j ++) {
- const buffer *prefix = a->data[a->sorted[j]]->key;
- for (k = j + 1; k < a->used; k ++) {
- const buffer *key = a->data[a->sorted[k]]->key;
-
- if (key->used < prefix->used) {
- break;
- }
- if (memcmp(key->ptr, prefix->ptr, prefix->used - 1) != 0) {
- break;
- }
- /* ok, they have same prefix. check position */
- if (a->sorted[j] < a->sorted[k]) {
- fprintf(stderr, "url.alias: `%s' will never match as `%s' matched first\n",
- key->ptr,
- prefix->ptr);
- return HANDLER_ERROR;
- }
- }
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(alias);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
- PATCH_OPTION(alias);
- }
- }
- }
-
- return 0;
-}
-
-PHYSICALPATH_FUNC(mod_alias_physical_handler) {
- plugin_data *p = p_d;
- int uri_len, basedir_len;
- char *uri_ptr;
- size_t k;
-
- if (con->physical.path->used == 0) return HANDLER_GO_ON;
-
- mod_alias_patch_connection(srv, con, p);
-
- /* not to include the tailing slash */
- basedir_len = (con->physical.basedir->used - 1) - 1;
- uri_len = con->physical.path->used - 1 - basedir_len;
- uri_ptr = con->physical.path->ptr + basedir_len;
-
- for (k = 0; k < p->conf.alias->used; k++) {
- data_string *ds = (data_string *)p->conf.alias->data[k];
- int alias_len = ds->key->used - 1;
-
- if (alias_len > uri_len) continue;
- if (ds->key->used == 0) continue;
-
- if (0 == (con->conf.force_lowercase_filenames ?
- strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
- strncmp(uri_ptr, ds->key->ptr, alias_len))) {
- /* matched */
-
- buffer_copy_string_buffer(con->physical.basedir, ds->value);
- buffer_copy_string_buffer(srv->tmp_buf, ds->value);
- buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
- buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
-
- return HANDLER_GO_ON;
- }
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_alias_plugin_init(plugin *p);
-LI_EXPORT int mod_alias_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("alias");
-
- p->init = mod_alias_init;
- p->handle_physical= mod_alias_physical_handler;
- p->set_defaults = mod_alias_set_defaults;
- p->cleanup = mod_alias_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_auth.c b/src/mod_auth.c
deleted file mode 100644
index 5b8307cc..00000000
--- a/src/mod_auth.c
+++ /dev/null
@@ -1,672 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include "settings.h"
-#include "plugin.h"
-#include "http_auth.h"
-#include "log.h"
-#include "response.h"
-
-#include "sys-strings.h"
-#include "sys-files.h"
-
-handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
-#ifdef USE_LDAP
-void auth_ldap_cleanup(ldap_plugin_config* p);
-#endif
-
-/**
- * the basic and digest auth framework
- *
- * - config handling
- * - protocol handling
- *
- * http_auth.c
- * http_auth_digest.c
- *
- * do the real work
- */
-
-INIT_FUNC(mod_auth_init) {
- mod_auth_plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- p->auth_user = buffer_init();
-#ifdef USE_LDAP
- p->ldap_filter = buffer_init();
-#endif
-
- return p;
-}
-
-FREE_FUNC(mod_auth_free) {
- mod_auth_plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- buffer_free(p->tmp_buf);
- buffer_free(p->auth_user);
-#ifdef USE_LDAP
- buffer_free(p->ldap_filter);
-#endif
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- mod_auth_plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->auth_require);
- buffer_free(s->auth_plain_groupfile);
- buffer_free(s->auth_plain_userfile);
- buffer_free(s->auth_htdigest_userfile);
- buffer_free(s->auth_htpasswd_userfile);
- buffer_free(s->auth_backend_conf);
-
- buffer_free(s->auth_ldap_url);
- buffer_free(s->auth_ldap_basedn);
- buffer_free(s->auth_ldap_binddn);
- buffer_free(s->auth_ldap_bindpw);
- buffer_free(s->auth_ldap_filter);
- buffer_free(s->auth_ldap_cafile);
- buffer_free(s->auth_ldap_cert);
- buffer_free(s->auth_ldap_key);
-
-#ifdef USE_LDAP
- buffer_free(s->ldap->ldap_filter_pre);
- buffer_free(s->ldap->ldap_filter_post);
-
- auth_ldap_cleanup(s->ldap);
- free(s->ldap);
-#endif
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
- size_t i, j;
- mod_auth_plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(auth_backend);
- PATCH_OPTION(auth_plain_groupfile);
- PATCH_OPTION(auth_plain_userfile);
- PATCH_OPTION(auth_htdigest_userfile);
- PATCH_OPTION(auth_htpasswd_userfile);
- PATCH_OPTION(auth_require);
- PATCH_OPTION(auth_debug);
- PATCH_OPTION(auth_ldap_url);
- PATCH_OPTION(auth_ldap_basedn);
- PATCH_OPTION(auth_ldap_binddn);
- PATCH_OPTION(auth_ldap_bindpw);
- PATCH_OPTION(auth_ldap_filter);
- PATCH_OPTION(auth_ldap_cafile);
- PATCH_OPTION(auth_ldap_cert);
- PATCH_OPTION(auth_ldap_key);
- PATCH_OPTION(auth_ldap_starttls);
- PATCH_OPTION(auth_ldap_allow_empty_pw);
-#ifdef USE_LDAP
- PATCH_OPTION(ldap);
-#endif
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
- PATCH_OPTION(auth_backend);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
- PATCH_OPTION(auth_plain_groupfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
- PATCH_OPTION(auth_plain_userfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
- PATCH_OPTION(auth_htdigest_userfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
- PATCH_OPTION(auth_htpasswd_userfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
- PATCH_OPTION(auth_require);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
- PATCH_OPTION(auth_debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.url"))) {
- PATCH_OPTION(auth_ldap_url);
-#ifdef USE_LDAP
- PATCH_OPTION(ldap);
-#endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
- PATCH_OPTION(auth_ldap_basedn);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-dn"))) {
- PATCH_OPTION(auth_ldap_binddn);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-pw"))) {
- PATCH_OPTION(auth_ldap_bindpw);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
- PATCH_OPTION(auth_ldap_filter);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
- PATCH_OPTION(auth_ldap_cafile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.cert"))) {
- PATCH_OPTION(auth_ldap_cert);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.key"))) {
- PATCH_OPTION(auth_ldap_key);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
- PATCH_OPTION(auth_ldap_starttls);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) {
- PATCH_OPTION(auth_ldap_allow_empty_pw);
- }
- }
- }
-
- return 0;
-}
-
-static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
- size_t k;
- int auth_required = 0, auth_satisfied = 0;
- char *http_authorization = NULL;
- data_string *ds;
- mod_auth_plugin_data *p = p_d;
- array *req;
-
- /* select the right config */
- mod_auth_patch_connection(srv, con, p);
-
- if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
-
- /*
- * AUTH
- *
- */
-
- /* do we have to ask for auth ? */
-
- auth_required = 0;
- auth_satisfied = 0;
-
- /* search auth-directives for path */
- for (k = 0; k < p->conf.auth_require->used; k++) {
- buffer *auth_path = p->conf.auth_require->data[k]->key;
-
- if (auth_path->used == 0) continue;
- if (con->uri.path->used < auth_path->used) continue;
-
- /* if we have a case-insensitive FS we have to lower-case the URI here too */
-
- if (con->conf.force_lowercase_filenames) {
- if (0 == strncasecmp(con->uri.path->ptr, auth_path->ptr, auth_path->used - 1)) {
- auth_required = 1;
- break;
- }
- } else {
- if (0 == strncmp(con->uri.path->ptr, auth_path->ptr, auth_path->used - 1)) {
- auth_required = 1;
- break;
- }
- }
- }
-
- /* nothing to do for us */
- if (auth_required == 0) return HANDLER_GO_ON;
-
- req = ((data_array *)(p->conf.auth_require->data[k]))->value;
-
- /* try to get Authorization-header */
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Authorization")))) {
- http_authorization = ds->value->ptr;
- }
-
- if (ds && ds->value && ds->value->used) {
- char *auth_realm;
- data_string *method;
-
- method = (data_string *)array_get_element(req, CONST_STR_LEN("method"));
-
- /* parse auth-header */
- if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
- int auth_type_len = auth_realm - http_authorization;
-
- if ((auth_type_len == 5) &&
- (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
-
- if (buffer_is_equal_string(method->value, CONST_STR_LEN("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))) {
- if (buffer_is_equal_string(method->value, CONST_STR_LEN("digest"))) {
- if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
- con->http_status = 400;
-
- /* a field was missing */
-
- return HANDLER_FINISHED;
- }
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "unknown authentification type:",
- http_authorization);
- }
- }
- }
-
- if (!auth_satisfied) {
- data_string *method, *realm;
- method = (data_string *)array_get_element(req, CONST_STR_LEN("method"));
- realm = (data_string *)array_get_element(req, CONST_STR_LEN("realm"));
-
- con->http_status = 401;
-
- if (buffer_is_equal_string(method->value, CONST_STR_LEN("basic"))) {
- buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Basic realm=\""));
- buffer_append_string_buffer(p->tmp_buf, realm->value);
- buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\""));
-
- response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
- } else if (buffer_is_equal_string(method->value, CONST_STR_LEN("digest"))) {
- char hh[33];
- http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
-
- buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Digest realm=\""));
- buffer_append_string_buffer(p->tmp_buf, realm->value);
- buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", nonce=\""));
- buffer_append_string(p->tmp_buf, hh);
- buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", qop=\"auth\""));
-
- response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
- } else {
- /* evil */
- }
- return HANDLER_FINISHED;
- } else {
- /* the REMOTE_USER header */
-
- buffer_copy_string_buffer(con->authed_user, p->auth_user);
- }
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_auth_set_defaults) {
- mod_auth_plugin_data *p = p_d;
- size_t i;
-
- config_values_t cv[] = {
- { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { "auth.require", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { "auth.backend.ldap.url" , NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
- { "auth.backend.ldap.base-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
- { "auth.backend.ldap.filter", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
- { "auth.backend.ldap.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
- { "auth.backend.ldap.cert", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
- { "auth.backend.ldap.key", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
- { "auth.backend.ldap.starttls", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
- { "auth.backend.ldap.bind-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
- { "auth.backend.ldap.bind-pw", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
- { "auth.backend.ldap.allow-empty-pw", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
- { "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
- { "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
- { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- mod_auth_plugin_config *s;
- size_t n;
- data_array *da;
- array *ca;
-
- s = calloc(1, sizeof(mod_auth_plugin_config));
- s->auth_plain_groupfile = buffer_init();
- s->auth_plain_userfile = buffer_init();
- s->auth_htdigest_userfile = buffer_init();
- s->auth_htpasswd_userfile = buffer_init();
- s->auth_backend_conf = buffer_init();
-
- s->auth_ldap_url = buffer_init();
- s->auth_ldap_basedn = buffer_init();
- s->auth_ldap_binddn = buffer_init();
- s->auth_ldap_bindpw = buffer_init();
- s->auth_ldap_filter = buffer_init();
- s->auth_ldap_cafile = buffer_init();
- s->auth_ldap_cert = buffer_init();
- s->auth_ldap_key = buffer_init();
- s->auth_ldap_starttls = 0;
- s->auth_debug = 0;
-
- s->auth_require = array_init();
-
-#ifdef USE_LDAP
- s->ldap = malloc (sizeof(ldap_plugin_config));
- s->ldap->ldap_filter_pre = buffer_init();
- s->ldap->ldap_filter_post = buffer_init();
- s->ldap->ldap = NULL;
-#endif
-
- cv[0].destination = s->auth_backend_conf;
- cv[1].destination = s->auth_plain_groupfile;
- cv[2].destination = s->auth_plain_userfile;
- cv[3].destination = s->auth_require;
- cv[4].destination = s->auth_ldap_url;
- cv[5].destination = s->auth_ldap_basedn;
- cv[6].destination = s->auth_ldap_filter;
- cv[7].destination = s->auth_ldap_cafile;
- cv[8].destination = s->auth_ldap_cert;
- cv[9].destination = s->auth_ldap_key;
- cv[10].destination = &(s->auth_ldap_starttls);
- cv[11].destination = s->auth_ldap_binddn;
- cv[12].destination = s->auth_ldap_bindpw;
- cv[13].destination = &(s->auth_ldap_allow_empty_pw);
- cv[14].destination = s->auth_htdigest_userfile;
- cv[15].destination = s->auth_htpasswd_userfile;
- cv[16].destination = &(s->auth_debug);
-
- p->config_storage[i] = s;
- ca = ((data_config *)srv->config_context->data[i])->value;
-
- if (0 != config_insert_values_global(srv, ca, cv)) {
- return HANDLER_ERROR;
- }
-
- if (!buffer_is_empty(s->auth_backend_conf)) {
- if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("htpasswd"))) {
- s->auth_backend = AUTH_BACKEND_HTPASSWD;
- } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("htdigest"))) {
- s->auth_backend = AUTH_BACKEND_HTDIGEST;
- } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("plain"))) {
- s->auth_backend = AUTH_BACKEND_PLAIN;
- } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("ldap"))) {
- s->auth_backend = AUTH_BACKEND_LDAP;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
-
- return HANDLER_ERROR;
- }
- }
-
- /* no auth.require for this section */
- if (NULL == (da = (data_array *)array_get_element(ca, CONST_STR_LEN("auth.require")))) continue;
-
- if (da->type != TYPE_ARRAY) continue;
-
- for (n = 0; n < da->value->used; n++) {
- size_t m;
- data_array *da_file = (data_array *)da->value->data[n];
- buffer *method, *realm, *require;
-
- if (da->value->data[n]->type != TYPE_ARRAY) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "auth.require should contain an array as in:",
- "auth.require = ( \"...\" => ( ..., ...) )");
-
- return HANDLER_ERROR;
- }
-
- method = realm = require = NULL;
-
- for (m = 0; m < da_file->value->used; m++) {
- data_string *ds_auth_req = (data_string *)da_file->value->data[m];
-
- if (ds_auth_req->type != TYPE_STRING) {
- log_error_write(srv, __FILE__, __LINE__, "ssbs",
- "a string was expected for:",
- "auth.require = ( \"...\" => ( ..., -> \"",
- ds_auth_req->key,
- "\" <- => \"...\" ) )");
-
- return HANDLER_ERROR;
- }
-
- if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("method"))) {
- method = ds_auth_req->value;
- } else if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("realm"))) {
- realm = ds_auth_req->value;
- } else if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("require"))) {
- require = ds_auth_req->value;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ssbs",
- "the field is unknown in:",
- "auth.require = ( \"...\" => ( ..., -> \"",
- da_file->value->data[m]->key,
- "\" <- => \"...\" ) )");
-
- return HANDLER_ERROR;
-
- }
- }
-
- if (method == NULL) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "the require field is missing in:",
- "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
- return HANDLER_ERROR;
- }
- if (!buffer_is_equal_string(method, CONST_STR_LEN("basic")) &&
- !buffer_is_equal_string(method, CONST_STR_LEN("digest"))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "method has to be either \"basic\" or \"digest\" in",
- "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
- return HANDLER_ERROR;
- }
-
- if (realm == NULL) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "the require field is missing in:",
- "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
- return HANDLER_ERROR;
- }
-
- if (require == NULL) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "the require field is missing in:",
- "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
- return HANDLER_ERROR;
- }
-
- if (method && realm && require) {
- data_string *ds;
- data_array *a;
-
- a = data_array_init();
- buffer_copy_string_buffer(a->key, da_file->key);
-
- ds = data_string_init();
-
- buffer_copy_string_len(ds->key, CONST_STR_LEN("method"));
- buffer_copy_string_buffer(ds->value, method);
-
- array_insert_unique(a->value, (data_unset *)ds);
-
- ds = data_string_init();
-
- buffer_copy_string_len(ds->key, CONST_STR_LEN("realm"));
- buffer_copy_string_buffer(ds->value, realm);
-
- array_insert_unique(a->value, (data_unset *)ds);
-
- ds = data_string_init();
-
- buffer_copy_string_len(ds->key, CONST_STR_LEN("require"));
- buffer_copy_string_buffer(ds->value, require);
-
- array_insert_unique(a->value, (data_unset *)ds);
-
- array_insert_unique(s->auth_require, (data_unset *)a);
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
-#ifdef USE_LDAP
- int ret;
- struct berval credentials;
- char *binddn_ptr = NULL;
-
- if (s->auth_ldap_filter->used) {
- char *dollar;
-
- /* parse filter */
-
- if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
- log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
-
- return HANDLER_ERROR;
- }
-
- buffer_copy_string_len(s->ldap->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
- buffer_copy_string(s->ldap->ldap_filter_post, dollar+1);
- }
-
- if (s->auth_ldap_url->used) {
- if ((ret = ldap_initialize(&s->ldap->ldap, s->auth_ldap_url->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- return HANDLER_ERROR;
- }
-
- {
- const int ldap_version = LDAP_VERSION3;
- ret = ldap_set_option(s->ldap->ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
- }
- if (ret != LDAP_OPT_SUCCESS) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_memfree(s->ldap->ldap);
- s->ldap->ldap = NULL;
-
- return HANDLER_ERROR;
- }
-
- if (s->auth_ldap_starttls == 1) {
- /* if no CA file is given, it is ok, as we will use encryption
- * if the server requires a CAfile it will tell us */
- if (!buffer_is_empty(s->auth_ldap_cafile)) {
- if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
- s->auth_ldap_cafile->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "Loading CA certificate failed:", ldap_err2string(ret));
-
- ldap_memfree(s->ldap->ldap);
- s->ldap->ldap = NULL;
-
- return HANDLER_ERROR;
- }
- }
-
- if (!buffer_is_empty(s->auth_ldap_cert)) {
- if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE,
- s->auth_ldap_cert->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "Loading TLS certificate failed:", ldap_err2string(ret));
-
- ldap_memfree(s->ldap->ldap);
- s->ldap->ldap = NULL;
-
- return HANDLER_ERROR;
- }
- }
-
- if (!buffer_is_empty(s->auth_ldap_key)) {
- if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE,
- s->auth_ldap_key->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "Loading TLS key certificate failed:", ldap_err2string(ret));
-
- ldap_memfree(s->ldap->ldap);
- s->ldap->ldap = NULL;
-
- return HANDLER_ERROR;
- }
- }
-
- if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap->ldap, NULL, NULL))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
-
- ldap_memfree(s->ldap->ldap);
- s->ldap->ldap = NULL;
-
- return HANDLER_ERROR;
- }
- }
-
-
- /* 1. */
- if (s->auth_ldap_binddn->used) {
- credentials.bv_val = s->auth_ldap_bindpw->ptr;
- credentials.bv_len = s->auth_ldap_bindpw->used;
- binddn_ptr = s->auth_ldap_binddn->ptr;
- } else {
- credentials.bv_val = NULL;
- credentials.bv_len = 0;
- binddn_ptr = NULL;
- }
- ret = ldap_sasl_bind_s(s->ldap->ldap, s->auth_ldap_binddn->ptr, LDAP_SASL_SIMPLE, &credentials, NULL, NULL, NULL);
- if(ret != LDAP_SUCCESS) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
-
- ldap_memfree(s->ldap->ldap);
- s->ldap->ldap = NULL;
- return HANDLER_ERROR;
- }
- }
-#else
- UNUSED(s);
- log_error_write(srv, __FILE__, __LINE__, "s", "no ldap support available");
- return HANDLER_ERROR;
-#endif
- return HANDLER_GO_ON;
-}
-
-#ifdef USE_LDAP
-void auth_ldap_cleanup(ldap_plugin_config *p) {
- if (p->ldap != NULL)
- ldap_unbind_ext_s(p->ldap, NULL, NULL);
- p->ldap = NULL;
-}
-#endif
-
-LI_EXPORT int mod_auth_plugin_init(plugin *p);
-LI_EXPORT int mod_auth_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("auth");
- p->init = mod_auth_init;
- p->set_defaults = mod_auth_set_defaults;
- p->handle_uri_clean = mod_auth_uri_handler;
- p->cleanup = mod_auth_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_auth.h b/src/mod_auth.h
deleted file mode 100644
index e69de29b..00000000
--- a/src/mod_auth.h
+++ /dev/null
diff --git a/src/mod_cgi.c b/src/mod_cgi.c
deleted file mode 100644
index 5e02826a..00000000
--- a/src/mod_cgi.c
+++ /dev/null
@@ -1,1312 +0,0 @@
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include <stdio.h>
-#include <fcntl.h>
-
-#include "server.h"
-#include "stat_cache.h"
-#include "keyvalue.h"
-#include "log.h"
-#include "connections.h"
-#include "joblist.h"
-#include "fdevent.h"
-#include "inet_ntop_cache.h"
-
-#include "plugin.h"
-#include "http_resp.h"
-
-#include "sys-files.h"
-#include "sys-mmap.h"
-#include "sys-socket.h"
-#include "sys-strings.h"
-#include "sys-process.h"
-
-#include "network_backends.h"
-
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-
-enum {EOL_UNSET, EOL_N, EOL_RN};
-
-typedef struct {
- char **ptr;
-
- size_t size;
- size_t used;
-} char_array;
-
-#define pid_t int
-typedef struct {
- pid_t *ptr;
- size_t used;
- size_t size;
-} buffer_pid_t;
-
-typedef struct {
- array *cgi;
- unsigned short execute_all;
- unsigned short execute_x_only;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
- buffer_pid_t cgi_pid;
-
- buffer *tmp_buf;
-
- http_resp *resp;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-typedef enum {
- CGI_STATE_UNSET,
- CGI_STATE_CONNECTING,
- CGI_STATE_READ_RESPONSE_HEADER,
- CGI_STATE_READ_RESPONSE_CONTENT
-} cgi_state_t;
-
-typedef struct {
- pid_t pid;
-
- iosocket *sock;
- iosocket *sock_err;
- iosocket *wb_sock;
-
- chunkqueue *rb;
- chunkqueue *rb_err;
- chunkqueue *wb;
-
- cgi_state_t state;
-
- connection *remote_con; /* dumb pointer */
-} cgi_session;
-
-static cgi_session * cgi_session_init() {
- cgi_session *sess = calloc(1, sizeof(*sess));
- assert(sess);
-
- sess->sock = iosocket_init();
- sess->sock_err = iosocket_init();
- sess->wb_sock = iosocket_init();
- sess->wb = chunkqueue_init();
- sess->rb = chunkqueue_init();
- sess->rb_err = chunkqueue_init();
-
- return sess;
-}
-
-static void cgi_session_free(cgi_session *sess) {
- if (!sess) return;
-
- iosocket_free(sess->sock);
- iosocket_free(sess->sock_err);
- iosocket_free(sess->wb_sock);
-
- chunkqueue_free(sess->wb);
- chunkqueue_free(sess->rb);
- chunkqueue_free(sess->rb_err);
-
- free(sess);
-}
-
-INIT_FUNC(mod_cgi_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- assert(p);
-
- p->tmp_buf = buffer_init();
- p->resp = http_response_init();
-
- return p;
-}
-
-
-FREE_FUNC(mod_cgi_free) {
- plugin_data *p = p_d;
- buffer_pid_t *r = &(p->cgi_pid);
-
- UNUSED(srv);
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- array_free(s->cgi);
-
- free(s);
- }
- free(p->config_storage);
- }
-
-
- if (r->ptr) free(r->ptr);
-
- buffer_free(p->tmp_buf);
- http_response_free(p->resp);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-#define PLUGIN_NAME "cgi"
-#define CONFIG_ASSIGN PLUGIN_NAME ".assign"
-#define CONFIG_EXECUTE_ALL PLUGIN_NAME ".execute-all"
-#define CONFIG_EXECUTE_X_ONLY PLUGIN_NAME ".execute-x-only"
-
-SETDEFAULTS_FUNC(mod_cgi_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { CONFIG_ASSIGN, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { CONFIG_EXECUTE_ALL, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { CONFIG_EXECUTE_X_ONLY, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- assert(s);
-
- s->cgi = array_init();
- s->execute_all = 0;
- s->execute_x_only = 0;
-
- cv[0].destination = s->cgi;
- cv[1].destination = &(s->execute_all);
- cv[2].destination = &(s->execute_x_only);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-
-static int cgi_pid_add(server *srv, plugin_data *p, pid_t pid) {
- int m = -1;
- size_t i;
- buffer_pid_t *r = &(p->cgi_pid);
-
- UNUSED(srv);
-
- for (i = 0; i < r->used; i++) {
- if (r->ptr[i] > m) m = r->ptr[i];
- }
-
- if (r->size == 0) {
- r->size = 16;
- r->ptr = malloc(sizeof(*r->ptr) * r->size);
- } else if (r->used == r->size) {
- r->size += 16;
- r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
- }
-
- r->ptr[r->used++] = pid;
-
- return m;
-}
-
-static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
- size_t i;
- buffer_pid_t *r = &(p->cgi_pid);
-
- UNUSED(srv);
-
- for (i = 0; i < r->used; i++) {
- if (r->ptr[i] == pid) break;
- }
-
- if (i != r->used) {
- /* found */
-
- if (i != r->used - 1) {
- r->ptr[i] = r->ptr[r->used - 1];
- }
- r->used--;
- }
-
- return 0;
-}
-
-/**
- * Copy decoded response content to client connection.
- */
-static int cgi_copy_response(server *srv, connection *con, cgi_session *sess) {
- chunk *c;
- int we_have = 0;
-
- UNUSED(srv);
-
- chunkqueue_remove_finished_chunks(sess->rb);
- /* copy the content to the next cq */
- for (c = sess->rb->first; c; c = c->next) {
- if (c->mem->used == 0) continue;
-
- we_have = chunkqueue_steal_chunk(con->send, c);
- sess->rb->bytes_out += we_have;
- con->send->bytes_in += we_have;
- }
- chunkqueue_remove_finished_chunks(sess->rb);
-
- if(sess->rb->is_closed) {
- con->send->is_closed = 1;
- }
- return 0;
-}
-
-
-static int cgi_demux_response(server *srv, connection *con, plugin_data *p) {
- cgi_session *sess = con->plugin_ctx[p->id];
-
- switch(srv->network_backend_read(srv, con, sess->sock, sess->rb)) {
- case NETWORK_STATUS_CONNECTION_CLOSE:
- fdevent_event_del(srv->ev, sess->sock);
-
- /* connection closed. close the read chunkqueue. */
- sess->rb->is_closed = 1;
- case NETWORK_STATUS_SUCCESS:
- /* we got content */
- break;
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- return 0;
- default:
- /* oops */
- ERROR("%s", "oops, read-pipe-read failed and I don't know why");
- return -1;
- }
-
- /* looks like we got some content
- *
- * split off the header from the incoming stream
- */
-
- if (con->file_started == 0) {
- size_t i;
- int have_content_length = 0;
-
- http_response_reset(p->resp);
-
- /* the response header is not fully received yet,
- *
- * extract the http-response header from the rb-cq
- */
- switch (http_response_parse_cq(sess->rb, p->resp)) {
- case PARSE_UNSET:
- case PARSE_ERROR:
- /* parsing failed */
-
- TRACE("%s", "response parser failed");
-
- con->http_status = 502; /* Bad Gateway */
- return -1;
- case PARSE_NEED_MORE:
- if (sess->rb->is_closed) {
- /* backend died before sending a header */
- con->http_status = 502; /* Bad Gateway */
- return -1;
- }
- return 0;
- case PARSE_SUCCESS:
- con->http_status = p->resp->status;
-
- chunkqueue_remove_finished_chunks(sess->rb);
-
- /* copy the http-headers */
- for (i = 0; i < p->resp->headers->used; i++) {
- const char *ign[] = { "Status", "Connection", NULL };
- size_t j;
- data_string *ds;
-
- data_string *header = (data_string *)p->resp->headers->data[i];
-
- /* some headers are ignored by default */
- for (j = 0; ign[j]; j++) {
- if (0 == strcasecmp(ign[j], header->key->ptr)) break;
- }
- if (ign[j]) continue;
-
- if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
- /* CGI/1.1 rev 03 - 7.2.1.2 */
- if (con->http_status == 0) con->http_status = 302;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
- have_content_length = 1;
- }
-
- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
- ds = data_response_init();
- }
- buffer_copy_string_buffer(ds->key, header->key);
- buffer_copy_string_buffer(ds->value, header->value);
-
- array_insert_unique(con->response.headers, (data_unset *)ds);
- }
-
- con->file_started = 1;
- /* if Status: ... is not set, 200 is our default status-code */
- if (con->http_status == 0) con->http_status = 200;
- sess->state = CGI_STATE_READ_RESPONSE_CONTENT;
-
- if (con->request.http_version == HTTP_VERSION_1_1 &&
- !have_content_length) {
- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
- }
-
- break;
- }
- }
-
- /* FIXME: pass the response-header to the other plugins to
- * setup the filter-queue
- *
- * - use next-queue instead of con->write_queue
- */
-
- /* copy the resopnse content */
- cgi_copy_response(srv, con, sess);
-
- joblist_append(srv, con);
-
- return 0;
-}
-
-static handler_t cgi_connection_close(server *srv, connection *con, plugin_data *p) {
- cgi_session *sess = con->plugin_ctx[p->id];
- int status;
- pid_t pid;
-
- if (NULL == sess) return HANDLER_GO_ON;
- if (con->mode != p->id) return HANDLER_GO_ON;
-
-#ifndef _WIN32
-
- /* the connection to the browser went away, but we still have a connection
- * to the CGI script
- *
- * close cgi-connection
- */
-
- if (sess->sock->fd != -1) {
- /* close connection to the cgi-script */
- fdevent_event_del(srv->ev, sess->sock);
- fdevent_unregister(srv->ev, sess->sock);
- }
-
- if (sess->sock_err->fd != -1) {
- /* close connection to the cgi-script */
- fdevent_event_del(srv->ev, sess->sock_err);
- fdevent_unregister(srv->ev, sess->sock_err);
- }
-
- if (sess->wb_sock->fd != -1) {
- close(sess->wb_sock->fd);
- sess->wb_sock->fd = -1;
- }
-
- pid = sess->pid;
-
- con->plugin_ctx[p->id] = NULL;
-
- /* is this a good idea ? */
- cgi_session_free(sess);
- sess = NULL;
-
- /* if waitpid hasn't been called by response.c yet, do it here */
- if (pid) {
- /* check if the CGI-script is already gone */
-#ifndef _WIN32
- switch(waitpid(pid, &status, WNOHANG)) {
- case 0:
- /* not finished yet */
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) child isn't done yet, pid:", pid);
-#endif
- break;
- case -1:
- /* */
- if (errno == EINTR) break;
-
- /*
- * errno == ECHILD happens if _subrequest catches the process-status before
- * we have read the response of the cgi process
- *
- * -> catch status
- * -> WAIT_FOR_EVENT
- * -> read response
- * -> we get here with waitpid == ECHILD
- *
- */
- if (errno == ECHILD) return HANDLER_GO_ON;
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
- return HANDLER_ERROR;
- default:
- /* Send an error if we haven't sent any data yet */
- if (0 == con->file_started) {
- if (con->http_status == 0) con->http_status = 500;
- con->mode = DIRECT;
- }
-
- if (WIFEXITED(status)) {
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
-#endif
- pid = 0;
-
- return HANDLER_GO_ON;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
- pid = 0;
- return HANDLER_GO_ON;
- }
- }
-
-
- kill(pid, SIGTERM);
-#endif
- /* cgi-script is still alive, queue the PID for removal */
- cgi_pid_add(srv, p, pid);
- }
-#endif
- return HANDLER_GO_ON;
-}
-
-static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
-
- return cgi_connection_close(srv, con, p);
-}
-
-static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) {
- server *srv = (server *)s;
- cgi_session *sess = ctx;
- connection *con = sess->remote_con;
-
- if (revents & FDEVENT_IN) {
- switch (sess->state) {
- case CGI_STATE_READ_RESPONSE_HEADER:
- /* parse the header and set file-started, the demuxer will care about it */
- joblist_append(srv, con);
-
- break;
- case CGI_STATE_READ_RESPONSE_CONTENT:
- /* just forward the content to the out-going queue */
-
- chunkqueue_remove_finished_chunks(sess->rb);
-
- switch (srv->network_backend_read(srv, con, sess->sock, sess->rb)) {
- case NETWORK_STATUS_CONNECTION_CLOSE:
- fdevent_event_del(srv->ev, sess->sock);
-
- /* connection closed. close the read chunkqueue. */
- sess->rb->is_closed = 1;
- case NETWORK_STATUS_SUCCESS:
- /* read even more, do we have all the content */
-
- /* how much do we want to read ? */
-
- /* copy the resopnse content */
- cgi_copy_response(srv, con, sess);
-
- break;
- default:
- ERROR("%s", "oops, we failed to read");
- break;
- }
-
- joblist_append(srv, con);
- break;
- default:
- TRACE("unexpected state for a FDEVENT_IN: %d", sess->state);
- break;
- }
- }
-
- if (revents & FDEVENT_OUT) {
- /* nothing to do */
- }
-
- /* perhaps this issue is already handled */
- if (revents & FDEVENT_HUP) {
- con->send->is_closed = 1;
-
- fdevent_event_del(srv->ev, sess->sock);
-
- joblist_append(srv, con);
- } else if (revents & FDEVENT_ERR) {
- con->send->is_closed = 1;
-
- /* kill all connections to the cgi process */
- fdevent_event_del(srv->ev, sess->sock);
- joblist_append(srv, con);
- }
-
- return HANDLER_FINISHED;
-}
-
-/* so all cgi errors have the same source line as origin */
-static void cgi_log_err(const char *msg) {
- ERROR("error from cgi: %s", msg);
-}
-
-static void cgi_copy_err(chunkqueue *cq) {
- buffer *line = buffer_init();
- chunk *c;
-
- for (c = cq->first; c; c = c->next) {
- off_t we_have;
- char *str, *nl;
-
- if (c->type != MEM_CHUNK) {
- ERROR("%s", "wrong chunk type");
- chunk_set_done(c);
- continue;
- }
-
- we_have = c->mem->used - 1 - c->offset;
- str = c->mem->ptr + c->offset;
- if (we_have <= 0) continue;
-
- for ( ; NULL != (nl = strchr(str, '\n')); str = nl+1) {
- *nl = '\0';
- if (!buffer_is_empty(line)) {
- buffer_append_string(line, str);
- cgi_log_err(SAFE_BUF_STR(line));
- buffer_reset(line);
- } else {
- cgi_log_err(str);
- }
- }
- if (*str) {
- buffer_append_string(line, str);
- }
- chunk_set_done(c);
- }
-
- if (!buffer_is_empty(line)) {
- cgi_log_err(SAFE_BUF_STR(line));
- }
- chunkqueue_remove_finished_chunks(cq);
-}
-
-static handler_t cgi_handle_err_fdevent(void *s, void *ctx, int revents) {
- server *srv = (server *)s;
- cgi_session *sess = ctx;
- connection *con = sess->remote_con;
-
- if (revents & (FDEVENT_IN | FDEVENT_HUP)) {
- switch (srv->network_backend_read(srv, con, sess->sock_err, sess->rb_err)) {
- case NETWORK_STATUS_CONNECTION_CLOSE:
- fdevent_event_del(srv->ev, sess->sock_err);
-
- /* connection closed. close the read chunkqueue. */
- sess->rb_err->is_closed = 1;
- break;
- case NETWORK_STATUS_SUCCESS:
- break;
- default:
- ERROR("%s", "oops, we failed to read");
- break;
- }
-
- cgi_copy_err(sess->rb_err);
- }
-
- if (revents & FDEVENT_ERR) {
- fdevent_event_del(srv->ev, sess->sock_err);
- }
-
- return HANDLER_FINISHED;
-}
-
-
-static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
- char *dst;
-
- if (!key || !val) return -1;
-
- dst = malloc(key_len + val_len + 3);
- memcpy(dst, key, key_len);
- dst[key_len] = '=';
- memcpy(dst + key_len + 1, val, val_len);
- dst[key_len + 1 + val_len] = '\0';
-
- if (env->size == 0) {
- env->size = 16;
- env->ptr = malloc(env->size * sizeof(*env->ptr));
- } else if (env->size == env->used) {
- env->size += 16;
- env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
- }
-
- env->ptr[env->used++] = dst;
-
- return 0;
-}
-
-static const char *sock_addr_to_p(server *srv, sock_addr *addr) {
- switch (addr->plain.sa_family) {
- case AF_INET:
- return inet_ntoa(addr->ipv4.sin_addr);
-#ifdef HAVE_IPV6
- case AF_INET6:
- return inet_ntop_cache_get_ip(srv, addr);
-#endif
-#ifdef HAVE_SYS_UN_H
- case AF_UNIX:
- return addr->un.sun_path;
-#endif
- }
- return "";
-}
-
-static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
- pid_t pid;
-
- int to_cgi_fds[2];
- int from_cgi_fds[2];
- int from_cgi_err_fds[2];
- struct stat st;
-
-#ifndef _WIN32
-
- if (cgi_handler && cgi_handler->used > 1) {
- /* stat the exec file */
- if (-1 == (stat(cgi_handler->ptr, &st))) {
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "stat for cgi-handler", cgi_handler,
- "failed:", strerror(errno));
- return -1;
- }
- }
-
- if (pipe(to_cgi_fds)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
- return -1;
- }
-
- if (pipe(from_cgi_fds)) {
- close(to_cgi_fds[0]); close(to_cgi_fds[1]);
- log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
- return -1;
- }
-
- if (pipe(from_cgi_err_fds)) {
- close(to_cgi_fds[0]); close(to_cgi_fds[1]);
- close(from_cgi_fds[0]); close(from_cgi_fds[1]);
- log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
- return -1;
- }
-
- /* fork, execve */
- switch (pid = fork()) {
- case 0: {
- /* child */
- char **args;
- int argc;
- int i = 0;
- char buf[32];
- size_t n;
- char_array env;
- char *c;
- const char *s;
- server_socket *srv_sock = con->srv_socket;
-
- /* move stdout to from_cgi_fd[1] */
- close(STDOUT_FILENO);
- dup2(from_cgi_fds[1], STDOUT_FILENO);
- close(from_cgi_fds[1]);
- /* not needed */
- close(from_cgi_fds[0]);
-
- /* move stderr to from_cgi_err_fd[1] */
- close(STDERR_FILENO);
- dup2(from_cgi_err_fds[1], STDERR_FILENO);
- close(from_cgi_err_fds[1]);
- /* not needed */
- close(from_cgi_err_fds[0]);
-
- /* move the stdin to to_cgi_fd[0] */
- close(STDIN_FILENO);
- dup2(to_cgi_fds[0], STDIN_FILENO);
- close(to_cgi_fds[0]);
- /* not needed */
- close(to_cgi_fds[1]);
-
- /* create environment */
- env.ptr = NULL;
- env.size = 0;
- env.used = 0;
-
- cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
-
- s = sock_addr_to_p(srv, &srv_sock->addr);
- cgi_env_add(&env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
- /* !!! careful: s maybe reused for SERVER_NAME !!! */
-
- if (!buffer_is_empty(con->server_name)) {
- size_t len = con->server_name->used - 1;
- char *colon = strchr(con->server_name->ptr, ':');
- if (colon) len = colon - con->server_name->ptr;
-
- cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), con->server_name->ptr, len);
- } else {
- /* use SERVER_ADDR */
- cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
- }
- cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
-
- s = get_http_version_name(con->request.http_version);
-
- cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
-
- LI_ltostr(buf, sock_addr_get_port(&srv_sock->addr));
- cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
-
- s = get_http_method_name(con->request.http_method);
- cgi_env_add(&env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
-
- if (!buffer_is_empty(con->request.pathinfo)) {
- cgi_env_add(&env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
- }
- cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
- if (!buffer_is_empty(con->uri.query)) {
- cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
- } else {
- /* set a empty QUERY_STRING */
- cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
- }
- if (!buffer_is_empty(con->request.orig_uri)) {
- cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
- }
-
- s = sock_addr_to_p(srv, &con->dst_addr);
- cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
-
- LI_ltostr(buf, sock_addr_get_port(&con->dst_addr));
- cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
-
- if (!buffer_is_empty(con->authed_user)) {
- cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
- CONST_BUF_LEN(con->authed_user));
- }
-
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- cgi_env_add(&env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
- }
-#endif
-
- /* request.content_length < SSIZE_MAX, see request.c */
- if (con->request.content_length > 0) {
- LI_ltostr(buf, con->request.content_length);
- cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
- }
- cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
- cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
- cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
-
- /* for valgrind */
- if (NULL != (s = getenv("LD_PRELOAD"))) {
- cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
- }
-
- if (NULL != (s = getenv("LD_LIBRARY_PATH"))) {
- cgi_env_add(&env, CONST_STR_LEN("LD_LIBRARY_PATH"), s, strlen(s));
- }
-#ifdef __CYGWIN__
- /* CYGWIN needs SYSTEMROOT */
- if (NULL != (s = getenv("SYSTEMROOT"))) {
- cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
- }
-#endif
-
- for (n = 0; n < con->request.headers->used; n++) {
- data_string *ds;
-
- ds = (data_string *)con->request.headers->data[n];
-
- if (ds->value->used && ds->key->used) {
- size_t j;
-
- buffer_reset(p->tmp_buf);
-
- if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
- buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("HTTP_"));
- p->tmp_buf->used--; /* strip \0 after HTTP_ */
- }
-
- buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
-
- for (j = 0; j < ds->key->used - 1; j++) {
- char cr = '_';
- if (light_isalpha(ds->key->ptr[j])) {
- /* upper-case */
- cr = ds->key->ptr[j] & ~32;
- } else if (light_isdigit(ds->key->ptr[j])) {
- /* copy */
- cr = ds->key->ptr[j];
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
-
- cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
- }
- }
-
- for (n = 0; n < con->environment->used; n++) {
- data_string *ds;
-
- ds = (data_string *)con->environment->data[n];
-
- if (ds->value->used && ds->key->used) {
- size_t j;
-
- buffer_reset(p->tmp_buf);
-
- buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
-
- for (j = 0; j < ds->key->used - 1; j++) {
- char cr = '_';
- if (light_isalpha(ds->key->ptr[j])) {
- /* upper-case */
- cr = ds->key->ptr[j] & ~32;
- } else if (light_isdigit(ds->key->ptr[j])) {
- /* copy */
- cr = ds->key->ptr[j];
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
-
- cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
- }
- }
-
- if (env.size == env.used) {
- env.size += 16;
- env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
- }
-
- env.ptr[env.used] = NULL;
-
- /* set up args */
- argc = 3;
- args = malloc(sizeof(*args) * argc);
- i = 0;
-
- if (cgi_handler && cgi_handler->used > 1) {
- args[i++] = cgi_handler->ptr;
- }
- args[i++] = con->physical.path->ptr;
- args[i++] = NULL;
-
- /* search for the last / */
- if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
- *c = '\0';
-
- /* change to the physical directory */
- if (-1 == chdir(con->physical.path->ptr)) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
- }
- *c = '/';
- }
-
- /* we don't need the client socket */
- for (i = 3; i < 256; i++) {
- close(i);
- }
-
- /* exec the cgi */
- execve(args[0], args, env.ptr);
-
- /* */
- SEGFAULT("execve(%s) failed: %s", args[0], strerror(errno));
- break;
- }
- case -1:
- /* error */
- ERROR("fork() failed: %s", strerror(errno));
- close(to_cgi_fds[0]); close(to_cgi_fds[1]);
- close(from_cgi_fds[0]); close(from_cgi_fds[1]);
- close(from_cgi_err_fds[0]); close(from_cgi_err_fds[1]);
- return -1;
- break;
- default: {
- cgi_session *sess;
- /* father */
-
- close(from_cgi_fds[1]);
- close(from_cgi_err_fds[1]);
- close(to_cgi_fds[0]);
-
- /* register PID and wait for them asyncronously */
- con->mode = p->id;
- buffer_reset(con->physical.path);
-
- sess = cgi_session_init();
-
- sess->remote_con = con;
- sess->pid = pid;
-
- assert(sess->sock);
-
- sess->sock->fd = from_cgi_fds[0];
- sess->sock->type = IOSOCKET_TYPE_PIPE;
- sess->sock_err->fd = from_cgi_err_fds[0];
- sess->sock_err->type = IOSOCKET_TYPE_PIPE;
- sess->wb_sock->fd = to_cgi_fds[1];
- sess->wb_sock->type = IOSOCKET_TYPE_PIPE;
-
- if (-1 == fdevent_fcntl_set(srv->ev, sess->sock)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
-
- cgi_session_free(sess);
-
- return -1;
- }
-
- if (-1 == fdevent_fcntl_set(srv->ev, sess->sock_err)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
-
- cgi_session_free(sess);
-
- return -1;
- }
-
- con->plugin_ctx[p->id] = sess;
-
- fdevent_register(srv->ev, sess->sock, cgi_handle_fdevent, sess);
- fdevent_event_add(srv->ev, sess->sock, FDEVENT_IN);
-
- fdevent_register(srv->ev, sess->sock_err, cgi_handle_err_fdevent, sess);
- fdevent_event_add(srv->ev, sess->sock_err, FDEVENT_IN);
-
- sess->state = CGI_STATE_READ_RESPONSE_HEADER;
-
- break;
- }
- }
-
- return 0;
-#else
- return -1;
-#endif
-}
-
-static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(cgi);
- PATCH_OPTION(execute_all);
- PATCH_OPTION(execute_x_only);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_ASSIGN))) {
- PATCH_OPTION(cgi);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_EXECUTE_ALL))) {
- PATCH_OPTION(execute_all);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_EXECUTE_X_ONLY))) {
- PATCH_OPTION(execute_x_only);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_cgi_start_backend) {
- size_t k, s_len;
- plugin_data *p = p_d;
- buffer *fn = con->physical.path;
- stat_cache_entry *sce = NULL;
-
- if (fn->used == 0) return HANDLER_GO_ON;
-
- mod_cgi_patch_connection(srv, con, p);
-
- if (p->conf.cgi->used == 0 && p->conf.execute_all == 0) {
- return HANDLER_GO_ON;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- checking request in mod_%s", "cgi");
- }
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) return HANDLER_GO_ON;
- if (!S_ISREG(sce->st.st_mode)) return HANDLER_GO_ON;
- if (p->conf.execute_x_only == 1 && (sce->st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) return HANDLER_GO_ON;
-
- s_len = fn->used - 1;
-
- for (k = 0; k < p->conf.cgi->used; k++) {
- data_string *ds = (data_string *)p->conf.cgi->data[k];
- size_t ct_len = ds->key->used - 1;
-
- if (ds->key->used == 0) continue;
- if (s_len < ct_len) continue;
-
- if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
- if (cgi_create_env(srv, con, p, ds->value)) {
- con->http_status = 500;
-
- buffer_reset(con->physical.path);
- return HANDLER_FINISHED;
- }
- return HANDLER_FINISHED;
- }
- }
-
- if (p->conf.execute_all) {
- if (cgi_create_env(srv, con, p, NULL)) {
- con->http_status = 500;
-
- buffer_reset(con->physical.path);
- return HANDLER_FINISHED;
- }
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
-}
-
-TRIGGER_FUNC(cgi_trigger) {
- plugin_data *p = p_d;
- size_t ndx;
- /* the trigger handle only cares about lonely PID which we have to wait for */
-#ifndef _WIN32
-
- for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
- int status;
-
- switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
- case 0:
- /* not finished yet */
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) child isn't done yet, pid:", p->cgi_pid.ptr[ndx]);
-#endif
- break;
- case -1:
- log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
-
- return HANDLER_ERROR;
- default:
-
- if (WIFEXITED(status)) {
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", p->cgi_pid.ptr[ndx]);
-#endif
- } else if (WIFSIGNALED(status)) {
- log_error_write(srv, __FILE__, __LINE__, "sdsd", "cgi signaled, pid:", p->cgi_pid.ptr[ndx], ", signal", WTERMSIG(status));
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sdsd", "cgi died, pid:", p->cgi_pid.ptr[ndx], ", status", status);
- }
-
- cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
- /* del modified the buffer structure
- * and copies the last entry to the current one
- * -> recheck the current index
- */
- ndx--;
- }
- }
-#endif
- return HANDLER_GO_ON;
-}
-
-SUBREQUEST_FUNC(mod_cgi_read_response_content) {
- int status;
- plugin_data *p = p_d;
- cgi_session *sess = con->plugin_ctx[p->id];
-
- if (con->mode != p->id) return HANDLER_GO_ON;
- if (NULL == sess) return HANDLER_GO_ON;
-
- switch (cgi_demux_response(srv, con, p)) {
- case 0:
- break;
- case 1:
- cgi_connection_close(srv, con, p);
-
- /* if we get a IN|HUP and have read everything don't exec the close twice */
- return HANDLER_FINISHED;
- case -1:
- cgi_connection_close(srv, con, p);
-
- if (0 == con->http_status) con->http_status = 500;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", sess, sess->pid);
-#endif
- if (sess->pid == 0) return HANDLER_FINISHED;
-#ifndef _WIN32
- switch(waitpid(sess->pid, &status, WNOHANG)) {
- case 0:
- /* we only have for events here if we don't have the header yet,
- * otherwise the event-handler will send us the incoming data */
-
- if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
- if (con->send->is_closed) return HANDLER_FINISHED;
-
- return HANDLER_GO_ON;
- case -1:
- if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
-
- if (errno == ECHILD && con->file_started == 0) {
- /*
- * second round but still not response
- */
- return HANDLER_WAIT_FOR_EVENT;
- }
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
- con->mode = DIRECT;
- con->http_status = 500;
-
- sess->pid = 0;
-
- fdevent_event_del(srv->ev, sess->sock);
- fdevent_unregister(srv->ev, sess->sock);
-
- fdevent_event_del(srv->ev, sess->sock_err);
- fdevent_unregister(srv->ev, sess->sock_err);
-
- cgi_session_free(sess);
- sess = NULL;
-
- con->plugin_ctx[p->id] = NULL;
-
- return HANDLER_FINISHED;
- default:
- con->send->is_closed = 1;
-
- if (WIFEXITED(status)) {
- /* nothing */
- } else {
- log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
-
- con->mode = DIRECT;
- con->http_status = 500;
-
- }
-
- sess->pid = 0;
-
- fdevent_event_del(srv->ev, sess->sock);
- fdevent_unregister(srv->ev, sess->sock);
-
- fdevent_event_del(srv->ev, sess->sock_err);
- fdevent_unregister(srv->ev, sess->sock_err);
-
- cgi_session_free(sess);
- sess = NULL;
-
- con->plugin_ctx[p->id] = NULL;
- return HANDLER_FINISHED;
- }
-#else
- return HANDLER_ERROR;
-#endif
-}
-
-URIHANDLER_FUNC(mod_cgi_send_request_content) {
- plugin_data *p = p_d;
- cgi_session *sess = con->plugin_ctx[p->id];
-
- if (p->id != con->mode) return HANDLER_GO_ON;
-
- if (con->request.content_length > 0 && con->recv->bytes_in > con->recv->bytes_out) {
- /* write request content. */
- switch (network_write_chunkqueue_write(srv, con, sess->wb_sock, con->recv)) {
- case NETWORK_STATUS_SUCCESS:
- /** fall through, still have data to write. */
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- /** fall through */
- case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
- break;
- case NETWORK_STATUS_CONNECTION_CLOSE:
- /* the script might have written a response already. */
- break;
- default:
- TRACE("%s", "(error)");
- return HANDLER_ERROR;
- }
- chunkqueue_remove_finished_chunks(con->recv);
- }
- /* we have to close the pipe to finish the request. */
- if ((con->recv->is_closed && con->recv->bytes_in == con->recv->bytes_out) ||
- con->request.content_length <= 0) {
- close(sess->wb_sock->fd);
- sess->wb_sock->fd = -1;
- } else {
- /* there is more data to write. */
- return HANDLER_GO_ON;
- }
-
- return mod_cgi_read_response_content(srv, con, p_d);
-}
-
-
-LI_EXPORT int mod_cgi_plugin_init(plugin *p);
-LI_EXPORT int mod_cgi_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("cgi");
-
- p->connection_reset = cgi_connection_close_callback;
- p->handle_start_backend = mod_cgi_start_backend;
- p->handle_send_request_content = mod_cgi_send_request_content;
- p->handle_read_response_content = mod_cgi_read_response_content;
-
- p->handle_trigger = cgi_trigger;
- p->init = mod_cgi_init;
- p->cleanup = mod_cgi_free;
- p->set_defaults = mod_cgi_set_defaults;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_chunked.c b/src/mod_chunked.c
deleted file mode 100644
index 567a3bdb..00000000
--- a/src/mod_chunked.c
+++ /dev/null
@@ -1,381 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "response.h"
-#include "filter.h"
-
-#include "plugin.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define CONFIG_CHUNKED_ENCODING "chunked.encoding"
-#define CONFIG_CHUNKED_DEBUG "chunked.debug"
-
-/**
- * This plugin adds HTTP/1.1 chunked encoding support
- * as a filter module.
- *
- */
-
-/* plugin config for all request/connections */
-
-typedef struct {
- unsigned short encoding;
- unsigned short debug;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-typedef struct {
- unsigned short debug;
- filter *fl;
-} handler_ctx;
-
-static handler_ctx * handler_ctx_init() {
- handler_ctx * hctx;
-
- hctx = calloc(1, sizeof(*hctx));
- hctx->debug = 0;
- hctx->fl = NULL;
-
- return hctx;
-}
-
-static void handler_ctx_free(handler_ctx *hctx) {
-
- free(hctx);
-}
-
-/* init the plugin data */
-INIT_FUNC(mod_chunked_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-/* destroy the plugin data */
-FREE_FUNC(mod_chunked_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_chunked_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { CONFIG_CHUNKED_ENCODING, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { CONFIG_CHUNKED_DEBUG, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->encoding = 1;
- s->debug = 0;
-
- cv[0].destination = &(s->encoding);
- cv[1].destination = &(s->debug);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-REQUESTDONE_FUNC(mod_chunked_reset) {
- plugin_data *p = p_d;
- handler_ctx *hctx = con->plugin_ctx[p->id];
-
- UNUSED(srv);
-
- if (NULL == hctx) return HANDLER_GO_ON;
-
- handler_ctx_free(hctx);
- con->plugin_ctx[p->id] = NULL;
-
- return HANDLER_GO_ON;
-}
-
-static int mod_chunked_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(encoding);
- PATCH_OPTION(debug);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_CHUNKED_ENCODING))) {
- PATCH_OPTION(encoding);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_CHUNKED_DEBUG))) {
- PATCH_OPTION(debug);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_chunked_response_header) {
- plugin_data *p = p_d;
- handler_ctx *hctx;
- filter *fl;
- chunkqueue *in;
- int use_chunked = 0;
-
- mod_chunked_patch_connection(srv, con, p);
-
- /* get filter. */
- fl = filter_chain_get_filter(con->send_filters, p->id);
- if (!fl) {
- if (p->conf.debug > 0) TRACE("%s", "add chunked filter to filter chain");
- fl = filter_chain_create_filter(con->send_filters, p->id);
- }
- /* get our input and output chunkqueues. */
- if (!fl || !fl->prev) {
- filter_chain_remove_filter(con->send_filters, fl);
- return HANDLER_GO_ON;
- }
- in = fl->prev->cq;
-
- if (in->is_closed && (con->response.content_length < 0 || con->request.http_method != HTTP_METHOD_HEAD)) {
- con->response.content_length = chunkqueue_length(in);
- }
- /* check if response needs chunked encoding. */
- if (con->request.http_method != HTTP_METHOD_HEAD) {
- if(con->response.content_length >= 0) {
- if (p->conf.debug > 0) TRACE("response content length known, disabling chunked encoding. len=%jd", (intmax_t) con->response.content_length);
- use_chunked = 0;
- } else {
- /* a HEAD request never gets a chunk-encoding, but might stay with keep-alive
- * in case the queue was closed already (above) we still have the content-length */
-
- /* we don't know the size of the content yet
- * - either enable chunking
- * - or disable keep-alive */
-
- if (con->request.http_version == HTTP_VERSION_1_1 && p->conf.encoding) {
- use_chunked = 1;
- } else {
- if (p->conf.debug > 0)
- TRACE("%s", "content length unknown and can't use chunked encoding. disable keep-alive");
- con->keep_alive = 0;
- use_chunked = 0;
- }
- }
- }
-
- if (!use_chunked) {
- /* chunked encoding disabled. remove filter */
- con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
- filter_chain_remove_filter(con->send_filters, fl);
- return HANDLER_GO_ON;
- }
-
- /* enable chunked encoding */
- con->response.transfer_encoding |= HTTP_TRANSFER_ENCODING_CHUNKED;
- hctx = handler_ctx_init();
- hctx->debug = p->conf.debug;
- con->plugin_ctx[p->id] = hctx;
- hctx->fl = fl;
-
- if (hctx->debug > 0)
- TRACE("%s", "chunked encoding enabled");
-
- return HANDLER_GO_ON;
-}
-
-static int http_chunk_append_len(chunkqueue *cq, size_t len) {
- size_t i, olen = len, j;
- buffer *b;
-
- b = buffer_init();
-
- if (len == 0) {
- buffer_copy_string_len(b, CONST_STR_LEN("0"));
- } else {
- for (i = 0; i < 8 && len; i++) {
- len >>= 4;
- }
-
- /* i is the number of hex digits we have */
- buffer_prepare_copy(b, i + 1);
-
- for (j = i-1, len = olen; j+1 > 0; j--) {
- b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
- len >>= 4;
- }
- b->used = i;
- b->ptr[b->used++] = '\0';
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
- chunkqueue_append_buffer(cq, b);
- len = b->used - 1;
-
- buffer_free(b);
-
- return len;
-}
-
-/**
- * apply HTTP/1.1 chunked encoding if necessary
- */
-URIHANDLER_FUNC(mod_chunked_encode_response_content) {
- plugin_data *p = p_d;
- handler_ctx *hctx = con->plugin_ctx[p->id];
- chunkqueue *in;
- chunkqueue *out;
- int we_have = 0;
- chunk *c;
-
- UNUSED(srv);
-
- /* check if chunk-encoding is enabled. */
- if (!hctx) return HANDLER_GO_ON;
-
- /* get our input and output chunkqueues. */
- if (!hctx->fl || !hctx->fl->prev) return HANDLER_GO_ON;
- in = hctx->fl->prev->cq;
- out = hctx->fl->cq;
-
- /* we are all done already (see the end of the function) */
- if (out->is_closed) return HANDLER_GO_ON;
-
- /* move all chunks to the out queue
- * and append a HTTP/1.1 chunked header to each chunk
- */
- for (c = in->first; c; c = c->next) {
- switch (c->type) {
- case MEM_CHUNK:
- if (c->mem->used == 0) continue;
-
- we_have = c->mem->used - c->offset - 1;
- in->bytes_out += we_have;
- if(we_have == 0) continue;
- we_have += http_chunk_append_len(out, we_have);
- chunkqueue_append_buffer(out, c->mem);
-
- chunk_set_done(c);
-
- break;
- case FILE_CHUNK:
- if (c->file.length == 0) continue;
-
- we_have = c->file.length;
- in->bytes_out += we_have;
- we_have += http_chunk_append_len(out, c->file.length);
-
- if(c->file.is_temp) {
- chunkqueue_steal_tempfile(out, c);
- } else {
- chunkqueue_append_file(out, c->file.name, c->file.start, c->file.length);
- }
-
- chunk_set_done(c);
-
- break;
- case UNUSED_CHUNK:
- break;
- }
- chunkqueue_append_mem(out, CONST_STR_LEN("\r\n"));
- we_have += 2;
- out->bytes_in += we_have;
- }
-
- /* terminate the last chunk */
- if (in->is_closed) {
- chunkqueue_append_mem(out, CONST_STR_LEN("0\r\n\r\n"));
- out->bytes_in += 5;
- }
-
- if (hctx->debug > 1) TRACE("chunk encoded: in=%jd, out=%jd", (intmax_t) in->bytes_out, (intmax_t) out->bytes_in);
-
- chunkqueue_remove_finished_chunks(in);
-
- /* the in side is closed, close out too */
- if (in->is_closed) {
- /* mark the output queue as finished. */
- out->is_closed = 1;
- }
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_chunked_plugin_init(plugin *p);
-LI_EXPORT int mod_chunked_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("chunked");
-
- p->init = mod_chunked_init;
- p->set_defaults = mod_chunked_set_defaults;
- p->handle_response_header = mod_chunked_response_header;
- p->handle_filter_response_content = mod_chunked_encode_response_content;
- p->connection_reset = mod_chunked_reset;
- p->cleanup = mod_chunked_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_compress.c b/src/mod_compress.c
deleted file mode 100644
index 7e72fb4a..00000000
--- a/src/mod_compress.c
+++ /dev/null
@@ -1,848 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <fcntl.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "response.h"
-#include "stat_cache.h"
-
-#include "plugin.h"
-
-#include "crc32.h"
-#include "etag.h"
-
-#if defined HAVE_ZLIB_H && defined HAVE_LIBZ
-# define USE_ZLIB
-# include <zlib.h>
-#endif
-
-#if defined HAVE_BZLIB_H && defined HAVE_LIBBZ2
-# define USE_BZ2LIB
-/* we don't need stdio interface */
-# define BZ_NO_STDIO
-# include <bzlib.h>
-#endif
-
-#include "sys-mmap.h"
-#include "sys-files.h"
-
-/* request: accept-encoding */
-#define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
-#define HTTP_ACCEPT_ENCODING_GZIP BV(1)
-#define HTTP_ACCEPT_ENCODING_DEFLATE BV(2)
-#define HTTP_ACCEPT_ENCODING_COMPRESS BV(3)
-#define HTTP_ACCEPT_ENCODING_BZIP2 BV(4)
-
-#ifdef __WIN32
-#define mkdir(x,y) mkdir(x)
-#endif
-
-typedef struct {
- buffer *compress_cache_dir;
- array *compress;
- off_t compress_max_filesize; /** max filesize in kb */
- int allowed_encodings;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
- buffer *ofn;
- buffer *b;
-
- plugin_config **config_storage;
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_compress_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->ofn = buffer_init();
- p->b = buffer_init();
-
- return p;
-}
-
-FREE_FUNC(mod_compress_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- buffer_free(p->ofn);
- buffer_free(p->b);
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->compress);
- buffer_free(s->compress_cache_dir);
-
- free(s);
- }
- free(p->config_storage);
- }
-
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* 0 on success, -1 for error */
-static 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 */
-static 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)) {
- ERROR("creating cache-directory \"%s\" failed: %s", filename, strerror(errno));
- *p = '/';
- return -1;
- }
-
- *p++ = '/';
- if (!*p) {
- ERROR("unexpected trailing slash for filename \"%s\"", filename);
- return -1;
- }
- }
-
- return 0;
-}
-
-SETDEFAULTS_FUNC(mod_compress_setdefaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
- { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { "compress.allowed-encodings", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- array *encodings_arr = array_init();
-
- s = calloc(1, sizeof(plugin_config));
- s->compress_cache_dir = buffer_init();
- s->compress = array_init();
- s->compress_max_filesize = 0;
- s->allowed_encodings = 0;
-
- cv[0].destination = s->compress_cache_dir;
- cv[1].destination = s->compress;
- cv[2].destination = &(s->compress_max_filesize);
- cv[3].destination = encodings_arr; /* temp array for allowed encodings list */
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (encodings_arr->used) {
- size_t j = 0;
- for (j = 0; j < encodings_arr->used; j++) {
- data_string *ds = (data_string *)encodings_arr->data[j];
-#ifdef USE_ZLIB
- if (NULL != strstr(ds->value->ptr, "gzip"))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
- if (NULL != strstr(ds->value->ptr, "deflate"))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
- /*
- if (NULL != strstr(ds->value->ptr, "compress"))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_COMPRESS;
- */
-#endif
-#ifdef USE_BZ2LIB
- if (NULL != strstr(ds->value->ptr, "bzip2"))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
-#endif
- }
- } else {
- /* default encodings */
- s->allowed_encodings = 0
-#ifdef USE_ZLIB
- | HTTP_ACCEPT_ENCODING_GZIP | HTTP_ACCEPT_ENCODING_DEFLATE
-#endif
-#ifdef USE_BZ2LIB
- | HTTP_ACCEPT_ENCODING_BZIP2
-#endif
- ;
- }
-
- array_free(encodings_arr);
-
- if (!buffer_is_empty(s->compress_cache_dir)) {
- struct stat st;
- if (0 != stat(s->compress_cache_dir->ptr, &st)) {
-
- ERROR("can't stat compress.cache-dir (%s), attempting to create '%s'", strerror(errno),SAFE_BUF_STR(s->compress_cache_dir));
- mkdir_recursive(s->compress_cache_dir->ptr);
-
- if (0 != stat(s->compress_cache_dir->ptr, &st)) {
- ERROR("can't stat compress.cache-dir (%s), failed to create '%s'", strerror(errno),SAFE_BUF_STR(s->compress_cache_dir));
- return HANDLER_ERROR;
- }
- }
- }
- }
-
- return HANDLER_GO_ON;
-
-}
-
-#ifdef USE_ZLIB
-static int deflate_file_to_buffer_gzip(server *srv, connection *con, plugin_data *p, char *start, off_t st_size, time_t mtime) {
- unsigned char *c;
- unsigned long crc;
- z_stream z;
-
- UNUSED(srv);
- UNUSED(con);
-
- z.zalloc = Z_NULL;
- z.zfree = Z_NULL;
- z.opaque = Z_NULL;
-
- if (Z_OK != deflateInit2(&z,
- Z_DEFAULT_COMPRESSION,
- Z_DEFLATED,
- -MAX_WBITS, /* supress zlib-header */
- 8,
- Z_DEFAULT_STRATEGY)) {
- return -1;
- }
-
- z.next_in = (unsigned char *)start;
- z.avail_in = st_size;
- z.total_in = 0;
-
-
- buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
-
- /* write gzip header */
-
- c = (unsigned char *)p->b->ptr;
- c[0] = 0x1f;
- c[1] = 0x8b;
- c[2] = Z_DEFLATED;
- c[3] = 0; /* options */
- c[4] = (mtime >> 0) & 0xff;
- c[5] = (mtime >> 8) & 0xff;
- c[6] = (mtime >> 16) & 0xff;
- c[7] = (mtime >> 24) & 0xff;
- c[8] = 0x00; /* extra flags */
- c[9] = 0x03; /* UNIX */
-
- p->b->used = 10;
- z.next_out = (unsigned char *)p->b->ptr + p->b->used;
- z.avail_out = p->b->size - p->b->used - 8;
- z.total_out = 0;
-
- if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
- deflateEnd(&z);
- return -1;
- }
-
- /* trailer */
- p->b->used += z.total_out;
-
- crc = generate_crc32c(start, st_size);
-
- c = (unsigned char *)p->b->ptr + p->b->used;
-
- c[0] = (crc >> 0) & 0xff;
- c[1] = (crc >> 8) & 0xff;
- c[2] = (crc >> 16) & 0xff;
- c[3] = (crc >> 24) & 0xff;
- c[4] = (z.total_in >> 0) & 0xff;
- c[5] = (z.total_in >> 8) & 0xff;
- c[6] = (z.total_in >> 16) & 0xff;
- c[7] = (z.total_in >> 24) & 0xff;
- p->b->used += 8;
-
- if (Z_OK != deflateEnd(&z)) {
- return -1;
- }
-
- return 0;
-}
-
-static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
- z_stream z;
-
- UNUSED(srv);
- UNUSED(con);
-
- z.zalloc = Z_NULL;
- z.zfree = Z_NULL;
- z.opaque = Z_NULL;
-
- if (Z_OK != deflateInit2(&z,
- Z_DEFAULT_COMPRESSION,
- Z_DEFLATED,
- -MAX_WBITS, /* supress zlib-header */
- 8,
- Z_DEFAULT_STRATEGY)) {
- return -1;
- }
-
- z.next_in = start;
- z.avail_in = st_size;
- z.total_in = 0;
-
- buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
-
- z.next_out = (unsigned char *)p->b->ptr;
- z.avail_out = p->b->size;
- z.total_out = 0;
-
- if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
- deflateEnd(&z);
- return -1;
- }
-
- /* trailer */
- p->b->used += z.total_out;
-
- if (Z_OK != deflateEnd(&z)) {
- return -1;
- }
-
- return 0;
-}
-
-#endif
-
-#ifdef USE_BZ2LIB
-static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
- bz_stream bz;
-
- UNUSED(srv);
- UNUSED(con);
-
- bz.bzalloc = NULL;
- bz.bzfree = NULL;
- bz.opaque = NULL;
-
- if (BZ_OK != BZ2_bzCompressInit(&bz,
- 9, /* blocksize = 900k */
- 0, /* no output */
- 0)) { /* workFactor: default */
- return -1;
- }
-
- bz.next_in = (char *)start;
- bz.avail_in = st_size;
- bz.total_in_lo32 = 0;
- bz.total_in_hi32 = 0;
-
- buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
-
- bz.next_out = p->b->ptr;
- bz.avail_out = p->b->size;
- bz.total_out_lo32 = 0;
- bz.total_out_hi32 = 0;
-
- if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
- BZ2_bzCompressEnd(&bz);
- return -1;
- }
-
- /* file is too large for now */
- if (bz.total_out_hi32) return -1;
-
- /* trailer */
- p->b->used = bz.total_out_lo32;
-
- if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
- return -1;
- }
-
- return 0;
-}
-#endif
-
-static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, buffer *fn, stat_cache_entry *sce, int type) {
- int ifd, ofd;
- int ret = -1;
- void *start;
- const char *filename = fn->ptr;
- ssize_t r;
- stat_cache_entry *compressed_sce = NULL;
-
- if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
-
- /* overflow */
- if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
-
- /* don't mmap files > 128Mb
- *
- * we could use a sliding window, but currently there is no need for it
- */
-
- if (sce->st.st_size > 128 * 1024 * 1024) return -1;
-
- buffer_reset(p->ofn);
- buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
- PATHNAME_APPEND_SLASH(p->ofn);
-
- if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
- buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
- buffer_copy_string_buffer(p->b, p->ofn);
- } else {
- buffer_append_string_buffer(p->ofn, con->uri.path);
- }
-
- switch(type) {
- case HTTP_ACCEPT_ENCODING_GZIP:
- buffer_append_string_len(p->ofn, CONST_STR_LEN("-gzip-"));
- break;
- case HTTP_ACCEPT_ENCODING_DEFLATE:
- buffer_append_string_len(p->ofn, CONST_STR_LEN("-deflate-"));
- break;
- case HTTP_ACCEPT_ENCODING_BZIP2:
- buffer_append_string_len(p->ofn, CONST_STR_LEN("-bzip2-"));
- break;
- default:
- ERROR("unknown compression type %d", type);
- return -1;
- }
-
- buffer_append_string_buffer(p->ofn, sce->etag);
-
-
- if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
- /* file exists */
- if (con->conf.log_request_handling) TRACE("file exists in the cache (%s), sending it", SAFE_BUF_STR(p->ofn));
-
- chunkqueue_reset(con->send);
- chunkqueue_append_file(con->send, p->ofn, 0, compressed_sce->st.st_size);
- con->send->is_closed = 1;
-
- return 0;
- }
-
- if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
- if (-1 == mkdir_for_file(p->ofn->ptr)) {
- return -1; // error message in mkdir_for_file
- } else if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
- ERROR("creating cachefile '%s' failed: %s", SAFE_BUF_STR(p->ofn), strerror(errno));
- return -1;
- }
- }
-
- if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
- ERROR("opening plain-file '%s' failed: %s", SAFE_BUF_STR(fn), strerror(errno));
- close(ofd);
- return -1;
- }
-
-
- if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
- ERROR("mmaping '%s' failed: %s", SAFE_BUF_STR(fn), strerror(errno));
- close(ofd);
- close(ifd);
- return -1;
- }
-
- switch(type) {
-#ifdef USE_ZLIB
- case HTTP_ACCEPT_ENCODING_GZIP:
- ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
- break;
- case HTTP_ACCEPT_ENCODING_DEFLATE:
- ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
- break;
-#endif
-#ifdef USE_BZ2LIB
- case HTTP_ACCEPT_ENCODING_BZIP2:
- ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
- break;
-#endif
- default:
- ret = -1;
- 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) {
-
- }
-
- munmap(start, sce->st.st_size);
- close(ofd);
- close(ifd);
-
- if (ret != 0) return -1;
-
- chunkqueue_reset(con->send);
- chunkqueue_append_file(con->send, p->ofn, 0, r);
- con->send->is_closed = 1;
-
- return 0;
-}
-
-static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p, buffer *fn, stat_cache_entry *sce, int type) {
- int ifd;
- int ret = -1;
- void *start;
- buffer *b;
-
- /* overflow */
- if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
-
- /* don't mmap files > 128M
- *
- * we could use a sliding window, but currently there is no need for it
- */
-
- if (sce->st.st_size > 128 * 1024 * 1024) return -1;
-
- if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
- ERROR("opening plain-file '%s' failed: %s", SAFE_BUF_STR(fn), strerror(errno));
-
- return -1;
- }
-
- start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
-
- close(ifd);
-
- if (MAP_FAILED == start) {
- ERROR("mmaping '%s' failed: %s", SAFE_BUF_STR(fn), strerror(errno));
-
- return -1;
- }
-
- switch(type) {
-#ifdef USE_ZLIB
- case HTTP_ACCEPT_ENCODING_GZIP:
- ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
- break;
- case HTTP_ACCEPT_ENCODING_DEFLATE:
- ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
- break;
-#endif
-#ifdef USE_BZ2LIB
- case HTTP_ACCEPT_ENCODING_BZIP2:
- ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
- break;
-#endif
- default:
- ret = -1;
- break;
- }
-
- munmap(start, sce->st.st_size);
-
- if (ret != 0) return -1;
-
- chunkqueue_reset(con->send);
- b = chunkqueue_get_append_buffer(con->send);
- buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
- con->send->bytes_in += b->used-1;
-
- buffer_reset(con->physical.path);
-
- con->send->is_closed = 1;
- con->file_started = 1;
-
- return 0;
-}
-
-static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(compress_cache_dir);
- PATCH_OPTION(compress);
- PATCH_OPTION(compress_max_filesize);
- PATCH_OPTION(allowed_encodings);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
- PATCH_OPTION(compress_cache_dir);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
- PATCH_OPTION(compress);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
- PATCH_OPTION(compress_max_filesize);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.allowed-encodings"))) {
- PATCH_OPTION(allowed_encodings);
- }
- }
- }
-
- return 0;
-}
-
-PHYSICALPATH_FUNC(mod_compress_physical) {
- plugin_data *p = p_d;
- size_t m;
- off_t max_fsize;
- stat_cache_entry *sce = NULL;
- data_string *ds;
- int accept_encoding = 0;
- char *value;
- int matched_encodings = 0;
- const char *dflt_gzip = "gzip";
- const char *dflt_deflate = "deflate";
- const char *dflt_bzip2 = "bzip2";
-
- const char *compression_name = NULL;
- int compression_type = 0;
- buffer *mtime, *content_type;
-
- if (con->mode != DIRECT) return HANDLER_GO_ON;
-
- if (con->conf.log_request_handling) TRACE("-- %s", "handling in mod_compress");
-
- /* only GET and POST can get compressed */
- if (con->request.http_method != HTTP_METHOD_GET &&
- con->request.http_method != HTTP_METHOD_POST) {
- return HANDLER_GO_ON;
- }
-
- if (buffer_is_empty(con->physical.path)) {
- return HANDLER_GO_ON;
- }
-
- mod_compress_patch_connection(srv, con, p);
-
- max_fsize = p->conf.compress_max_filesize;
-
- if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- if (con->conf.log_request_handling) TRACE("file '%s' not found", SAFE_BUF_STR(con->physical.path));
- return HANDLER_GO_ON;
- }
-
- /* don't compress files that are too large as we need to much time to handle them */
- if (max_fsize && (sce->st.st_size >> 10) > max_fsize) {
- if (con->conf.log_request_handling) TRACE("file '%s' is too large: %jd",
- SAFE_BUF_STR(con->physical.path),
- (intmax_t) sce->st.st_size);
-
- return HANDLER_GO_ON;
- }
-
- /* compressing the file might lead to larger files instead */
- if (sce->st.st_size < 128) {
- if (con->conf.log_request_handling) TRACE("file '%s' is too small: %jd",
- SAFE_BUF_STR(con->physical.path),
- (intmax_t) sce->st.st_size);
-
- return HANDLER_GO_ON;
- }
-
- /* check if mimetype is in compress-config */
- content_type = 0;
- if (sce->content_type->ptr) {
- char *c;
- if ( (c = strchr(BUF_STR(sce->content_type), ';')) != 0) {
- content_type = buffer_init();
- buffer_copy_string_len(content_type, BUF_STR(sce->content_type), c - BUF_STR(sce->content_type));
- }
- }
- for (m = 0; m < p->conf.compress->used; m++) {
- data_string *compress_ds = (data_string *)p->conf.compress->data[m];
-
- if (!compress_ds) {
- ERROR("evil: %s .. %s", SAFE_BUF_STR(con->physical.path), SAFE_BUF_STR(con->uri.path));
-
- return HANDLER_GO_ON;
- }
-
- if (buffer_is_equal(compress_ds->value, sce->content_type)
- || (content_type && buffer_is_equal(compress_ds->value, content_type))) {
- break;
- }
- }
- buffer_free(content_type);
-
- if (m == p->conf.compress->used) {
- return HANDLER_GO_ON;
- }
- /* mimetype found */
-
-
- if (con->send->is_closed == 0) {
- if (con->conf.log_request_handling) TRACE("we can't compress streams: is_closed = %d", con->send->is_closed);
- return HANDLER_GO_ON;
- }
-
- if (con->send->first == NULL) {
- if (con->conf.log_request_handling) TRACE("we can't compress streams: ->first = %p", NULL);
- return HANDLER_GO_ON;
- }
-
- if (con->send->first->next != NULL) {
- if (con->conf.log_request_handling) TRACE("we can't compress streams: ->first->next = %p", NULL);
- return HANDLER_GO_ON;
- }
-
- if (con->send->first->type != FILE_CHUNK) {
- if (con->conf.log_request_handling) TRACE("we can compress file-chunks: ->type = %d", con->send->first->type);
- return HANDLER_GO_ON;
- }
-
- /* the response might change according to Accept-Encoding */
- response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
-
- if (NULL == (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Accept-Encoding")))) {
- if (con->conf.log_request_handling) TRACE("couldn't find a Accept-Encoding header: %s", "");
- return HANDLER_GO_ON;
- }
-
- value = ds->value->ptr;
-
- /* get client side support encodings */
-#ifdef USE_ZLIB
- if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
- if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
- if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
-#endif
-#ifdef USE_BZ2LIB
- if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
-#endif
- if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
-
- /* find matching entries */
- matched_encodings = accept_encoding & p->conf.allowed_encodings;
- if (0 == matched_encodings) {
- if (con->conf.log_request_handling) TRACE("we don't support the requested encoding: %s", value);
- return HANDLER_GO_ON;
- }
-
- mtime = strftime_cache_get(srv, sce->st.st_mtime);
- etag_mutate(con->physical.etag, sce->etag);
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
-
- /* perhaps we don't even have to compress the file as the browser still has the
- * current version */
- if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
- if (con->conf.log_request_handling) TRACE("%s is still the same, caching", SAFE_BUF_STR(con->physical.path));
- return HANDLER_FINISHED;
- }
-
- /* select best matching encoding */
- if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
- compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
- compression_name = dflt_bzip2;
- } else if (matched_encodings & HTTP_ACCEPT_ENCODING_GZIP) {
- compression_type = HTTP_ACCEPT_ENCODING_GZIP;
- compression_name = dflt_gzip;
- } else if (matched_encodings & HTTP_ACCEPT_ENCODING_DEFLATE) {
- compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
- compression_name = dflt_deflate;
- }
-
- if (con->conf.log_request_handling) TRACE("we are fine, let's compress: %s", "");
-
- /* deflate it to file (cached) or to memory */
- if (0 == deflate_file_to_file(srv, con, p,
- con->physical.path, sce, compression_type) ||
- 0 == deflate_file_to_buffer(srv, con, p,
- con->physical.path, sce, compression_type)) {
-
- response_header_overwrite(srv, con,
- CONST_STR_LEN("Content-Encoding"),
- compression_name, strlen(compression_name));
-
- response_header_overwrite(srv, con,
- CONST_STR_LEN("Content-Type"),
- CONST_BUF_LEN(sce->content_type));
-
- con->response.content_length = chunkqueue_length(con->send);
-
- if (con->conf.log_request_handling) TRACE("looks like %s could be compressed", SAFE_BUF_STR(con->physical.path));
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_compress_plugin_init(plugin *p);
-LI_EXPORT int mod_compress_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("compress");
-
- p->init = mod_compress_init;
- p->set_defaults = mod_compress_setdefaults;
-
- /* we have to hook into the response-header settings */
- p->handle_response_header = mod_compress_physical;
-
- p->cleanup = mod_compress_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_deflate.c b/src/mod_deflate.c
deleted file mode 100644
index 79deb11d..00000000
--- a/src/mod_deflate.c
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * mod_deflate - dynamic compression
- *
- * This plugin is a response filter.
- *
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <fcntl.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <assert.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "response.h"
-#include "joblist.h"
-#include "stat_cache.h"
-#include "filter.h"
-
-#include "plugin.h"
-
-#include "crc32.h"
-#include "etag.h"
-#include "inet_ntop_cache.h"
-
-#if defined HAVE_ZLIB_H && defined HAVE_LIBZ
-# define USE_ZLIB
-# include <zlib.h>
-#endif
-
-#if defined HAVE_BZLIB_H && defined HAVE_LIBBZ2
-# define USE_BZ2LIB
-/* we don't need stdio interface */
-# define BZ_NO_STDIO
-# include <bzlib.h>
-#endif
-
-#include "sys-mmap.h"
-
-/* request: accept-encoding */
-#define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
-#define HTTP_ACCEPT_ENCODING_GZIP BV(1)
-#define HTTP_ACCEPT_ENCODING_DEFLATE BV(2)
-#define HTTP_ACCEPT_ENCODING_COMPRESS BV(3)
-#define HTTP_ACCEPT_ENCODING_BZIP2 BV(4)
-
-/* encoding names */
-#define ENCODING_NAME_IDENTITY "identity"
-#define ENCODING_NAME_GZIP "gzip"
-#define ENCODING_NAME_DEFLATE "deflate"
-#define ENCODING_NAME_COMPRESS "compress"
-#define ENCODING_NAME_BZIP2 "bzip2"
-
-
-#define CONFIG_DEFLATE_OUTPUT_BUFFER_SIZE "deflate.output-buffer-size"
-#define CONFIG_DEFLATE_MIMETYPES "deflate.mimetypes"
-#define CONFIG_DEFLATE_COMPRESSION_LEVEL "deflate.compression-level"
-#define CONFIG_DEFLATE_MEM_LEVEL "deflate.mem-level"
-#define CONFIG_DEFLATE_WINDOW_SIZE "deflate.window-size"
-#define CONFIG_DEFLATE_MIN_COMPRESS_SIZE "deflate.min-compress-size"
-#define CONFIG_DEFLATE_WORK_BLOCK_SIZE "deflate.work-block-size"
-#define CONFIG_DEFLATE_ENABLED "deflate.enabled"
-#define CONFIG_DEFLATE_DEBUG "deflate.debug"
-#define CONFIG_DEFLATE_ALLOWED_ENCODINGS "deflate.allowed_encodings"
-#define CONFIG_DEFLATE_SYNC_FLUSH "deflate.sync-flush"
-
-#define KByte * 1024
-#define MByte * 1024 KByte
-#define GByte * 1024 MByte
-
-typedef struct {
- unsigned short debug;
- unsigned short enabled;
- unsigned short sync_flush;
- unsigned short output_buffer_size;
- unsigned short min_compress_size;
- unsigned short work_block_size;
- int allowed_encodings;
- short mem_level;
- short compression_level;
- short window_size;
- array *mimetypes;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
- buffer *tmp_buf;
- array *encodings_arr;
-
- plugin_config **config_storage;
- plugin_config conf;
-} plugin_data;
-
-typedef struct {
- off_t bytes_in;
- filter *fl;
- chunkqueue *in;
- chunkqueue *out;
- buffer *output;
- /* compression type & state */
- int compression_type;
- int stream_open;
-#ifdef USE_ZLIB
- unsigned long crc;
- z_stream z;
- unsigned short gzip_header;
-#endif
-#ifdef USE_BZ2LIB
- bz_stream bz;
-#endif
- plugin_data *plugin_data;
-} handler_ctx;
-
-static handler_ctx *handler_ctx_init() {
- handler_ctx *hctx;
-
- hctx = calloc(1, sizeof(*hctx));
- hctx->in = NULL;
- hctx->out = NULL;
-
- return hctx;
-}
-
-static void handler_ctx_free(handler_ctx *hctx) {
- free(hctx);
-}
-
-INIT_FUNC(mod_deflate_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
- p->encodings_arr = array_init();
-
- return p;
-}
-
-FREE_FUNC(mod_deflate_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->mimetypes);
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->tmp_buf);
- array_free(p->encodings_arr);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_deflate_setdefaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { CONFIG_DEFLATE_OUTPUT_BUFFER_SIZE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_MIMETYPES, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_COMPRESSION_LEVEL, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_MEM_LEVEL, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_WINDOW_SIZE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_MIN_COMPRESS_SIZE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_WORK_BLOCK_SIZE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_ENABLED, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_DEBUG, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_SYNC_FLUSH, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
- { CONFIG_DEFLATE_ALLOWED_ENCODINGS, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- array_reset(p->encodings_arr);
-
- s = calloc(1, sizeof(plugin_config));
- s->enabled = 1;
- s->sync_flush = 0;
- s->allowed_encodings = 0;
- s->debug = 0;
- s->output_buffer_size = 0;
- s->mem_level = 9;
- s->window_size = 15;
- s->min_compress_size = 0;
- s->work_block_size = 2048;
- s->compression_level = -1;
- s->mimetypes = array_init();
-
- cv[0].destination = &(s->output_buffer_size);
- cv[1].destination = s->mimetypes;
- cv[2].destination = &(s->compression_level);
- cv[3].destination = &(s->mem_level);
- cv[4].destination = &(s->window_size);
- cv[5].destination = &(s->min_compress_size);
- cv[6].destination = &(s->work_block_size);
- cv[7].destination = &(s->enabled);
- cv[8].destination = &(s->debug);
- cv[9].destination = &(s->sync_flush);
- cv[10].destination = p->encodings_arr; /* temp array for allowed encodings list */
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (p->encodings_arr->used) {
- size_t j = 0;
- for (j = 0; j < p->encodings_arr->used; j++) {
- data_string *ds = (data_string *)p->encodings_arr->data[j];
-#ifdef USE_ZLIB
- if (NULL != strstr(BUF_STR(ds->value), ENCODING_NAME_GZIP))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
- if (NULL != strstr(BUF_STR(ds->value), ENCODING_NAME_DEFLATE))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
-#endif
- /*
- if (NULL != strstr(BUF_STR(ds->value), ENCODING_NAME_COMPRESS))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_COMPRESS;
- */
-#ifdef USE_BZ2LIB
- if (NULL != strstr(BUF_STR(ds->value), ENCODING_NAME_BZIP2))
- s->allowed_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
-#endif
- }
- } else {
- /* default encodings */
- s->allowed_encodings = HTTP_ACCEPT_ENCODING_IDENTITY | HTTP_ACCEPT_ENCODING_GZIP |
- HTTP_ACCEPT_ENCODING_DEFLATE | HTTP_ACCEPT_ENCODING_COMPRESS | HTTP_ACCEPT_ENCODING_BZIP2;
- }
-
- if((s->compression_level < 1 || s->compression_level > 9) &&
- s->compression_level != -1) {
- ERROR("compression-level must be between 1 and 9: %i", s->compression_level);
- return HANDLER_ERROR;
- }
-
- if(s->mem_level < 1 || s->mem_level > 9) {
- ERROR("mem-level must be between 1 and 9: %i", s->mem_level);
- return HANDLER_ERROR;
- }
-
- if(s->window_size < 1 || s->window_size > 15) {
- ERROR("window-size must be between 1 and 15: %i", s->window_size);
- return HANDLER_ERROR;
- }
- s->window_size = 0 - s->window_size;
-
- if(s->sync_flush) {
- s->output_buffer_size = 0;
- }
- }
-
- return HANDLER_GO_ON;
-
-}
-
-#ifdef USE_ZLIB
-/* Copied gzip_header from apache 2.2's mod_deflate.c */
-/* RFC 1952 Section 2.3 defines the gzip header:
- *
- * +---+---+---+---+---+---+---+---+---+---+
- * |ID1|ID2|CM |FLG| MTIME |XFL|OS |
- * +---+---+---+---+---+---+---+---+---+---+
- */
-static const char gzip_header[10] =
-{ '\037', '\213', Z_DEFLATED, 0,
- 0, 0, 0, 0, /* mtime */
- 0, 0x03 /* Unix OS_CODE */
-};
-static int stream_deflate_init(server *srv, connection *con, handler_ctx *hctx) {
- plugin_data *p = hctx->plugin_data;
- z_stream *z;
- int r, compression_level;
-
- UNUSED(srv);
- UNUSED(con);
-
- z = &(hctx->z);
- z->zalloc = Z_NULL;
- z->zfree = Z_NULL;
- z->opaque = Z_NULL;
- z->total_in = 0;
- z->total_out = 0;
- z->next_out = NULL;
- z->avail_out = 0;
-
- compression_level = p->conf.compression_level;
- if(compression_level == -1)
- compression_level = Z_DEFAULT_COMPRESSION;
-
- if(p->conf.debug) {
- TRACE("output-buffer-size: %i", p->conf.output_buffer_size);
- TRACE("compression-level: %i", compression_level);
- TRACE("mem-level: %i", p->conf.mem_level);
- TRACE("window-size: %i", p->conf.window_size);
- TRACE("min-compress-size: %i", p->conf.min_compress_size);
- TRACE("work-block-size: %i", p->conf.work_block_size);
- }
- if (Z_OK != (r = deflateInit2(z,
- compression_level,
- Z_DEFLATED,
- p->conf.window_size, /* supress zlib-header */
- p->conf.mem_level,
- Z_DEFAULT_STRATEGY))) {
- ERROR("deflateInit2() failed with %d", r);
- return -1;
- }
- hctx->stream_open = 1;
-
- return 0;
-}
-
-static int stream_deflate_compress(server *srv, connection *con, handler_ctx *hctx, unsigned char *start, off_t st_size) {
- plugin_data *p = hctx->plugin_data;
- z_stream *z;
- int len;
- int in = 0, out = 0;
-
- UNUSED(srv);
- UNUSED(con);
-
- z = &(hctx->z);
-
- if(z->next_out == NULL) {
- z->next_out = (unsigned char *)hctx->output->ptr;
- z->avail_out = hctx->output->size;
- }
-
- if(hctx->compression_type == HTTP_ACCEPT_ENCODING_GZIP) {
- if(hctx->gzip_header == 0) {
- hctx->gzip_header = 1;
- /* copy gzip header into output buffer */
- buffer_copy_memory(hctx->output, gzip_header, sizeof(gzip_header));
- if(p->conf.debug) {
- TRACE("gzip_header len=%zu", sizeof(gzip_header));
- }
- /* initialize crc32 */
- hctx->crc = crc32(0L, Z_NULL, 0);
- z->next_out = (unsigned char *)(hctx->output->ptr + sizeof(gzip_header));
- z->avail_out = hctx->output->size - sizeof(gzip_header);
- }
- hctx->crc = crc32(hctx->crc, start, st_size);
- }
-
- z->next_in = start;
- z->avail_in = st_size;
- hctx->bytes_in += st_size;
-
- /* compress data */
- in = z->avail_in;
- do {
- if (Z_OK != deflate(z, Z_NO_FLUSH)) {
- deflateEnd(z);
- hctx->stream_open = 0;
- return -1;
- }
-
- if(z->avail_out == 0 || z->avail_in > 0) {
- len = hctx->output->size - z->avail_out;
- out += len;
- chunkqueue_append_mem(hctx->out, hctx->output->ptr, len);
- hctx->out->bytes_in += len;
- z->next_out = (unsigned char *)hctx->output->ptr;
- z->avail_out = hctx->output->size;
- }
- } while (z->avail_in > 0);
-
- if(p->conf.debug) {
- TRACE("compress: in=%i, out=%i", in, out);
- }
- return st_size;
-}
-
-static int stream_deflate_flush(server *srv, connection *con, handler_ctx *hctx, int end) {
- plugin_data *p = hctx->plugin_data;
- z_stream *z;
- int len;
- int rc = 0;
- int done;
- int flush = 1;
- int in = 0, out = 0;
-
- UNUSED(srv);
- UNUSED(con);
-
- z = &(hctx->z);
-
- if(z->next_out == NULL) {
- z->next_out = (unsigned char *)hctx->output->ptr;
- z->avail_out = hctx->output->size;
- }
- /* compress data */
- in = z->avail_in;
- do {
- done = 1;
- if(end) {
- rc = deflate(z, Z_FINISH);
- if (rc == Z_OK) {
- done = 0;
- } else if (rc != Z_STREAM_END) {
- deflateEnd(z);
- hctx->stream_open = 0;
- return -1;
- }
- } else {
- if(p->conf.sync_flush) {
- rc = deflate(z, Z_SYNC_FLUSH);
- } else if(z->avail_in > 0) {
- if(p->conf.output_buffer_size > 0) flush = 0;
- rc = deflate(z, Z_NO_FLUSH);
- } else {
- if(p->conf.output_buffer_size > 0) flush = 0;
- rc = Z_OK;
- }
- if (rc != Z_OK) {
- deflateEnd(z);
- hctx->stream_open = 0;
- return -1;
- }
- }
-
- len = hctx->output->size - z->avail_out;
- if(z->avail_out == 0 || (flush && len > 0)) {
- out += len;
- chunkqueue_append_mem(hctx->out, hctx->output->ptr, len);
- hctx->out->bytes_in += len;
- z->next_out = (unsigned char *)hctx->output->ptr;
- z->avail_out = hctx->output->size;
- }
- } while (z->avail_in != 0 || !done);
-
-
- if(p->conf.debug) {
- TRACE("flush: in=%i, out=%i", in, out);
- }
- if(p->conf.sync_flush) {
- z->next_out = NULL;
- z->avail_out = 0;
- }
- return 0;
-}
-
-static int stream_deflate_end(server *srv, connection *con, handler_ctx *hctx) {
- plugin_data *p = hctx->plugin_data;
- z_stream *z;
- int rc;
-
- UNUSED(srv);
- UNUSED(con);
-
- z = &(hctx->z);
- if(!hctx->stream_open) return 0;
- hctx->stream_open = 0;
-
- if(hctx->compression_type == HTTP_ACCEPT_ENCODING_GZIP && (hctx->gzip_header)) {
- /* write gzip footer */
- unsigned char c[8];
-
- c[0] = (hctx->crc >> 0) & 0xff;
- c[1] = (hctx->crc >> 8) & 0xff;
- c[2] = (hctx->crc >> 16) & 0xff;
- c[3] = (hctx->crc >> 24) & 0xff;
- c[4] = (z->total_in >> 0) & 0xff;
- c[5] = (z->total_in >> 8) & 0xff;
- c[6] = (z->total_in >> 16) & 0xff;
- c[7] = (z->total_in >> 24) & 0xff;
- /* append footer to write_queue */
- chunkqueue_append_mem(hctx->out, (char *)c, 8);
- hctx->out->bytes_in += 8;
- if(p->conf.debug) {
- TRACE("gzip_footer len=%i", 8);
- }
- }
-
- if ((rc = deflateEnd(z)) != Z_OK) {
- if(rc == Z_DATA_ERROR) return 0;
- if(z->msg != NULL) {
- ERROR("deflateEnd error ret=%i, msg='%s'", rc, z->msg);
- } else {
- ERROR("deflateEnd error ret=%i", rc);
- }
- return -1;
- }
- return 0;
-}
-
-#endif
-
-#ifdef USE_BZ2LIB
-static int stream_bzip2_init(server *srv, connection *con, handler_ctx *hctx) {
- plugin_data *p = hctx->plugin_data;
- bz_stream *bz;
- int compression_level;
-
- UNUSED(srv);
- UNUSED(con);
-
- bz = &(hctx->bz);
- bz->bzalloc = NULL;
- bz->bzfree = NULL;
- bz->opaque = NULL;
- bz->total_in_lo32 = 0;
- bz->total_in_hi32 = 0;
- bz->total_out_lo32 = 0;
- bz->total_out_hi32 = 0;
-
- compression_level = p->conf.compression_level;
- if(compression_level == -1)
- compression_level = 9;
-
- if(p->conf.debug) {
- TRACE("output-buffer-size: %i", p->conf.output_buffer_size);
- TRACE("compression-level: %i", compression_level);
- TRACE("mem-level: %i", p->conf.mem_level);
- TRACE("window-size: %i", p->conf.window_size);
- TRACE("min-compress-size: %i", p->conf.min_compress_size);
- TRACE("work-block-size: %i", p->conf.work_block_size);
- }
- if (BZ_OK != BZ2_bzCompressInit(bz,
- compression_level, /* blocksize */
- 0, /* no output */
- 30)) { /* workFactor: default */
- return -1;
- }
- hctx->stream_open = 1;
-
- return 0;
-}
-
-static int stream_bzip2_compress(server *srv, connection *con, handler_ctx *hctx, unsigned char *start, off_t st_size) {
- plugin_data *p = hctx->plugin_data;
- bz_stream *bz;
- int len;
- int rc;
- int in = 0, out = 0;
-
- UNUSED(srv);
- UNUSED(con);
-
- bz = &(hctx->bz);
-
- if(bz->next_out == NULL) {
- bz->next_out = hctx->output->ptr;
- bz->avail_out = hctx->output->size;
- }
-
- bz->next_in = (char *)start;
- bz->avail_in = st_size;
- hctx->bytes_in += st_size;
-
- /* compress data */
- in = bz->avail_in;
- do {
- rc = BZ2_bzCompress(bz, BZ_RUN);
- if (rc != BZ_RUN_OK) {
- BZ2_bzCompressEnd(bz);
- hctx->stream_open = 0;
- return -1;
- }
-
- if(bz->avail_out == 0 || bz->avail_in > 0) {
- len = hctx->output->size - bz->avail_out;
- out += len;
- chunkqueue_append_mem(hctx->out, hctx->output->ptr, len);
- hctx->out->bytes_in += len;
- bz->next_out = hctx->output->ptr;
- bz->avail_out = hctx->output->size;
- }
- } while (bz->avail_in > 0);
- if(p->conf.debug) {
- TRACE("compress: in=%i, out=%i", in, out);
- }
- return st_size;
-}
-
-static int stream_bzip2_flush(server *srv, connection *con, handler_ctx *hctx, int end) {
- plugin_data *p = hctx->plugin_data;
- bz_stream *bz;
- int len;
- int rc;
- int done;
- int flush = 1;
- int in = 0, out = 0;
-
- UNUSED(srv);
- UNUSED(con);
-
- bz = &(hctx->bz);
-
- if(bz->next_out == NULL) {
- bz->next_out = hctx->output->ptr;
- bz->avail_out = hctx->output->size;
- }
- /* compress data */
- in = bz->avail_in;
- do {
- done = 1;
- if(end) {
- rc = BZ2_bzCompress(bz, BZ_FINISH);
- if (rc == BZ_FINISH_OK) {
- done = 0;
- } else if (rc != BZ_STREAM_END) {
- BZ2_bzCompressEnd(bz);
- hctx->stream_open = 0;
- return -1;
- }
- } else if(bz->avail_in > 0) {
- rc = BZ2_bzCompress(bz, BZ_RUN);
- if (rc != BZ_RUN_OK) {
- BZ2_bzCompressEnd(bz);
- hctx->stream_open = 0;
- return -1;
- }
- if(p->conf.output_buffer_size > 0) flush = 0;
- }
-
- len = hctx->output->size - bz->avail_out;
- if(bz->avail_out == 0 || (flush && len > 0)) {
- out += len;
- chunkqueue_append_mem(hctx->out, hctx->output->ptr, len);
- hctx->out->bytes_in += len;
- bz->next_out = hctx->output->ptr;
- bz->avail_out = hctx->output->size;
- }
- } while (bz->avail_in != 0 || !done);
- if(p->conf.debug) {
- TRACE("flush: in=%i, out=%i", in, out);
- }
- if(p->conf.sync_flush) {
- bz->next_out = NULL;
- bz->avail_out = 0;
- }
- return 0;
-}
-
-static int stream_bzip2_end(server *srv, connection *con, handler_ctx *hctx) {
- plugin_data *p = hctx->plugin_data;
- bz_stream *bz;
- int rc;
-
- UNUSED(p);
- UNUSED(srv);
- UNUSED(con);
-
- bz = &(hctx->bz);
- if(!hctx->stream_open) return 0;
- hctx->stream_open = 0;
-
- if ((rc = BZ2_bzCompressEnd(bz)) != BZ_OK) {
- if(rc == BZ_DATA_ERROR) return 0;
- ERROR("BZ2_bzCompressEnd error ret=%i", rc);
- return -1;
- }
- return 0;
-}
-
-#endif
-
-static int mod_deflate_compress(server *srv, connection *con, handler_ctx *hctx, unsigned char *start, off_t st_size) {
- int ret = -1;
- if(st_size == 0) return 0;
- switch(hctx->compression_type) {
-#ifdef USE_ZLIB
- case HTTP_ACCEPT_ENCODING_GZIP:
- case HTTP_ACCEPT_ENCODING_DEFLATE:
- ret = stream_deflate_compress(srv, con, hctx, start, st_size);
- break;
-#endif
-#ifdef USE_BZ2LIB
- case HTTP_ACCEPT_ENCODING_BZIP2:
- ret = stream_bzip2_compress(srv, con, hctx, start, st_size);
- break;
-#endif
- default:
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-static int mod_deflate_stream_flush(server *srv, connection *con, handler_ctx *hctx, int end) {
- int ret = -1;
-
- if(hctx->bytes_in == 0) return 0;
- switch(hctx->compression_type) {
-#ifdef USE_ZLIB
- case HTTP_ACCEPT_ENCODING_GZIP:
- case HTTP_ACCEPT_ENCODING_DEFLATE:
- ret = stream_deflate_flush(srv, con, hctx, end);
- break;
-#endif
-#ifdef USE_BZ2LIB
- case HTTP_ACCEPT_ENCODING_BZIP2:
- ret = stream_bzip2_flush(srv, con, hctx, end);
- break;
-#endif
- default:
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-static int mod_deflate_stream_end(server *srv, connection *con, handler_ctx *hctx) {
- int ret = -1;
- switch(hctx->compression_type) {
-#ifdef USE_ZLIB
- case HTTP_ACCEPT_ENCODING_GZIP:
- case HTTP_ACCEPT_ENCODING_DEFLATE:
- ret = stream_deflate_end(srv, con, hctx);
- break;
-#endif
-#ifdef USE_BZ2LIB
- case HTTP_ACCEPT_ENCODING_BZIP2:
- ret = stream_bzip2_end(srv, con, hctx);
- break;
-#endif
- default:
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-static int mod_deflate_file_chunk(server *srv, connection *con, handler_ctx *hctx, chunk *c, off_t st_size) {
- plugin_data *p = hctx->plugin_data;
- off_t abs_offset;
- off_t toSend;
- stat_cache_entry *sce = NULL;
- size_t we_want_to_mmap = 2 MByte;
- size_t we_want_to_send = st_size;
- char *start = NULL;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- ERROR("stat_cache_get_entry('%s') failed: %s",
- SAFE_BUF_STR(c->file.name), strerror(errno));
- return -1;
- }
-
- abs_offset = c->file.start + c->offset;
-
- if (c->file.length + c->file.start > sce->st.st_size) {
- ERROR("file '%s' was shrinked: was %ju, is %ju (%ju, %ju)",
- SAFE_BUF_STR(c->file.name), (intmax_t) c->file.length + c->file.start, (intmax_t) sce->st.st_size,
- (intmax_t) c->file.start, (intmax_t) c->offset);
-
- return -1;
- }
-
- we_want_to_send = st_size;
- /* mmap the buffer
- * - first mmap
- * - new mmap as the we are at the end of the last one */
- if (c->file.mmap.start == MAP_FAILED ||
- abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
-
- /* Optimizations for the future:
- *
- * adaptive mem-mapping
- * the problem:
- * we mmap() the whole file. If someone has alot large files and 32bit
- * machine the virtual address area will be unrun and we will have a failing
- * mmap() call.
- * solution:
- * only mmap 16M in one chunk and move the window as soon as we have finished
- * the first 8M
- *
- * read-ahead buffering
- * the problem:
- * sending out several large files in parallel trashes the read-ahead of the
- * kernel leading to long wait-for-seek times.
- * solutions: (increasing complexity)
- * 1. use madvise
- * 2. use a internal read-ahead buffer in the chunk-structure
- * 3. use non-blocking IO for file-transfers
- * */
-
- /* all mmap()ed areas are 512kb expect the last which might be smaller */
- size_t to_mmap;
-
- /* this is a remap, move the mmap-offset */
- if (c->file.mmap.start != MAP_FAILED) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.offset += we_want_to_mmap;
- } else {
- /* in case the range-offset is after the first mmap()ed area we skip the area */
- c->file.mmap.offset = 0;
-
- while (c->file.mmap.offset + (off_t) we_want_to_mmap < c->file.start) {
- c->file.mmap.offset += we_want_to_mmap;
- }
- }
-
- /* length is rel, c->offset too, assume there is no limit at the mmap-boundaries */
- to_mmap = (c->file.start + c->file.length) - c->file.mmap.offset;
- if(to_mmap > we_want_to_mmap) to_mmap = we_want_to_mmap;
- /* we have more to send than we can mmap() at once */
- if(we_want_to_send > to_mmap) we_want_to_send = to_mmap;
-
- if (-1 == c->file.fd) { /* open the file if not already open */
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
- ERROR("open failed for '%s': %s", SAFE_BUF_STR(c->file.name), strerror(errno));
- return -1;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
- }
-
- if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
- /* close it here, otherwise we'd have to set FD_CLOEXEC */
-
- ERROR("mmap failed for '%s' (%i): %s", SAFE_BUF_STR(c->file.name), c->file.fd, strerror(errno));
- return -1;
- }
-
- c->file.mmap.length = to_mmap;
-#ifdef LOCAL_BUFFERING
- buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
-#else
-#ifdef HAVE_MADVISE
- /* don't advise files < 64Kb */
- if (c->file.mmap.length > (64 KByte) &&
- 0 != madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED)) {
- ERROR("madvise failed for '%s' (%i): %s", SAFE_BUF_STR(c->file.name), c->file.fd, strerror(errno));
- }
-#endif
-#endif
-
- /* chunk_reset() or chunk_free() will cleanup for us */
- }
-
- /* to_send = abs_mmap_end - abs_offset */
- toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
- if (toSend > (off_t) we_want_to_send) toSend = we_want_to_send;
-
- if (toSend < 0) {
- ERROR("toSend is negative: %u %u %u %u",
- (unsigned int) toSend,
- (unsigned int) c->file.mmap.length,
- (unsigned int) abs_offset,
- (unsigned int) c->file.mmap.offset);
- assert(toSend < 0);
- }
-
-#ifdef LOCAL_BUFFERING
- start = c->mem->ptr;
-#else
- start = c->file.mmap.start;
-#endif
-
- if(p->conf.debug) {
- TRACE("compress file chunk: offset=%i, toSend=%i", (int)c->offset, (int)toSend);
- }
- if (mod_deflate_compress(srv, con, hctx,
- (unsigned char *)start + (abs_offset - c->file.mmap.offset), toSend) < 0) {
- ERROR("%s", "compress failed.");
- return -1;
- }
-
- return toSend;
-}
-
-static int deflate_compress_cleanup(server *srv, connection *con, handler_ctx *hctx) {
- plugin_data *p = hctx->plugin_data;
- int rc;
-
- rc = mod_deflate_stream_end(srv, con, hctx);
- if(rc < 0) {
- TRACE("error closing compressed stream for '%s', compressing with %d: %d",
- SAFE_BUF_STR(con->uri.path_raw), hctx->compression_type, rc);
- }
-
- if(p->conf.debug && hctx->bytes_in < hctx->out->bytes_in) {
- TRACE("compressing uri '%s' increased the sent content-size from %jd to %jd",
- SAFE_BUF_STR(con->uri.path_raw), (intmax_t) hctx->bytes_in, (intmax_t) hctx->out->bytes_in);
- }
-
- /* cleanup compression state */
- if(hctx->output != p->tmp_buf) {
- buffer_free(hctx->output);
- }
- handler_ctx_free(hctx);
- con->plugin_ctx[p->id] = NULL;
-
- return 0;
-}
-
-/**
- * compress the in queue and move the content to the out queue
- *
- */
-static handler_t deflate_compress_response(server *srv, connection *con, handler_ctx *hctx, int end) {
- plugin_data *p = hctx->plugin_data;
- chunk *c;
- size_t chunks_written = 0;
- int chunk_finished = 0;
- int rc=-1;
- int we_want = 0, we_have = 0;
- int out = 0, max = 0;
-
- we_have = chunkqueue_length(hctx->in);
- if (p->conf.debug) {
- TRACE("compress: in_queue len=%i", we_have);
- }
- /* calculate max bytes to compress for this call. */
- if (!end) {
- max = p->conf.work_block_size * 1024;
- if(max == 0 || max > we_have) max = we_have;
- } else {
- max = we_have;
- }
-
- /* Compress chunks from in queue into chunks for out queue */
- for (c = hctx->in->first; c && max > 0; c = c->next) {
- chunk_finished = 0;
- we_have = 0;
- we_want = 0;
-
- switch(c->type) {
- case MEM_CHUNK:
- if (c->mem->used == 0) continue;
-
- we_have = c->mem->used - c->offset - 1;
- if (we_have == 0) continue;
-
- we_want = we_have < max ? we_have : max;
-
- if (mod_deflate_compress(srv, con, hctx, (unsigned char *)(c->mem->ptr + c->offset), we_want) < 0) {
- ERROR("%s", "compress failed.");
- return HANDLER_ERROR;
- }
-
- break;
- case FILE_CHUNK:
- if (c->file.length == 0) continue;
-
- we_have = c->file.length - c->offset;
- if (we_have == 0) continue;
-
- we_want = we_have < max ? we_have : max;
-
- if ((we_want = mod_deflate_file_chunk(srv, con, hctx, c, we_want)) < 0) {
- ERROR("%s", "compress file chunk failed.");
- return HANDLER_ERROR;
- }
-
- break;
- default:
- ERROR("type not known: %d", c->type);
-
- return HANDLER_ERROR;
- }
-
- hctx->in->bytes_out += we_want;
- c->offset += we_want;
- out += we_want;
- max -= we_want;
-
- if (c->type == FILE_CHUNK &&
- c->offset == c->file.length &&
- c->file.mmap.start != MAP_FAILED) {
- /* we don't need the mmaping anymore */
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
- }
-
- if (we_have == we_want) {
- /* chunk finished */
- chunk_finished = 1;
- chunks_written++;
- }
- /* make sure we finished compressing the chunk before going to the next chunk */
- if(!chunk_finished) break;
- }
-
- if (p->conf.debug) {
- TRACE("compressed bytes: %i", out);
- }
-
- if (chunks_written > 0) {
- chunkqueue_remove_finished_chunks(hctx->in);
- }
-
- /* check if we finished compressing all the content. */
- end = (hctx->in->is_closed && hctx->in->bytes_in == hctx->in->bytes_out);
-
- if (p->conf.debug) {
- TRACE("end: %d - %jd - %jd", hctx->in->is_closed, (intmax_t) hctx->in->bytes_in, (intmax_t) hctx->in->bytes_out);
- }
-
- /* flush the output buffer to make room for more data. */
- rc = mod_deflate_stream_flush(srv, con, hctx, end);
-
- if (rc < 0) {
- ERROR("%s", "flush error");
- }
-
- if (end) {
- hctx->out->is_closed = 1;
- if(p->conf.debug) {
- TRACE("finished uri: '%s', query: '%s'", SAFE_BUF_STR(con->uri.path_raw), SAFE_BUF_STR(con->uri.query));
- }
- } else if (hctx->in->first) {
- /* We have more data to compress. */
- joblist_append(srv, con);
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_deflate_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(output_buffer_size);
- PATCH_OPTION(mimetypes);
- PATCH_OPTION(compression_level);
- PATCH_OPTION(mem_level);
- PATCH_OPTION(window_size);
- PATCH_OPTION(min_compress_size);
- PATCH_OPTION(work_block_size);
- PATCH_OPTION(enabled);
- PATCH_OPTION(debug);
- PATCH_OPTION(allowed_encodings);
- PATCH_OPTION(sync_flush);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_OUTPUT_BUFFER_SIZE))) {
- PATCH_OPTION(output_buffer_size);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_MIMETYPES))) {
- PATCH_OPTION(mimetypes);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_COMPRESSION_LEVEL))) {
- PATCH_OPTION(compression_level);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_MEM_LEVEL))) {
- PATCH_OPTION(mem_level);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_WINDOW_SIZE))) {
- PATCH_OPTION(window_size);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_MIN_COMPRESS_SIZE))) {
- PATCH_OPTION(min_compress_size);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_WORK_BLOCK_SIZE))) {
- PATCH_OPTION(work_block_size);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_ENABLED))) {
- PATCH_OPTION(enabled);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_DEBUG))) {
- PATCH_OPTION(debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_ALLOWED_ENCODINGS))) {
- PATCH_OPTION(allowed_encodings);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEFLATE_SYNC_FLUSH))) {
- PATCH_OPTION(sync_flush);
- }
- }
- }
-
- return 0;
-}
-
-PHYSICALPATH_FUNC(mod_deflate_handle_response_header) {
- plugin_data *p = p_d;
- handler_ctx *hctx;
- filter *fl;
- chunkqueue *in;
- data_string *ds;
- int accept_encoding = 0;
- char *value;
- int matched_encodings = 0;
- const char *compression_name = NULL;
- int file_len=0;
- int rc=-2;
- int end = 0;
- size_t m;
-
- /* disable compression for some http status types. */
- switch(con->http_status) {
- case 100:
- case 101:
- case 204:
- case 205:
- case 304:
- /* disable compression as we have no response entity */
- return HANDLER_GO_ON;
- default:
- break;
- }
-
- mod_deflate_patch_connection(srv, con, p);
-
- /* is compression allowed */
- if(!p->conf.enabled) {
- if(p->conf.debug) {
- TRACE("%s", "compression disabled.");
- }
- return HANDLER_GO_ON;
- }
-
- /* Check if response has a Content-Encoding. */
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, CONST_STR_LEN("Content-Encoding")))) {
- return HANDLER_GO_ON;
- }
-
- /* Check Accept-Encoding for supported encoding. */
- if (NULL == (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Accept-Encoding")))) {
- return HANDLER_GO_ON;
- }
-
- /* get client side support encodings */
- value = ds->value->ptr;
-#ifdef USE_ZLIB
- if (NULL != strstr(value, ENCODING_NAME_GZIP)) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
- if (NULL != strstr(value, ENCODING_NAME_DEFLATE)) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
-#endif
- /* if (NULL != strstr(value, ENCODING_NAME_COMPRESS)) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS; */
-#ifdef USE_BZ2LIB
- if (NULL != strstr(value, ENCODING_NAME_BZIP2)) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
-#endif
- if (NULL != strstr(value, ENCODING_NAME_IDENTITY)) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
-
- /* find matching encodings */
- matched_encodings = accept_encoding & p->conf.allowed_encodings;
- if (!matched_encodings) {
- return HANDLER_GO_ON;
- }
-
-#if 0
- /* TODO: add option to disable compression for HTTP 1.0 clients. */
- if (con->request.true_http_10_client) {
- /*disable gzip/bzip2 when we meet HTTP 1.0 client with Accept-Encoding
- * maybe old buggy proxy server
- */
- /* most of buggy clients are Yahoo Slurp;) */
- if (p->conf.debug) TRACE("Buggy HTTP 1.0 client sending 'Accept Encoding: gzip, deflate': %i",
- (char *) inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
- return HANDLER_GO_ON;
- }
-#endif
-
- /* get filter. */
- fl = filter_chain_get_filter(con->send_filters, p->id);
- if (!fl) {
- if(p->conf.debug) TRACE("%s", "add deflate filter to filter chain");
- fl = filter_chain_create_filter(con->send_filters, p->id);
- }
- /* get our input and output chunkqueues. */
- if (!fl || !fl->prev) {
- filter_chain_remove_filter(con->send_filters, fl);
- return HANDLER_GO_ON;
- }
- in = fl->prev->cq;
-
- /* check if size of response is below min-compress-size */
- if(in->is_closed && con->request.http_method != HTTP_METHOD_HEAD) {
- file_len = chunkqueue_length(in);
- if(file_len == 0) {
- filter_chain_remove_filter(con->send_filters, fl);
- return HANDLER_GO_ON;
- }
- } else {
- file_len = 0;
- }
-
- if(file_len > 0 && p->conf.min_compress_size > 0 && file_len < p->conf.min_compress_size) {
- if(p->conf.debug) {
- TRACE("Content-Length smaller then min_compress_size: file_len=%i", file_len);
- }
- filter_chain_remove_filter(con->send_filters, fl);
- return HANDLER_GO_ON;
- }
-
- /* Check mimetype in response header "Content-Type" */
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, CONST_STR_LEN("Content-Type")))) {
- int found = 0;
- if(p->conf.debug) {
- TRACE("Content-Type: %s", SAFE_BUF_STR(ds->value));
- }
- for (m = 0; m < p->conf.mimetypes->used; m++) {
- data_string *mimetype = (data_string *)p->conf.mimetypes->data[m];
-
- if(p->conf.debug) {
- TRACE("mime-type: %s", SAFE_BUF_STR(mimetype->value));
- }
- if (strncmp(mimetype->value->ptr, ds->value->ptr, mimetype->value->used-1) == 0) {
- /* mimetype found */
- found = 1;
- break;
- }
- }
- if(!found && p->conf.mimetypes->used > 0) {
- if(p->conf.debug) {
- TRACE("No compression for mimetype: %s", SAFE_BUF_STR(ds->value));
- }
- filter_chain_remove_filter(con->send_filters, fl);
- return HANDLER_GO_ON;
- }
-#if 0
- if(strncasecmp(ds->value->ptr, "application/x-javascript", 24) == 0) {
- /*reset compress type to deflate for javascript
- * prevent buggy IE6 SP1 doesn't work for js in IFrame
- */
- matched_encodings = HTTP_ACCEPT_ENCODING_DEFLATE;
- }
-#endif
- }
-
- /* the response might change according to Accept-Encoding */
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, CONST_STR_LEN("Vary")))) {
- /* append Accept-Encoding to Vary header */
- if (NULL == strstr(ds->value->ptr, "Accept-Encoding")) {
- buffer_append_string_len(ds->value, CONST_STR_LEN(",Accept-Encoding"));
- if (p->conf.debug) {
- TRACE("appending ,Accept-Encoding for '%s'", SAFE_BUF_STR(con->uri.path));
- }
- }
- } else {
- if (p->conf.debug) {
- TRACE("add Vary: Accept-Encoding for '%s'", SAFE_BUF_STR(con->uri.path));
- }
- response_header_insert(srv, con, CONST_STR_LEN("Vary"),
- CONST_STR_LEN("Accept-Encoding"));
- }
-
- /* enable compression */
- hctx = handler_ctx_init();
- hctx->plugin_data = p;
- hctx->fl = fl;
- hctx->in = fl->prev->cq;
- hctx->out = fl->cq;
-
- rc = -1;
-
- /* select best matching encoding */
- if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
-#ifdef USE_BZ2LIB
- hctx->compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
- compression_name = ENCODING_NAME_BZIP2;
- rc = stream_bzip2_init(srv, con, hctx);
-#endif
- } else if (matched_encodings & HTTP_ACCEPT_ENCODING_GZIP) {
-#ifdef USE_ZLIB
- hctx->compression_type = HTTP_ACCEPT_ENCODING_GZIP;
- compression_name = ENCODING_NAME_GZIP;
- rc = stream_deflate_init(srv, con, hctx);
- } else if (matched_encodings & HTTP_ACCEPT_ENCODING_DEFLATE) {
- hctx->compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
- compression_name = ENCODING_NAME_DEFLATE;
- rc = stream_deflate_init(srv, con, hctx);
-#endif
- } else if (matched_encodings & HTTP_ACCEPT_ENCODING_IDENTITY) {
- /* no compression */
- } else {
- ERROR("Failed to initialize compression for '%s' with compression = %s",
- SAFE_BUF_STR(con->uri.path),
- value);
- }
-
- if (rc == -1 && compression_name) {
- ERROR("Failed to initialize compression for '%s' with compression = %s",
- SAFE_BUF_STR(con->uri.path),
- compression_name);
- }
-
- if (rc < 0) {
- filter_chain_remove_filter(con->send_filters, hctx->fl);
- handler_ctx_free(hctx);
- return HANDLER_GO_ON;
- }
-
- if (p->conf.debug) {
- TRACE("compressing '%s' with compression = %s",
- SAFE_BUF_STR(con->uri.path),
- compression_name);
- }
-
- /* setup output buffer. */
- if(p->conf.sync_flush || p->conf.output_buffer_size == 0) {
- buffer_prepare_copy(p->tmp_buf, 32 * 1024);
- hctx->output = p->tmp_buf;
- } else {
- hctx->output = buffer_init();
- buffer_prepare_copy(hctx->output, p->conf.output_buffer_size);
- }
- con->plugin_ctx[p->id] = hctx;
-
- /* set Content-Encoding to show selected compression type. */
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
-
- /* clear old Content-Length */
- con->response.content_length = -1;
-
- if (hctx->in->is_closed &&
- (p->conf.work_block_size == 0 || file_len < (p->conf.work_block_size * 1024))
- && con->request.http_method != HTTP_METHOD_HEAD) {
- end = 1;
- if(p->conf.debug) {
- TRACE("Compress all content and use Content-Length header: uncompress len=%i", file_len);
- }
- }
-
- if (p->conf.debug)
- TRACE("end = %i for uri '%s'", end, SAFE_BUF_STR(con->uri.path));
-
- rc = deflate_compress_response(srv, con, hctx, end);
- /* check if we finished compressing all the content. */
- if (rc == HANDLER_GO_ON && hctx->out->is_closed) {
- con->response.content_length = chunkqueue_length(hctx->out);
-
- deflate_compress_cleanup(srv, con, hctx);
- }
-
- return rc;
-}
-
-CONNECTION_FUNC(mod_deflate_handle_filter_response_content) {
- plugin_data *p = p_d;
- handler_ctx *hctx = con->plugin_ctx[p->id];
- handler_t ret;
-
- if (hctx == NULL) return HANDLER_GO_ON;
- if (!hctx->stream_open) return HANDLER_GO_ON;
-
- /**
- * HEAD requests don't have a content body */
- if (con->request.http_method == HTTP_METHOD_HEAD) return HANDLER_GO_ON;
-
- /** compress the streams */
- ret = deflate_compress_response(srv, con, hctx, 0);
-
- if (ret == HANDLER_GO_ON && hctx->out->is_closed) {
- deflate_compress_cleanup(srv, con, hctx);
- }
-
- return ret;
-}
-
-static handler_t mod_deflate_cleanup(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
- handler_ctx *hctx = con->plugin_ctx[p->id];
-
- if(hctx == NULL) return HANDLER_GO_ON;
-
- if(p->conf.debug && hctx->stream_open) {
- TRACE("stream open at cleanup. uri='%s', query='%s'", SAFE_BUF_STR(con->uri.path_raw), SAFE_BUF_STR(con->uri.query));
- }
-
- deflate_compress_cleanup(srv, con, hctx);
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_deflate_plugin_init(plugin *p);
-LI_EXPORT int mod_deflate_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("deflate");
-
- p->init = mod_deflate_init;
- p->cleanup = mod_deflate_free;
- p->set_defaults = mod_deflate_setdefaults;
- p->connection_reset = mod_deflate_cleanup;
- p->handle_connection_close = mod_deflate_cleanup;
- p->handle_response_header = mod_deflate_handle_response_header;
- p->handle_filter_response_content = mod_deflate_handle_filter_response_content;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c
deleted file mode 100644
index 63f412dc..00000000
--- a/src/mod_dirlisting.c
+++ /dev/null
@@ -1,957 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "response.h"
-#include "stat_cache.h"
-#include "stream.h"
-#include "etag.h"
-
-#include "sys-strings.h"
-
-/**
- * this is a dirlisting for a lighttpd plugin
- */
-
-
-#ifdef HAVE_SYS_SYSLIMITS_H
-#include <sys/syslimits.h>
-#endif
-
-#ifdef HAVE_XATTR
-#include <attr/attributes.h>
-#endif
-
-#include "sys-files.h"
-#include "sys-strings.h"
-
-/* plugin config for all request/connections */
-
-typedef struct {
-#ifdef HAVE_PCRE_H
- pcre *regex;
-#endif
- buffer *string;
-} excludes;
-
-typedef struct {
- excludes **ptr;
-
- size_t used;
- size_t size;
-} excludes_buffer;
-
-typedef struct {
- unsigned short dir_listing;
- unsigned short hide_dot_files;
- unsigned short show_readme;
- unsigned short hide_readme_file;
- unsigned short show_header;
- unsigned short hide_header_file;
-
- excludes_buffer *excludes;
-
- buffer *external_css;
- buffer *encoding;
- buffer *set_footer;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *tmp_buf;
- buffer *content_charset;
- buffer *path;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-static excludes_buffer *excludes_buffer_init(void) {
- excludes_buffer *exb;
-
- exb = calloc(1, sizeof(*exb));
-
- return exb;
-}
-
-static int excludes_buffer_append(excludes_buffer *exb, buffer *string) {
-#ifdef HAVE_PCRE_H
- size_t i;
- const char *errptr;
- int erroff;
-
- if (!string) return -1;
-
- if (exb->size == 0) {
- exb->size = 4;
- exb->used = 0;
-
- exb->ptr = malloc(exb->size * sizeof(*exb->ptr));
-
- for(i = 0; i < exb->size ; i++) {
- exb->ptr[i] = calloc(1, sizeof(**exb->ptr));
- }
- } else if (exb->used == exb->size) {
- exb->size += 4;
-
- exb->ptr = realloc(exb->ptr, exb->size * sizeof(*exb->ptr));
-
- for(i = exb->used; i < exb->size; i++) {
- exb->ptr[i] = calloc(1, sizeof(**exb->ptr));
- }
- }
-
-
- if (NULL == (exb->ptr[exb->used]->regex = pcre_compile(string->ptr, 0,
- &errptr, &erroff, NULL))) {
- return -1;
- }
-
- exb->ptr[exb->used]->string = buffer_init();
- buffer_copy_string_buffer(exb->ptr[exb->used]->string, string);
-
- exb->used++;
-
- return 0;
-#else
- UNUSED(exb);
- UNUSED(string);
-
- return -1;
-#endif
-}
-
-static void excludes_buffer_free(excludes_buffer *exb) {
-#ifdef HAVE_PCRE_H
- size_t i;
-
- for (i = 0; i < exb->size; i++) {
- if (exb->ptr[i]->regex) pcre_free(exb->ptr[i]->regex);
- if (exb->ptr[i]->string) buffer_free(exb->ptr[i]->string);
- free(exb->ptr[i]);
- }
-
- if (exb->ptr) free(exb->ptr);
-#endif
-
- free(exb);
-}
-
-/* init the plugin data */
-INIT_FUNC(mod_dirlisting_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
- p->content_charset = buffer_init();
- p->path = buffer_init();
-
- return p;
-}
-
-/* destroy the plugin data */
-FREE_FUNC(mod_dirlisting_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- excludes_buffer_free(s->excludes);
- buffer_free(s->external_css);
- buffer_free(s->encoding);
- buffer_free(s->set_footer);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->tmp_buf);
- buffer_free(p->path);
- buffer_free(p->content_charset);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option) {
- data_unset *du;
-
- if (NULL != (du = array_get_element(ca, option, strlen(option)))) {
- data_array *da = (data_array *)du;
- size_t j;
-
- if (du->type != TYPE_ARRAY) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "unexpected type for key: ", option, "array of strings");
-
- return HANDLER_ERROR;
- }
-
- da = (data_array *)du;
-
- for (j = 0; j < da->value->used; j++) {
- if (da->value->data[j]->type != TYPE_STRING) {
- log_error_write(srv, __FILE__, __LINE__, "sssbs",
- "unexpected type for key: ", option, "[",
- da->value->data[j]->key, "](string)");
-
- return HANDLER_ERROR;
- }
-
- if (0 != excludes_buffer_append(s->excludes,
- ((data_string *)(da->value->data[j]))->value)) {
-#ifdef HAVE_PCRE_H
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
-#else
- log_error_write(srv, __FILE__, __LINE__, "s",
- "pcre support is missing, please install libpcre and the headers");
-#endif
- }
- }
- }
-
- return 0;
-}
-
-/* handle plugin config and check values */
-
-#define CONFIG_EXCLUDE "dir-listing.exclude"
-#define CONFIG_ACTIVATE "dir-listing.activate"
-#define CONFIG_HIDE_DOTFILES "dir-listing.hide-dotfiles"
-#define CONFIG_EXTERNAL_CSS "dir-listing.external-css"
-#define CONFIG_ENCODING "dir-listing.encoding"
-#define CONFIG_SHOW_README "dir-listing.show-readme"
-#define CONFIG_HIDE_README_FILE "dir-listing.hide-readme-file"
-#define CONFIG_SHOW_HEADER "dir-listing.show-header"
-#define CONFIG_HIDE_HEADER_FILE "dir-listing.hide-header-file"
-#define CONFIG_DIR_LISTING "server.dir-listing"
-#define CONFIG_SET_FOOTER "dir-listing.set-footer"
-
-
-SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { CONFIG_EXCLUDE, NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { CONFIG_ACTIVATE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { CONFIG_HIDE_DOTFILES, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { CONFIG_EXTERNAL_CSS, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { CONFIG_ENCODING, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
- { CONFIG_SHOW_README, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
- { CONFIG_HIDE_README_FILE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
- { CONFIG_SHOW_HEADER, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
- { CONFIG_HIDE_HEADER_FILE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
- { CONFIG_DIR_LISTING, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
- { CONFIG_SET_FOOTER, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
-
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- array *ca;
-
- s = calloc(1, sizeof(plugin_config));
- s->excludes = excludes_buffer_init();
- s->dir_listing = 0;
- s->external_css = buffer_init();
- s->hide_dot_files = 0;
- s->show_readme = 0;
- s->hide_readme_file = 0;
- s->show_header = 0;
- s->hide_header_file = 0;
- s->encoding = buffer_init();
- s->set_footer = buffer_init();
-
- cv[0].destination = s->excludes;
- cv[1].destination = &(s->dir_listing);
- cv[2].destination = &(s->hide_dot_files);
- cv[3].destination = s->external_css;
- cv[4].destination = s->encoding;
- cv[5].destination = &(s->show_readme);
- cv[6].destination = &(s->hide_readme_file);
- cv[7].destination = &(s->show_header);
- cv[8].destination = &(s->hide_header_file);
- cv[9].destination = &(s->dir_listing); /* old name */
- cv[10].destination = s->set_footer;
-
- p->config_storage[i] = s;
- ca = ((data_config *)srv->config_context->data[i])->value;
-
- if (0 != config_insert_values_global(srv, ca, cv)) {
- return HANDLER_ERROR;
- }
-
- parse_config_entry(srv, s, ca, CONFIG_EXCLUDE);
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(dir_listing);
- PATCH_OPTION(external_css);
- PATCH_OPTION(hide_dot_files);
- PATCH_OPTION(encoding);
- PATCH_OPTION(show_readme);
- PATCH_OPTION(hide_readme_file);
- PATCH_OPTION(show_header);
- PATCH_OPTION(hide_header_file);
- PATCH_OPTION(excludes);
- PATCH_OPTION(set_footer);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_ACTIVATE)) ||
- buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DIR_LISTING))) {
- PATCH_OPTION(dir_listing);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_HIDE_DOTFILES))) {
- PATCH_OPTION(hide_dot_files);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_EXTERNAL_CSS))) {
- PATCH_OPTION(external_css);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_ENCODING))) {
- PATCH_OPTION(encoding);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_SHOW_README))) {
- PATCH_OPTION(show_readme);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_HIDE_README_FILE))) {
- PATCH_OPTION(hide_readme_file);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_SHOW_HEADER))) {
- PATCH_OPTION(show_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_HIDE_HEADER_FILE))) {
- PATCH_OPTION(hide_header_file);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_SET_FOOTER))) {
- PATCH_OPTION(set_footer);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_EXCLUDE))) {
- PATCH_OPTION(excludes);
- }
- }
- }
-
- return 0;
-}
-
-typedef struct {
- size_t namelen;
- time_t mtime;
- off_t size;
-} dirls_entry_t;
-
-typedef struct {
- dirls_entry_t **ent;
- size_t used;
- size_t size;
-} dirls_list_t;
-
-#define DIRLIST_ENT_NAME(ent) ((char*)(ent) + sizeof(dirls_entry_t))
-#define DIRLIST_BLOB_SIZE 16
-
-/* simple combsort algorithm */
-static void http_dirls_sort(dirls_entry_t **ent, int num) {
- int gap = num;
- int i, j;
- int swapped;
- dirls_entry_t *tmp;
-
- do {
- gap = (gap * 10) / 13;
- if (gap == 9 || gap == 10)
- gap = 11;
- if (gap < 1)
- gap = 1;
- swapped = 0;
-
- for (i = 0; i < num - gap; i++) {
- j = i + gap;
- if (strcmp(DIRLIST_ENT_NAME(ent[i]), DIRLIST_ENT_NAME(ent[j])) > 0) {
- tmp = ent[i];
- ent[i] = ent[j];
- ent[j] = tmp;
- swapped = 1;
- }
- }
-
- } while (gap > 1 || swapped);
-}
-
-/* buffer must be able to hold "999.9K"
- * conversion is simple but not perfect
- */
-static int http_list_directory_sizefmt(char *buf, off_t size) {
- const char unit[] = "KMGTPE"; /* Kilo, Mega, Tera, Peta, Exa */
- const char *u = unit - 1; /* u will always increment at least once */
- int remain;
- char *out = buf;
-
- if (size < 100)
- size += 99;
- if (size < 100)
- size = 0;
-
- while (1) {
- remain = (int) size & 1023;
- size >>= 10;
- u++;
- if ((size & (~0 ^ 1023)) == 0)
- break;
- }
-
- remain /= 100;
- if (remain > 9)
- remain = 9;
- if (size > 999) {
- size = 0;
- remain = 9;
- u++;
- }
-
- out += LI_ltostr(out, size);
- out[0] = '.';
- out[1] = remain + '0';
- out[2] = *u;
- out[3] = '\0';
-
- return (out + 3 - buf);
-}
-
-static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
- UNUSED(srv);
-
- buffer_append_string_len(out, CONST_STR_LEN(
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
- "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
- "<head>\n"
- "<title>Index of "
- ));
- buffer_append_string_encoded(out, CONST_BUF_LEN(con->uri.path), ENCODING_MINIMAL_XML);
- buffer_append_string_len(out, CONST_STR_LEN("</title>\n"));
-
- if (p->conf.external_css->used > 1) {
- buffer_append_string_len(out, CONST_STR_LEN("<link rel=\"stylesheet\" type=\"text/css\" href=\""));
- buffer_append_string_buffer(out, p->conf.external_css);
- buffer_append_string_len(out, CONST_STR_LEN("\" />\n"));
- } else {
- buffer_append_string_len(out, CONST_STR_LEN(
- "<style type=\"text/css\">\n"
- "a, a:active {text-decoration: none; color: blue;}\n"
- "a:visited {color: #48468F;}\n"
- "a:hover, a:focus {text-decoration: underline; color: red;}\n"
- "body {background-color: #F5F5F5;}\n"
- "h2 {margin-bottom: 12px;}\n"
- "table {margin-left: 12px;}\n"
- "th, td {"
- " font: 90% monospace;"
- " text-align: left;"
- "}\n"
- "th {"
- " font-weight: bold;"
- " padding-right: 14px;"
- " padding-bottom: 3px;"
- "}\n"
-
- "td {padding-right: 14px;}\n"
- "td.s, th.s {text-align: right;}\n"
- "div.list {"
- " background-color: white;"
- " border-top: 1px solid #646464;"
- " border-bottom: 1px solid #646464;"
- " padding-top: 10px;"
- " padding-bottom: 14px;"
- "}\n"
- "div.foot {"
- " font: 90% monospace;"
- " color: #787878;"
- " padding-top: 4px;"
- "}\n"
- "</style>\n"
- ));
- }
-
- buffer_append_string_len(out, CONST_STR_LEN("</head>\n<body>\n"));
-
- /* HEADER.txt */
- if (p->conf.show_header) {
- stream s;
- /* if we have a HEADER file, display it in <pre class="header"></pre> */
-
- buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
- PATHNAME_APPEND_SLASH(p->tmp_buf);
- buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("HEADER.txt"));
-
- if (-1 != stream_open(&s, p->tmp_buf)) {
- buffer_append_string_len(out, CONST_STR_LEN("<pre class=\"header\">"));
- buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
- buffer_append_string_len(out, CONST_STR_LEN("</pre>"));
- }
- stream_close(&s);
- }
-
- buffer_append_string_len(out, CONST_STR_LEN("<h2>Index of "));
- buffer_append_string_encoded(out, CONST_BUF_LEN(con->uri.path), ENCODING_MINIMAL_XML);
- buffer_append_string_len(out, CONST_STR_LEN(
- "</h2>\n"
- "<div class=\"list\">\n"
- "<table summary=\"Directory Listing\" cellpadding=\"0\" cellspacing=\"0\">\n"
- "<thead>"
- "<tr>"
- "<th class=\"n\">Name</th>"
- "<th class=\"m\">Last Modified</th>"
- "<th class=\"s\">Size</th>"
- "<th class=\"t\">Type</th>"
- "</tr>"
- "</thead>\n"
- "<tbody>\n"
- "<tr>"
- "<td class=\"n\"><a href=\"../\">Parent Directory</a>/</td>"
- "<td class=\"m\">&nbsp;</td>"
- "<td class=\"s\">- &nbsp;</td>"
- "<td class=\"t\">Directory</td>"
- "</tr>\n"
- ));
-}
-
-static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
- UNUSED(srv);
-
- buffer_append_string_len(out, CONST_STR_LEN(
- "</tbody>\n"
- "</table>\n"
- "</div>\n"
- ));
-
- if (p->conf.show_readme) {
- stream s;
- /* if we have a README file, display it in <pre class="readme"></pre> */
-
- buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
- PATHNAME_APPEND_SLASH(p->tmp_buf);
- buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("README.txt"));
-
- if (-1 != stream_open(&s, p->tmp_buf)) {
- buffer_append_string_len(out, CONST_STR_LEN("<pre class=\"readme\">"));
- buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
- buffer_append_string_len(out, CONST_STR_LEN("</pre>"));
- }
- stream_close(&s);
- }
-
- buffer_append_string_len(out, CONST_STR_LEN(
- "<div class=\"foot\">"
- ));
-
- if (p->conf.set_footer->used > 1) {
- buffer_append_string_buffer(out, p->conf.set_footer);
- } else if (buffer_is_empty(con->conf.server_tag)) {
- buffer_append_string_len(out, CONST_STR_LEN(PACKAGE_NAME "/" PACKAGE_VERSION));
- } else {
- buffer_append_string_buffer(out, con->conf.server_tag);
- }
-
- buffer_append_string_len(out, CONST_STR_LEN(
- "</div>\n"
- "</body>\n"
- "</html>\n"
- ));
-}
-
-static int http_list_directory(server *srv, connection *con, plugin_data *p, buffer *dir) {
- DIR *dp;
- buffer *out;
- struct dirent *dent;
- struct stat st;
- size_t i;
- int hide_dotfiles = p->conf.hide_dot_files;
- dirls_list_t dirs, files, *list;
- dirls_entry_t *tmp;
- char sizebuf[sizeof("999.9K")];
- char datebuf[sizeof("2005-Jan-01 22:23:24")];
- size_t k;
- const char *content_type;
- long name_max;
-
-#ifdef HAVE_XATTR
- char attrval[128];
- int attrlen;
-#endif
-#ifdef HAVE_LOCALTIME_R
- struct tm tm;
-#endif
-
- /* empty pathname, never ... */
- if (buffer_is_empty(dir)) return -1;
-
- /* max-length for the opendir */
-#ifdef HAVE_PATHCONF
- if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
-#ifdef NAME_MAX
- name_max = NAME_MAX;
-#else
- name_max = 256; /* stupid default */
-#endif
- }
-#elif defined _WIN32
- name_max = FILENAME_MAX;
-#else
- name_max = NAME_MAX;
-#endif
-
- buffer_copy_string_buffer(p->path, dir);
- PATHNAME_APPEND_SLASH(p->path);
-
-#ifdef _WIN32
- /* append *.* to the path */
- buffer_append_string_len(p->path, CONST_STR_LEN("*.*"));
-#endif
-
- if (NULL == (dp = opendir(p->path->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "opendir failed:", dir, strerror(errno));
-
- return -1;
- }
-
- dirs.ent = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
- assert(dirs.ent);
- dirs.size = DIRLIST_BLOB_SIZE;
- dirs.used = 0;
- files.ent = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
- assert(files.ent);
- files.size = DIRLIST_BLOB_SIZE;
- files.used = 0;
-
- while ((dent = readdir(dp)) != NULL) {
- unsigned short exclude_match = 0;
-
- if (dent->d_name[0] == '.') {
- if (hide_dotfiles)
- continue;
- if (dent->d_name[1] == '\0')
- continue;
- if (dent->d_name[1] == '.' && dent->d_name[2] == '\0')
- continue;
- }
-
- if (p->conf.hide_readme_file) {
- if (strcmp(dent->d_name, "README.txt") == 0)
- continue;
- }
- if (p->conf.hide_header_file) {
- if (strcmp(dent->d_name, "HEADER.txt") == 0)
- continue;
- }
-
- /* compare d_name against excludes array
- * elements, skipping any that match.
- */
-#ifdef HAVE_PCRE_H
- for(i = 0; i < p->conf.excludes->used; i++) {
- int n;
-#define N 10
- int ovec[N * 3];
- pcre *regex = p->conf.excludes->ptr[i]->regex;
-
- if ((n = pcre_exec(regex, NULL, dent->d_name,
- strlen(dent->d_name), 0, 0, ovec, 3 * N)) < 0) {
- if (n != PCRE_ERROR_NOMATCH) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "execution error while matching:", n);
-
- return -1;
- }
- }
- else {
- exclude_match = 1;
- break;
- }
- }
-
- if (exclude_match) {
- continue;
- }
-#endif
-
- i = strlen(dent->d_name);
-
- /* NOTE: the manual says, d_name is never more than NAME_MAX
- * so this should actually not be a buffer-overflow-risk
- */
- if (i > (size_t)name_max) continue;
-
- /* build the dirname */
- buffer_copy_string_buffer(p->path, dir);
- PATHNAME_APPEND_SLASH(p->path);
- buffer_append_string(p->path, dent->d_name);
-
- if (stat(p->path->ptr, &st) != 0) {
- fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, p->path->ptr, strerror(errno));
- continue;
- }
-
- list = &files;
- if (S_ISDIR(st.st_mode))
- list = &dirs;
-
- if (list->used == list->size) {
- list->size += DIRLIST_BLOB_SIZE;
- list->ent = (dirls_entry_t**) realloc(list->ent, sizeof(dirls_entry_t*) * list->size);
- assert(list->ent);
- }
-
- tmp = (dirls_entry_t*) malloc(sizeof(dirls_entry_t) + 1 + i);
- tmp->mtime = st.st_mtime;
- tmp->size = st.st_size;
- tmp->namelen = i;
- memcpy(DIRLIST_ENT_NAME(tmp), dent->d_name, i + 1);
-
- list->ent[list->used++] = tmp;
- }
- closedir(dp);
-
- if (dirs.used) http_dirls_sort(dirs.ent, dirs.used);
-
- if (files.used) http_dirls_sort(files.ent, files.used);
-
- out = chunkqueue_get_append_buffer(con->send);
- buffer_copy_string_len(out, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\""));
- if (buffer_is_empty(p->conf.encoding)) {
- buffer_append_string_len(out, CONST_STR_LEN("iso-8859-1"));
- } else {
- buffer_append_string_buffer(out, p->conf.encoding);
- }
- buffer_append_string_len(out, CONST_STR_LEN("\"?>\n"));
- http_list_directory_header(srv, con, p, out);
-
- /* directories */
- for (i = 0; i < dirs.used; i++) {
- tmp = dirs.ent[i];
-
-#ifdef HAVE_LOCALTIME_R
- localtime_r(&(tmp->mtime), &tm);
- strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
-#else
- strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
-#endif
-
- buffer_append_string_len(out, CONST_STR_LEN("<tr><td class=\"n\"><a href=\""));
- buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
- buffer_append_string_len(out, CONST_STR_LEN("/\">"));
- buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_MINIMAL_XML);
- buffer_append_string_len(out, CONST_STR_LEN("</a>/</td><td class=\"m\">"));
- buffer_append_string_len(out, datebuf, sizeof(datebuf) - 1);
- buffer_append_string_len(out, CONST_STR_LEN("</td><td class=\"s\">- &nbsp;</td><td class=\"t\">Directory</td></tr>\n"));
-
- free(tmp);
- }
-
- /* files */
- for (i = 0; i < files.used; i++) {
- tmp = files.ent[i];
-
- content_type = NULL;
-
-#ifdef HAVE_XATTR
- if (con->conf.use_xattr) {
- /* build the dirname */
- buffer_copy_string_buffer(p->path, dir);
- PATHNAME_APPEND_SLASH(p->path);
- buffer_append_string_len(p->path, DIRLIST_ENT_NAME(tmp), tmp->namelen);
-
- attrlen = sizeof(attrval) - 1;
- if (attr_get(p->path->ptr, "Content-Type", attrval, &attrlen, 0) == 0) {
- attrval[attrlen] = '\0';
- content_type = attrval;
- }
- }
-#endif
-
- if (content_type == NULL) {
- content_type = "application/octet-stream";
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
- size_t ct_len;
-
- if (ds->key->used == 0)
- continue;
-
- ct_len = ds->key->used - 1;
- if (tmp->namelen < ct_len)
- continue;
-
- if (0 == strncasecmp(DIRLIST_ENT_NAME(tmp) + tmp->namelen - ct_len, ds->key->ptr, ct_len)) {
- content_type = ds->value->ptr;
- break;
- }
- }
- }
-
-#ifdef HAVE_LOCALTIME_R
- localtime_r(&(tmp->mtime), &tm);
- strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
-#else
- strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
-#endif
- http_list_directory_sizefmt(sizebuf, tmp->size);
-
- buffer_append_string_len(out, CONST_STR_LEN("<tr><td class=\"n\"><a href=\""));
- buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
- buffer_append_string_len(out, CONST_STR_LEN("\">"));
- buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_MINIMAL_XML);
- buffer_append_string_len(out, CONST_STR_LEN("</a></td><td class=\"m\">"));
- buffer_append_string_len(out, datebuf, sizeof(datebuf) - 1);
- buffer_append_string_len(out, CONST_STR_LEN("</td><td class=\"s\">"));
- buffer_append_string(out, sizebuf);
- buffer_append_string_len(out, CONST_STR_LEN("</td><td class=\"t\">"));
- buffer_append_string(out, content_type);
- buffer_append_string_len(out, CONST_STR_LEN("</td></tr>\n"));
-
- free(tmp);
- }
-
- free(files.ent);
- free(dirs.ent);
-
- http_list_directory_footer(srv, con, p, out);
-
- /* Insert possible charset to Content-Type */
- if (buffer_is_empty(p->conf.encoding)) {
- response_header_insert(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
- } else {
- buffer_copy_string_len(p->content_charset, CONST_STR_LEN("text/html; charset="));
- buffer_append_string_buffer(p->content_charset, p->conf.encoding);
- response_header_insert(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->content_charset));
- }
-
- con->send->bytes_in += out->used - 1;
-
- con->send->is_closed = 1;
-
- return 0;
-}
-
-
-
-URIHANDLER_FUNC(mod_dirlisting_subrequest) {
- plugin_data *p = p_d;
- stat_cache_entry *sce = NULL;
- buffer *mtime;
- data_string *ds;
-
- /* we only handle GET, POST and HEAD */
- switch(con->request.http_method) {
- case HTTP_METHOD_GET:
- case HTTP_METHOD_POST:
- case HTTP_METHOD_HEAD:
- break;
- default:
- return HANDLER_GO_ON;
- }
-
- if (con->uri.path->used < 2) return HANDLER_GO_ON;
- if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
- if (con->physical.path->used == 0) return HANDLER_GO_ON;
-
- mod_dirlisting_patch_connection(srv, con, p);
-
- if (!p->conf.dir_listing) return HANDLER_GO_ON;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- /* just a second ago the file was still there */
- return HANDLER_GO_ON;
- }
-
- if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
-
- if (con->conf.log_request_handling) {
- log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
- log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
- }
-
- /* perhaps this a cachable request
- * - we use the etag of the directory
- * */
-
- etag_mutate(con->physical.etag, sce->etag);
- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
-
- /* prepare header */
- if (NULL == (ds = (data_string *)array_get_element(con->response.headers, CONST_STR_LEN("Last-Modified")))) {
- mtime = strftime_cache_get(srv, sce->st.st_mtime);
- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
- } else {
- mtime = ds->value;
- }
-
- if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
- return HANDLER_FINISHED;
- }
-
- if (http_list_directory(srv, con, p, con->physical.path)) {
- /* dirlisting failed */
- con->http_status = 403;
- }
-
- buffer_reset(con->physical.path);
-
- /* not found */
- return HANDLER_FINISHED;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_dirlisting_plugin_init(plugin *p);
-LI_EXPORT int mod_dirlisting_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("dirlisting");
-
- p->init = mod_dirlisting_init;
- p->handle_start_backend = mod_dirlisting_subrequest;
- p->set_defaults = mod_dirlisting_set_defaults;
- p->cleanup = mod_dirlisting_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_evasive.c b/src/mod_evasive.c
deleted file mode 100644
index 1c0e5586..00000000
--- a/src/mod_evasive.c
+++ /dev/null
@@ -1,200 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "inet_ntop_cache.h"
-
-/**
- * mod_evasive
- *
- * we indent to implement all features the mod_evasive from apache has
- *
- * - limit of connections per IP
- * - provide a list of block-listed ip/networks (no access)
- * - provide a white-list of ips/network which is not affected by the limit
- * (hmm, conditionals might be enough)
- * - provide a bandwidth limiter per IP
- *
- * started by:
- * - w1zzard@techpowerup.com
- */
-
-typedef struct {
- unsigned short max_conns;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_evasive_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-FREE_FUNC(mod_evasive_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->max_conns = 0;
-
- cv[0].destination = &(s->max_conns);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(max_conns);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
- PATCH_OPTION(max_conns);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_evasive_uri_handler) {
- plugin_data *p = p_d;
- size_t conns_by_ip = 0;
- size_t j;
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_evasive_patch_connection(srv, con, p);
-
- /* no limit set, nothing to block */
- if (p->conf.max_conns == 0) return HANDLER_GO_ON;
-
- switch (con->dst_addr.plain.sa_family) {
- case AF_INET:
-#ifdef HAVE_IPV6
- case AF_INET6:
-#endif
- break;
- default: // Address family not supported
- return HANDLER_GO_ON;
- };
-
- for (j = 0; j < srv->conns->used; j++) {
- connection *c = srv->conns->ptr[j];
-
- /* check if other connections are already actively serving data for the same IP
- * we can only ban connections which are already behind the 'read request' state
- * */
- if (c->dst_addr.plain.sa_family != con->dst_addr.plain.sa_family) continue;
- if (c->state <= CON_STATE_HANDLE_REQUEST_HEADER) continue;
-
- switch (con->dst_addr.plain.sa_family) {
- case AF_INET:
- if (c->dst_addr.ipv4.sin_addr.s_addr != con->dst_addr.ipv4.sin_addr.s_addr) continue;
- break;
-#ifdef HAVE_IPV6
- case AF_INET6:
- if (0 != memcmp(c->dst_addr.ipv6.sin6_addr.s6_addr, con->dst_addr.ipv6.sin6_addr.s6_addr, 16)) continue;
- break;
-#endif
- default: // Address family not supported, should never be reached
- continue;
- };
- conns_by_ip++;
-
- if (conns_by_ip > p->conf.max_conns) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
- "turned away. Too many connections.");
-
- con->http_status = 403;
- return HANDLER_FINISHED;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-
-LI_EXPORT int mod_evasive_plugin_init(plugin *p);
-LI_EXPORT int mod_evasive_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("evasive");
-
- p->init = mod_evasive_init;
- p->set_defaults = mod_evasive_set_defaults;
- p->handle_uri_clean = mod_evasive_uri_handler;
- p->cleanup = mod_evasive_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_evhost.c b/src/mod_evhost.c
deleted file mode 100644
index 8b8d016e..00000000
--- a/src/mod_evhost.c
+++ /dev/null
@@ -1,347 +0,0 @@
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "plugin.h"
-#include "log.h"
-#include "response.h"
-#include "stat_cache.h"
-
-#include "sys-files.h"
-
-typedef struct {
- /* unparsed pieces */
- buffer *path_pieces_raw;
-
- /* pieces for path creation */
- size_t len;
- buffer **path_pieces;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
- buffer *tmp_buf;
-
- plugin_config **config_storage;
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_evhost_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- return p;
-}
-
-FREE_FUNC(mod_evhost_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- if(s->path_pieces) {
- size_t j;
- for (j = 0; j < s->len; j++) {
- buffer_free(s->path_pieces[j]);
- }
-
- free(s->path_pieces);
- }
-
- buffer_free(s->path_pieces_raw);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-static void mod_evhost_parse_pattern(plugin_config *s) {
- char *ptr = s->path_pieces_raw->ptr,*pos;
-
- s->path_pieces = NULL;
-
- for(pos=ptr;*ptr;ptr++) {
- if(*ptr == '%') {
- s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
- s->path_pieces[s->len] = buffer_init();
- s->path_pieces[s->len+1] = buffer_init();
-
- buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
- pos = ptr + 2;
-
- buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
-
- s->len += 2;
- }
- }
-
- if(*pos != '\0') {
- s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
- s->path_pieces[s->len] = buffer_init();
-
- buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
-
- s->len += 1;
- }
-}
-
-SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
- plugin_data *p = p_d;
- size_t i;
-
- /**
- *
- * #
- * # define a pattern for the host url finding
- * # %% => % sign
- * # %0 => domain name + tld
- * # %1 => tld
- * # %2 => domain name without tld
- * # %3 => subdomain 1 name
- * # %4 => subdomain 2 name
- * # %_ => fqdn (without port info)
- * #
- * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
- *
- */
-
- config_values_t cv[] = {
- { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->path_pieces_raw = buffer_init();
- s->path_pieces = NULL;
- s->len = 0;
-
- cv[0].destination = s->path_pieces_raw;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (s->path_pieces_raw->used != 0) {
- mod_evhost_parse_pattern(s);
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * assign the different parts of the domain to array-indezes (sub2.sub1.domain.tld)
- * - %0 - domain.tld
- * - %1 - tld
- * - %2 - domain
- * - %3 - sub1
- * - ...
- */
-
-static int mod_evhost_parse_host(connection *con,array *host) {
- /* con->uri.authority->used is always > 0 if we come here */
- register char *ptr = con->uri.authority->ptr + con->uri.authority->used - 1;
- char *colon = ptr; /* needed to filter out the colon (if exists) */
- int first = 1;
- data_string *ds;
- int i;
-
- /* first, find the domain + tld */
- for(;ptr > con->uri.authority->ptr;ptr--) {
- if(*ptr == '.') {
- if(first) first = 0;
- else break;
- } else if(*ptr == ':') {
- colon = ptr;
- first = 1;
- }
- }
-
- ds = data_string_init();
- buffer_copy_string_len(ds->key,CONST_STR_LEN("%0"));
-
- /* if we stopped at a dot, skip the dot */
- if (*ptr == '.') ptr++;
- buffer_copy_string_len(ds->value, ptr, colon-ptr);
-
- array_insert_unique(host,(data_unset *)ds);
-
- /* if the : is not the start of the authority, go on parsing the hostname */
-
- if (colon != con->uri.authority->ptr) {
- for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
- if(*ptr == '.') {
- if (ptr != colon - 1) {
- /* is something between the dots */
- ds = data_string_init();
- buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
- buffer_append_long(ds->key, i++);
- buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
-
- array_insert_unique(host,(data_unset *)ds);
- }
- colon = ptr;
- }
- }
-
- /* if the . is not the first charactor of the hostname */
- if (colon != ptr) {
- ds = data_string_init();
- buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
- buffer_append_long(ds->key, i++);
- buffer_copy_string_len(ds->value,ptr,colon-ptr);
-
- array_insert_unique(host,(data_unset *)ds);
- }
- }
-
- return 0;
-}
-
-static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(path_pieces);
- PATCH_OPTION(len);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
- PATCH_OPTION(path_pieces);
- PATCH_OPTION(len);
- }
- }
- }
-
- return 0;
-}
-
-static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
- size_t i;
- array *parsed_host;
- register char *ptr;
- int not_good = 0;
- stat_cache_entry *sce = NULL;
-
- /* not authority set */
- if (con->uri.authority->used == 0) return HANDLER_GO_ON;
-
- mod_evhost_patch_connection(srv, con, p);
-
- /* missing even default(global) conf */
- if (0 == p->conf.len) {
- return HANDLER_GO_ON;
- }
-
- parsed_host = array_init();
-
- mod_evhost_parse_host(con, parsed_host);
-
- /* build document-root */
- buffer_reset(p->tmp_buf);
-
- for (i = 0; i < p->conf.len; i++) {
- ptr = p->conf.path_pieces[i]->ptr;
- if (*ptr == '%') {
- data_string *ds;
-
- if (*(ptr+1) == '%') {
- /* %% */
- buffer_append_string_len(p->tmp_buf,CONST_STR_LEN("%"));
- } else if (*(ptr+1) == '_' ) {
- /* %_ == full hostname */
- char *colon = strchr(con->uri.authority->ptr, ':');
-
- if(colon == NULL) {
- buffer_append_string_buffer(p->tmp_buf, con->uri.authority); /* adds fqdn */
- } else {
- /* strip the port out of the authority-part of the URI scheme */
- buffer_append_string_len(p->tmp_buf, con->uri.authority->ptr, colon - con->uri.authority->ptr); /* adds fqdn */
- }
- } else if (NULL != (ds = (data_string *)array_get_element(parsed_host, CONST_BUF_LEN(p->conf.path_pieces[i])))) {
- if (ds->value->used) {
- buffer_append_string_buffer(p->tmp_buf,ds->value);
- }
- } else {
- /* unhandled %-sequence */
- }
- } else {
- buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
- }
- }
-
- PATHNAME_APPEND_SLASH(p->tmp_buf);
-
- array_free(parsed_host);
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
- not_good = 1;
- } else if(!S_ISDIR(sce->st.st_mode)) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
- not_good = 1;
- }
-
- if (!not_good) {
- buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
- }
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_evhost_plugin_init(plugin *p);
-LI_EXPORT int mod_evhost_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("evhost");
- p->init = mod_evhost_init;
- p->set_defaults = mod_evhost_set_defaults;
- p->handle_docroot = mod_evhost_uri_handler;
- p->cleanup = mod_evhost_free;
-
- p->data = NULL;
-
- return 0;
-}
-
-/* eof */
diff --git a/src/mod_expire.c b/src/mod_expire.c
deleted file mode 100644
index c844deeb..00000000
--- a/src/mod_expire.c
+++ /dev/null
@@ -1,375 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "response.h"
-
-#include "plugin.h"
-#include "stat_cache.h"
-
-/**
- * this is a expire module for a lighttpd
- *
- * set 'Expires:' HTTP Headers on demand
- */
-
-
-
-/* plugin config for all request/connections */
-
-typedef struct {
- array *expire_url;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *expire_tstmp;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_expire_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->expire_tstmp = buffer_init();
-
- buffer_prepare_copy(p->expire_tstmp, 255);
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_expire_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- buffer_free(p->expire_tstmp);
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
- if (!s) continue;
-
- array_free(s->expire_url);
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, time_t *offset) {
- char *ts;
- int type = -1;
- time_t retts = 0;
-
- UNUSED(p);
-
- /*
- * parse
- *
- * '(access|now|modification) [plus] {<num> <type>}*'
- *
- * e.g. 'access 1 years'
- */
-
- if (expire->used == 0) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "empty:");
- return -1;
- }
-
- ts = expire->ptr;
-
- if (0 == strncmp(ts, "access ", 7)) {
- type = 0;
- ts += 7;
- } else if (0 == strncmp(ts, "now ", 4)) {
- type = 0;
- ts += 4;
- } else if (0 == strncmp(ts, "modification ", 13)) {
- type = 1;
- ts += 13;
- } else {
- /* invalid type-prefix */
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "invalid <base>:", ts);
- return -1;
- }
-
- if (0 == strncmp(ts, "plus ", 5)) {
- /* skip the optional plus */
- ts += 5;
- }
-
- /* the rest is just <number> (years|months|weeks|days|hours|minutes|seconds) */
- while (1) {
- char *space, *err;
- int num;
-
- if (NULL == (space = strchr(ts, ' '))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "missing space after <num>:", ts);
- return -1;
- }
-
- num = strtol(ts, &err, 10);
- if (*err != ' ') {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "missing <type> after <num>:", ts);
- return -1;
- }
-
- ts = space + 1;
-
- if (NULL != (space = strchr(ts, ' '))) {
- int slen;
- /* */
-
- slen = space - ts;
-
- if (slen == 5 &&
- 0 == strncmp(ts, "years", slen)) {
- num *= 60 * 60 * 24 * 30 * 12;
- } else if (slen == 6 &&
- 0 == strncmp(ts, "months", slen)) {
- num *= 60 * 60 * 24 * 30;
- } else if (slen == 5 &&
- 0 == strncmp(ts, "weeks", slen)) {
- num *= 60 * 60 * 24 * 7;
- } else if (slen == 4 &&
- 0 == strncmp(ts, "days", slen)) {
- num *= 60 * 60 * 24;
- } else if (slen == 5 &&
- 0 == strncmp(ts, "hours", slen)) {
- num *= 60 * 60;
- } else if (slen == 7 &&
- 0 == strncmp(ts, "minutes", slen)) {
- num *= 60;
- } else if (slen == 7 &&
- 0 == strncmp(ts, "seconds", slen)) {
- num *= 1;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "unknown type:", ts);
- return -1;
- }
-
- retts += num;
-
- ts = space + 1;
- } else {
- if (0 == strcmp(ts, "years")) {
- num *= 60 * 60 * 24 * 30 * 12;
- } else if (0 == strcmp(ts, "months")) {
- num *= 60 * 60 * 24 * 30;
- } else if (0 == strcmp(ts, "weeks")) {
- num *= 60 * 60 * 24 * 7;
- } else if (0 == strcmp(ts, "days")) {
- num *= 60 * 60 * 24;
- } else if (0 == strcmp(ts, "hours")) {
- num *= 60 * 60;
- } else if (0 == strcmp(ts, "minutes")) {
- num *= 60;
- } else if (0 == strcmp(ts, "seconds")) {
- num *= 1;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "unknown type:", ts);
- return -1;
- }
-
- retts += num;
-
- break;
- }
- }
-
- if (offset != NULL) *offset = retts;
-
- return type;
-}
-
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_expire_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0, k;
-
- config_values_t cv[] = {
- { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->expire_url = array_init();
-
- cv[0].destination = s->expire_url;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- for (k = 0; k < s->expire_url->used; k++) {
- data_string *ds = (data_string *)s->expire_url->data[k];
-
- /* parse lines */
- if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "parsing expire.url failed:", ds->value);
- return HANDLER_ERROR;
- }
- }
- }
-
-
- return HANDLER_GO_ON;
-}
-
-static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(expire_url);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
- PATCH_OPTION(expire_url);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_expire_path_handler) {
- plugin_data *p = p_d;
- int s_len;
- size_t k;
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_expire_patch_connection(srv, con, p);
-
- s_len = con->uri.path->used - 1;
-
- for (k = 0; k < p->conf.expire_url->used; k++) {
- data_string *ds = (data_string *)p->conf.expire_url->data[k];
- int ct_len = ds->key->used - 1;
-
- if (ct_len > s_len) continue;
- if (ds->key->used == 0) continue;
-
- if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
- time_t ts, expires;
- size_t len;
-
- switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
- case 0:
- /* access */
- expires = (ts + srv->cur_ts);
- break;
- case 1: {
- /* modification */
- stat_cache_entry *sce = NULL;
-
- if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
-
- if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- /* it failed for some reason, just skip it */
- return HANDLER_GO_ON;
- }
-
- expires = (ts + sce->st.st_mtime);
-
- break; }
- default:
- /* -1 is handled at parse-time */
- break;
- }
-
- /* expires should be at least srv->cur_ts */
- if (expires < srv->cur_ts) expires = srv->cur_ts;
-
- if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
- "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(expires))))) {
- /* could not set expire header, out of mem */
-
- return HANDLER_GO_ON;
- }
-
- p->expire_tstmp->used = len + 1;
-
- /* HTTP/1.0 */
- response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
-
- /* HTTP/1.1 */
- buffer_copy_string_len(p->expire_tstmp, CONST_STR_LEN("max-age="));
- buffer_append_long(p->expire_tstmp, expires - srv->cur_ts); /* as expires >= srv->cur_ts the difference is >= 0 */
-
- response_header_append(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
-
- return HANDLER_GO_ON;
- }
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_expire_plugin_init(plugin *p);
-LI_EXPORT int mod_expire_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("expire");
-
- p->init = mod_expire_init;
- p->handle_response_header = mod_expire_path_handler;
- p->set_defaults = mod_expire_set_defaults;
- p->cleanup = mod_expire_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_flv_streaming.c b/src/mod_flv_streaming.c
deleted file mode 100644
index b527ad58..00000000
--- a/src/mod_flv_streaming.c
+++ /dev/null
@@ -1,322 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "response.h"
-#include "stat_cache.h"
-
-#include "plugin.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* plugin config for all request/connections */
-
-typedef struct {
- array *extensions;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *query_str;
- array *get_params;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_flv_streaming_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->query_str = buffer_init();
- p->get_params = array_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_flv_streaming_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->extensions);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->query_str);
- array_free(p->get_params);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->extensions = array_init();
-
- cv[0].destination = s->extensions;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(extensions);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
- PATCH_OPTION(extensions);
- }
- }
- }
-
- return 0;
-}
-
-static int split_get_params(array *get_params, buffer *qrystr) {
- size_t is_key = 1;
- size_t i;
- char *key = NULL, *val = NULL;
-
- key = qrystr->ptr;
-
- /* we need the \0 */
- for (i = 0; i < qrystr->used; i++) {
- switch(qrystr->ptr[i]) {
- case '=':
- if (is_key) {
- val = qrystr->ptr + i + 1;
-
- qrystr->ptr[i] = '\0';
-
- is_key = 0;
- }
-
- break;
- case '&':
- case '\0': /* fin symbol */
- if (!is_key) {
- data_string *ds;
- /* we need at least a = since the last & */
-
- /* terminate the value */
- qrystr->ptr[i] = '\0';
-
- if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
- ds = data_string_init();
- }
- buffer_copy_string_len(ds->key, key, strlen(key));
- buffer_copy_string_len(ds->value, val, strlen(val));
-
- array_insert_unique(get_params, (data_unset *)ds);
- }
-
- key = qrystr->ptr + i + 1;
- val = NULL;
- is_key = 1;
- break;
- }
- }
-
- return 0;
-}
-
-/**
- *
- * @param
- */
-URIHANDLER_FUNC(mod_flv_streaming_path_handler) {
- plugin_data *p = p_d;
- int s_len;
- size_t k;
-
- UNUSED(srv);
-
- if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
-
- if (con->conf.log_request_handling) {
- TRACE("-- handling %s in mod_flv_streaming", SAFE_BUF_STR(con->physical.path));
- }
-
- mod_flv_streaming_patch_connection(srv, con, p);
-
- s_len = con->physical.path->used - 1;
-
- for (k = 0; k < p->conf.extensions->used; k++) {
- data_string *ds = (data_string *)p->conf.extensions->data[k];
- int ct_len = ds->value->used - 1;
-
- if (ct_len > s_len) continue;
- if (ds->value->used == 0) continue;
-
- if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
- data_string *get_param;
- stat_cache_entry *sce = NULL;
- buffer *b;
- long start;
- char *err = NULL;
- /* if there is a start=[0-9]+ in the header use it as start,
- * otherwise send the full file */
-
- array_reset(p->get_params);
- buffer_copy_string_buffer(p->query_str, con->uri.query);
- split_get_params(p->get_params, p->query_str);
-
- if (NULL == (get_param = (data_string *)array_get_element(p->get_params, CONST_STR_LEN("start")))) {
- if (con->conf.log_request_handling) {
- TRACE("start=... not found, skipping %s", SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- /* too short */
- if (get_param->value->used < 2) {
- if (con->conf.log_request_handling) {
- TRACE("start=... found, but empty, skipping %s", SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- /* check if it is a number */
- start = strtol(get_param->value->ptr, &err, 10);
- if (*err != '\0') {
- if (con->conf.log_request_handling) {
- TRACE("parsing start '%s' as number failed, skipping %s",
- SAFE_BUF_STR(get_param->value), SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- if (start <= 0) {
- if (con->conf.log_request_handling) {
- TRACE("start is <= 0, skipping %s", SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- /* check if start is > filesize */
- if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- if (con->conf.log_request_handling) {
- TRACE("stat() for %s failed", SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- if (start > sce->st.st_size) {
- if (con->conf.log_request_handling) {
- TRACE("start > file-size, skipping %s", SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- /* we are safe now, let's build a flv header */
- b = chunkqueue_get_append_buffer(con->send);
- buffer_copy_string_len(b, CONST_STR_LEN("FLV\x1\x1\0\0\0\x9\0\0\0\x9"));
-
- chunkqueue_append_file(con->send, con->physical.path, start, sce->st.st_size - start);
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/x-flv"));
-
- con->send->is_closed = 1;
-
- if (con->conf.log_request_handling) {
- TRACE("sending %s from position %ld", SAFE_BUF_STR(con->physical.path), start);
- }
-
- return HANDLER_FINISHED;
- }
- }
-
- if (con->conf.log_request_handling) {
- TRACE("none of the extensions matched %s, leaving", SAFE_BUF_STR(con->physical.path));
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_flv_streaming_plugin_init(plugin *p);
-LI_EXPORT int mod_flv_streaming_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("flv_streaming");
-
- p->init = mod_flv_streaming_init;
- p->handle_physical = mod_flv_streaming_path_handler;
- p->set_defaults = mod_flv_streaming_set_defaults;
- p->cleanup = mod_flv_streaming_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_indexfile.c b/src/mod_indexfile.c
deleted file mode 100644
index d48ee03f..00000000
--- a/src/mod_indexfile.c
+++ /dev/null
@@ -1,254 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "configfile.h"
-
-#include "stat_cache.h"
-
-#include "sys-strings.h"
-#include "sys-files.h"
-
-#include "configfile.h"
-/* plugin config for all request/connections */
-
-typedef struct {
- array *indexfiles;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *tmp_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_indexfile_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_indexfile_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->indexfiles);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->indexfiles = array_init();
-
- cv[0].destination = s->indexfiles;
- cv[1].destination = s->indexfiles; /* old name for [0] */
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(indexfiles);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
- PATCH_OPTION(indexfiles);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
- PATCH_OPTION(indexfiles);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_indexfile_subrequest) {
- plugin_data *p = p_d;
- size_t k;
- stat_cache_entry *sce = NULL;
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
- if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
-
- mod_indexfile_patch_connection(srv, con, p);
-
- /* is the physical-path really a dir ? */
- switch(stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- case HANDLER_WAIT_FOR_EVENT:
- return HANDLER_WAIT_FOR_EVENT;
- case HANDLER_ERROR:
- return HANDLER_GO_ON;
- default:
- break;
- }
-
- if (!S_ISDIR(sce->st.st_mode)) {
- return HANDLER_GO_ON;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "handling the request as Indexfile");
- TRACE("URI : %s", SAFE_BUF_STR(con->uri.path));
- }
-
- /* indexfile */
- for (k = 0; k < p->conf.indexfiles->used; k++) {
- data_string *ds = (data_string *)p->conf.indexfiles->data[k];
-
- if (ds->value && ds->value->ptr[0] == '/') {
- /* if the index-file starts with a prefix as use this file as
- * index-generator */
- buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
- } else {
- buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
- PATHNAME_APPEND_SLASH(p->tmp_buf);
- }
- buffer_append_string_buffer(p->tmp_buf, ds->value);
-
- switch(stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
- case HANDLER_WAIT_FOR_EVENT:
- return HANDLER_WAIT_FOR_EVENT;
- case HANDLER_ERROR:
- if (errno == EACCES) {
- con->http_status = 403;
- buffer_reset(con->physical.path);
-
- return HANDLER_FINISHED;
- }
-
- if (errno != ENOENT &&
- errno != ENOTDIR) {
- /* we have no idea what happend. let's tell the user so. */
-
- con->http_status = 500;
-
- log_error_write(srv, __FILE__, __LINE__, "ssbsb",
- "file not found ... or so: ", strerror(errno),
- con->uri.path,
- "->", con->physical.path);
-
- buffer_reset(con->physical.path);
-
- return HANDLER_FINISHED;
- }
- continue;
- default:
- break;
- }
-
- /* rewrite uri.path to the real path (/ -> /index.php) */
- buffer_append_string_buffer(con->uri.path, ds->value);
- buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
-
- if (con->conf.log_request_handling) {
- TRACE("rewrite path to %s (%s)",
- SAFE_BUF_STR(con->physical.path),
- SAFE_BUF_STR(con->uri.path));
- }
-
- /* need to reset condition cache since uri.path changed. */
- config_cond_cache_reset_item(srv, con, COMP_PHYSICAL_PATH);
- config_cond_cache_reset_item(srv, con, COMP_PHYSICAL_PATH_EXISTS);
- config_cond_cache_reset_item(srv, con, COMP_HTTP_URL);
-
- return HANDLER_GO_ON;
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_indexfile_plugin_init(plugin *p);
-LI_EXPORT int mod_indexfile_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("indexfile");
-
- p->init = mod_indexfile_init;
- p->handle_start_backend = mod_indexfile_subrequest;
- p->set_defaults = mod_indexfile_set_defaults;
- p->cleanup = mod_indexfile_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_magnet.c b/src/mod_magnet.c
deleted file mode 100644
index d1260396..00000000
--- a/src/mod_magnet.c
+++ /dev/null
@@ -1,984 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <setjmp.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "mod_magnet_cache.h"
-#include "response.h"
-#include "stat_cache.h"
-#include "status_counter.h"
-#include "etag.h"
-#include "configfile.h"
-
-#ifdef HAVE_LUA_H
-#include <lua.h>
-#include <lauxlib.h>
-
-#define PLUGIN_NAME "magnet"
-
-#define MAGNET_CONFIG_RAW_URL PLUGIN_NAME ".attract-raw-url-to"
-#define MAGNET_CONFIG_PHYSICAL_PATH PLUGIN_NAME ".attract-physical-path-to"
-#define MAGNET_CONFIG_FILTER_CONTENT PLUGIN_NAME ".attract-response-content-to"
-#define MAGNET_CONFIG_FILTER_HEADER PLUGIN_NAME ".attract-response-header-to"
-#define MAGNET_RESTART_REQUEST 99
-
-/* plugin config for all request/connections */
-
-static jmp_buf exceptionjmp;
-
-typedef struct {
- array *url_raw;
- array *physical_path;
- array *filter_header;
- array *filter_content;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- script_cache *cache;
-
- buffer *encode_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_magnet_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->cache = script_cache_init();
- p->encode_buf = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_magnet_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->url_raw);
- array_free(s->physical_path);
- array_free(s->filter_header);
- array_free(s->filter_content);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- script_cache_free(p->cache);
- buffer_free(p->encode_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_magnet_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { MAGNET_CONFIG_RAW_URL, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { MAGNET_CONFIG_PHYSICAL_PATH, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { MAGNET_CONFIG_FILTER_CONTENT, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { MAGNET_CONFIG_FILTER_HEADER, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->url_raw = array_init();
- s->physical_path = array_init();
- s->filter_content = array_init();
- s->filter_header = array_init();
-
- cv[0].destination = s->url_raw;
- cv[1].destination = s->physical_path;
- cv[2].destination = s->filter_content;
- cv[3].destination = s->filter_header;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-#define PATCH(x) \
- p->conf.x = s->x;
-static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH(url_raw);
- PATCH(physical_path);
- PATCH(filter_header);
- PATCH(filter_content);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_RAW_URL))) {
- PATCH(url_raw);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_PHYSICAL_PATH))) {
- PATCH(physical_path);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_FILTER_CONTENT))) {
- PATCH(filter_content);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_FILTER_HEADER))) {
- PATCH(filter_header);
- }
- }
- }
-
- return 0;
-}
-#undef PATCH
-
-static int magnet_print(lua_State *L) {
- const char *s = luaL_checkstring(L, 1);
- server *srv;
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "(lua-print)", s);
-
- return 0;
-}
-
-static int magnet_stat(lua_State *L) {
- const char *s = luaL_checkstring(L, 1);
- server *srv;
- connection *con;
- buffer sb;
- stat_cache_entry *sce = NULL;
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- lua_pushstring(L, "lighty.con");
- lua_gettable(L, LUA_REGISTRYINDEX);
- con = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- sb.ptr = (char *)s;
- sb.used = sb.size = strlen(s) + 1;
-
- if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, &sb, &sce)) {
- lua_pushnil(L);
-
- return 1;
- }
-
- lua_newtable(L);
-
- lua_pushboolean(L, S_ISREG(sce->st.st_mode));
- lua_setfield(L, -2, "is_file");
-
- lua_pushboolean(L, S_ISDIR(sce->st.st_mode));
- lua_setfield(L, -2, "is_dir");
-
- lua_pushboolean(L, S_ISCHR(sce->st.st_mode));
- lua_setfield(L, -2, "is_char");
-
- lua_pushboolean(L, S_ISBLK(sce->st.st_mode));
- lua_setfield(L, -2, "is_block");
-
- lua_pushboolean(L, S_ISSOCK(sce->st.st_mode));
- lua_setfield(L, -2, "is_socket");
-
- lua_pushboolean(L, S_ISLNK(sce->st.st_mode));
- lua_setfield(L, -2, "is_link");
-
- lua_pushboolean(L, S_ISFIFO(sce->st.st_mode));
- lua_setfield(L, -2, "is_fifo");
-
- lua_pushinteger(L, sce->st.st_mtime);
- lua_setfield(L, -2, "st_mtime");
-
- lua_pushinteger(L, sce->st.st_ctime);
- lua_setfield(L, -2, "st_ctime");
-
- lua_pushinteger(L, sce->st.st_atime);
- lua_setfield(L, -2, "st_atime");
-
- lua_pushinteger(L, sce->st.st_uid);
- lua_setfield(L, -2, "st_uid");
-
- lua_pushinteger(L, sce->st.st_gid);
- lua_setfield(L, -2, "st_gid");
-
- lua_pushinteger(L, sce->st.st_size);
- lua_setfield(L, -2, "st_size");
-
- lua_pushinteger(L, sce->st.st_ino);
- lua_setfield(L, -2, "st_ino");
-
-
- if (!buffer_is_empty(sce->etag)) {
- /* we have to mutate the etag */
- buffer *b = buffer_init();
- etag_mutate(b, sce->etag);
-
- lua_pushlstring(L, b->ptr, b->used - 1);
- buffer_free(b);
- } else {
- lua_pushnil(L);
- }
- lua_setfield(L, -2, "etag");
-
- if (!buffer_is_empty(sce->content_type)) {
- lua_pushlstring(L, sce->content_type->ptr, sce->content_type->used - 1);
- } else {
- lua_pushnil(L);
- }
- lua_setfield(L, -2, "content-type");
-
- return 1;
-}
-
-
-static int magnet_atpanic(lua_State *L) {
- const char *s = luaL_checkstring(L, 1);
- server *srv;
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "(lua-atpanic)", s);
-
- longjmp(exceptionjmp, 1);
-}
-
-static int magnet_reqhdr_get(lua_State *L) {
- server *srv;
- connection *con;
- data_string *ds;
-
- const char *key = luaL_checkstring(L, 2);
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- lua_pushstring(L, "lighty.con");
- lua_gettable(L, LUA_REGISTRYINDEX);
- con = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key, strlen(key)))) {
- if (ds->value->used) {
- lua_pushlstring(L, ds->value->ptr, ds->value->used - 1);
- } else {
- lua_pushnil(L);
- }
- } else {
- lua_pushnil(L);
- }
- return 1;
-}
-
-static int magnet_status_get(lua_State *L) {
- data_integer *di;
- server *srv;
- size_t key_len = 0;
-
- const char *key = luaL_checklstring(L, 2, &key_len);
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- di = status_counter_get_counter(key, key_len);
-
- lua_pushnumber(L, (double)di->value);
-
- return 1;
-}
-
-static int magnet_status_set(lua_State *L) {
- size_t key_len = 0;
- server *srv;
-
- const char *key = luaL_checklstring(L, 2, &key_len);
- int counter = luaL_checkint(L, 3);
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- status_counter_set(key, key_len, counter);
-
- return 0;
-}
-
-typedef struct {
- const char *name;
- enum {
- MAGNET_ENV_UNSET,
-
- MAGNET_ENV_PHYICAL_PATH,
- MAGNET_ENV_PHYICAL_REL_PATH,
- MAGNET_ENV_PHYICAL_DOC_ROOT,
-
- MAGNET_ENV_URI_PATH,
- MAGNET_ENV_URI_PATH_RAW,
- MAGNET_ENV_URI_SCHEME,
- MAGNET_ENV_URI_AUTHORITY,
- MAGNET_ENV_URI_QUERY,
-
- MAGNET_ENV_REQUEST_METHOD,
- MAGNET_ENV_REQUEST_URI,
- MAGNET_ENV_REQUEST_ORIG_URI,
- MAGNET_ENV_REQUEST_PROTOCOL
- } type;
-} magnet_env_t;
-
-static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *key) {
- buffer *dest = NULL;
- size_t i;
-
- const magnet_env_t env[] = {
- { "physical.path", MAGNET_ENV_PHYICAL_PATH },
- { "physical.rel-path", MAGNET_ENV_PHYICAL_REL_PATH },
- { "physical.doc-root", MAGNET_ENV_PHYICAL_DOC_ROOT },
-
- { "uri.path", MAGNET_ENV_URI_PATH },
- { "uri.path-raw", MAGNET_ENV_URI_PATH_RAW },
- { "uri.scheme", MAGNET_ENV_URI_SCHEME },
- { "uri.authority", MAGNET_ENV_URI_AUTHORITY },
- { "uri.query", MAGNET_ENV_URI_QUERY },
-
- { "request.method", MAGNET_ENV_REQUEST_METHOD },
- { "request.uri", MAGNET_ENV_REQUEST_URI },
- { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI },
- { "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL },
-
- { NULL, MAGNET_ENV_UNSET }
- };
-
- UNUSED(srv);
-
- /**
- * map all internal variables to lua
- *
- */
-
- for (i = 0; env[i].name; i++) {
- if (0 == strcmp(key, env[i].name)) break;
- }
-
- switch (env[i].type) {
- case MAGNET_ENV_PHYICAL_PATH: dest = con->physical.path; break;
- case MAGNET_ENV_PHYICAL_REL_PATH: dest = con->physical.rel_path; break;
- case MAGNET_ENV_PHYICAL_DOC_ROOT: dest = con->physical.doc_root; break;
-
- case MAGNET_ENV_URI_PATH: dest = con->uri.path; break;
- case MAGNET_ENV_URI_PATH_RAW: dest = con->uri.path_raw; break;
- case MAGNET_ENV_URI_SCHEME: dest = con->uri.scheme; break;
- case MAGNET_ENV_URI_AUTHORITY: dest = con->uri.authority; break;
- case MAGNET_ENV_URI_QUERY: dest = con->uri.query; break;
-
- case MAGNET_ENV_REQUEST_METHOD:
- buffer_copy_string(srv->tmp_buf, get_http_method_name(con->request.http_method));
- dest = srv->tmp_buf;
- break;
- case MAGNET_ENV_REQUEST_URI: dest = con->request.uri; break;
- case MAGNET_ENV_REQUEST_ORIG_URI: dest = con->request.orig_uri; break;
- case MAGNET_ENV_REQUEST_PROTOCOL:
- buffer_copy_string(srv->tmp_buf, get_http_version_name(con->request.http_version));
- dest = srv->tmp_buf;
- break;
-
- case MAGNET_ENV_UNSET: break;
- }
-
- return dest;
-}
-
-static int magnet_env_get(lua_State *L) {
- server *srv;
- connection *con;
-
- const char *key = luaL_checkstring(L, 2);
- buffer *dest = NULL;
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- lua_pushstring(L, "lighty.con");
- lua_gettable(L, LUA_REGISTRYINDEX);
- con = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- dest = magnet_env_get_buffer(srv, con, key);
-
- if (dest && dest->used) {
- lua_pushlstring(L, dest->ptr, dest->used - 1);
- } else {
- lua_pushnil(L);
- }
-
- return 1;
-}
-
-static int magnet_env_set(lua_State *L) {
- server *srv;
- connection *con;
-
- const char *key = luaL_checkstring(L, 2);
- const char *val = luaL_checkstring(L, 3);
- buffer *dest = NULL;
-
- lua_pushstring(L, "lighty.srv");
- lua_gettable(L, LUA_REGISTRYINDEX);
- srv = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- lua_pushstring(L, "lighty.con");
- lua_gettable(L, LUA_REGISTRYINDEX);
- con = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- if (NULL != (dest = magnet_env_get_buffer(srv, con, key))) {
- buffer_copy_string(dest, val);
- } else {
- /* couldn't save */
-
- return luaL_error(L, "couldn't store '%s' in lighty.env[]", key);
- }
-
- return 0;
-}
-
-
-static int magnet_cgi_get(lua_State *L) {
- connection *con;
- data_string *ds;
-
- const char *key = luaL_checkstring(L, 2);
-
- lua_pushstring(L, "lighty.con");
- lua_gettable(L, LUA_REGISTRYINDEX);
- con = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- if (NULL != (ds = (data_string *)array_get_element(con->environment, key, strlen(key))) && ds->value->used)
- lua_pushlstring(L, CONST_BUF_LEN(ds->value));
- else
- lua_pushnil(L);
-
- return 1;
-}
-
-static int magnet_cgi_set(lua_State *L) {
- connection *con;
-
- const char *key = luaL_checkstring(L, 2);
- const char *val = luaL_checkstring(L, 3);
-
- lua_pushstring(L, "lighty.con");
- lua_gettable(L, LUA_REGISTRYINDEX);
- con = lua_touserdata(L, -1);
- lua_pop(L, 1);
-
- array_set_key_value(con->environment, key, strlen(key), val, strlen(val));
-
- return 0;
-}
-
-
-static int magnet_copy_response_header(server *srv, connection *con, plugin_data *p, lua_State *L) {
- UNUSED(p);
- /**
- * get the environment of the function
- */
-
- lua_getfenv(L, -1); /* -1 is the function */
-
- /* lighty.header */
-
- lua_getfield(L, -1, "lighty"); /* lighty.* from the env */
- assert(lua_istable(L, -1));
-
- lua_getfield(L, -1, "header"); /* lighty.header */
- if (lua_istable(L, -1)) {
- /* header is found, and is a table */
-
- lua_pushnil(L);
- while (lua_next(L, -2) != 0) {
- if (lua_isstring(L, -1) && lua_isstring(L, -2)) {
- const char *key, *val;
- size_t key_len, val_len;
-
- key = lua_tolstring(L, -2, &key_len);
- val = lua_tolstring(L, -1, &val_len);
-
- response_header_overwrite(srv, con, key, key_len, val, val_len);
- }
-
- lua_pop(L, 1);
- }
- }
-
- lua_pop(L, 1); /* pop the header-table */
- lua_pop(L, 1); /* pop the lighty-env */
- lua_pop(L, 1); /* pop the function env */
-
- return 0;
-}
-
-/**
- * walk through the content array
- *
- * content = { "<pre>", { file = "/content" } , "</pre>" }
- *
- * header["Content-Type"] = "text/html"
- *
- * return 200
- */
-static int magnet_attach_content(server *srv, connection *con, plugin_data *p, lua_State *L) {
- UNUSED(p);
- /**
- * get the environment of the function
- */
-
- assert(lua_isfunction(L, -1));
- lua_getfenv(L, -1); /* -1 is the function */
-
- lua_getfield(L, -1, "lighty"); /* lighty.* from the env */
- assert(lua_istable(L, -1));
-
- lua_getfield(L, -1, "content"); /* lighty.content */
- if (lua_istable(L, -1)) {
- int i;
- /* header is found, and is a table */
-
- for (i = 1; ; i++) {
- lua_rawgeti(L, -1, i);
-
- /* -1 is the value and should be the value ... aka a table */
- if (lua_isstring(L, -1)) {
- size_t s_len = 0;
- const char *s = lua_tolstring(L, -1, &s_len);
-
- chunkqueue_append_mem(con->send, s, s_len);
- } else if (lua_istable(L, -1)) {
- lua_getfield(L, -1, "filename");
- lua_getfield(L, -2, "length");
- lua_getfield(L, -3, "offset");
-
- if (lua_isstring(L, -3)) { /* filename has to be a string */
- buffer *fn = buffer_init();
- stat_cache_entry *sce;
-
- buffer_copy_string(fn, lua_tostring(L, -3));
-
- if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, fn, &sce)) {
- off_t off = 0;
- off_t len = 0;
-
- if (lua_isnumber(L, -1)) {
- off = lua_tonumber(L, -1);
- }
-
- if (lua_isnumber(L, -2)) {
- len = lua_tonumber(L, -2);
- } else {
- len = sce->st.st_size;
- }
-
- if (off < 0) {
- return luaL_error(L, "offset for '%s' is negative", fn->ptr);
- }
-
- if (len < off) {
- return luaL_error(L, "offset > length for '%s'", fn->ptr);
- }
-
- chunkqueue_append_file(con->send, fn, off, len - off);
- }
-
- buffer_free(fn);
- } else {
- lua_pop(L, 3 + 2); /* correct the stack */
-
- return luaL_error(L, "content[%d] is a table and requires the field \"filename\"", i);
- }
-
- lua_pop(L, 3);
- } else if (lua_isnil(L, -1)) {
- /* oops, end of list */
-
- lua_pop(L, 1);
-
- break;
- } else {
- lua_pop(L, 4);
-
- return luaL_error(L, "content[%d] is neither a string nor a table: ", i);
- }
-
- lua_pop(L, 1); /* pop the content[...] table */
- }
- } else {
- return luaL_error(L, "lighty.content has to be a table");
- }
- lua_pop(L, 1); /* pop the header-table */
- lua_pop(L, 1); /* pop the lighty-table */
- lua_pop(L, 1); /* php the function env */
-
- return 0;
-}
-
-static int traceback (lua_State *L) {
- if (!lua_isstring(L, 1)) /* 'message' not a string? */
- return 1; /* keep it intact */
- lua_getfield(L, LUA_GLOBALSINDEX, "debug");
- if (!lua_istable(L, -1)) {
- lua_pop(L, 1);
- return 1;
- }
- lua_getfield(L, -1, "traceback");
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 2);
- return 1;
- }
- lua_pushvalue(L, 1); /* pass error message */
- lua_pushinteger(L, 2); /* skip this function and traceback */
- lua_call(L, 2, 1); /* call debug.traceback */
- return 1;
-}
-
-static int push_traceback(lua_State *L, int narg) {
- int base = lua_gettop(L) - narg; /* function index */
- lua_pushcfunction(L, traceback);
- lua_insert(L, base);
- return base;
-}
-
-static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, buffer *name) {
- lua_State *L;
- int lua_return_value = -1;
- int errfunc;
- /* get the script-context */
-
-
- L = script_cache_get_script(srv, con, p->cache, name);
-
- if (lua_isstring(L, -1)) {
- log_error_write(srv, __FILE__, __LINE__,
- "sbss",
- "loading script",
- name,
- "failed:",
- lua_tostring(L, -1));
-
- lua_pop(L, 1);
-
- assert(lua_gettop(L) == 0); /* only the function should be on the stack */
-
- con->http_status = 500;
-
- return HANDLER_FINISHED;
- }
-
- lua_pushstring(L, "lighty.srv");
- lua_pushlightuserdata(L, srv);
- lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = srv */
-
- lua_pushstring(L, "lighty.con");
- lua_pushlightuserdata(L, con);
- lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = con */
-
- lua_atpanic(L, magnet_atpanic);
-
- /**
- * we want to create empty environment for our script
- *
- * setmetatable({}, {__index = _G})
- *
- * if a function, symbol is not defined in our env, __index will lookup
- * in the global env.
- *
- * all variables created in the script-env will be thrown
- * away at the end of the script run.
- */
- lua_newtable(L); /* my empty environment aka {} (sp += 1) */
-
- /* we have to overwrite the print function */
- lua_pushcfunction(L, magnet_print); /* (sp += 1) */
- lua_setfield(L, -2, "print"); /* -1 is the env we want to set(sp -= 1) */
-
- /**
- * lighty.request[] has the HTTP-request headers
- * lighty.content[] is a table of string/file
- * lighty.header[] is an array to set response headers
- */
-
- lua_newtable(L); /* lighty.* (sp += 1) */
-
- lua_newtable(L); /* {} (sp += 1) */
- lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
- lua_pushcfunction(L, magnet_reqhdr_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
- lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */
- lua_setfield(L, -2, "request"); /* content = {} (sp -= 1) */
-
- lua_newtable(L); /* {} (sp += 1) */
- lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
- lua_pushcfunction(L, magnet_env_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
- lua_pushcfunction(L, magnet_env_set); /* (sp += 1) */
- lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
- lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */
- lua_setfield(L, -2, "env"); /* content = {} (sp -= 1) */
-
- lua_newtable(L); /* {} (sp += 1) */
- lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
- lua_pushcfunction(L, magnet_cgi_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
- lua_pushcfunction(L, magnet_cgi_set); /* (sp += 1) */
- lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
- lua_setmetatable(L, -2); /* tie the metatable to req_env (sp -= 1) */
- lua_setfield(L, -2, "req_env"); /* content = {} (sp -= 1) */
-
- lua_newtable(L); /* {} (sp += 1) */
- lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
- lua_pushcfunction(L, magnet_status_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
- lua_pushcfunction(L, magnet_status_set); /* (sp += 1) */
- lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
- lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */
- lua_setfield(L, -2, "status"); /* content = {} (sp -= 1) */
-
- /* add empty 'content' and 'header' tables */
- lua_newtable(L); /* {} (sp += 1) */
- lua_setfield(L, -2, "content"); /* content = {} (sp -= 1) */
-
- lua_newtable(L); /* {} (sp += 1) */
- lua_setfield(L, -2, "header"); /* header = {} (sp -= 1) */
-
- lua_pushinteger(L, MAGNET_RESTART_REQUEST);
- lua_setfield(L, -2, "RESTART_REQUEST");
-
- lua_pushcfunction(L, magnet_stat); /* (sp += 1) */
- lua_setfield(L, -2, "stat"); /* -1 is the env we want to set (sp -= 1) */
-
- lua_setfield(L, -2, "lighty"); /* lighty.* (sp -= 1) */
-
- lua_newtable(L); /* the meta-table for the new env (sp += 1) */
- lua_pushvalue(L, LUA_GLOBALSINDEX); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* { __index = _G } (sp -= 1) */
- lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) (sp -= 1) */
-
-
- lua_setfenv(L, -2); /* on the stack should be a modified env (sp -= 1) */
-
- errfunc = push_traceback(L, 0);
- if (lua_pcall(L, 0, 1, errfunc)) {
- lua_remove(L, errfunc);
- log_error_write(srv, __FILE__, __LINE__,
- "ss",
- "lua_pcall():",
- lua_tostring(L, -1));
- lua_pop(L, 1); /* remove the error-msg and the function copy from the stack */
-
- assert(lua_gettop(L) == 1); /* only the function should be on the stack */
-
- con->http_status = 500;
-
- return HANDLER_FINISHED;
- }
- lua_remove(L, errfunc);
-
- /* we should have the function-copy and the return value on the stack */
- assert(lua_gettop(L) == 2);
-
- if (lua_isnumber(L, -1)) {
- /* if the ret-value is a number, take it */
- lua_return_value = lua_tointeger(L, -1);
- }
- lua_pop(L, 1); /* pop the ret-value */
-
- magnet_copy_response_header(srv, con, p, L);
-
- if (lua_return_value > 99) {
- con->http_status = lua_return_value;
- con->send->is_closed = 1;
-
- /* try { ...*/
- if (0 == setjmp(exceptionjmp)) {
- magnet_attach_content(srv, con, p, L);
- } else {
- /* } catch () { */
- con->http_status = 500;
- }
-
- if (chunkqueue_is_empty(con->send)) {
- con->mode = DIRECT;
- } else {
- con->mode = p->id;
- }
-
- assert(lua_gettop(L) == 1); /* only the function should be on the stack */
-
- /* we are finished */
- return HANDLER_FINISHED;
- } else if (MAGNET_RESTART_REQUEST == lua_return_value) {
- assert(lua_gettop(L) == 1); /* only the function should be on the stack */
- buffer_reset(con->physical.path);
-
- return HANDLER_COMEBACK;
- } else {
- assert(lua_gettop(L) == 1); /* only the function should be on the stack */
-
- return HANDLER_GO_ON;
- }
-}
-
-static handler_t magnet_attract_array(server *srv, connection *con, plugin_data *p, array *files) {
- size_t i;
- handler_t ret = HANDLER_GO_ON;
-
- /* no filename set */
- if (files->used == 0) return HANDLER_GO_ON;
-
- /**
- * execute all files and jump out on the first !HANDLER_GO_ON
- */
- for (i = 0; i < files->used; i++) {
- data_string *ds = (data_string *)files->data[i];
-
- if (buffer_is_empty(ds->value)) continue;
-
- ret = magnet_attract(srv, con, p, ds->value);
-
- if (ret != HANDLER_GO_ON) break;
- }
-
- /* reset conditional cache. */
- config_cond_cache_reset_all_items(srv, con);
-
- return ret;
-}
-
-URIHANDLER_FUNC(mod_magnet_uri_handler) {
- plugin_data *p = p_d;
-
- mod_magnet_patch_connection(srv, con, p);
-
- return magnet_attract_array(srv, con, p, p->conf.url_raw);
-}
-
-URIHANDLER_FUNC(mod_magnet_physical) {
- plugin_data *p = p_d;
-
- mod_magnet_patch_connection(srv, con, p);
-
- return magnet_attract_array(srv, con, p, p->conf.physical_path);
-}
-
-URIHANDLER_FUNC(mod_magnet_handle_response_header) {
- plugin_data *p = p_d;
-
- mod_magnet_patch_connection(srv, con, p);
-
- return magnet_attract_array(srv, con, p, p->conf.filter_header);
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_magnet_plugin_init(plugin *p);
-LI_EXPORT int mod_magnet_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string(PLUGIN_NAME);
-
- p->init = mod_magnet_init;
- p->set_defaults = mod_magnet_set_defaults;
- p->cleanup = mod_magnet_free;
-
- p->handle_uri_clean = mod_magnet_uri_handler; /* match against the uri */
- p->handle_physical = mod_magnet_physical; /* match against the filename */
-
- p->handle_response_header = mod_magnet_handle_response_header;
-#if 0
- p->handle_filter_response_content = mod_magnet_handle_filter_response_content;
-#endif
-
- p->data = NULL;
-
- return 0;
-}
-
-#else
-LI_EXPORT int mod_magnet_plugin_init(plugin *p);
-LI_EXPORT int mod_magnet_plugin_init(plugin *p) {
- UNUSED(p);
- return -1;
-}
-#endif
diff --git a/src/mod_magnet_cache.c b/src/mod_magnet_cache.c
deleted file mode 100644
index 0cd1bcc3..00000000
--- a/src/mod_magnet_cache.c
+++ /dev/null
@@ -1,137 +0,0 @@
-#include <stdlib.h>
-#include <time.h>
-#include <assert.h>
-
-#include "stat_cache.h"
-#include "mod_magnet_cache.h"
-
-#ifdef HAVE_LUA_H
-#include <lualib.h>
-#include <lauxlib.h>
-
-static script *script_init() {
- script *sc;
-
- sc = calloc(1, sizeof(*sc));
- sc->name = buffer_init();
- sc->etag = buffer_init();
-
- return sc;
-}
-
-static void script_free(script *sc) {
- if (!sc) return;
-
- lua_pop(sc->L, 1); /* the function copy */
-
- buffer_free(sc->name);
- buffer_free(sc->etag);
-
- lua_close(sc->L);
-
- free(sc);
-}
-
-script_cache *script_cache_init() {
- script_cache *p;
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-void script_cache_free(script_cache *p) {
- size_t i;
-
- if (!p) return;
-
- for (i = 0; i < p->used; i++) {
- script_free(p->ptr[i]);
- }
-
- free(p->ptr);
-
- free(p);
-}
-
-lua_State *script_cache_get_script(server *srv, connection *con, script_cache *cache, buffer *name) {
- size_t i;
- script *sc = NULL;
- stat_cache_entry *sce;
-
- for (i = 0; i < cache->used; i++) {
- sc = cache->ptr[i];
-
- if (buffer_is_equal(name, sc->name)) {
- sc->last_used = time(NULL);
-
- /* oops, the script failed last time */
-
- if (lua_gettop(sc->L) == 0) break;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, sc->name, &sce)) {
- lua_pop(sc->L, 1); /* pop the old function */
- break;
- }
-
- if (!buffer_is_equal(sce->etag, sc->etag)) {
- /* the etag is outdated, reload the function */
- lua_pop(sc->L, 1);
- break;
- }
-
- assert(lua_isfunction(sc->L, -1));
- lua_pushvalue(sc->L, -1); /* copy the function-reference */
-
- return sc->L;
- }
-
- sc = NULL;
- }
-
- /* if the script was script already loaded but either got changed or
- * failed to load last time */
- if (sc == NULL) {
- sc = script_init();
-
- if (cache->size == 0) {
- cache->size = 16;
- cache->ptr = malloc(cache->size * sizeof(*(cache->ptr)));
- } else if (cache->used == cache->size) {
- cache->size += 16;
- cache->ptr = realloc(cache->ptr, cache->size * sizeof(*(cache->ptr)));
- }
-
- cache->ptr[cache->used++] = sc;
-
- buffer_copy_string_buffer(sc->name, name);
-
- sc->L = luaL_newstate();
- luaL_openlibs(sc->L);
- }
-
- sc->last_used = time(NULL);
-
- if (0 != luaL_loadfile(sc->L, name->ptr)) {
- /* oops, an error, return it */
-
- return sc->L;
- }
-
- if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, sc->name, &sce)) {
- buffer_copy_string_buffer(sc->etag, sce->etag);
- }
-
- /**
- * pcall() needs the function on the stack
- *
- * as pcall() will pop the script from the stack when done, we have to
- * duplicate it here
- */
- assert(lua_isfunction(sc->L, -1));
- lua_pushvalue(sc->L, -1); /* copy the function-reference */
-
- return sc->L;
-}
-
-#endif
diff --git a/src/mod_magnet_cache.h b/src/mod_magnet_cache.h
deleted file mode 100644
index 50c9e44a..00000000
--- a/src/mod_magnet_cache.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _MOD_MAGNET_CACHE_H_
-#define _MOD_MAGNET_CACHE_H_
-
-#include "buffer.h"
-#include "base.h"
-
-#ifdef HAVE_LUA_H
-#include <lua.h>
-
-typedef struct {
- buffer *name;
- buffer *etag;
-
- lua_State *L;
-
- time_t last_used; /* LRU */
-} script;
-
-typedef struct {
- script **ptr;
-
- size_t used;
- size_t size;
-} script_cache;
-
-script_cache *script_cache_init(void);
-void script_cache_free(script_cache *cache);
-
-lua_State *script_cache_get_script(server *srv, connection *con,
- script_cache *cache, buffer *name);
-
-#endif
-#endif
diff --git a/src/mod_mysql_vhost.c b/src/mod_mysql_vhost.c
deleted file mode 100644
index 68b65d52..00000000
--- a/src/mod_mysql_vhost.c
+++ /dev/null
@@ -1,309 +0,0 @@
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_MYSQL_H
-# ifdef HAVE_LIBMYSQL
-# define HAVE_MYSQL
-# endif
-#endif
-
-#ifdef HAVE_MYSQL
-#include <mysql.h>
-#endif
-
-#include "plugin.h"
-#include "log.h"
-
-#include "stat_cache.h"
-#include "sys-files.h"
-
-#include "mod_sql_vhost_core.h"
-
-#ifdef HAVE_MYSQL
-
-#define CORE_PLUGIN "mod_sql_vhost_core"
-
-typedef struct {
- MYSQL *mysql;
-
- buffer *mysql_pre;
- buffer *mysql_post;
-
- mod_sql_vhost_core_plugin_config *core;
-} plugin_config;
-
-/* global plugin data */
-typedef struct {
- PLUGIN_DATA;
-
- buffer *tmp_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
-
-/* init the plugin data */
-INIT_FUNC(mod_mysql_vhost_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- return p;
-}
-
-/* cleanup the plugin data */
-SERVER_FUNC(mod_mysql_vhost_cleanup) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- mysql_close(s->mysql);
-
- buffer_free(s->mysql_pre);
- buffer_free(s->mysql_post);
-
- free(s);
- }
- free(p->config_storage);
- }
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* set configuration values */
-SERVER_FUNC(mod_mysql_vhost_set_defaults) {
- plugin_data *p = p_d;
- mod_sql_vhost_core_plugin_data *core_config;
-
- size_t i = 0;
-
- /* our very own plugin storage, one entry for each conditional
- *
- * srv->config_context->used is the number of conditionals
- * */
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- /* get the config of the core-plugin */
- core_config = plugin_get_config(srv, CORE_PLUGIN);
-
- /* walk through all conditionals and check for assignments */
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- buffer *sel;
- char *qmark;
-
- /* get the config from the core plugin for this conditional-context */
- s = calloc(1, sizeof(plugin_config));
-
- s->core = core_config->config_storage[i];
-
- s->mysql = NULL;
-
- s->mysql_pre = buffer_init();
- s->mysql_post = buffer_init();
-
- p->config_storage[i] = s;
-
- /* check if we are the plugin for this backend */
- if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
-
- /* attach us to the core-plugin */
- s->core->backend_data = p;
- s->core->get_vhost = mod_mysql_vhost_get_vhost;
-
- sel = buffer_init();
- buffer_copy_string_buffer(sel, s->core->select_vhost);
-
- if (sel->used && (qmark = strchr(sel->ptr, '?'))) {
- *qmark = '\0';
- buffer_copy_string(s->mysql_pre, sel->ptr);
- buffer_copy_string(s->mysql_post, qmark+1);
- } else {
- buffer_copy_string_buffer(s->mysql_pre, sel);
- }
- buffer_free(sel);
-
- /* required:
- * - username
- * - database
- *
- * optional:
- * - password, default: empty
- * - socket, default: mysql default
- * - hostname, if set overrides socket
- * - port, default: 3306
- */
-
- /* all have to be set */
- if (!(buffer_is_empty(s->core->user) ||
- buffer_is_empty(s->core->db))) {
-
- int fd;
-
- if (NULL == (s->mysql = mysql_init(NULL))) {
- log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
-
- return HANDLER_ERROR;
- }
-
-#if MYSQL_VERSION_ID >= 50003
- /* in mysql versions above 5.0.3 the reconnect flag is off by default */
- {
- my_bool reconnect = 1;
- mysql_options(s->mysql, MYSQL_OPT_RECONNECT, &reconnect);
- }
-#endif
-
-#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
-
- s->mysql->free_me = 1;
-
- if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
- FOO(db), s->core->port, FOO(sock), 0)) {
- log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
-
- return HANDLER_ERROR;
- }
-#undef FOO
- /* set close_on_exec for mysql the hard way */
- /* Note: this only works as it is done during startup, */
- /* otherwise we cannot be sure that mysql is fd i-1 */
- if (-1 == (fd = open("/dev/null", 0))) {
- close(fd);
- fcntl(fd-1, F_SETFD, FD_CLOEXEC);
- }
- }
- }
-
-
-
- return HANDLER_GO_ON;
-}
-
-static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(mysql_pre);
- PATCH_OPTION(mysql_post);
- PATCH_OPTION(mysql);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- if (s->mysql) {
- PATCH_OPTION(mysql);
- PATCH_OPTION(mysql_pre);
- PATCH_OPTION(mysql_post);
- }
- }
-
- return 0;
-}
-
-/**
- * get the vhost info from the database
- */
-SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
- plugin_data *p = p_d;
- unsigned cols;
- MYSQL_ROW row;
- MYSQL_RES *result = NULL;
-
- UNUSED(host);
-
- /* no host specified? */
- if (!con->uri.authority->used) return HANDLER_ERROR;
-
- mod_mysql_vhost_patch_connection(srv, con, p);
-
- if (!p->conf.mysql) return HANDLER_ERROR;
-
- /* build and run SQL query */
- buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
- if (p->conf.mysql_post->used) {
- buffer_append_string_buffer(p->tmp_buf, con->uri.authority);
- buffer_append_string_buffer(p->tmp_buf, p->conf.mysql_post);
- }
- if (mysql_query(p->conf.mysql, BUF_STR(p->tmp_buf))) {
- ERROR("mysql_query(%s) failed: %s", SAFE_BUF_STR(p->tmp_buf), mysql_error(p->conf.mysql));
-
- mysql_free_result(result);
- return HANDLER_ERROR;
- }
- result = mysql_store_result(p->conf.mysql);
- cols = mysql_num_fields(result);
- row = mysql_fetch_row(result);
-
- if (!row || cols < 1) {
- /* no such virtual host */
- mysql_free_result(result);
- return HANDLER_ERROR;
- }
-
- buffer_copy_string(docroot, row[0]);
-
- mysql_free_result(result);
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-LI_EXPORT int mod_mysql_vhost_plugin_init(plugin *p);
-LI_EXPORT int mod_mysql_vhost_plugin_init(plugin *p) {
- data_string *ds;
-
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mysql_vhost");
-
- p->init = mod_mysql_vhost_init;
- p->cleanup = mod_mysql_vhost_cleanup;
-
- p->set_defaults = mod_mysql_vhost_set_defaults;
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN));
- array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
-}
-#else
-/* we don't have mysql support, this plugin does nothing */
-LI_EXPORT int mod_mysql_vhost_plugin_init(plugin *p);
-LI_EXPORT int mod_mysql_vhost_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mysql_vhost");
-
- return 0;
-}
-#endif
diff --git a/src/mod_postgresql_vhost.c b/src/mod_postgresql_vhost.c
deleted file mode 100644
index 2e0f4a7f..00000000
--- a/src/mod_postgresql_vhost.c
+++ /dev/null
@@ -1,371 +0,0 @@
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdbool.h>
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_LIBPQ_FE_H
-# ifdef HAVE_LIBPQ
-# define HAVE_POSTGRESQL
-# endif
-#endif
-
-#ifdef HAVE_POSTGRESQL
-#include <glib.h>
-#include <libpq-fe.h>
-#include <time.h>
-#endif
-
-#include "plugin.h"
-#include "log.h"
-
-#include "stat_cache.h"
-#include "sys-files.h"
-
-#include "mod_sql_vhost_core.h"
-
-#ifdef HAVE_POSTGRESQL
-// Define a couple constants so the cache expires and we
-// do a countdown for when to do some cleanup.
-
-typedef struct {
- PGconn **pconn;
- PGconn *conn;
-
- buffer *postgresql_pre;
- buffer *postgresql_post;
-
- buffer *conninfo;
-
- mod_sql_vhost_core_plugin_config *core;
-} plugin_config;
-
-/* global plugin data */
-typedef struct {
- PLUGIN_DATA;
-
- buffer *tmp_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-#define CORE_PLUGIN "mod_sql_vhost_core"
-
-SQLVHOST_BACKEND_GETVHOST(mod_postgresql_vhost_get_vhost);
-
-/* init the plugin data */
-INIT_FUNC(mod_postgresql_vhost_init) {
- plugin_data *p;
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- return p;
-}
-
-/* cleanup the plugin data */
-SERVER_FUNC(mod_postgresql_vhost_cleanup) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- PQfinish(s->conn);
- buffer_free(s->postgresql_pre);
- buffer_free(s->postgresql_post);
- buffer_free(s->conninfo);
-
- free(s);
- }
- free(p->config_storage);
- }
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-
-/* set configuration values */
-SERVER_FUNC(mod_postgresql_vhost_set_defaults) {
- plugin_data *p = p_d;
- mod_sql_vhost_core_plugin_data *core_config;
-
- size_t i = 0;
-
- /* our very own plugin storage, one entry for each conditional
- *
- * srv->config_context->used is the number of conditionals
- * */
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- /* get the config of the core-plugin */
- core_config = plugin_get_config(srv, CORE_PLUGIN);
-
- /* walk through all conditionals and check for assignments */
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- buffer *sel;
- char *qmark;
-
- /* get the config from the core plugin for this conditional-context */
- s = calloc(1, sizeof(plugin_config));
-
- s->core = core_config->config_storage[i];
- s->conn = NULL;
- s->pconn = &(s->conn);
-
- s->postgresql_pre = buffer_init();
- s->postgresql_post = buffer_init();
- s->conninfo = buffer_init();
-
- p->config_storage[i] = s;
-
- /* check if we are the plugin for this backend */
- if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("postgresql"))) continue;
-
- /* attach us to the core-plugin */
- s->core->backend_data = p;
- s->core->get_vhost = mod_postgresql_vhost_get_vhost;
-
- sel = buffer_init();
- buffer_copy_string_buffer(sel, s->core->select_vhost);
-
- if (sel->used && (qmark = strchr(sel->ptr, '?'))) {
- *qmark = '\0';
- buffer_copy_string(s->postgresql_pre, sel->ptr);
- buffer_copy_string(s->postgresql_post, qmark+1);
- } else {
- buffer_copy_string_buffer(s->postgresql_pre, sel);
- }
- buffer_free(sel);
-
- /* see if we can build our connection string based on the parts we know from the config
- *
- * "host=/tmp dbname=lighttpd user=lighttpd"
- * */
-
- if (!buffer_is_empty(s->core->hostname)) {
- buffer_append_string_len(s->conninfo, CONST_STR_LEN("host="));
- buffer_append_string_buffer(s->conninfo, s->core->hostname);
- if (s->core->port) {
- buffer_append_string_len(s->conninfo, CONST_STR_LEN(" "));
- buffer_append_string_len(s->conninfo, CONST_STR_LEN("port="));
- buffer_append_long(s->conninfo, s->core->port);
- }
- } else if (!buffer_is_empty(s->core->sock)) {
- buffer_append_string_len(s->conninfo, CONST_STR_LEN("host="));
- buffer_append_string_buffer(s->conninfo, s->core->sock);
- }
-
- if (!buffer_is_empty(s->core->db)) {
- if (!buffer_is_empty(s->conninfo)) buffer_append_string_len(s->conninfo, CONST_STR_LEN(" "));
- buffer_append_string_len(s->conninfo, CONST_STR_LEN("dbname="));
- buffer_append_string_buffer(s->conninfo, s->core->db);
- }
-
- if (!buffer_is_empty(s->core->user)) {
- if (!buffer_is_empty(s->conninfo)) buffer_append_string_len(s->conninfo, CONST_STR_LEN(" "));
- buffer_append_string_len(s->conninfo, CONST_STR_LEN("user="));
- buffer_append_string_buffer(s->conninfo, s->core->user);
- }
-
- if (!buffer_is_empty(s->core->pass)) {
- if (!buffer_is_empty(s->conninfo)) buffer_append_string_len(s->conninfo, CONST_STR_LEN(" "));
- buffer_append_string_len(s->conninfo, CONST_STR_LEN("password="));
- buffer_append_string_buffer(s->conninfo, s->core->pass);
- }
-
- }
-
- return HANDLER_GO_ON;
-}
-
-
-static int mod_postgresql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(postgresql_pre);
- PATCH_OPTION(postgresql_post);
- PATCH_OPTION(conn);
- PATCH_OPTION(pconn);
- PATCH_OPTION(conninfo);
- PATCH_OPTION(core);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("postgresql"))) continue;
-
- PATCH_OPTION(pconn);
- PATCH_OPTION(conn);
- PATCH_OPTION(conninfo);
- PATCH_OPTION(postgresql_pre);
- PATCH_OPTION(postgresql_post);
- PATCH_OPTION(core);
- }
-
- return 0;
-}
-
-/*
- * get the vhost info from the database
- */
-SQLVHOST_BACKEND_GETVHOST(mod_postgresql_vhost_get_vhost) {
- plugin_data *p = p_d;
- int nFields;
- PGresult *result;
- gchar *field;
-
- UNUSED(host);
-
- /* no host specified? */
- if (buffer_is_empty(con->uri.authority)) return HANDLER_ERROR;
-
- mod_postgresql_vhost_patch_connection(srv, con, p);
-
- if (buffer_is_empty(p->conf.conninfo)) return HANDLER_ERROR;
-
- /**
- * try to connect the pg-server
- */
- if (p->conf.conn == NULL) {
- if (p->conf.core->debug) TRACE("connecting to postgres: %s", SAFE_BUF_STR(p->conf.conninfo));
-
- if (NULL == (p->conf.conn = PQconnectdb(BUF_STR(p->conf.conninfo)))) {
- ERROR("%s", "postgresql malloc failure");
-
- return HANDLER_ERROR;
- }
-
- /* we have to update the pointer in the conditional cache too */
- *(p->conf.pconn) = p->conf.conn;
-
- /* For when we move to Async requests
- * PQsetnonblocking(s->conn,1);
- */
-
- if (CONNECTION_BAD == PQstatus(p->conf.conn)) {
- /* Even if bad connection. maybe next time it can be fixed
- */
- ERROR("Bad connection for '%s': %s", SAFE_BUF_STR(p->conf.conninfo), PQerrorMessage(p->conf.conn));
-
- PQfinish(p->conf.conn);
-
- p->conf.conn = NULL;
-
- return HANDLER_ERROR;
- }
-
- if (PQstatus(p->conf.conn) != CONNECTION_OK){
- ERROR("PQconnectdb() failed: %i", PQstatus(p->conf.conn));
-
- PQfinish(p->conf.conn);
-
- p->conf.conn = NULL;
-
- return HANDLER_ERROR;
- }
- }
-
- /**
- * TODO: Change to a stored proc to simiplify this
- * build and run SQL query
- */
- if (PQstatus(p->conf.conn) != CONNECTION_OK) {
- PQreset(p->conf.conn);
- }
-
- buffer_copy_string_buffer(p->tmp_buf, p->conf.postgresql_pre);
- if (p->conf.postgresql_post->used) {
- buffer_append_string_buffer(p->tmp_buf, con->uri.authority);
- buffer_append_string_buffer(p->tmp_buf, p->conf.postgresql_post);
- }
-
- result = PQexec(p->conf.conn, p->tmp_buf->ptr);
-
- /**
- * For Async requests. Database will block/slow down your daemon
- * result = PQsendQuery(p->conf.conn, p->tmp_buf->ptr);
- */
- if (result == NULL) {
- ERROR("PQexec(%s) failed: %s", SAFE_BUF_STR(p->tmp_buf), PQerrorMessage(p->conf.conn));
- return HANDLER_ERROR;
- }
-
- if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- ERROR("PQresultStatus(%s): %s", SAFE_BUF_STR(p->tmp_buf), PQerrorMessage(p->conf.conn));
-
- PQclear(result);
-
- return HANDLER_ERROR;
- }
- /**
- * FIXME:
- * We checked for tupels already, but will add more sanity
- */
- nFields = PQnfields(result);
- if (PQntuples(result) < 1 || nFields < 1 ||
- (field = PQgetvalue(result, 0, 0)) == NULL || !*field) {
- /* no such virtual host */
- PQclear(result);
-
- return HANDLER_ERROR;
- }
-
- buffer_copy_string(docroot, field);
-
- PQclear(result);
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-LI_EXPORT int mod_postgresql_vhost_plugin_init(plugin *p);
-LI_EXPORT int mod_postgresql_vhost_plugin_init(plugin *p) {
- data_string *ds;
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("postgresql_vhost");
- p->init = mod_postgresql_vhost_init;
- p->cleanup = mod_postgresql_vhost_cleanup;
- p->set_defaults = mod_postgresql_vhost_set_defaults;
-
- ds = data_string_init();
-
- buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN));
- array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
-}
-#else
-/* we don't have postgresql support, this plugin does nothing */
-LI_EXPORT int mod_postgresql_vhost_plugin_init(plugin *p);
-LI_EXPORT int mod_postgresql_vhost_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("postgresql_vhost");
-
- return 0;
-}
-#endif
diff --git a/src/mod_proxy_backend_ajp13.c b/src/mod_proxy_backend_ajp13.c
deleted file mode 100644
index 1c674f8f..00000000
--- a/src/mod_proxy_backend_ajp13.c
+++ /dev/null
@@ -1,836 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#include "inet_ntop_cache.h"
-#include "mod_proxy_core.h"
-#include "mod_proxy_core_protocol.h"
-#include "buffer.h"
-#include "log.h"
-#include "array.h"
-#include "keyvalue.h"
-#include "ajp13.h"
-
-#define CORE_PLUGIN "mod_proxy_core"
-
-typedef struct {
- http_method_t http;
- ajp13_method_t ajp13;
-} http_method_map;
-
-static http_method_map http_methods[] = {
- { HTTP_METHOD_GET, AJP13_METHOD_GET },
- { HTTP_METHOD_POST, AJP13_METHOD_POST },
- { HTTP_METHOD_HEAD, AJP13_METHOD_HEAD },
- { HTTP_METHOD_OPTIONS, AJP13_METHOD_OPTIONS },
- { HTTP_METHOD_PROPFIND, AJP13_METHOD_PROPFIND },
- { HTTP_METHOD_MKCOL, AJP13_METHOD_MKCOL },
- { HTTP_METHOD_PUT, AJP13_METHOD_PUT },
- { HTTP_METHOD_DELETE, AJP13_METHOD_DELETE },
- { HTTP_METHOD_COPY, AJP13_METHOD_COPY },
- { HTTP_METHOD_MOVE, AJP13_METHOD_MOVE },
- { HTTP_METHOD_PROPPATCH, AJP13_METHOD_PROPPATCH },
- { HTTP_METHOD_REPORT, AJP13_METHOD_REPORT },
- { HTTP_METHOD_CHECKOUT, AJP13_METHOD_CHECKOUT },
- { HTTP_METHOD_CHECKIN, AJP13_METHOD_CHECKIN },
- { HTTP_METHOD_VERSION_CONTROL, AJP13_METHOD_VERSION_CONTROL },
- { HTTP_METHOD_UNCHECKOUT, AJP13_METHOD_UNCHECKOUT },
- { HTTP_METHOD_MKACTIVITY, AJP13_METHOD_MKACTIVITY },
- { HTTP_METHOD_MERGE, AJP13_METHOD_MERGE },
- { HTTP_METHOD_LOCK, AJP13_METHOD_LOCK },
- { HTTP_METHOD_UNLOCK, AJP13_METHOD_UNLOCK },
- { HTTP_METHOD_LABEL, AJP13_METHOD_LABEL },
- { HTTP_METHOD_CONNECT, AJP13_METHOD_UNKNOWN },
- { HTTP_METHOD_UNSET, AJP13_METHOD_UNKNOWN }
-};
-
-static ajp13_method_t ajp13_convert_http_method(http_method_t http_method) {
- int i;
- /* try fast lookup. if http_methods[] is sorted, we will find it this way. */
- if(http_method != HTTP_METHOD_UNSET) {
- if(http_methods[http_method].http == http_method) {
- return http_methods[http_method].ajp13;
- }
- }
- /* walk the list to find ajp13 method. */
- for(i = 0; http_methods[i].http != HTTP_METHOD_UNSET; i++) {
- if(http_methods[i].http == http_method) return http_methods[i].http;
- }
- return AJP13_METHOD_UNKNOWN;
-}
-
-/*
- * request header keyvalue map.
- *
- * Note: The strings have to be uppercase
- */
-static keyvalue request_headers[] = {
- { AJP13_REQ_ACCEPT, "ACCEPT" },
- { AJP13_REQ_ACCEPT_CHARSET, "ACCEPT-CHARSET" },
- { AJP13_REQ_ACCEPT_ENCODING, "ACCEPT-ENCODING" },
- { AJP13_REQ_ACCEPT_LANGUAGE, "ACCEPT-LANGUAGE" },
- { AJP13_REQ_AUTHORIZATION, "AUTHORIZATION" },
- { AJP13_REQ_CONNECTION, "CONNECTION" },
- { AJP13_REQ_CONTENT_TYPE, "CONTENT-TYPE" },
- { AJP13_REQ_CONTENT_LENGTH, "CONTENT-LENGTH" },
- { AJP13_REQ_COOKIE, "COOKIE" },
- { AJP13_REQ_COOKIE2, "COOKIE2" },
- { AJP13_REQ_HOST, "HOST" },
- { AJP13_REQ_PRAGMA, "PRAGMA" },
- { AJP13_REQ_REFERER, "REFERER" },
- { AJP13_REQ_USER_AGENT, "USER-AGENT" },
-
- { -1, NULL }
-};
-
-/*
- * response header keyvalue map
- *
- * Note: The strings don't have to be all uppercase here
- */
-static keyvalue response_headers[] = {
- { AJP13_RESP_CONTENT_TYPE, "Content-Type" },
- { AJP13_RESP_CONTENT_LANGUAGE, "Content-Language" },
- { AJP13_RESP_CONTENT_LENGTH, "Content-Length" },
- { AJP13_RESP_DATE, "Date" },
- { AJP13_RESP_LAST_MODIFIED, "Last-Modified" },
- { AJP13_RESP_LOCATION, "Location" },
- { AJP13_RESP_SET_COOKIE, "Set-Cookie" },
- { AJP13_RESP_SET_COOKIE2, "Set-Cookie2" },
- { AJP13_RESP_SERVLET_ENGINE, "Servlet-Engine" },
- { AJP13_RESP_STATUS, "Status" },
- { AJP13_RESP_WWW_AUTHENTICATE, "WWW-Authenticate" },
- { -1, NULL }
-};
-
-
-typedef struct {
- PLUGIN_DATA;
-
- proxy_protocol *protocol;
-} protocol_plugin_data;
-
-typedef struct {
- size_t len;
- off_t offset;
- int type;
-} ajp13_packet;
-
-typedef struct {
- unsigned char magicB0;
- unsigned char magicB1;
- unsigned char lengthB0;
- unsigned char lengthB1;
- unsigned char type;
-} AJP13_Header;
-
-/**
- * init the AJP13_header
- */
-static int ajp13_header(char *ptr, int length) {
- AJP13_Header * header = (AJP13_Header *)ptr;
- header->magicB0 = (AJP13_SERVER_MAGIC >> 8) & 0xff;
- header->magicB1 = (AJP13_SERVER_MAGIC ) & 0xff;
- header->lengthB0 = (length >> 8) & 0xff;
- header->lengthB1 = (length ) & 0xff;
- return AJP13_HEADER_LEN;
-}
-
-/**
- * The ajp13 protocol decoder will use this struct for storing state variables
- * used in decoding the stream
- */
-typedef struct {
- buffer *buf; /* holds raw header bytes or used to buffer STDERR */
- off_t offset; /* parse offset into buffer. */
- ajp13_packet packet; /* parsed info about current packet. */
- size_t chunk_len; /* chunk length */
- size_t requested_bytes; /* backend requested we send this many bytes of the request content. */
-} ajp13_state_data;
-
-static ajp13_state_data *ajp13_state_data_init(void) {
- ajp13_state_data *data;
-
- data = calloc(1, sizeof(*data));
- data->buf = buffer_init();
-
- return data;
-}
-
-static void ajp13_state_data_free(ajp13_state_data *data) {
- buffer_free(data->buf);
- free(data);
-}
-
-static void ajp13_state_data_reset(ajp13_state_data *data) {
- buffer_reset(data->buf);
- data->packet.len = 0;
- data->packet.offset = 0;
- data->packet.type = 0;
- data->offset = 0;
- data->chunk_len = 0;
-}
-
-/**
- * encode ajp13 byte/boolean
- */
-static int ajp13_encode_byte(buffer *buf, int val) {
-
- /* format : 2 bytes integer */
- buffer_prepare_append(buf, 1);
-
- buf->ptr[buf->used++] = val;
-
- return 1;
-}
-
-/**
- * encode ajp13 integer (2 bytes)
- */
-static int ajp13_encode_int(buffer *buf, int val) {
-
- /* format : 2 bytes integer */
- buffer_prepare_append(buf, 2);
-
- buf->ptr[buf->used++] = (val >> 8) & 0xff;
- buf->ptr[buf->used++] = (val >> 0) & 0xff;
-
- return 2;
-}
-
-/**
- * encode ajp13 string.
- */
-static int ajp13_encode_string(buffer *buf, const char *str, size_t str_len) {
- size_t len = 0;
-
- if (!str || str_len == 0) {
- return ajp13_encode_int(buf,0xFFFF);
- }
-
- /* format : 2 byte string length : string : null */
- len = 2 + str_len + 1;
-
- buffer_prepare_append(buf, len);
-
- ajp13_encode_int(buf,str_len);
- /* include the NUL */
- buffer_append_memory(buf, str, str_len + 1);
-
- return len;
-}
-
-/**
- * add a key-value pair to the ajp13-buffer
- */
-#define MAX_KEY_LEN 16
-static int ajp13_env_add(buffer *buf, const char *key, size_t key_len, const char *val, size_t val_len) {
- char uppercase_key[MAX_KEY_LEN];
- size_t len = 0;
- int code = -1;
- size_t i;
-
- if (!key || !val) return -1;
-
- if(key_len < MAX_KEY_LEN) {
- /* convert key to uppercase */
- for(i=0;i <key_len;i++) {
- uppercase_key[i] = toupper(key[i]);
- }
- uppercase_key[key_len] = '\0';
- code = keyvalue_get_key(request_headers, uppercase_key);
- }
- if(code >= 0) {
- len += ajp13_encode_int(buf, AJP13_COMMON_HEADER_CODE + code);
- } else {
- len += ajp13_encode_string(buf, key, key_len);
- }
- len += ajp13_encode_string(buf, val, val_len);
-
- return len;
-}
-
-/**
- * decode ajp13 integer (2 bytes)
- */
-static int ajp13_decode_int(ajp13_state_data *data) {
- int val = 0;
-
- if ((data->buf->used - data->offset) <= 2) return -1;
-
- val = (unsigned char)data->buf->ptr[data->offset++];
- val <<= 8;
- val |= (unsigned char)data->buf->ptr[data->offset++];
-
- return val;
-}
-
-/**
- * decode ajp13 string.
- */
-static int ajp13_decode_string(buffer *str, ajp13_state_data *data, int is_header) {
- size_t len = 0;
- const char *p = NULL;
-
- if (!str) {
- return len;
- }
-
- /* string length */
- len = ajp13_decode_int(data);
- if ((ssize_t)len == -1) {
- ERROR("ajp13_decode_int() returned invalid len: %zu", len);
- return len;
- }
-#ifdef AJP13_DEBUG
- TRACE("ajp13_decode_string() string-len: %zu (is_header: %d, common-header: %zd)", len, is_header, (len & AJP13_COMMON_HEADER_CODE));
-#endif
-
- /* if string is header, check for common header code. */
- if (is_header && (len & AJP13_COMMON_HEADER_CODE)) {
- p = keyvalue_get_value(response_headers, len & ~AJP13_COMMON_HEADER_CODE);
- if (p) {
- len = strlen(p);
- } else {
- ERROR("ajp13_decode_string() can't resolve common-header: %zd", len & ~AJP13_COMMON_HEADER_CODE);
-
- return -1;
- }
- }
- /* copy string from buffer. */
- if (p == NULL) {
- if ((data->buf->used - data->offset) <= (len + 1)) {
- ERROR("we have %jd bytes, but a partial-string wants %zu. no way", (intmax_t) (data->buf->used - data->offset), len);
- return -1;
- }
- p = data->buf->ptr + data->offset;
- data->offset += len + 1;
- }
- buffer_copy_string_len(str, p, len);
-
- return len;
-}
-
-/**
- * decode ajp13 response headers
- */
-static int ajp13_decode_response_headers(http_resp *resp, ajp13_state_data *data) {
- buffer *key, *value;
- int key_len, value_len;
- int i,num;
-
- resp->protocol = HTTP_VERSION_UNSET;
- resp->status = ajp13_decode_int(data);
-
- if (resp->status == -1) {
- ERROR("parsing AJP13 response-status failed, got %d", resp->status);
- return -1;
- }
-
- if (ajp13_decode_string(resp->reason, data, 0) == -1) {
- ERROR("parsing AJP13 response-reason failed: %s", "...");
- return -1;
- }
-
-#ifdef AJP13_DEBUG
- TRACE("ajp13: header-status: %d", resp->status);
- TRACE("ajp13: header-reason: %s", resp->reason->ptr);
-#endif
-
- /* leave if we have no headers to decode */
- num = ajp13_decode_int(data);
-#ifdef AJP13_DEBUG
- TRACE("ajp13: header-count: %d", num);
-#endif
-
- if (0 == num) return 0;
-
- key = buffer_init();
- value = buffer_init();
- for(i = 0; i < num; i++) {
- key_len = ajp13_decode_string(key, data, 1);
- value_len = ajp13_decode_string(value, data, 1);
-#ifdef AJP13_DEBUG
- TRACE("ajp13: header[%d]: key-len: %d, value-len: %d", i, key_len, value_len);
-#endif
-
- if (key_len > 0 && value_len >= 0) {
- data_string *HDR;
- if (NULL == (HDR = (data_string *)array_get_unused_element(resp->headers, TYPE_STRING))) {
- HDR = data_response_init();
- }
-
- buffer_copy_string_len(HDR->key, key->ptr, key_len);
- buffer_copy_string_len(HDR->value, value->ptr, value_len);
-
- array_insert_unique(resp->headers, (data_unset *)HDR);
-#ifdef AJP13_DEBUG
- TRACE("ajp13: header[%d]: %s = %s", i, key->ptr, value->ptr);
-#endif
- } else {
- ERROR("ajp13: response-headers skipped: key-len = %d, val-len = %d", key_len, value_len);
- }
- }
- buffer_free(key);
- buffer_free(value);
-
- return 0;
-}
-
-PROXY_CONNECTION_FUNC(proxy_ajp13_init) {
- UNUSED(srv);
-
- if(!proxy_con->protocol_data) {
- proxy_con->protocol_data = ajp13_state_data_init();
- }
- return 1;
-}
-
-PROXY_CONNECTION_FUNC(proxy_ajp13_cleanup) {
- UNUSED(srv);
-
- if(proxy_con->protocol_data) {
- ajp13_state_data_free((ajp13_state_data *)proxy_con->protocol_data);
- proxy_con->protocol_data = NULL;
- }
- return 1;
-}
-
-static int proxy_ajp13_forward_request(server *srv, connection *con, proxy_session *sess, buffer *packet) {
- char buf[32];
- const char *str;
- server_socket *srv_sock = con->srv_socket;
-#ifdef HAVE_IPV6
- char b2[INET6_ADDRSTRLEN + 1];
-#endif
- int len = 0,port = 0;
- size_t i;
-
- /* prefix_code */
- len += ajp13_encode_byte(packet, AJP13_TYPE_FORWARD_REQUEST);
-
- /* http method */
- len += ajp13_encode_byte(packet, ajp13_convert_http_method(con->request.http_method));
-
- /* protocol */
- str = get_http_version_name(con->request.http_version);
- len += ajp13_encode_string(packet, str, strlen(str));
-
- /* request uri
- *
- * the docs where unspecific here, but it looks like tomcat wants to get
- * the uri without the query-string here */
- len += ajp13_encode_string(packet, CONST_BUF_LEN(con->uri.path));
-
- /* remote address */
- str = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- len += ajp13_encode_string(packet, str, strlen(str));
-
- /* remote host */
- len += ajp13_encode_string(packet, CONST_STR_LEN(""));
-
- /* server name */
- if (con->server_name->used) {
- len += ajp13_encode_string(packet, CONST_BUF_LEN(con->server_name));
- } else {
-#ifdef HAVE_IPV6
- str = inet_ntop(srv_sock->addr.plain.sa_family,
- srv_sock->addr.plain.sa_family == AF_INET6 ?
- (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
- (const void *) &(srv_sock->addr.ipv4.sin_addr),
- b2, sizeof(b2)-1);
-#else
- str = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
-#endif
- len += ajp13_encode_string(packet, str, strlen(str));
- }
-
- /* server port */
-#ifdef HAVE_IPV6
- port = ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port);
-#else
- port = ntohs(srv_sock->addr.ipv4.sin_port);
-#endif
- len += ajp13_encode_int(packet, port);
-
- /* is_ssl */
-#ifdef USE_OPENSSL
- len += ajp13_encode_byte(packet, srv_sock->is_ssl);
-#else
- len += ajp13_encode_byte(packet, 0);
-#endif
-
- /* make sure we have content-length header */
- if(con->request.content_length > 0) {
- LI_ltostr(buf, con->request.content_length);
- array_set_key_value(sess->request_headers, CONST_STR_LEN("Content-Length"), buf, strlen(buf));
- } else {
- array_set_key_value(sess->request_headers, CONST_STR_LEN("Content-Length"), CONST_STR_LEN("0"));
- }
-
- /* request headers count */
- len += ajp13_encode_int(packet, sess->request_headers->used);
-
- /* request headers */
- for (i = 0; i < sess->request_headers->used; i++) {
- data_string *ds;
- ds = (data_string *)sess->request_headers->data[i];
- len += ajp13_env_add(packet, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
- }
-
- /* remote user */
- if (!buffer_is_empty(con->authed_user)) {
- len += ajp13_encode_byte(packet, AJP13_ATTRIBUTE_REMOTE_USER);
- len += ajp13_encode_string(packet, CONST_BUF_LEN(con->authed_user));
- }
-
- /* query string */
- if (!buffer_is_empty(con->uri.query)) {
- len += ajp13_encode_byte(packet, AJP13_ATTRIBUTE_QUERY_STRING);
- len += ajp13_encode_string(packet, CONST_BUF_LEN(con->uri.query));
- }
-
- /* jvm_route */
- if (!buffer_is_empty(sess->proxy_con->address->name)) {
- len += ajp13_encode_byte(packet, AJP13_ATTRIBUTE_JVM_ROUTE);
- len += ajp13_encode_string(packet, CONST_BUF_LEN(sess->proxy_con->address->name));
- }
-
- /* request terminator */
- len += ajp13_encode_byte(packet, AJP13_ATTRIBUTE_ARE_DONE);
-
- return len;
-}
-
-PROXY_STREAM_ENCODER_FUNC(proxy_ajp13_encode_request_headers) {
- proxy_connection *proxy_con = sess->proxy_con;
- ajp13_state_data *data = (ajp13_state_data *)proxy_con->protocol_data;
- chunkqueue *out = proxy_con->send;
- connection *con = sess->remote_con;
- buffer *packet;
- size_t len;
-
- UNUSED(srv);
- UNUSED(in);
-
- packet = chunkqueue_get_append_buffer(out);
- buffer_prepare_copy(packet, 1024);
-
- /* reserve bytes for header. Will over right header when we know packet length. */
- packet->used += AJP13_HEADER_LEN;
-
- /* send AJP13_TYPE_FORWARD_REQUEST */
- len = proxy_ajp13_forward_request(srv, con, sess, packet);
- packet->used++; /* this is needed because the network will only write "used - 1" bytes */
- out->bytes_in += packet->used - 1;
-
- /* rewrite packet header with correct length. */
- ajp13_header(packet->ptr, len);
-
- if(con->request.content_length > AJP13_MAX_BODY_PACKET_SIZE) {
- data->requested_bytes = AJP13_MAX_BODY_PACKET_SIZE;
- } else if(con->request.content_length > 0) {
- data->requested_bytes = con->request.content_length;
- } else {
- data->requested_bytes = 0;
- }
-
- return HANDLER_FINISHED;
-}
-
-/*
- * copy len bytes from chunk-chain into buffer
- */
-static int proxy_ajp13_fill_buffer(ajp13_state_data *data, chunkqueue *in, size_t len) {
- off_t we_have = 0, we_need = len;
- chunk *c;
-
- buffer_prepare_append(data->buf, we_need);
- for (c = in->first; c && we_need > 0; c = c->next) {
- if(c->mem->used == 0) continue;
-
- we_have = c->mem->used - c->offset - 1;
- if (we_have == 0) continue;
- if (we_have > we_need) we_have = we_need;
-
- buffer_append_string_len(data->buf, c->mem->ptr + c->offset, we_have);
- data->packet.offset += we_have;
- c->offset += we_have;
- in->bytes_out += we_have;
- we_need -= we_have;
- }
- return we_need;
-}
-
-PROXY_STREAM_DECODER_FUNC(proxy_ajp13_stream_decoder_internal) {
- proxy_connection *proxy_con = sess->proxy_con;
- ajp13_state_data *data = (ajp13_state_data *)proxy_con->protocol_data;
- chunkqueue *in = proxy_con->recv;
- AJP13_Header *header;
- size_t we_parsed = 0, we_need = 0;
- handler_t rc = HANDLER_GO_ON;
- int magic = 0;
- int reuse = 0;
-
- UNUSED(srv);
-
- /* no data ? */
- if (!in->first) return HANDLER_WAIT_FOR_EVENT;
-
- /* parse the packet header. */
- if(data->packet.offset < AJP13_FULL_HEADER_LEN) {
- we_need = (AJP13_FULL_HEADER_LEN - data->packet.offset);
- /* copy ajp13 header to buffer */
- we_need = proxy_ajp13_fill_buffer(data, in, we_need);
- /* make sure we have the full ajp13 header. */
- if(we_need > 0) {
- /* we need more data to parse the header. */
- return HANDLER_WAIT_FOR_EVENT;
- }
- /* parse raw header. */
- header = (AJP13_Header *)(data->buf->ptr);
-
- data->packet.len = ((header->lengthB0 << 8) | header->lengthB1);
- data->packet.len--; /* packet type byte already parsed. */
- data->packet.type = header->type;
- magic = ((header->magicB0 << 8) | header->magicB1);
- if (magic != AJP13_CONTAINER_MAGIC) {
- ERROR("%s", "bad ajp13 magic code, invalid protocl stream");
- return HANDLER_ERROR;
- }
-
- /* Finished parsing raw header bytes. */
- buffer_reset(data->buf);
- }
-
- /* for most packet types copy the content into the data buffer */
- if (data->packet.type != AJP13_TYPE_SEND_BODY_CHUNK) {
- we_need = data->packet.len - (data->packet.offset - AJP13_FULL_HEADER_LEN);
- if(we_need > 0) {
- /* copy ajp13 packet contents to buffer */
- we_need = proxy_ajp13_fill_buffer(data, in, we_need);
- /* make sure we have the full ajp13 packet content. */
- if(we_need > 0) {
- /* we need more data to parse the content. */
- return HANDLER_WAIT_FOR_EVENT;
- }
- }
- }
-
- switch (data->packet.type) {
- case AJP13_TYPE_GET_BODY_CHUNK:
- data->requested_bytes = ajp13_decode_int(data);
- break;
- case AJP13_TYPE_SEND_HEADERS:
- if (ajp13_decode_response_headers(sess->resp, data) == -1) {
- ERROR("%s", "Error parsing response_headers");
- rc = HANDLER_ERROR;
- }
- sess->have_response_headers = 1;
- break;
- case AJP13_TYPE_SEND_BODY_CHUNK:
- /* parse chunk length */
- we_parsed = (data->packet.offset - AJP13_FULL_HEADER_LEN);
- if (we_parsed < 2) {
- we_need = 2 - we_parsed;
- /* copy chunk length bytes to buffer */
- we_need = proxy_ajp13_fill_buffer(data, in, we_need);
- if(we_need > 0) {
- /* we need more data to parse the chunk length. */
- return HANDLER_WAIT_FOR_EVENT;
- }
- /* parse chunk length */
- data->chunk_len = ajp13_decode_int(data);
- }
- /* parse chunk data. */
- we_parsed = (data->packet.offset - 2 - AJP13_FULL_HEADER_LEN);
- if(we_parsed < data->chunk_len) {
- we_need = data->chunk_len - we_parsed;
- /* copy chunk data */
- we_parsed = chunkqueue_steal_chunks_len(out, in->first, we_need);
- data->packet.offset += we_parsed;
- we_need -= we_parsed;
- in->bytes_out += we_parsed;
- out->bytes_in += we_parsed;
- }
- we_need = data->packet.len - (data->packet.offset - AJP13_FULL_HEADER_LEN);
- /* ignore padding */
- if(we_need > 0) {
- we_parsed = chunkqueue_skip(in, we_need);
- data->packet.offset += we_parsed;
- we_need -= we_parsed;
- in->bytes_out += we_parsed;
- }
- rc = HANDLER_GO_ON;
- break;
- case AJP13_TYPE_END_RESPONSE:
- if(data->buf->used >= 1) {
- reuse = data->buf->ptr[0];
- }
- if(reuse != 1) {
- sess->is_closing = 1;
- }
- sess->is_request_finished = 1;
- /* close the queues. no more data to decode. */
- in->is_closed = 1;
- out->is_closed = 1;
- /* make sure the send queue is closed, since we can't send any more request content. */
- proxy_con->send->is_closed = 1;
- rc = HANDLER_FINISHED;
- break;
- default:
- TRACE("unknown packet.type: %d", data->packet.type);
- rc = HANDLER_ERROR;
- break;
- }
-
- if(we_need == 0) {
- /* packet finished, reset state for next packet */
- ajp13_state_data_reset(data);
- }
-
- chunkqueue_remove_finished_chunks(in);
-
- return rc;
-}
-
-PROXY_STREAM_DECODER_FUNC(proxy_ajp13_stream_decoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *in = proxy_con->recv;
- int res;
-
- if(out->is_closed) return 1;
- /* decode the whole packet stream */
- do {
- /* decode the packet */
- res = proxy_ajp13_stream_decoder_internal(srv, sess, out);
- } while (in->first && res == HANDLER_GO_ON);
-
- if (res == HANDLER_WAIT_FOR_EVENT) {
- if (in->is_closed) return HANDLER_ERROR;
- return HANDLER_GO_ON;
- }
-
- return res;
-}
-
-/**
- * transform the content-stream into a valid FastCGI STDIN content-stream
- *
- * as we don't apply chunked-encoding here, pass it on AS IS
- */
-PROXY_STREAM_ENCODER_FUNC(proxy_ajp13_stream_encoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- ajp13_state_data *data = (ajp13_state_data *)proxy_con->protocol_data;
- chunkqueue *out = proxy_con->send;
- size_t we_need = 0, we_have = 0;
- buffer *b;
-
- UNUSED(srv);
-
- /* output queue closed, can't encode any more data. */
- if(out->is_closed) return HANDLER_FINISHED;
-
- if (data->requested_bytes == 0) {
- /* backend needs to send a request for more content before we can encode more. */
- return HANDLER_GO_ON;
- }
-
- /* calculate how many bytes we can encode. */
- if (in->bytes_in > in->bytes_out) {
- we_need = in->bytes_in - in->bytes_out;
- if (we_need > AJP13_MAX_BODY_PACKET_SIZE) we_need = AJP13_MAX_BODY_PACKET_SIZE;
- if (we_need > data->requested_bytes) we_need = data->requested_bytes;
-
- data->requested_bytes = 0;
- }
- /*
- * write ajp13 header
- */
- b = chunkqueue_get_append_buffer(out);
- buffer_prepare_copy(b, AJP13_HEADER_LEN);
- b->used += AJP13_HEADER_LEN;
- if (we_need > 0) {
- ajp13_header(b->ptr, we_need + 2);
- ajp13_encode_int(b, we_need);
- } else {
- /* empty body packet to mark EOF, if the backend requested data beyond
- * the end of the request content.
- */
- ajp13_header(b->ptr, we_need);
- }
- out->bytes_in += b->used;
- b->used++;
-
- we_have = chunkqueue_steal_chunks_len(out, in->first, we_need);
- in->bytes_out += we_have;
- out->bytes_in += we_have;
-
- if (in->bytes_in == in->bytes_out && in->is_closed) {
- /* We are finished encoding the request content,
- * but we can't close the send queue here since the backend might
- * try to request more request content then is available and
- * we will have to response with a 0 length body packet.
- */
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
-}
-
-INIT_FUNC(mod_proxy_backend_ajp13_init) {
- mod_proxy_core_plugin_data *core_data;
- protocol_plugin_data *p;
-
- /* get the plugin_data of the core-plugin */
- core_data = plugin_get_config(srv, CORE_PLUGIN);
- if(!core_data) return NULL;
-
- p = calloc(1, sizeof(*p));
-
- /* define protocol handler callbacks */
- p->protocol = core_data->proxy_register_protocol("ajp13");
-
- p->protocol->proxy_stream_init = proxy_ajp13_init;
- p->protocol->proxy_stream_cleanup = proxy_ajp13_cleanup;
- p->protocol->proxy_stream_decoder = proxy_ajp13_stream_decoder;
- p->protocol->proxy_stream_encoder = proxy_ajp13_stream_encoder;
- p->protocol->proxy_encode_request_headers = proxy_ajp13_encode_request_headers;
-
- return p;
-}
-
-FREE_FUNC(mod_proxy_backend_ajp13_free) {
- protocol_plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_proxy_backend_ajp13_plugin_init(plugin *p);
-LI_EXPORT int mod_proxy_backend_ajp13_plugin_init(plugin *p) {
- data_string *ds;
-
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mod_proxy_backend_ajp13");
-
- p->init = mod_proxy_backend_ajp13_init;
- p->cleanup = mod_proxy_backend_ajp13_free;
-
- p->data = NULL;
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN));
- array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
-}
-
-
diff --git a/src/mod_proxy_backend_fastcgi.c b/src/mod_proxy_backend_fastcgi.c
deleted file mode 100644
index 3ba7c5e6..00000000
--- a/src/mod_proxy_backend_fastcgi.c
+++ /dev/null
@@ -1,819 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "sys-strings.h"
-#include "inet_ntop_cache.h"
-#include "mod_proxy_core.h"
-#include "mod_proxy_core_protocol.h"
-#include "buffer.h"
-#include "log.h"
-#include "fastcgi.h"
-#include "array.h"
-
-#define CORE_PLUGIN "mod_proxy_core"
-
-typedef struct {
- PLUGIN_DATA;
-
- proxy_protocol *protocol;
-} protocol_plugin_data;
-
-/**
- * we aren't supporting multiplexing
- *
- * use always the same request-id
- */
-#define PROXY_FASTCGI_REQUEST_ID 1
-#if 1
-#define PROXY_FASTCGI_USE_KEEP_ALIVE 1
-#endif
-
-typedef struct {
- size_t len;
- off_t offset;
- int type;
- int padding;
- size_t request_id;
-} fastcgi_packet;
-
-/**
- * The fastcgi protocol decoder will use this struct for storing state variables
- * used in decoding the stream
- */
-typedef struct {
- buffer *buf; /* holds raw header bytes or used to buffer STDERR */
- fastcgi_packet packet; /* parsed info about current packet. */
- int is_complete;
-} fcgi_state_data;
-
-static fcgi_state_data *fcgi_state_data_init(void) {
- fcgi_state_data *data;
-
- data = calloc(1, sizeof(*data));
- data->buf = buffer_init();
-
- return data;
-}
-
-static void fcgi_state_data_free(fcgi_state_data *data) {
- buffer_free(data->buf);
- free(data);
-}
-
-static void fcgi_state_data_reset(fcgi_state_data *data) {
- buffer_reset(data->buf);
- data->packet.len = 0;
- data->packet.offset = 0;
- data->packet.type = 0;
- data->packet.padding = 0;
- data->packet.request_id = 0;
- data->is_complete = 0;
-}
-
-PROXY_CONNECTION_FUNC(proxy_fastcgi_init) {
- UNUSED(srv);
-
- if(!proxy_con->protocol_data) {
- proxy_con->protocol_data = fcgi_state_data_init();
- }
- return 1;
-}
-
-PROXY_CONNECTION_FUNC(proxy_fastcgi_cleanup) {
- UNUSED(srv);
-
- if(proxy_con->protocol_data) {
- fcgi_state_data_free((fcgi_state_data *)proxy_con->protocol_data);
- proxy_con->protocol_data = NULL;
- }
- return 1;
-}
-
-static int proxy_fastcgi_get_env_fastcgi(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
- char buf[32];
- const char *s;
- server_socket *srv_sock = con->srv_socket;
-#ifdef HAVE_IPV6
- char b2[INET6_ADDRSTRLEN + 1];
-#endif
-
- sock_addr our_addr;
- socklen_t our_addr_len;
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
-
- if (con->server_name->used) {
- size_t len = con->server_name->used - 1;
- char *colon = strchr(con->server_name->ptr, ':');
- if (colon) len = colon - con->server_name->ptr;
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_NAME"), con->server_name->ptr, len);
- } else {
-#ifdef HAVE_IPV6
- s = inet_ntop(srv_sock->addr.plain.sa_family,
- srv_sock->addr.plain.sa_family == AF_INET6 ?
- (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
- (const void *) &(srv_sock->addr.ipv4.sin_addr),
- b2, sizeof(b2)-1);
-#else
- s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
-#endif
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
- }
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
-
- LI_ltostr(buf,
-#ifdef HAVE_IPV6
- ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
-#else
- ntohs(srv_sock->addr.ipv4.sin_port)
-#endif
- );
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
-
- /* get the server-side of the connection to the client */
- our_addr_len = sizeof(our_addr);
-
- if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) {
- s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
- } else {
- s = inet_ntop_cache_get_ip(srv, &(our_addr));
- }
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
-
- LI_ltostr(buf,
-#ifdef HAVE_IPV6
- ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
-#else
- ntohs(con->dst_addr.ipv4.sin_port)
-#endif
- );
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
-
- s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
-
- if (!buffer_is_empty(con->authed_user)) {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REMOTE_USER"),
- CONST_BUF_LEN(con->authed_user));
- }
-
- if (con->request.content_length > 0) {
- /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
-
- /* request.content_length < SSIZE_MAX, see request.c */
- LI_ltostr(buf, con->request.content_length);
- array_set_key_value(sess->env_headers, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
- }
-
-
- /*
- * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
- * http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
- * (6.1.14, 6.1.6, 6.1.7)
- * For AUTHORIZER mode these headers should be omitted.
- */
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
-
- if (!buffer_is_empty(con->request.pathinfo)) {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
-
- /* PATH_TRANSLATED is only defined if PATH_INFO is set */
-
- buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
- buffer_append_string_buffer(p->tmp_buf, con->request.pathinfo);
- array_set_key_value(sess->env_headers, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->tmp_buf));
- } else {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN(""));
- }
-
- /*
- * SCRIPT_FILENAME and DOCUMENT_ROOT for php. The PHP manual
- * http://www.php.net/manual/en/reserved.variables.php
- * treatment of PATH_TRANSLATED is different from the one of CGI specs.
- * TODO: this code should be checked against cgi.fix_pathinfo php
- * parameter.
- */
-
- if (1) {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
- array_set_key_value(sess->env_headers, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
- }
-
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
-
- if (!buffer_is_equal(sess->request_uri, con->request.orig_uri)) {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(sess->request_uri));
- }
- if (!buffer_is_empty(con->uri.query)) {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
- } else {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
- }
-
- s = get_http_method_name(con->request.http_method);
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
- array_set_key_value(sess->env_headers, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
- s = get_http_version_name(con->request.http_version);
- array_set_key_value(sess->env_headers, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
-
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- array_set_key_value(sess->env_headers, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
- }
-#endif
-
- return 0;
-}
-
-/**
- * transform the HTTP-Request headers into CGI notation
- */
-static int proxy_fastcgi_get_env_request(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
- size_t i;
-
- UNUSED(srv);
- UNUSED(con);
-
- /* the request header got already copied into the sess->request_headers for us
- * no extra filter is needed
- *
- * prepend a HTTP_ and uppercase the keys
- */
- for (i = 0; i < sess->request_headers->used; i++) {
- data_string *ds;
- size_t j;
-
- ds = (data_string *)sess->request_headers->data[i];
-
- buffer_reset(p->tmp_buf);
-
- if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
- buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("HTTP_"));
- p->tmp_buf->used--;
- }
-
- buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
- for (j = 0; j < ds->key->used - 1; j++) {
- char c = '_';
- if (light_isalpha(ds->key->ptr[j])) {
- /* upper-case */
- c = ds->key->ptr[j] & ~32;
- } else if (light_isdigit(ds->key->ptr[j])) {
- /* copy */
- c = ds->key->ptr[j];
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = c;
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
-
- array_set_key_value(sess->env_headers, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
- }
-
- for (i = 0; i < con->environment->used; i++) {
- data_string *ds;
- size_t j;
-
- ds = (data_string *)con->environment->data[i];
-
- buffer_reset(p->tmp_buf);
-
- buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
- for (j = 0; j < ds->key->used - 1; j++) {
- char c = '_';
- if (light_isalpha(ds->key->ptr[j])) {
- /* upper-case */
- c = ds->key->ptr[j] & ~32;
- } else if (light_isdigit(ds->key->ptr[j])) {
- /* copy */
- c = ds->key->ptr[j];
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = c;
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
-
- array_set_key_value(sess->env_headers, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
- }
-
- return 0;
-}
-
-
-/**
- * add a key-value pair to the fastcgi-buffer
- */
-
-static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
- size_t len;
-
- if (!key || !val) return -1;
-
- len = key_len + val_len;
-
- len += key_len > 127 ? 4 : 1;
- len += val_len > 127 ? 4 : 1;
-
- /**
- * ensure we don't create a longer packet than fastcgi can handle
- */
- if (env->used + len >= FCGI_MAX_LENGTH) {
- return -1;
- }
-
- buffer_prepare_append(env, len);
-
- if (key_len > 127) {
- env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
- env->ptr[env->used++] = (key_len >> 16) & 0xff;
- env->ptr[env->used++] = (key_len >> 8) & 0xff;
- env->ptr[env->used++] = (key_len >> 0) & 0xff;
- } else {
- env->ptr[env->used++] = (key_len >> 0) & 0xff;
- }
-
- if (val_len > 127) {
- env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
- env->ptr[env->used++] = (val_len >> 16) & 0xff;
- env->ptr[env->used++] = (val_len >> 8) & 0xff;
- env->ptr[env->used++] = (val_len >> 0) & 0xff;
- } else {
- env->ptr[env->used++] = (val_len >> 0) & 0xff;
- }
-
- memcpy(env->ptr + env->used, key, key_len);
- env->used += key_len;
- memcpy(env->ptr + env->used, val, val_len);
- env->used += val_len;
-
- return 0;
-}
-
-/**
- * init the FCGI_header
- */
-static int fcgi_header(FCGI_Header * header, unsigned char type, size_t request_id, int contentLength, unsigned char paddingLength) {
- header->version = FCGI_VERSION_1;
- header->type = type;
- header->requestIdB0 = request_id & 0xff;
- header->requestIdB1 = (request_id >> 8) & 0xff;
- header->contentLengthB0 = contentLength & 0xff;
- header->contentLengthB1 = (contentLength >> 8) & 0xff;
- header->paddingLength = paddingLength;
- header->reserved = 0;
-
- return 0;
-}
-
-
-PROXY_STREAM_ENCODER_FUNC(proxy_fastcgi_encode_request_headers) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *out = proxy_con->send;
- connection *con = sess->remote_con;
- buffer *b, *packet;
- size_t i;
- FCGI_BeginRequestRecord beginRecord;
- FCGI_Header header;
- plugin_data *p = sess->p;
-
- UNUSED(srv);
- UNUSED(in);
-
- b = chunkqueue_get_append_buffer(out);
- /* send FCGI_BEGIN_REQUEST */
-
- fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, PROXY_FASTCGI_REQUEST_ID, sizeof(beginRecord.body), 0);
- beginRecord.body.roleB0 = FCGI_RESPONDER;
- beginRecord.body.roleB1 = 0;
-#ifdef PROXY_FASTCGI_USE_KEEP_ALIVE
- if (p->conf.max_keep_alive_requests && p->conf.max_pool_size) {
- /**
- * only announce keep-alive if we really can handle it
- */
- beginRecord.body.flags = FCGI_KEEP_CONN;
- } else {
- beginRecord.body.flags = 0;
- }
-#else
- beginRecord.body.flags = 0;
-#endif
- memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
-
- buffer_copy_string_len(b, (const char *)&beginRecord, sizeof(beginRecord));
- out->bytes_in += sizeof(beginRecord);
-
- /* send FCGI_PARAMS */
- b = chunkqueue_get_append_buffer(out);
- buffer_prepare_copy(b, 1024);
-
- /* fill the sess->env_headers */
- array_reset(sess->env_headers);
- proxy_fastcgi_get_env_request(srv, con, p, sess);
- proxy_fastcgi_get_env_fastcgi(srv, con, p, sess);
-
- packet = buffer_init();
-
- for (i = 0; i < sess->env_headers->used; i++) {
- data_string *ds;
-
- ds = (data_string *)sess->env_headers->data[i];
- fcgi_env_add(packet, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
- }
-
- fcgi_header(&(header), FCGI_PARAMS, PROXY_FASTCGI_REQUEST_ID, packet->used, 0);
- buffer_append_memory(b, (const char *)&header, sizeof(header));
- buffer_append_memory(b, (const char *)packet->ptr, packet->used);
- out->bytes_in += sizeof(header);
- out->bytes_in += packet->used - 1;
-
- buffer_free(packet);
-
- fcgi_header(&(header), FCGI_PARAMS, PROXY_FASTCGI_REQUEST_ID, 0, 0);
- buffer_append_memory(b, (const char *)&header, sizeof(header));
- b->used++;
- out->bytes_in += sizeof(header) + 1;
-
- return HANDLER_FINISHED;
-}
-
-/**
- * parse the HTTP response header
- */
-static handler_t proxy_fastcgi_http_response_headers(proxy_session *sess, chunkqueue *in) {
- http_response_reset(sess->resp);
-
- /* http response parser. */
- switch(http_response_parse_cq(in, sess->resp)) {
- case PARSE_ERROR:
- /* bad gateway */
- http_response_reset(sess->resp);
- sess->have_response_headers = 1;
- sess->resp->status = 502;
- return HANDLER_ERROR;
- case PARSE_NEED_MORE:
- return HANDLER_GO_ON;
- case PARSE_SUCCESS:
- default:
- /* finished parsing response headers. */
- sess->have_response_headers = 1;
- return HANDLER_FINISHED;
- }
-}
-
-PROXY_STREAM_DECODER_FUNC(proxy_fastcgi_stream_decoder_internal) {
- proxy_connection *proxy_con = sess->proxy_con;
- fcgi_state_data *data = (fcgi_state_data *)proxy_con->protocol_data;
- chunkqueue *in = proxy_con->recv;
- FCGI_Header *header;
- off_t we_have = 0, we_need = 0;
- handler_t rc = HANDLER_GO_ON;
- chunk *c;
-
- UNUSED(srv);
-
- if ((in->bytes_in == in->bytes_out) && in->is_closed) {
- /* everything got passed through,
- *
- * as we usually have a FIN packet we should expect to get a is_closed within the
- * fcgi-stream. Looks like the remote side crashed
- * */
- out->is_closed = 1;
-
- TRACE("%jd / %jd -> %d",
- (intmax_t) in->bytes_in, (intmax_t) in->bytes_out,
- in->is_closed);
-
-
- ERROR("looks like the fastcgi-backend (%s) terminated before it sent a FIN packet", SAFE_BUF_STR(sess->request_uri));
-
- return HANDLER_FINISHED;
- }
-
- /* no data ? */
- if (!in->first) return HANDLER_GO_ON;
-
- /* a single network packet might contain multiple fcgi packets */
- if(!data->is_complete) {
- we_need = (FCGI_HEADER_LEN - data->packet.offset);
-
- /**
- * a the fcgi header might spread over multiple network packets
- */
- for (c = in->first; c && we_need > 0; c = c->next) {
- if (c->mem->used == 0) continue;
-
- we_have = c->mem->used - c->offset - 1;
- if (we_have == 0) continue;
- if (we_have > we_need) we_have = we_need;
-
- buffer_append_string_len(data->buf, c->mem->ptr + c->offset, we_have);
- data->packet.offset += we_have;
- c->offset += we_have;
- in->bytes_out += we_have;
- we_need -= we_have;
- }
- /* make sure we have the full fastcgi header. */
- if(we_need > 0) {
- chunkqueue_remove_finished_chunks(in);
- /* we need more data to parse the header. */
- return HANDLER_GO_ON;
- }
-
- /* parse raw header. */
- header = (FCGI_Header *)(data->buf->ptr);
-
- data->packet.len = (header->contentLengthB0 | (header->contentLengthB1 << 8));
- data->packet.request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
- data->packet.type = header->type;
- data->packet.padding = header->paddingLength;
- data->is_complete = 1;
-
- /* Finished parsing raw header bytes. */
- buffer_reset(data->buf);
- }
-
- /* proccess the packet's contents. */
- we_need = data->packet.len - (data->packet.offset - FCGI_HEADER_LEN);
-
- switch (data->packet.type) {
- case FCGI_STDOUT:
- if (we_need > 0) {
- /* copy packet contents */
- we_have = chunkqueue_steal_chunks_len(out, in->first, we_need);
- data->packet.offset += we_have;
- we_need -= we_have;
- in->bytes_out += we_have;
- out->bytes_in += we_have;
- } else {
- /**
- * we might come here again if the padding is part of the next packet
- *
- * read(15, "\1\6\0\1\1D\4\0", 16384) = 8
- * read(15, "Status: 200 Ok\r\nCache-contro...
- * read(15, "\0\0\0\0\1\6\0\1\37\370\0\0", 16384) = 12
- *
- */
-#if 0
- /* FIXME: for which case did we set this to 1 ? */
- out->is_closed = 1;
-#endif
- }
-
- /* parse response headers. */
- if (!sess->have_response_headers) {
- /* check if we have all the response headers */
- switch (proxy_fastcgi_http_response_headers(sess, out)) {
- case HANDLER_FINISHED:
- /* the headers are complete */
-
- rc = HANDLER_GO_ON;
- break;
- case HANDLER_GO_ON:
- /* no finished yet */
- rc = HANDLER_GO_ON;
- break;
- default:
- /* something failed */
- rc = HANDLER_ERROR;
- break;
- }
- } else {
- rc = HANDLER_GO_ON;
- }
- break;
- case FCGI_STDERR:
- if(we_need > 0) {
- buffer *b = buffer_init();
- buffer_prepare_append(b, we_need);
- for (c = in->first; c && we_need > 0; c = c->next) {
- if (c->mem->used == 0) continue;
-
- we_have = c->mem->used - c->offset - 1;
- if (we_have == 0) continue;
- if (we_have > we_need) we_have = we_need;
-
- buffer_append_string_len(b, c->mem->ptr + c->offset, we_have);
- data->packet.offset += we_have;
- c->offset += we_have;
- in->bytes_out += we_have;
- we_need -= we_have;
- }
-/**
-==18752== Conditional jump or move depends on uninitialised value(s)
-==18752== at 0x401D255: strlen (mc_replace_strmem.c:246)
-==18752== by 0x42B7A1B: vfprintf (in /lib/tls/i686/cmov/libc-2.3.6.so)
-==18752== by 0x42D6280: vsnprintf (in /lib/tls/i686/cmov/libc-2.3.6.so)
-==18752== by 0x805EAAD: log_trace (log.c:325)
-==18752== by 0x4513C5B: proxy_fastcgi_stream_decoder (mod_proxy_backend_fastcgi.c:594)
-==18752== by 0x4565130: proxy_stream_decoder (mod_proxy_core.c:587)
-==18752== by 0x4565D46: proxy_stream_encode_decode (mod_proxy_core.c:855)
-==18752== by 0x4567D69: proxy_state_engine (mod_proxy_core.c:1567)
-==18752== by 0x45686C7: mod_proxy_core_start_backend (mod_proxy_core.c:2397)
-==18752== by 0x4568CBC: mod_proxy_send_request_content (mod_proxy_core.c:2441)
-==18752== by 0x80634EC: plugins_call_handle_send_request_content (plugin.c:387)
-==18752== by 0x8054CE7: connection_state_machine (connections.c:1192)
-==18752==
-==18752== Syscall param write(buf) points to uninitialised byte(s)
-==18752== at 0x4000792: (within /lib/ld-2.3.6.so)
-==18752== by 0x4513C5B: proxy_fastcgi_stream_decoder (mod_proxy_backend_fastcgi.c:594)
-==18752== by 0x4565130: proxy_stream_decoder (mod_proxy_core.c:587)
-==18752== by 0x4565D46: proxy_stream_encode_decode (mod_proxy_core.c:855)
-==18752== by 0x4567D69: proxy_state_engine (mod_proxy_core.c:1567)
-==18752== by 0x45686C7: mod_proxy_core_start_backend (mod_proxy_core.c:2397)
-==18752== by 0x4568CBC: mod_proxy_send_request_content (mod_proxy_core.c:2441)
-==18752== by 0x80634EC: plugins_call_handle_send_request_content (plugin.c:387)
-==18752== by 0x8054CE7: connection_state_machine (connections.c:1192)
-==18752== by 0x804F5D8: lighty_mainloop (server.c:1001)
-==18752== by 0x80517AE: main (server.c:1705)
-==18752== Address 0x4A7C899 is 81 bytes inside a block of size 4,160 alloc'd
-==18752== at 0x401C4B0: malloc (vg_replace_malloc.c:149)
-==18752== by 0x805DCFA: buffer_prepare_copy (buffer.c:85)
-==18752== by 0x805EA7E: log_trace (log.c:321)
-==18752== by 0x4513C5B: proxy_fastcgi_stream_decoder (mod_proxy_backend_fastcgi.c:594)
-==18752== by 0x4565130: proxy_stream_decoder (mod_proxy_core.c:587)
-==18752== by 0x4565D46: proxy_stream_encode_decode (mod_proxy_core.c:855)
-==18752== by 0x4567D69: proxy_state_engine (mod_proxy_core.c:1567)
-==18752== by 0x45686C7: mod_proxy_core_start_backend (mod_proxy_core.c:2397)
-==18752== by 0x4568CBC: mod_proxy_send_request_content (mod_proxy_core.c:2441)
-==18752== by 0x80634EC: plugins_call_handle_send_request_content (plugin.c:387)
-==18752== by 0x8054CE7: connection_state_machine (connections.c:1192)
-==18752== by 0x804F5D8: lighty_mainloop (server.c:1001)
-mod_proxy_backend_fastcgi.c.597: (trace) (stderr from 127.0.0.1:9090 for /trac/) SERVER_ADDR
-*/
- TRACE("(stderr from %s for %s) %s",
- SAFE_BUF_STR(proxy_con->address->name),
- SAFE_BUF_STR(sess->remote_con->uri.path),
- SAFE_BUF_STR(b));
- buffer_free(b);
- }
- rc = HANDLER_GO_ON;
- break;
- case FCGI_END_REQUEST:
- /* ignore packet content. */
- if(we_need > 0) {
- we_have = chunkqueue_skip(in, we_need);
- data->packet.offset += we_have;
- we_need -= we_have;
- in->bytes_out += we_have;
- }
- if(we_need == 0) {
-#ifndef PROXY_FASTCGI_USE_KEEP_ALIVE
- sess->is_closing = 1;
-#endif
- sess->have_response_headers = 1;
- sess->is_request_finished = 1;
- in->is_closed = 1;
- out->is_closed = 1;
- rc = HANDLER_FINISHED;
- }
- break;
- default:
- TRACE("unknown packet.type: %d", data->packet.type);
- rc = HANDLER_ERROR;
- break;
- }
-
- /* skip packet padding, once content has been processed. */
- if(we_need == 0 && data->packet.padding > 0) {
- we_have = chunkqueue_skip(in, data->packet.padding);
- data->packet.padding -= we_have;
- in->bytes_out += we_have;
- }
-
- if(we_need == 0 && data->packet.padding == 0) {
- /* packet finished, reset state for next packet */
- fcgi_state_data_reset(data);
- }
-
- chunkqueue_remove_finished_chunks(in);
-
- return rc;
-}
-
-PROXY_STREAM_DECODER_FUNC(proxy_fastcgi_stream_decoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *in = proxy_con->recv;
- int res;
-
- if(out->is_closed) return HANDLER_FINISHED;
- /* decode the whole packet stream */
- do {
- /* decode the packet */
- res = proxy_fastcgi_stream_decoder_internal(srv, sess, out);
- } while (in->first && res == HANDLER_GO_ON);
-
- return res;
-}
-
-/**
- * transform the content-stream into a valid FastCGI STDIN content-stream
- *
- * as we don't apply chunked-encoding here, pass it on AS IS
- */
-PROXY_STREAM_ENCODER_FUNC(proxy_fastcgi_stream_encoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *out = proxy_con->send;
- chunk *c;
- buffer *b;
- FCGI_Header header;
- off_t we_need = 0, we_have = 0;
-
- UNUSED(srv);
-
- /* output queue closed, can't encode any more data. */
- if(out->is_closed) return HANDLER_FINISHED;
-
- /* encode data into output queue. */
- for (c = in->first; in->bytes_out < in->bytes_in; ) {
- /*
- * write fcgi header
- */
- if(we_need == 0) {
- we_need = in->bytes_in - in->bytes_out;
- if(we_need > FCGI_MAX_LENGTH) we_need = FCGI_MAX_LENGTH;
-
- b = chunkqueue_get_append_buffer(out);
- fcgi_header(&(header), FCGI_STDIN, PROXY_FASTCGI_REQUEST_ID, we_need, 0);
- buffer_copy_memory(b, (const char *)&header, sizeof(header) + 1);
- out->bytes_in += sizeof(header);
- }
-
- we_have = chunkqueue_steal_chunks_len(out, c, we_need);
- in->bytes_out += we_have;
- out->bytes_in += we_have;
- we_need -= we_have;
- }
-
- if (in->bytes_in == in->bytes_out && in->is_closed && !out->is_closed) {
- /* send the closing packet */
- b = chunkqueue_get_append_buffer(out);
- /* terminate STDIN */
- fcgi_header(&(header), FCGI_STDIN, PROXY_FASTCGI_REQUEST_ID, 0, 0);
- buffer_copy_memory(b, (const char *)&header, sizeof(header) + 1);
-
- out->bytes_in += sizeof(header);
- out->is_closed = 1;
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
-}
-
-INIT_FUNC(mod_proxy_backend_fastcgi_init) {
- mod_proxy_core_plugin_data *core_data;
- protocol_plugin_data *p;
-
- /* get the plugin_data of the core-plugin */
- core_data = plugin_get_config(srv, CORE_PLUGIN);
- if(!core_data) return NULL;
-
- p = calloc(1, sizeof(*p));
-
- /* define protocol handler callbacks */
- p->protocol = core_data->proxy_register_protocol("fastcgi");
-
- p->protocol->proxy_stream_init = proxy_fastcgi_init;
- p->protocol->proxy_stream_cleanup = proxy_fastcgi_cleanup;
- p->protocol->proxy_stream_decoder = proxy_fastcgi_stream_decoder;
- p->protocol->proxy_stream_encoder = proxy_fastcgi_stream_encoder;
- p->protocol->proxy_encode_request_headers = proxy_fastcgi_encode_request_headers;
-
- return p;
-}
-
-FREE_FUNC(mod_proxy_backend_fastcgi_free) {
- protocol_plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_proxy_backend_fastcgi_plugin_init(plugin *p);
-LI_EXPORT int mod_proxy_backend_fastcgi_plugin_init(plugin *p) {
- data_string *ds;
-
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mod_proxy_backend_fastcgi");
-
- p->init = mod_proxy_backend_fastcgi_init;
- p->cleanup = mod_proxy_backend_fastcgi_free;
-
- p->data = NULL;
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN));
- array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
-}
-
-
diff --git a/src/mod_proxy_backend_http.c b/src/mod_proxy_backend_http.c
deleted file mode 100644
index a56bd602..00000000
--- a/src/mod_proxy_backend_http.c
+++ /dev/null
@@ -1,423 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include "mod_proxy_core.h"
-#include "mod_proxy_core_protocol.h"
-#include "configfile.h"
-#include "buffer.h"
-#include "log.h"
-#include "sys-strings.h"
-
-#define CORE_PLUGIN "mod_proxy_core"
-
-typedef struct {
- PLUGIN_DATA;
-
- proxy_protocol *protocol;
-} protocol_plugin_data;
-
-typedef enum {
- HTTP_CHUNK_LEN,
- HTTP_CHUNK_EXTENSION,
- HTTP_CHUNK_DATA,
- HTTP_CHUNK_END
-} http_chunk_state_t;
-
-/**
- * The protocol will use this struct for storing state variables
- * used in decoding the stream
- */
-typedef struct {
- http_chunk_state_t chunk_parse_state;
- off_t chunk_len;
- off_t chunk_offset;
- buffer *buf;
-} protocol_state_data;
-
-static protocol_state_data *protocol_state_data_init(void) {
- protocol_state_data *data;
-
- data = calloc(1, sizeof(*data));
- data->chunk_parse_state = HTTP_CHUNK_LEN;
- data->buf = buffer_init();
-
- return data;
-}
-
-static void protocol_state_data_free(protocol_state_data *data) {
- buffer_free(data->buf);
- free(data);
-}
-
-static void protocol_state_data_reset(protocol_state_data *data) {
- buffer_reset(data->buf);
- data->chunk_parse_state = HTTP_CHUNK_LEN;
-}
-
-PROXY_CONNECTION_FUNC(proxy_http_init) {
-
- UNUSED(srv);
-
- if(!proxy_con->protocol_data) {
- proxy_con->protocol_data = protocol_state_data_init();
- }
- return 1;
-}
-
-PROXY_CONNECTION_FUNC(proxy_http_cleanup) {
-
- UNUSED(srv);
-
- if(proxy_con->protocol_data) {
- protocol_state_data_free((protocol_state_data *)proxy_con->protocol_data);
- proxy_con->protocol_data = NULL;
- }
- return 1;
-}
-
-/**
- * parse the HTTP response header
- */
-static handler_t proxy_http_parse_response_headers(proxy_session *sess, chunkqueue *in) {
- data_string *ds;
-
- http_response_reset(sess->resp);
-
- /* http response parser. */
- switch(http_response_parse_cq(in, sess->resp)) {
- case PARSE_ERROR:
- /* bad gateway */
- http_response_reset(sess->resp);
- sess->have_response_headers = 1;
- sess->resp->status = 502;
- return HANDLER_ERROR;
- case PARSE_NEED_MORE:
- return HANDLER_GO_ON;
- case PARSE_SUCCESS:
- default:
- break;
- }
- /* check for Transfer-Encoding header. */
- if (NULL != (ds = (data_string *)array_get_element(sess->resp->headers, CONST_STR_LEN("Transfer-Encoding")))) {
- if (strstr(ds->value->ptr, "chunked")) {
- sess->is_chunked = 1;
- }
- }
- /* finished parsing response headers. */
- sess->have_response_headers = 1;
-
- switch (sess->resp->status) {
- case 205: /* class: header only */
- case 304:
- sess->is_request_finished = 1;
- }
- return HANDLER_FINISHED;
-}
-
-static handler_t proxy_http_parse_chunked_stream(server *srv, proxy_session *sess, chunkqueue *in, chunkqueue *out) {
- protocol_state_data *data = (protocol_state_data *)sess->proxy_con->protocol_data;
- char *err = NULL;
- off_t we_have = 0, we_want = 0;
- off_t chunk_len = 0;
- off_t offset = 0;
- buffer *b;
- chunk *c;
- char ch = '\0';
- int finished = 0;
-
- UNUSED(srv);
-
- for (c = in->first; c && !finished;) {
- if(c->mem->used == 0) {
- c = c->next;
- continue;
- }
- switch(data->chunk_parse_state) {
- case HTTP_CHUNK_LEN:
- /* parse chunk len. */
- for(offset = c->offset; (size_t)(offset) < (c->mem->used - 1) ; offset++) {
- ch = c->mem->ptr[offset];
- if(!light_isxdigit(ch)) break;
- }
- if(offset > c->offset) {
- buffer_append_string_len(data->buf, (c->mem->ptr + c->offset), offset - c->offset);
- in->bytes_out += (offset - c->offset);
- c->offset = offset;
- }
- if ( (size_t)offset == c->mem->used - 1) {
- break; /* get next chunk from queue */
- }
- /* now ch is the last character, and it wasn't an xdigit */
- if (!(ch == ' ' || ch == '\r' || ch == ';')) {
- /* protocol error. bad http-chunk len */
- return HANDLER_ERROR;
- }
- data->chunk_len = strtol(BUF_STR(data->buf), &err, 16);
- data->chunk_offset = 0;
- buffer_reset(data->buf);
- data->chunk_parse_state = HTTP_CHUNK_EXTENSION;
- case HTTP_CHUNK_EXTENSION:
- /* find CRLF. discard chunk-extension */
- for(ch = 0; (size_t)(c->offset) < (c->mem->used - 1) && ch != '\n' ;) {
- ch = c->mem->ptr[c->offset];
- c->offset++;
- in->bytes_out++;
- }
- if(ch != '\n') {
- /* get next chunk from queue */
- break;
- }
- if(data->chunk_len > 0) {
- data->chunk_parse_state = HTTP_CHUNK_DATA;
- } else {
- data->chunk_parse_state = HTTP_CHUNK_END;
- }
- case HTTP_CHUNK_DATA:
- chunk_len = data->chunk_len - data->chunk_offset;
- /* copy chunk_len bytes from in queue to out queue. */
- we_have = c->mem->used - c->offset - 1;
- we_want = chunk_len > we_have ? we_have : chunk_len;
-
- if (c->offset == 0 && we_want == we_have) {
- /* we are copying the whole buffer, just steal it */
- chunkqueue_steal_chunk(out, c);
- /* c is an empty chunk now */
- } else {
- b = chunkqueue_get_append_buffer(out);
- buffer_copy_string_len(b, c->mem->ptr + c->offset, we_want);
- c->offset += we_want;
- }
-
- chunk_len -= we_want;
- out->bytes_in += we_want;
- in->bytes_out += we_want;
- data->chunk_offset += we_want;
- if(chunk_len > 0) {
- /* get next chunk from queue */
- break;
- }
- data->chunk_offset = 0;
- data->chunk_parse_state = HTTP_CHUNK_END;
- case HTTP_CHUNK_END:
- /* discard CRLF.*/
- for(ch = 0; c->mem->used > 0 && (size_t)(c->offset) < (c->mem->used - 1) && ch != '\n' ;) {
- ch = c->mem->ptr[c->offset];
- c->offset++;
- in->bytes_out++;
- }
- if(ch != '\n') {
- /* get next chunk from queue */
- break;
- }
- /* final chunk */
- if(data->chunk_len == 0) {
- finished = 1;
- }
- /* finished http-chunk. reset and parse next chunk. */
- protocol_state_data_reset(data);
- break;
- }
- if((size_t)(c->offset) == c->mem->used - 1) {
- c = c->next;
- }
- }
- chunkqueue_remove_finished_chunks(in);
- if (finished) {
- sess->is_request_finished = 1;
- return HANDLER_FINISHED;
- }
- /* ran out of data. */
- return HANDLER_GO_ON;
-}
-
-PROXY_STREAM_DECODER_FUNC(proxy_http_stream_decoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *in = proxy_con->recv;
- chunk *c;
-
- if (in->first == NULL) {
- if ((sess->content_length >= 0 && sess->bytes_read == sess->content_length) || in->is_closed) {
- sess->is_request_finished = 1;
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
- }
-
- /* parse response headers. */
- if (!sess->have_response_headers) {
- handler_t rc = proxy_http_parse_response_headers(sess, in);
- if (rc != HANDLER_FINISHED) return rc;
- }
-
- if (sess->is_request_finished) return HANDLER_FINISHED;
-
- if (sess->is_chunked) {
- return proxy_http_parse_chunked_stream(srv, sess, in, out);
- } else {
- /* no chunked encoding, ok, perhaps a content-length ? */
-
- chunkqueue_remove_finished_chunks(in);
- for (c = in->first; c; c = c->next) {
- buffer *b;
-
- if (c->mem->used == 0) continue;
-
- out->bytes_in += c->mem->used - c->offset - 1;
- in->bytes_out += c->mem->used - c->offset - 1;
-
- sess->bytes_read += c->mem->used - c->offset - 1;
-
- if (c->offset == 0) {
- /* we are copying the whole buffer, just steal it */
-
- chunkqueue_steal_chunk(out, c);
- } else {
- b = chunkqueue_get_append_buffer(out);
- buffer_copy_string_len(b, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
- c->offset = c->mem->used - 1; /* marks is read */
- }
-
- if (sess->bytes_read == sess->content_length) {
- break;
- }
- }
-
- if (in->is_closed || sess->bytes_read == sess->content_length) {
- sess->is_request_finished = 1;
- return HANDLER_FINISHED; /* finished */
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * transform the content-stream into a valid HTTP-content-stream
- *
- * as we don't apply chunked-encoding here, pass it on AS IS
- */
-PROXY_STREAM_ENCODER_FUNC(proxy_http_stream_encoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *out = proxy_con->send;
- int we_have = 0;
-
- UNUSED(srv);
-
- /* output queue closed, can't encode any more data. */
- if(out->is_closed) return HANDLER_FINISHED;
-
- /* encode all request content data into output queue. */
- we_have = chunkqueue_steal_all_chunks(out, in);
- in->bytes_out += we_have;
- out->bytes_in += we_have;
-
- if (in->bytes_in == in->bytes_out && in->is_closed) {
- out->is_closed = 1;
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * generate a HTTP/1.1 proxy request from the set of request-headers
- *
- */
-PROXY_STREAM_ENCODER_FUNC(proxy_http_encode_request_headers) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *out = proxy_con->send;
- connection *con = sess->remote_con;
- buffer *b;
- size_t i;
-
- UNUSED(srv);
- UNUSED(in);
-
- b = chunkqueue_get_append_buffer(out);
-
- /* request line */
- buffer_copy_string(b, get_http_method_name(con->request.http_method));
- buffer_append_string_len(b, CONST_STR_LEN(" "));
-
- /* request uri */
- buffer_append_string_buffer(b, sess->request_uri);
-
- if (con->request.http_version == HTTP_VERSION_1_1) {
- buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.1\r\n"));
- } else {
- buffer_append_string_len(b, CONST_STR_LEN(" HTTP/1.0\r\n"));
- }
-
- for (i = 0; i < sess->request_headers->used; i++) {
- data_string *ds;
-
- ds = (data_string *)sess->request_headers->data[i];
-
- buffer_append_string_buffer(b, ds->key);
- buffer_append_string_len(b, CONST_STR_LEN(": "));
- buffer_append_string_buffer(b, ds->value);
- buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
-
- out->bytes_in += b->used - 1;
-
- return HANDLER_FINISHED;
-}
-
-INIT_FUNC(mod_proxy_backend_http_init) {
- mod_proxy_core_plugin_data *core_data;
- protocol_plugin_data *p;
-
- /* get the plugin_data of the core-plugin */
- core_data = plugin_get_config(srv, CORE_PLUGIN);
- if(!core_data) return NULL;
-
- p = calloc(1, sizeof(*p));
-
- /* define protocol handler callbacks */
- p->protocol = (core_data->proxy_register_protocol)("http");
-
- p->protocol->proxy_stream_init = proxy_http_init;
- p->protocol->proxy_stream_cleanup = proxy_http_cleanup;
- p->protocol->proxy_stream_decoder = proxy_http_stream_decoder;
- p->protocol->proxy_stream_encoder = proxy_http_stream_encoder;
- p->protocol->proxy_encode_request_headers = proxy_http_encode_request_headers;
-
- return p;
-}
-
-FREE_FUNC(mod_proxy_backend_http_free) {
- protocol_plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_proxy_backend_http_plugin_init(plugin *p);
-LI_EXPORT int mod_proxy_backend_http_plugin_init(plugin *p) {
- data_string *ds;
-
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mod_proxy_backend_http");
-
- p->init = mod_proxy_backend_http_init;
- p->cleanup = mod_proxy_backend_http_free;
-
- p->data = NULL;
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN));
- array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
-}
-
-
diff --git a/src/mod_proxy_backend_scgi.c b/src/mod_proxy_backend_scgi.c
deleted file mode 100644
index 60e1de83..00000000
--- a/src/mod_proxy_backend_scgi.c
+++ /dev/null
@@ -1,475 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-
-#include "sys-strings.h"
-#include "inet_ntop_cache.h"
-#include "mod_proxy_core.h"
-#include "mod_proxy_core_protocol.h"
-#include "buffer.h"
-#include "log.h"
-#include "array.h"
-
-#define CORE_PLUGIN "mod_proxy_core"
-
-typedef struct {
- PLUGIN_DATA;
-
- proxy_protocol *protocol;
-} protocol_plugin_data;
-
-/*
-PROXY_CONNECTION_FUNC(proxy_scgi_init) {
- return 1;
-}
-*/
-
-/*
-PROXY_CONNECTION_FUNC(proxy_scgi_cleanup) {
- return 1;
-}
-*/
-
-/**
- * add a key-value pair to the scgi-buffer
- */
-static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
- size_t len;
-
- if (!key || !val) return -1;
-
- len = key_len + val_len + 2;
-
- buffer_prepare_append(env, len);
-
- buffer_append_memory(env, key, key_len);
- env->ptr[env->used++] = '\0';
- buffer_append_memory(env, val, val_len);
- env->ptr[env->used++] = '\0';
-
- return 0;
-}
-
-static int proxy_scgi_get_env_scgi(server *srv, proxy_session *sess, buffer *env_headers) {
- connection *con = sess->remote_con;
- server_socket *srv_sock = con->srv_socket;
- plugin_data *p = sess->p;
- socklen_t our_addr_len;
- sock_addr our_addr;
- const char *s;
- char buf[32];
- int len;
-#ifdef HAVE_IPV6
- char b2[INET6_ADDRSTRLEN + 1];
-#endif
-
- /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
-
- /* request.content_length < SSIZE_MAX, see request.c */
- if(con->request.content_length > 0) {
- len = LI_ltostr(buf, con->request.content_length);
- } else {
- buf[0] = '0';
- buf[1] = '\0';
- len = 1;
- }
- scgi_env_add(env_headers, CONST_STR_LEN("CONTENT_LENGTH"), buf, len);
- scgi_env_add(env_headers, CONST_STR_LEN("SCGI"), CONST_STR_LEN("1"));
-
- scgi_env_add(env_headers, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
-
- if (con->server_name->used) {
- size_t _len = con->server_name->used - 1;
- char *colon = strchr(con->server_name->ptr, ':');
- if (colon) _len = colon - con->server_name->ptr;
-
- scgi_env_add(env_headers, CONST_STR_LEN("SERVER_NAME"), con->server_name->ptr, _len);
- } else {
-#ifdef HAVE_IPV6
- s = inet_ntop(srv_sock->addr.plain.sa_family,
- srv_sock->addr.plain.sa_family == AF_INET6 ?
- (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
- (const void *) &(srv_sock->addr.ipv4.sin_addr),
- b2, sizeof(b2)-1);
-#else
- s = inet_ntoa(srv_sock->addr.ipv4.sin_addr);
-#endif
- scgi_env_add(env_headers, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
- }
-
- scgi_env_add(env_headers, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
-
- len = LI_ltostr(buf,
-#ifdef HAVE_IPV6
- ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
-#else
- ntohs(srv_sock->addr.ipv4.sin_port)
-#endif
- );
-
- scgi_env_add(env_headers, CONST_STR_LEN("SERVER_PORT"), buf, len);
-
- /* get the server-side of the connection to the client */
- our_addr_len = sizeof(our_addr);
-
- if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) {
- s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
- } else {
- s = inet_ntop_cache_get_ip(srv, &(our_addr));
- }
- scgi_env_add(env_headers, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
-
- len = LI_ltostr(buf,
-#ifdef HAVE_IPV6
- ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
-#else
- ntohs(con->dst_addr.ipv4.sin_port)
-#endif
- );
-
- scgi_env_add(env_headers, CONST_STR_LEN("REMOTE_PORT"), buf, len);
-
- s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- scgi_env_add(env_headers, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
-
- if (!buffer_is_empty(con->authed_user)) {
- scgi_env_add(env_headers, CONST_STR_LEN("REMOTE_USER"),
- CONST_BUF_LEN(con->authed_user));
- }
-
- /*
- * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
- * http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
- * (6.1.14, 6.1.6, 6.1.7)
- * For AUTHORIZER mode these headers should be omitted.
- */
-
- scgi_env_add(env_headers, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
-
- if (!buffer_is_empty(con->request.pathinfo)) {
- scgi_env_add(env_headers, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
-
- /* PATH_TRANSLATED is only defined if PATH_INFO is set */
-
- buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
- buffer_append_string_buffer(p->tmp_buf, con->request.pathinfo);
- scgi_env_add(env_headers, CONST_STR_LEN("PATH_TRANSLATED"), CONST_BUF_LEN(p->tmp_buf));
- } else {
- scgi_env_add(env_headers, CONST_STR_LEN("PATH_INFO"), CONST_STR_LEN(""));
- }
-
- /*
- * SCRIPT_FILENAME and DOCUMENT_ROOT for php. The PHP manual
- * http://www.php.net/manual/en/reserved.variables.php
- * treatment of PATH_TRANSLATED is different from the one of CGI specs.
- * TODO: this code should be checked against cgi.fix_pathinfo php
- * parameter.
- */
-
- if (1) {
- scgi_env_add(env_headers, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
- scgi_env_add(env_headers, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
- }
-
- scgi_env_add(env_headers, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
-
- if (!buffer_is_equal(sess->request_uri, con->request.orig_uri)) {
- scgi_env_add(env_headers, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(sess->request_uri));
- }
- if (!buffer_is_empty(con->uri.query)) {
- scgi_env_add(env_headers, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
- } else {
- scgi_env_add(env_headers, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
- }
-
- s = get_http_method_name(con->request.http_method);
- scgi_env_add(env_headers, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
- scgi_env_add(env_headers, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
- s = get_http_version_name(con->request.http_version);
- scgi_env_add(env_headers, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
-
-#ifdef USE_OPENSSL
- if (srv_sock->is_ssl) {
- scgi_env_add(env_headers, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
- }
-#endif
-
- return 0;
-}
-
-/**
- * transform the HTTP-Request headers into CGI notation
- */
-static int proxy_scgi_get_env_request(server *srv, proxy_session *sess, buffer *env_headers) {
- connection *con = sess->remote_con;
- plugin_data *p = sess->p;
- size_t i;
-
- UNUSED(srv);
-
- /* the request header got already copied into the sess->request_headers for us
- * no extra filter is needed
- *
- * prepend a HTTP_ and uppercase the keys
- */
- for (i = 0; i < sess->request_headers->used; i++) {
- data_string *ds;
- size_t j;
-
- ds = (data_string *)sess->request_headers->data[i];
- if (ds->value->used == 0 || ds->key->used == 0) continue;
-
- buffer_reset(p->tmp_buf);
-
- if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
- buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("HTTP_"));
- p->tmp_buf->used--;
- }
-
- buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
- for (j = 0; j < ds->key->used - 1; j++) {
- char c = ds->key->ptr[j];
- if (light_isalpha(c)) {
- /* upper-case */
- c = toupper(c);
- } else if (light_isdigit(c)) {
- /* copy */
- c = c;
- } else {
- c = '_';
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = c;
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
-
- scgi_env_add(env_headers, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
- }
-
- for (i = 0; i < con->environment->used; i++) {
- data_string *ds;
- size_t j;
-
- ds = (data_string *)con->environment->data[i];
- if (ds->value->used == 0 || ds->key->used == 0) continue;
-
- buffer_reset(p->tmp_buf);
-
- buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
- for (j = 0; j < ds->key->used - 1; j++) {
- char c = ds->key->ptr[j];
- if (light_isalpha(c)) {
- /* upper-case */
- c = toupper(c);
- } else {
- c = '_';
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = c;
- }
- p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
-
- scgi_env_add(env_headers, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
- }
-
- return 0;
-}
-
-PROXY_STREAM_ENCODER_FUNC(proxy_scgi_encode_request_headers) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *out = proxy_con->send;
- size_t headers_len = 0;
- buffer *len_buf;
- buffer *env_headers;
-
- UNUSED(in);
-
- /* get buffer to write headers length into */
- len_buf = chunkqueue_get_append_buffer(out);
-
- /* write SCGI request headers */
- env_headers = chunkqueue_get_append_buffer(out);
- buffer_prepare_copy(env_headers, 1024);
- proxy_scgi_get_env_scgi(srv, sess, env_headers);
- proxy_scgi_get_env_request(srv, sess, env_headers);
- headers_len = env_headers->used;
- out->bytes_in += headers_len;
-
- /* append "," after headers */
- buffer_append_memory(env_headers, CONST_STR_LEN(","));
- env_headers->used++; /* this is needed because the network will only write "used - 1" bytes */
- out->bytes_in++;
-
- /* prepend [headers_len]: */
- buffer_append_long(len_buf, headers_len);
- buffer_append_string_len(len_buf, CONST_STR_LEN(":"));
- out->bytes_in += len_buf->used - 1;
-
- return HANDLER_FINISHED;
-}
-
-/**
- * parse the HTTP response header
- */
-static handler_t proxy_scgi_parse_response_headers(proxy_session *sess, chunkqueue *in) {
- http_response_reset(sess->resp);
-
- /* http response parser. */
- switch(http_response_parse_cq(in, sess->resp)) {
- case PARSE_ERROR:
- /* bad gateway */
- http_response_reset(sess->resp);
- sess->have_response_headers = 1;
- sess->resp->status = 502;
- return HANDLER_ERROR;
- case PARSE_NEED_MORE:
- return HANDLER_GO_ON;
- case PARSE_SUCCESS:
- default:
- /* finished parsing response headers. */
- sess->have_response_headers = 1;
- return HANDLER_FINISHED;
- }
-}
-
-PROXY_STREAM_DECODER_FUNC(proxy_scgi_stream_decoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *in = proxy_con->recv;
- chunk *c;
-
- UNUSED(srv);
-
- if (in->first == NULL) {
- if ((sess->content_length >= 0 && sess->bytes_read == sess->content_length) || in->is_closed) {
- sess->is_request_finished = 1;
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
- }
-
- /* parse response headers. */
- if (!sess->have_response_headers) {
- handler_t rc = proxy_scgi_parse_response_headers(sess, in);
- if (rc != HANDLER_FINISHED) return rc;
- }
-
- /* no chunked encoding, ok, perhaps a content-length ? */
-
- chunkqueue_remove_finished_chunks(in);
- for (c = in->first; c; c = c->next) {
- buffer *b;
-
- if (c->mem->used == 0) continue;
-
- out->bytes_in += c->mem->used - c->offset - 1;
- in->bytes_out += c->mem->used - c->offset - 1;
-
- sess->bytes_read += c->mem->used - c->offset - 1;
-
- if (c->offset == 0) {
- /* we are copying the whole buffer, just steal it */
-
- chunkqueue_steal_chunk(out, c);
- } else {
- b = chunkqueue_get_append_buffer(out);
- buffer_copy_string_len(b, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
- c->offset = c->mem->used - 1; /* marks is read */
- }
-
- if (sess->bytes_read == sess->content_length) {
- break;
- }
- }
-
- if (in->is_closed || sess->bytes_read == sess->content_length) {
- sess->is_request_finished = 1;
- return HANDLER_FINISHED; /* finished */
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * transform the content-stream into a valid HTTP-content-stream
- *
- * as we don't apply chunked-encoding here, pass it on AS IS
- */
-PROXY_STREAM_ENCODER_FUNC(proxy_scgi_stream_encoder) {
- proxy_connection *proxy_con = sess->proxy_con;
- chunkqueue *out = proxy_con->send;
- int we_have = 0;
-
- UNUSED(srv);
-
- /* output queue closed, can't encode any more data. */
- if(out->is_closed) return HANDLER_FINISHED;
-
- /* encode all request content data into output queue. */
- we_have = chunkqueue_steal_all_chunks(out, in);
- in->bytes_out += we_have;
- out->bytes_in += we_have;
-
- if (in->bytes_in == in->bytes_out && in->is_closed) {
- out->is_closed = 1;
- return HANDLER_FINISHED;
- }
-
- return HANDLER_GO_ON;
-}
-
-INIT_FUNC(mod_proxy_backend_scgi_init) {
- mod_proxy_core_plugin_data *core_data;
- protocol_plugin_data *p;
-
- /* get the plugin_data of the core-plugin */
- core_data = plugin_get_config(srv, CORE_PLUGIN);
- if(!core_data) return NULL;
-
- p = calloc(1, sizeof(*p));
-
- /* define protocol handler callbacks */
- p->protocol = core_data->proxy_register_protocol("scgi");
-
- /*
- p->protocol->proxy_stream_init = proxy_scgi_init;
- p->protocol->proxy_stream_cleanup = proxy_scgi_cleanup;
- */
- p->protocol->proxy_stream_decoder = proxy_scgi_stream_decoder;
- p->protocol->proxy_stream_encoder = proxy_scgi_stream_encoder;
- p->protocol->proxy_encode_request_headers = proxy_scgi_encode_request_headers;
-
- return p;
-}
-
-FREE_FUNC(mod_proxy_backend_scgi_free) {
- protocol_plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_proxy_backend_scgi_plugin_init(plugin *p);
-LI_EXPORT int mod_proxy_backend_scgi_plugin_init(plugin *p) {
- data_string *ds;
-
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mod_proxy_backend_scgi");
-
- p->init = mod_proxy_backend_scgi_init;
- p->cleanup = mod_proxy_backend_scgi_free;
-
- p->data = NULL;
-
- ds = data_string_init();
- buffer_copy_string_len(ds->value, CONST_STR_LEN(CORE_PLUGIN));
- array_insert_unique(p->required_plugins, (data_unset *)ds);
-
- return 0;
-}
-
-
diff --git a/src/mod_proxy_core.c b/src/mod_proxy_core.c
deleted file mode 100644
index 31f884a7..00000000
--- a/src/mod_proxy_core.c
+++ /dev/null
@@ -1,2624 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
-#include <fcntl.h>
-#include "base.h"
-#include "sys-strings.h"
-
-#include "buffer.h"
-#include "array.h"
-#include "log.h"
-
-#include "plugin.h"
-#include "joblist.h"
-#include "sys-files.h"
-#include "inet_ntop_cache.h"
-#include "crc32.h"
-#include "configfile.h"
-#include "stat_cache.h"
-#include "buffer.h"
-#include "array.h"
-#include "log.h"
-#include "status_counter.h"
-
-#include "mod_proxy_core.h"
-#include "mod_proxy_core_protocol.h"
-
-#define PROXY_CORE "proxy-core"
-#define CONFIG_PROXY_CORE_BALANCER PROXY_CORE ".balancer"
-#define CONFIG_PROXY_CORE_PROTOCOL PROXY_CORE ".protocol"
-#define CONFIG_PROXY_CORE_DEBUG PROXY_CORE ".debug"
-#define CONFIG_PROXY_CORE_MAX_KEEP_ALIVE PROXY_CORE ".max-keep-alive-requests"
-#define CONFIG_PROXY_CORE_BACKENDS PROXY_CORE ".backends"
-#define CONFIG_PROXY_CORE_REWRITE_REQUEST PROXY_CORE ".rewrite-request"
-#define CONFIG_PROXY_CORE_REWRITE_RESPONSE PROXY_CORE ".rewrite-response"
-#define CONFIG_PROXY_CORE_ALLOW_X_SENDFILE PROXY_CORE ".allow-x-sendfile"
-#define CONFIG_PROXY_CORE_ALLOW_X_REWRITE PROXY_CORE ".allow-x-rewrite"
-#define CONFIG_PROXY_CORE_MAX_POOL_SIZE PROXY_CORE ".max-pool-size"
-#define CONFIG_PROXY_CORE_CHECK_LOCAL PROXY_CORE ".check-local"
-#define CONFIG_PROXY_CORE_SPLIT_HOSTNAMES PROXY_CORE ".split-hostnames"
-#define CONFIG_PROXY_CORE_DISABLE_TIME PROXY_CORE ".disable-time"
-#define CONFIG_PROXY_CORE_MAX_BACKLOG_SIZE PROXY_CORE ".max-backlog-size"
-
-static int mod_proxy_wakeup_connections(server *srv, plugin_data *p, plugin_config *p_conf);
-
-static int array_insert_int(array *a, const char *key, int val) {
- data_integer *di;
-
- if (NULL == (di = (data_integer *)array_get_unused_element(a, TYPE_INTEGER))) {
- di = data_integer_init();
- }
-
- buffer_copy_string(di->key, key);
- di->value = val;
- array_insert_unique(a, (data_unset *)di);
-
- return 0;
-}
-
-static proxy_protocol *mod_proxy_core_register_protocol(const char *name) {
- proxy_protocol *protocol = proxy_protocol_init();
-
- protocol->name = buffer_init_string(name);
-
- proxy_protocols_register(protocol);
- return protocol;
-}
-
-INIT_FUNC(mod_proxy_core_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- proxy_protocols_init();
-
- p = calloc(1, sizeof(*p));
-
- /* create some backends as long as we don't have the config-parser */
-
- p->possible_balancers = array_init();
- array_insert_int(p->possible_balancers, "sqf", PROXY_BALANCE_SQF);
- array_insert_int(p->possible_balancers, "carp", PROXY_BALANCE_CARP);
- array_insert_int(p->possible_balancers, "round-robin", PROXY_BALANCE_RR);
- array_insert_int(p->possible_balancers, "static", PROXY_BALANCE_STATIC);
-
- p->proxy_register_protocol = mod_proxy_core_register_protocol;
-
- /* statistics counters. */
- p->request_count = status_counter_get_counter(CONST_STR_LEN(PROXY_CORE ".requests"));
-
- p->balance_buf = buffer_init();
- p->protocol_buf = buffer_init();
- p->replace_buf = buffer_init();
- p->backends_arr = array_init();
-
- p->tmp_buf = buffer_init();
-
-#if 0
- /**
- * create a small pool of session objects
- *
- * instead of creating new one each time,
- * cleanup old ones and put them into the pool
- *
- * 8 clean items should be enough at a time, destroy the other ones
- */
- p->session_pool = proxy_session_pool_init();
-#endif
-
- return p;
-}
-
-FREE_FUNC(mod_proxy_core_free) {
- plugin_data *p = p_d;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- proxy_backends_free(s->backends);
- proxy_backlog_free(s->backlog);
-
- proxy_rewrites_free(s->request_rewrites);
- proxy_rewrites_free(s->response_rewrites);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- array_free(p->possible_balancers);
- array_free(p->backends_arr);
-
- buffer_free(p->balance_buf);
- buffer_free(p->protocol_buf);
- buffer_free(p->replace_buf);
- buffer_free(p->tmp_buf);
-
-#if 0
- proxy_session_pool_free(p->session_pool);
-#endif
-
- free(p);
-
- proxy_protocols_free();
-
- return HANDLER_GO_ON;
-}
-
-static handler_t mod_proxy_core_config_parse_rewrites(proxy_rewrites *dest, array *src, const char *config_key) {
- data_unset *du;
- size_t j;
-
- if (NULL != (du = array_get_element(src, config_key, strlen(config_key)))) {
- data_array *keys = (data_array *)du;
-
- if (keys->type != TYPE_ARRAY) {
- ERROR("%s = <...>",
- config_key);
-
- return HANDLER_ERROR;
- }
-
- /*
- * proxy-core.rewrite-request = (
- * "_uri" => ( ... )
- * )
- */
-
- for (j = 0; j < keys->value->used; j++) {
- size_t k;
- data_array *headers = (data_array *)keys->value->data[j];
-
- /* keys->key should be "_uri" and the value a array of rewrite */
- if (headers->type != TYPE_ARRAY) {
- ERROR("%s = ( %s => <...> ) has to a array",
- config_key,
- SAFE_BUF_STR(headers->key));
-
- return HANDLER_ERROR;
- }
-
- if (headers->value->used > 1) {
- ERROR("%s = ( %s => <...> ) has to a array with only one element",
- config_key,
- SAFE_BUF_STR(headers->key));
-
- return HANDLER_ERROR;
-
- }
-
- for (k = 0; k < headers->value->used; k++) {
- data_string *rewrites = (data_string *)headers->value->data[k];
- proxy_rewrite *rw;
-
- /* keys->key should be "_uri" and the value a array of rewrite */
- if (rewrites->type != TYPE_STRING) {
- ERROR("%s = ( \"%s\" => ( \"%s\" => <value> ) ) has to a string",
- config_key,
- SAFE_BUF_STR(headers->key),
- SAFE_BUF_STR(rewrites->key));
-
- return HANDLER_ERROR;
- }
-
- rw = proxy_rewrite_init();
-
- if (0 != proxy_rewrite_set_regex(rw, rewrites->key)) {
- return HANDLER_ERROR;
- }
- buffer_copy_string_buffer(rw->replace, rewrites->value);
- buffer_copy_string_buffer(rw->match, rewrites->key);
- buffer_copy_string_buffer(rw->header, headers->key);
-
- proxy_rewrites_add(dest, rw);
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static void mod_proxy_core_create_backend_stats(plugin_data *p, buffer *stat_basename, proxy_backend *backend) {
-#define COUNTER_NAME(b, x) \
- buffer_copy_string_buffer(b, stat_basename); \
- buffer_append_string_len(b, CONST_STR_LEN("\"")); \
- buffer_append_string_buffer(b, backend->name); \
- buffer_append_string_len(b, CONST_STR_LEN("\"." x));
-
- /* request count stat. */
- COUNTER_NAME(p->tmp_buf, "requests");
- backend->request_count = status_counter_get_counter(CONST_BUF_LEN(p->tmp_buf));
-
- /* load */
- COUNTER_NAME(p->tmp_buf, "load");
- backend->load = status_counter_get_counter(CONST_BUF_LEN(p->tmp_buf));
-
- /* pool size */
- COUNTER_NAME(p->tmp_buf, "pool_size");
- backend->pool_size = status_counter_get_counter(CONST_BUF_LEN(p->tmp_buf));
-
- COUNTER_NAME(p->tmp_buf, "requests_failed");
- backend->requests_failed = status_counter_get_counter(CONST_BUF_LEN(p->tmp_buf));
-#undef COUNTER_NAME
-}
-
-SETDEFAULTS_FUNC(mod_proxy_core_set_defaults) {
- plugin_data *p = p_d;
- buffer *stat_basename;
- size_t i, j;
- int proxy_counter = 0;
-
- config_values_t cv[] = {
- { CONFIG_PROXY_CORE_BACKENDS, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { CONFIG_PROXY_CORE_DEBUG, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { CONFIG_PROXY_CORE_BALANCER, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { CONFIG_PROXY_CORE_PROTOCOL, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { CONFIG_PROXY_CORE_REWRITE_REQUEST, NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
- { CONFIG_PROXY_CORE_REWRITE_RESPONSE, NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
- { CONFIG_PROXY_CORE_ALLOW_X_SENDFILE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
- { CONFIG_PROXY_CORE_ALLOW_X_REWRITE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
- { CONFIG_PROXY_CORE_MAX_POOL_SIZE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
- { CONFIG_PROXY_CORE_CHECK_LOCAL, "use $PHYSICAL[\"existing-path\"] =~ ... { ... } instead",
- T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
- { CONFIG_PROXY_CORE_MAX_KEEP_ALIVE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
- { CONFIG_PROXY_CORE_SPLIT_HOSTNAMES, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
- { CONFIG_PROXY_CORE_DISABLE_TIME, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
- { CONFIG_PROXY_CORE_MAX_BACKLOG_SIZE, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- stat_basename = buffer_init();
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- array *ca;
- proxy_backend *backend;
-
- array_reset(p->backends_arr);
- buffer_reset(p->balance_buf);
- buffer_reset(p->protocol_buf);
-
- s = calloc(1, sizeof(plugin_config));
- s->debug = 0;
- s->balancer = PROXY_BALANCE_UNSET;
- s->protocol = NULL;
- s->backends = proxy_backends_init();
- s->backlog = proxy_backlog_init();
- s->response_rewrites = proxy_rewrites_init();
- s->request_rewrites = proxy_rewrites_init();
- s->check_local = 0;
- s->split_hostnames = 1;
- s->max_keep_alive_requests = 0;
- s->disable_time = 1;
- s->max_backlog_size = 4;
-
- cv[0].destination = p->backends_arr;
- cv[1].destination = &(s->debug);
- cv[2].destination = p->balance_buf; /* parse into a constant */
- cv[3].destination = p->protocol_buf; /* parse into a constant */
- cv[6].destination = &(s->allow_x_sendfile);
- cv[7].destination = &(s->allow_x_rewrite);
- cv[8].destination = &(s->max_pool_size);
- cv[10].destination = &(s->max_keep_alive_requests);
- cv[11].destination = &(s->split_hostnames);
- cv[12].destination = &(s->disable_time);
- cv[13].destination = &(s->max_backlog_size);
-
- buffer_reset(p->balance_buf);
-
- p->config_storage[i] = s;
- ca = ((data_config *)srv->config_context->data[i])->value;
-
- if (0 != config_insert_values_global(srv, ca, cv)) {
- return HANDLER_ERROR;
- }
-
- if (!buffer_is_empty(p->balance_buf)) {
- data_integer *di;
-
- if (NULL != (di = (data_integer *)array_get_element(p->possible_balancers, CONST_BUF_LEN(p->balance_buf)))) {
- s->balancer = di->value;
- } else {
- ERROR("proxy.balance has to be one of 'round-robin', 'carp', 'sqf', 'static': got %s", SAFE_BUF_STR(p->balance_buf));
- return HANDLER_ERROR;
- }
- }
-
- if (!buffer_is_empty(p->protocol_buf)) {
- proxy_protocol *protocol = NULL;
- if (NULL == (protocol = proxy_get_protocol(p->protocol_buf))) {
- ERROR("proxy.protocol has to be one of { %s } got %s, you might have to load 'mod_proxy_backend_%s'",
- proxy_available_protocols(),
- SAFE_BUF_STR(p->protocol_buf),
- SAFE_BUF_STR(p->protocol_buf)
- );
- return HANDLER_ERROR;
- }
- s->protocol = protocol;
- }
-
- if (p->backends_arr->used) {
- /* statistics base name. */
- buffer_copy_string_len(stat_basename, CONST_STR_LEN(PROXY_CORE "."));
- buffer_append_long(stat_basename, proxy_counter);
-
- /* backlog size stats */
- buffer_copy_string_buffer(p->tmp_buf, stat_basename);
- buffer_append_string_len(p->tmp_buf, CONST_STR_LEN(".backlogged"));
- s->backlog_size = status_counter_get_counter(CONST_BUF_LEN(p->tmp_buf));
-
- /* backends stats base name. */
- buffer_append_string_len(stat_basename, CONST_STR_LEN(".backends."));
-
- /* check if the backends have a valid host-name */
- for (j = 0; j < p->backends_arr->used; j++) {
- data_string *ds = (data_string *)p->backends_arr->data[j];
- backend = proxy_backend_init();
-
- /* save name of backend for config. */
- buffer_copy_string_buffer(backend->name, ds->value);
- /* the values should be ips or hostnames */
- if (0 != proxy_address_pool_add_string(backend->address_pool, ds->value)) {
- return HANDLER_ERROR;
- }
-
- if (s->max_pool_size) {
- backend->pool->max_size = s->max_pool_size;
- }
-
- /* append backend to list of backends */
- proxy_backends_add(s->backends, backend);
-
- /* if there is more then one address in the pool, split them out into seperate backends */
- if (s->split_hostnames && backend->address_pool->used > 1) {
- proxy_address_pool *pool = backend->address_pool;
-
- /* change current backend's name to name of the first ip address in the pool. */
- buffer_copy_string_buffer(backend->name, pool->ptr[0]->name);
-
- /* setup stats */
- mod_proxy_core_create_backend_stats(p, stat_basename, backend);
-
- /* move all addresses from the pool into new backends, except for the first one */
- while (pool->used > 1) {
- /* remove last address from pool */
- proxy_address *address = pool->ptr[--(pool->used)];
-
- /* create new backend for address */
- backend = proxy_backend_init();
-
- /* set backend name to name of address */
- buffer_copy_string_buffer(backend->name, address->name);
-
- /* setup stats */
- mod_proxy_core_create_backend_stats(p, stat_basename, backend);
-
- /* add address to pool */
- proxy_address_pool_add(backend->address_pool, address);
-
- if (s->max_pool_size) {
- backend->pool->max_size = s->max_pool_size;
- }
-
- /* append backend to list of backends */
- proxy_backends_add(s->backends, backend);
- }
- } else {
- /* setup stats */
- mod_proxy_core_create_backend_stats(p, stat_basename, backend);
- }
- }
- /* counter number of "proxy-core.backends" groups */
- proxy_counter++;
- }
-
- if (HANDLER_GO_ON != mod_proxy_core_config_parse_rewrites(s->request_rewrites, ca, CONFIG_PROXY_CORE_REWRITE_REQUEST)) {
- return HANDLER_ERROR;
- }
-
- if (HANDLER_GO_ON != mod_proxy_core_config_parse_rewrites(s->response_rewrites, ca, CONFIG_PROXY_CORE_REWRITE_RESPONSE)) {
- return HANDLER_ERROR;
- }
- }
-
- buffer_free(stat_basename);
-
- return HANDLER_GO_ON;
-}
-
-
-static proxy_session *proxy_session_init(void) {
- proxy_session *sess;
-
- sess = calloc(1, sizeof(*sess));
-
- sess->state = PROXY_STATE_UNSET;
- sess->request_uri = buffer_init();
- sess->request_headers = array_init();
- sess->env_headers = array_init();
-
- sess->resp = http_response_init();
-
- sess->recv = chunkqueue_init();
-
- sess->is_chunked = 0;
- sess->content_length = -1;
- sess->send_response_content = 1;
- sess->do_new_session = 0;
- sess->do_x_rewrite_backend = 0;
- sess->sticky_session = NULL;
-
- return sess;
-}
-
-static void proxy_session_reset(proxy_session *sess) {
- if (!sess) return;
-
- buffer_reset(sess->request_uri);
- array_reset(sess->request_headers);
- array_reset(sess->env_headers);
-
- http_response_reset(sess->resp);
- sess->p = NULL;
-
- chunkqueue_reset(sess->recv);
-
- sess->state = PROXY_STATE_UNSET;
-
- sess->is_chunked = 0;
- sess->send_response_content = 1;
-
- sess->bytes_read = 0;
- sess->connect_start_ts = 0;
- sess->content_length = -1;
- sess->internal_redirect_count = 0;
- sess->do_internal_redirect = 0;
- sess->is_closing = 0;
- sess->is_closed = 0;
- sess->is_request_finished = 0;
- sess->have_response_headers = 0;
-
- sess->do_new_session = 0;
- sess->do_x_rewrite_backend = 0;
- buffer_free(sess->sticky_session);
- sess->sticky_session = NULL;
-
- sess->remote_con = NULL;
- sess->proxy_con = NULL;
- sess->proxy_backend = NULL;
-}
-
-static void proxy_session_free(proxy_session *sess) {
- if (!sess) return;
-
- buffer_free(sess->request_uri);
- array_free(sess->request_headers);
- array_free(sess->env_headers);
-
- http_response_free(sess->resp);
- sess->p = NULL;
-
- chunkqueue_free(sess->recv);
-
- buffer_free(sess->sticky_session);
- free(sess);
-}
-
-/**
- * Copy decoded response content to client connection.
- */
-static int proxy_copy_response(server *srv, connection *con, proxy_session *sess) {
- chunk *c;
- int we_have = 0;
-
- UNUSED(srv);
-
- chunkqueue_remove_finished_chunks(sess->recv);
- /* copy the content to the next cq */
- for (c = sess->recv->first; c; c = c->next) {
- if (c->mem->used == 0) continue;
-
- we_have = c->mem->used - c->offset - 1;
- sess->recv->bytes_out += we_have;
- if (sess->send_response_content) {
- con->send->bytes_in += we_have;
- /* X-Sendfile ignores the content-body */
- chunkqueue_steal_chunk(con->send, c);
- } else {
- /* discard the data */
- chunk_set_done(c);
- }
- }
- chunkqueue_remove_finished_chunks(sess->recv);
-
- if(sess->recv->is_closed && sess->send_response_content) {
- con->send->is_closed = 1;
- }
- return 0;
-}
-
-/**
- * Initialize protocol stream.
- *
- */
-static int proxy_stream_init(server *srv, proxy_session *sess) {
- proxy_protocol *protocol = (sess->proxy_backend) ? sess->proxy_backend->protocol : NULL;
- if(protocol && protocol->proxy_stream_init) {
- return (protocol->proxy_stream_init)(srv, sess->proxy_con);
- }
- return 1;
-}
-
-/**
- * Cleanup protocol state data.
- *
- */
-static int proxy_stream_cleanup(server *srv, proxy_session *sess) {
- proxy_protocol *protocol = (sess->proxy_backend) ? sess->proxy_backend->protocol : NULL;
- if(protocol && protocol->proxy_stream_cleanup) {
- return (protocol->proxy_stream_cleanup)(srv, sess->proxy_con);
- }
- return 1;
-}
-
-/**
- * decode the content for the protocol
- *
- * http might have chunk-encoding
- * fastcgi has the fastcgi wrapper code
- *
- * @param out chunkqueue for the plain content
- */
-
-static handler_t proxy_stream_decoder(server *srv, proxy_session *sess, chunkqueue *out) {
- proxy_protocol *protocol = (sess->proxy_backend) ? sess->proxy_backend->protocol : NULL;
- if(protocol && protocol->proxy_stream_decoder) {
- return (protocol->proxy_stream_decoder)(srv, sess, out);
- }
- ERROR("protocol '%s' is not supported yet", SAFE_BUF_STR(protocol->name));
- return HANDLER_ERROR;
-}
-
-/**
- * encode the content for the protocol
- *
- * @param in chunkqueue with the content to (no encoding)
- */
-static handler_t proxy_stream_encoder(server *srv, proxy_session *sess, chunkqueue *in) {
- proxy_protocol *protocol = (sess->proxy_backend) ? sess->proxy_backend->protocol : NULL;
- if(protocol && protocol->proxy_stream_encoder) {
- return (protocol->proxy_stream_encoder)(srv, sess, in);
- }
- ERROR("protocol '%s' is not supported yet", SAFE_BUF_STR(protocol->name));
- return HANDLER_ERROR;
-}
-
-/**
- * encode the request for the protocol
- *
- * @param in chunkqueue with the content to (no encoding)
- * @param out chunkqueue for the encoded, protocol specific data
- */
-static handler_t proxy_encode_request_headers(server *srv, proxy_session *sess, chunkqueue *in) {
- proxy_protocol *protocol = (sess->proxy_backend) ? sess->proxy_backend->protocol : NULL;
- if(protocol && protocol->proxy_encode_request_headers) {
- /* reset proxy connection queues before we encode a new request.
- */
- chunkqueue_reset(sess->proxy_con->send);
- chunkqueue_reset(sess->proxy_con->recv);
- return (protocol->proxy_encode_request_headers)(srv, sess, in);
- }
-
- if (protocol == NULL) {
- ERROR("protocol is not set: %s", "");
- } else {
- ERROR("protocol '%s' is not supported yet", SAFE_BUF_STR(protocol->name));
- }
- return HANDLER_ERROR;
-}
-
-static handler_t proxy_handle_response_headers(server *srv, connection *con, plugin_data *p,
- proxy_session *sess, chunkqueue *out) {
- int have_content_length = 0;
- int do_x_rewrite = 0;
- size_t i;
-
- /* finished parsing http response headers from backend, now prepare http response headers
- * for client response.
- */
- sess->content_length = -1;
- con->http_status = sess->resp->status;
-
- /* copy the http-headers */
- for (i = 0; i < sess->resp->headers->used; i++) {
- const char *ign[] = { "Status", NULL };
- size_t j, k;
- data_string *ds;
-
- data_string *header = (data_string *)sess->resp->headers->data[i];
-
- /* some headers are ignored by default */
- for (j = 0; ign[j]; j++) {
- if (0 == strcasecmp(ign[j], header->key->ptr)) break;
- }
- if (ign[j]) continue;
-
- if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
- /* CGI/1.1 rev 03 - 7.2.1.2 */
- if (con->http_status == 0) con->http_status = 302;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
- have_content_length = 1;
-
- sess->content_length = strtol(header->value->ptr, NULL, 10);
-
- if (sess->content_length < 0) {
- return HANDLER_ERROR;
- }
- con->response.content_length = sess->content_length;
- /* don't save this header, other modules might change the content length. */
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
- 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
- if (p->conf.allow_x_sendfile) {
- sess->send_response_content = 0;
- sess->do_internal_redirect = 1;
-
- /* don't try to rewrite this request through mod_proxy_core again */
- sess->internal_redirect_count = MAX_INTERNAL_REDIRECTS;
-
- buffer_copy_string_buffer(con->physical.path, header->value);
-
- /* as we want to support ETag and friends we set the physical path for the file
- * and hope mod_staticfile catches up */
- }
-
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-tempfile"))) {
- if (p->conf.allow_x_sendfile && !buffer_is_empty(header->value)) {
- stat_cache_entry *sce = NULL;
-
- if (HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
- chunk *c;
- sess->send_response_content = 0;
-
- if(sce->st.st_size > 0) {
- chunkqueue_append_file(con->send, header->value, 0, sce->st.st_size);
- con->send->bytes_in += sce->st.st_size;
- c = con->send->last;
- c->file.is_temp = 1;
- } else {
- if(unlink(BUF_STR(header->value)) < 0) {
- ERROR("Failed to delete empty tempfile: file=%s, error: %s", SAFE_BUF_STR(header->value), strerror(errno));
- }
- }
- con->response.content_length = sce->st.st_size;
- have_content_length = 1;
- con->send->is_closed = 1;
- } else {
- ERROR("Failed to send tempfile: file=%s, error: %s", SAFE_BUF_STR(header->value), strerror(errno));
- }
- }
-
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Rewrite-URI"))) {
- if (p->conf.allow_x_rewrite) {
- do_x_rewrite = 1;
- buffer_copy_string_buffer(con->request.uri, header->value);
- }
-
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Rewrite-Host"))) {
- if (p->conf.allow_x_rewrite) {
- do_x_rewrite = 1;
- buffer_copy_string_buffer(con->request.http_host, header->value);
- /* replace Host request header */
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Host")))) {
- buffer_copy_string_buffer(ds->value, header->value);
- } else {
- /* insert Host request header */
- if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
- ds = data_response_init();
- }
- buffer_copy_string_len(ds->key, CONST_STR_LEN("Host"));
- buffer_copy_string_buffer(ds->value, header->value);
- array_insert_unique(con->request.headers, (data_unset *)ds);
- }
- }
-
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Rewrite-Backend"))) {
- if (p->conf.allow_x_rewrite) {
- do_x_rewrite = 1;
- if (!sess->sticky_session) sess->sticky_session = buffer_init();
- buffer_copy_string_buffer(sess->sticky_session, header->value);
- sess->do_x_rewrite_backend = 1;
- }
-
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Transfer-Encoding"))) {
- if (strstr(header->value->ptr, "chunked")) {
- sess->is_chunked = 1;
- }
- /* ignore the header */
- continue;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Connection"))) {
- if (strstr(header->value->ptr, "close")) {
- sess->is_closing = 1;
- }
- /* ignore the header */
- continue;
-
- }
-
- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
- ds = data_response_init();
- }
-
-
- buffer_copy_string_buffer(ds->key, header->key);
-
-#ifdef HAVE_PCRE_H
- for (k = 0; k < p->conf.response_rewrites->used; k++) {
- proxy_rewrite *rw = p->conf.response_rewrites->ptr[k];
-
- if (buffer_is_equal(rw->header, header->key)) {
- int ret;
-
- if ((ret = pcre_replace(rw->regex, rw->replace, header->value, p->replace_buf)) < 0) {
- switch (ret) {
- case PCRE_ERROR_NOMATCH:
- /* hmm, ok. no problem */
- buffer_append_string_buffer(ds->value, header->value);
- break;
- default:
- TRACE("oops, pcre_replace failed with: %d", ret);
- break;
- }
- } else {
- buffer_append_string_buffer(ds->value, p->replace_buf);
- }
-
- break;
- }
- }
-
- if (k == p->conf.response_rewrites->used) {
- buffer_copy_string_buffer(ds->value, header->value);
- }
-#else
- buffer_copy_string_buffer(ds->value, header->value);
-#endif
-
- array_insert_unique(con->response.headers, (data_unset *)ds);
- }
-
- if (do_x_rewrite) {
- sess->send_response_content = 0;
- sess->do_internal_redirect = 1;
- sess->do_new_session = 1;
- sess->is_chunked = 0;
- con->http_status = 0;
- sess->content_length = -1;
- con->response.content_length = -1;
-
- /* we are restarting the whole request, reset all the response headers */
- array_reset(con->response.headers);
-
- buffer_reset(con->physical.path);
-
- config_cond_cache_reset(srv, con);
- }
-
- /* we are finished decoding the response headers. */
- if(!out->is_closed) {
- /* We don't have all the response content try to enable chunked encoding. */
- /* does the client allow us to send chunked encoding ? */
- if (con->request.http_version == HTTP_VERSION_1_1 &&
- !have_content_length) {
- con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
- }
- }
-
- /* we might have part of the response content too */
- proxy_copy_response(srv, con, sess);
-
- return HANDLER_FINISHED; /* we have a full header */
-}
-
-/*
- * if there is data in the send queue enable FDEVENT_OUT & FDEVENT_IN.
- * else just enable FDEVENT_IN.
- */
-static int proxy_connection_enable_events(server *srv, proxy_connection *proxy_con) {
- int events = FDEVENT_IN;
- if (proxy_con->send->bytes_out < proxy_con->send->bytes_in) events |= FDEVENT_OUT;
- return fdevent_event_add(srv->ev, proxy_con->sock, events);
-}
-
-/**
- * encode/decode stream data from backend connection.
- *
- */
-static handler_t proxy_stream_encode_decode(server *srv, proxy_session *sess) {
- //proxy_connection *proxy_con = sess->proxy_con;
- connection *con = sess->remote_con;
-
- if (!sess->recv->is_closed) {
- /* call stream-decoder (HTTP-chunked, FastCGI, ... ) */
- switch (proxy_stream_decoder(srv, sess, sess->recv)) {
- case HANDLER_FINISHED:
- /* finished decoding reponse. */
- /* we are done, close the response content queue */
- sess->recv->is_closed = 1;
- break;
- case HANDLER_GO_ON:
- break;
- case HANDLER_ERROR:
- ERROR("%s", "stream decoder failed.");
- /* error */
- return HANDLER_ERROR;
- default:
- TRACE("stream-decoder: %s", "foo");
- break;
- }
- }
-
- /* encode request content. */
- switch(proxy_stream_encoder(srv, sess, con->recv)) {
- case HANDLER_FINISHED:
- /* finished encoding request content. */
- break;
- case HANDLER_GO_ON:
- break;
- case HANDLER_ERROR:
- ERROR("%s", "stream encoder failed.");
- /* error */
- return HANDLER_ERROR;
- default:
- TRACE("stream-encoder: %s", "foo");
- break;
- }
- chunkqueue_remove_finished_chunks(con->recv);
-
- if (!sess->is_closed) {
- /* enable FDEVENT_OUT if there is data to send. */
- proxy_connection_enable_events(srv, sess->proxy_con);
- }
-
- return HANDLER_GO_ON;
-}
-
-static handler_t proxy_connection_connect(proxy_connection *con) {
- int fd;
-#ifdef _WIN32
- int io_ctl = 1;
- int win_err = 0;
-#endif
-
- if (-1 == (fd = socket(con->address->addr.plain.sa_family, SOCK_STREAM, 0))) {
- switch (errno) {
- case EMFILE:
- return HANDLER_WAIT_FOR_FD;
- default:
- ERROR("socket failed: %s (%d)", strerror(errno), errno);
- return HANDLER_ERROR;
- }
- }
-
-#ifdef O_NONBLOCK
- fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
-#elif defined _WIN32
- ioctlsocket(fd, FIONBIO, &io_ctl);
-#endif
-
- con->sock->fd = fd;
- con->sock->fde_ndx = -1;
- con->sock->type = IOSOCKET_TYPE_SOCKET;
-
- if (-1 == connect(fd, &(con->address->addr.plain), con->address->addrlen)) {
- switch(light_sock_errno()) {
- case EINPROGRESS:
- case EALREADY:
- case EINTR:
-#ifdef _WIN32
- case EWOULDBLOCK:
-#endif
- return HANDLER_WAIT_FOR_EVENT;
- default:
- closesocket(fd);
- con->sock->fd = -1;
-
- ERROR("connect(%s) failed: %s (%d)",
- SAFE_BUF_STR(con->address->name),
- strerror(errno), errno);
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * event-handler for idling connections
- *
- * unused (idling) keep-alive connections are not bound to a session
- * and need their own event-handler
- *
- * if the connection closes (we get a FDEVENT_IN), close our side too and
- * let the trigger-func handle the cleanup
- *
- * @see proxy_trigger
- */
-
-
-static handler_t proxy_handle_fdevent_idle(void *s, void *ctx, int revents) {
- server *srv = (server *)s;
- proxy_connection *proxy_con = ctx;
- char buf[4096];
-
- if (revents & FDEVENT_IN) {
- switch (proxy_con->state) {
- case PROXY_CONNECTION_STATE_IDLE:
- proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
-
- /* close + unregister have to be in the same call,
- * otherwise we get a events for a re-opened fd */
-
- sockread(proxy_con->sock->fd, buf, sizeof(buf));
-
- fdevent_event_del(srv->ev, proxy_con->sock);
-
- /* we have to notify the pool, that this connection is free now */
-
- break;
- case PROXY_CONNECTION_STATE_CLOSED:
- /* poll() is state-driven, we will get events as long as it isn't disabled
- * the close() above should disable the events too */
- ERROR("%s", "hurry up buddy, I got another event for a closed idle-connection");
- break;
- default:
- ERROR("invalid connection state: %d, should be idle", proxy_con->state);
- break;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-
-/* don't call any proxy functions directly */
-static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) {
- server *srv = (server *)s;
- proxy_session *sess = ctx;
- proxy_connection *proxy_con;
- connection *con;
- int call_append = 1;
-
- /**
- * we might receive a event for a connection that should be closed already
- */
-
- if (sess == NULL) {
- /**
- * race
- * the other fd of the connection might have been closed already
- * mod_proxy_connection_close_callback() frees the
- */
-
- ERROR("the session ctx is NULL: %p, expect a crash", (void*) sess);
- // FIXME: do not dereference an known NULL ???
- }
-
- proxy_con = sess->proxy_con;
- con = sess->remote_con;
-
- if (revents & FDEVENT_IN) {
- chunkqueue_remove_finished_chunks(proxy_con->recv);
- switch (srv->network_backend_read(srv, con, proxy_con->sock, proxy_con->recv)) {
- case NETWORK_STATUS_CONNECTION_CLOSE:
- /* a close here means we can't read/write any more data. */
- sess->is_closed = 1;
- proxy_con->send->is_closed = 1;
- proxy_con->recv->is_closed = 1;
- break;
- case NETWORK_STATUS_SUCCESS:
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- break;
- default:
- ERROR("%s", "oops, we failed to read");
- break;
- }
- }
-
- if (revents & FDEVENT_OUT) {
- fdevent_event_add(srv->ev, proxy_con->sock, FDEVENT_IN);
-
- switch (srv->network_backend_write(srv, con, proxy_con->sock, proxy_con->send)) {
- case NETWORK_STATUS_SUCCESS:
- break;
- case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
- call_append = 0; /* let the joblist-queue-handler call the connection again */
- break;
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- fdevent_event_add(srv->ev, proxy_con->sock, FDEVENT_IN | FDEVENT_OUT);
- break;
- case NETWORK_STATUS_CONNECTION_CLOSE:
- /* done mark the connection closed here only the send queue,
- * since there might be more data to read.
- */
- proxy_con->send->is_closed = 1;
- break;
- default:
- ERROR("%s", "oops, we failed to write");
- break;
- }
- chunkqueue_remove_finished_chunks(proxy_con->send);
- }
-
- if (revents & FDEVENT_HUP) {
- if (!(revents & FDEVENT_IN)) {
- /* if we only received the FDEVENT_HUP event, then there is no more data to read. */
- sess->is_closed = 1;
- proxy_con->recv->is_closed = 1;
- }
- /* can't write on a closed socket, so close the send queue. */
- proxy_con->send->is_closed = 1;
- }
-
- if (sess->is_closed) {
- sess->recv->is_closed = 1;
- fdevent_event_del(srv->ev, sess->proxy_con->sock);
- }
-
- /**
- * on NETWORK_STATUS_WAIT_FOR_AIO_EVENT we are not allowed to call the state-engine
- * the connection has to sleep until our disk-read is finished
- *
- * the joblist_append() will be called by the joblist_append_queue_handler in server.c
- */
- if (call_append) joblist_append(srv, con);
-
- return HANDLER_GO_ON;
-}
-
-/**
- * Cleanup backend proxy connection.
- */
-static int proxy_remove_backend_connection(server *srv, proxy_session *sess) {
-
- if(!sess->proxy_con) return -1;
-
- /* cleanup protocol stream */
- proxy_stream_cleanup(srv, sess);
-
- /* remove closed connection from pool. */
- proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con);
-
- /* update stats. */
- COUNTER_SET(sess->proxy_backend->pool_size, sess->proxy_backend->pool->used);
- COUNTER_DEC(sess->proxy_backend->load);
-
- /* the backend might have been disabled by a full connection pool, re-enable
- * if there is at least one active address.
- */
- if (sess->proxy_backend->disabled_addresses <= sess->proxy_backend->address_pool->used) {
- sess->proxy_backend->state = PROXY_BACKEND_STATE_ACTIVE;
- }
-
- if (sess->proxy_con->sock->fd != -1) {
- /* if we fail in connect() might not have a FD yet */
- fdevent_event_del(srv->ev, sess->proxy_con->sock);
- fdevent_unregister(srv->ev, sess->proxy_con->sock);
- }
-
- proxy_connection_free(sess->proxy_con);
- sess->proxy_con = NULL;
-
- return 0;
-}
-
-/**
- * Recycle backend proxy connection.
- *
- * 1. close the connection if keep-alive is disable
- * 2. or set the connection idling and wake up a backlogged request.
- *
- */
-static int proxy_recycle_backend_connection(server *srv, plugin_data *p, proxy_session *sess) {
- proxy_request *req;
- int reuse = 1;
-
- if (!sess) return HANDLER_GO_ON;
-
- if (sess->proxy_con) {
- COUNTER_INC(p->request_count);
- COUNTER_INC(sess->proxy_backend->request_count);
- COUNTER_DEC(sess->proxy_backend->load);
- switch (sess->proxy_con->state) {
- case PROXY_CONNECTION_STATE_CONNECTED:
- /*
- * Set the connection to idling if:
- *
- * 1. keep-alive was not disabled (sess->is_closing)
- * 2. backend connection is already closed (sess->is_closed)
- * 3. backend protocol finished parsing all data for this request. (sess->recv->is_closed)
- * 4. keep-alive request count hasn't reached max-keep-alive-requests
- */
- if (sess->is_closing || sess->is_closed) {
- reuse = 0;
- }
-
- sess->proxy_con->request_count++;
- if (p->conf.debug) TRACE("request_count=%d", sess->proxy_con->request_count);
- if (sess->proxy_con->request_count >= p->conf.max_keep_alive_requests) {
- reuse = 0;
- }
- if (reuse && sess->recv->is_closed) {
- sess->proxy_con->state = PROXY_CONNECTION_STATE_IDLE;
-
- /* make sure backend is active since we have a free connection. */
- sess->proxy_backend->state = PROXY_BACKEND_STATE_ACTIVE;
-
- /* don't ignore events as the FD is idle
- * we might get a HUP as the remote connection might close */
- fdevent_event_del(srv->ev, sess->proxy_con->sock);
- fdevent_unregister(srv->ev, sess->proxy_con->sock);
-
- fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent_idle, sess->proxy_con);
- fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
-
- break;
- }
-
- /* fall-through for non-keep-alive or response parsing didn't finish */
-
- case PROXY_CONNECTION_STATE_CLOSED:
- /* user terminated connection and proxy connection is still in CONNECTING mode.
- * this happens frequently when backends are slow
- */
- case PROXY_CONNECTION_STATE_CONNECTING:
- proxy_remove_backend_connection(srv, sess);
- case PROXY_CONNECTION_STATE_IDLE:
- default:
- break;
- }
- sess->proxy_con = NULL;
- }
-
- /* wake up a connection from the backlog */
- if ((req = proxy_backlog_shift(p->conf.backlog))) {
- connection *next_con = req->con;
-
- if (p->conf.debug) TRACE("wakeup a connection from backlog: con=%d", next_con->sock->fd);
- joblist_append(srv, next_con);
-
- COUNTER_DEC(p->conf.backlog_size);
- proxy_request_free(req);
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * push the session into the backlog
- *
- * @returns HANDLER_ERROR in case we reach the max-connect-retry limit
- */
-static handler_t mod_proxy_core_backlog_connection(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
- proxy_request *req;
-
- if (sess->sent_to_backlog >= p->conf.max_backlog_size) {
- return HANDLER_ERROR;
- }
-
- /* connection pool is full, queue the request for now */
- req = proxy_request_init();
- req->added_ts = srv->cur_ts;
- req->con = con;
-
- proxy_backlog_push(p->conf.backlog, req);
-
- COUNTER_INC(p->conf.backlog_size);
- sess->sent_to_backlog++;
-
- return HANDLER_GO_ON;
-}
-
-/**
- * build the request-header array and call the backend specific request formater
- * to fill the chunkqueue
- */
-static int proxy_get_request_header(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
- /* request line */
- const char *remote_ip;
- size_t i;
-
- remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- array_append_key_value(sess->request_headers, CONST_STR_LEN("X-Forwarded-For"), remote_ip, strlen(remote_ip));
-
- /* http_host is NOT is just a pointer to a buffer
- * which is NULL if it is not set */
- if (con->request.http_host &&
- !buffer_is_empty(con->request.http_host)) {
- array_set_key_value(sess->request_headers, CONST_STR_LEN("X-Host"), CONST_BUF_LEN(con->request.http_host));
- }
- if (con->conf.is_ssl) {
- array_set_key_value(sess->request_headers, CONST_STR_LEN("X-Forwarded-Proto"), CONST_STR_LEN("https"));
- } else {
- array_set_key_value(sess->request_headers, CONST_STR_LEN("X-Forwarded-Proto"), CONST_STR_LEN("http"));
- }
-
- /* request header */
- for (i = 0; i < con->request.headers->used; i++) {
- data_string *ds;
- size_t k;
-
- ds = (data_string *)con->request.headers->data[i];
-
- if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
-
- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue;
- if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Expect"))) continue;
-#ifdef HAVE_PCRE_H
- for (k = 0; k < p->conf.request_rewrites->used; k++) {
- proxy_rewrite *rw = p->conf.request_rewrites->ptr[k];
-
- if (buffer_is_equal(rw->header, ds->key)) {
- int ret;
-
- if ((ret = pcre_replace(rw->regex, rw->replace, ds->value, p->replace_buf)) < 0) {
- switch (ret) {
- case PCRE_ERROR_NOMATCH:
- /* hmm, ok. no problem */
- array_set_key_value(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
- break;
- default:
- TRACE("oops, pcre_replace failed with: %d", ret);
- break;
- }
- } else {
- array_set_key_value(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(p->replace_buf));
- }
-
- break;
- }
- }
-
- if (k == p->conf.request_rewrites->used) {
- array_set_key_value(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
- }
-#else
- array_set_key_value(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
-#endif
- }
-
- /* populate sess->request_uri with the actually requested path
- * (con->request.uri). if we have pcre and there is a _uri request
- * rewrite, it will be overwritten later
- */
- buffer_copy_string_buffer(sess->request_uri, con->request.uri);
-
- /* check if we want to rewrite the uri */
-#ifdef HAVE_PCRE_H
- for (i = 0; i < p->conf.request_rewrites->used; i++) {
- proxy_rewrite *rw = p->conf.request_rewrites->ptr[i];
-
- if (buffer_is_equal_string(rw->header, CONST_STR_LEN("_uri"))) {
- int ret;
-
- if ((ret = pcre_replace(rw->regex, rw->replace, con->request.uri, p->replace_buf)) < 0) {
- switch (ret) {
- case PCRE_ERROR_NOMATCH:
- /* hmm, ok. no problem */
- buffer_copy_string_buffer(sess->request_uri, con->request.uri);
- break;
- default:
- TRACE("oops, pcre_replace failed with: %d", ret);
- break;
- }
- } else {
- buffer_copy_string_buffer(sess->request_uri, p->replace_buf);
- }
- } else if (buffer_is_equal_string(rw->header, CONST_STR_LEN("_docroot"))) {
- int ret;
-
- if ((ret = pcre_replace(rw->regex, rw->replace, con->physical.doc_root, p->replace_buf)) < 0) {
- switch (ret) {
- case PCRE_ERROR_NOMATCH:
- /* hmm, ok. no problem */
- break;
- default:
- TRACE("oops, pcre_replace failed with: %d", ret);
- break;
- }
- } else {
- /* adjust DOCUMENT_ROOT */
- buffer_copy_string_buffer(con->physical.doc_root, p->replace_buf);
-
- /* adjust SCRIPT_FILENAME */
- buffer_copy_string_buffer(con->physical.path, p->replace_buf);
- buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
- }
- } else if (buffer_is_equal_string(rw->header, CONST_STR_LEN("_pathinfo"))) {
- int ret;
-
- if ((ret = pcre_replace(rw->regex, rw->replace, con->uri.path, p->replace_buf)) < 0) {
- switch (ret) {
- case PCRE_ERROR_NOMATCH:
- /* hmm, ok. no problem */
- break;
- default:
- TRACE("oops, pcre_replace failed with: %d", ret);
- break;
- }
- } else {
- /* we matched, cool. */
- buffer_copy_string_buffer(con->request.pathinfo, p->replace_buf);
- }
- } else if (buffer_is_equal_string(rw->header, CONST_STR_LEN("_scriptname"))) {
- int ret;
-
- if ((ret = pcre_replace(rw->regex, rw->replace, con->uri.path, p->replace_buf)) < 0) {
- switch (ret) {
- case PCRE_ERROR_NOMATCH:
- /* hmm, ok. no problem */
- break;
- default:
- TRACE("oops, pcre_replace failed with: %d", ret);
- break;
- }
- } else {
- /* we matched, cool. */
- buffer_copy_string_buffer(con->uri.path, p->replace_buf);
- }
-
- }
- }
-#endif
-
- proxy_encode_request_headers(srv, sess, con->recv);
-
- return 0;
-}
-
-/* we are event-driven
- *
- * the first entry is connect() call, if the doesn't need a event
- *
- * a bit boring
- * - connect (+ delayed connect)
- * - write header + content
- * - read header + content
- *
- * as soon as have read the response header we switch con->file_started and return HANDLER_GO_ON to
- * tell the core we are ready to stream out the content.
- * */
-static handler_t proxy_state_engine(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
- /* do we have a connection ? */
-
- if (p->conf.debug > 0)
- TRACE("proxy_state_engine: state=%d", sess->state);
-
- switch (sess->state) {
- case PROXY_STATE_UNSET:
- /* we are not started yet */
- sess->connect_start_ts = srv->cur_ts;
- switch(proxy_connection_connect(sess->proxy_con)) {
- case HANDLER_WAIT_FOR_EVENT:
- /* waiting on the connect call */
-
- fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess);
- fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_OUT);
-
- sess->state = PROXY_STATE_CONNECTING;
- sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTING;
- /**
- * if we are in
- *
- * connect(...) = -1 EINPROGRESS
- *
- * it might take ages until we get a response
- */
- sess->proxy_con->state_ts = srv->cur_ts;
- sess->proxy_con->proxy_sess = sess;
-
- /* if the client connection closes its end get notified */
- fdevent_event_add(srv->ev, con->sock, FDEVENT_HUP);
-
- return HANDLER_WAIT_FOR_EVENT;
- case HANDLER_GO_ON:
- /* we are connected */
- sess->state = PROXY_STATE_CONNECTED;
- sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED;
-
- /* initialize stream. */
- proxy_stream_init(srv, sess);
-
- fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess);
-
- break;
- case HANDLER_WAIT_FOR_FD:
- /* we have to come back later when we have a fd */
- return HANDLER_WAIT_FOR_FD;
- case HANDLER_ERROR:
- /* there is no-one on the other side */
- sess->proxy_con->address->disabled_until = srv->cur_ts + p->conf.disable_time;
-
- TRACE("connecting to address %s (%p) failed, disabling for %u sec",
- SAFE_BUF_STR(sess->proxy_con->address->name),
- (void*) sess->proxy_con->address,
- (unsigned int) p->conf.disable_time);
- COUNTER_INC(sess->proxy_backend->requests_failed);
-
- sess->proxy_con->address->state = PROXY_ADDRESS_STATE_DISABLED;
- sess->proxy_backend->disabled_addresses++;
- /* if all addresses in address_pool are disabled, then disable this backend. */
-
- if (sess->proxy_backend->disabled_addresses == sess->proxy_backend->address_pool->used) {
- sess->proxy_backend->state = PROXY_BACKEND_STATE_DISABLED;
- }
- /* try another backend instead */
- return HANDLER_COMEBACK;
- default:
- /* not good, something failed */
- return HANDLER_ERROR;
-
- }
-
- /* fall through */
- case PROXY_STATE_CONNECTING:
- /* skip if already connected */
- if (sess->state == PROXY_STATE_CONNECTING) {
- int socket_error;
- socklen_t socket_error_len = sizeof(socket_error);
-
- fdevent_event_del(srv->ev, sess->proxy_con->sock);
-
- switch (sess->proxy_con->state) {
- case PROXY_CONNECTION_STATE_CONNECTING:
- if (0 != getsockopt(sess->proxy_con->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
- ERROR("getsockopt failed: %s", strerror(errno));
-
- return HANDLER_ERROR;
- }
- if (socket_error != 0) {
- switch (socket_error) {
- case ECONNREFUSED:
- /* there is no-one on the other side */
- sess->proxy_con->address->disabled_until = srv->cur_ts + p->conf.disable_time;
-
- TRACE("address %s refused us, disabling for %u sec", sess->proxy_con->address->name->ptr, (unsigned int) p->conf.disable_time);
- COUNTER_INC(sess->proxy_backend->requests_failed);
-
- break;
- case EHOSTUNREACH:
- /* there is no-one on the other side */
- sess->proxy_con->address->disabled_until = srv->cur_ts + p->conf.disable_time;
-
- TRACE("host %s is unreachable, disabling for %u sec", sess->proxy_con->address->name->ptr, (unsigned int) p->conf.disable_time);
- break;
- default:
- sess->proxy_con->address->disabled_until = srv->cur_ts + p->conf.disable_time;
-
- TRACE("connected finally failed: %s (%d)", strerror(socket_error), socket_error);
-
- TRACE("connect to address %s failed and I don't know why, disabling for %u sec", sess->proxy_con->address->name->ptr, (unsigned int) p->conf.disable_time);
-
- break;
- }
-
- sess->proxy_con->address->state = PROXY_ADDRESS_STATE_DISABLED;
- sess->proxy_backend->disabled_addresses++;
- /* if all addresses in address_pool are disabled, then disable this backend. */
- if (sess->proxy_backend->disabled_addresses == sess->proxy_backend->address_pool->used) {
- sess->proxy_backend->state = PROXY_BACKEND_STATE_DISABLED;
- }
- return HANDLER_COMEBACK;
- }
-
- sess->state = PROXY_STATE_CONNECTED;
- sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED;
-
- /* initialize stream. */
- proxy_stream_init(srv, sess);
-
- break;
- case PROXY_CONNECTION_STATE_CLOSED:
- /* looks like the connect() timed out */
- sess->proxy_con->address->disabled_until = srv->cur_ts + p->conf.disable_time;
- sess->proxy_con->address->state = PROXY_ADDRESS_STATE_DISABLED;
-
- /* the connection */
- sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
-
- /* if all addresses in address_pool are disabled, then disable this backend. */
- sess->proxy_backend->disabled_addresses++;
-
- if (sess->proxy_backend->disabled_addresses == sess->proxy_backend->address_pool->used) {
- sess->proxy_backend->state = PROXY_BACKEND_STATE_DISABLED;
- }
- TRACE("connect(%s) to failed: trying another backed",
- SAFE_BUF_STR(sess->proxy_con->address->name));
- return HANDLER_COMEBACK;
- default:
- ERROR("invalid connection-state: %d", sess->proxy_con->state);
- break;
- }
- }
-
- /* fall through */
- case PROXY_STATE_CONNECTED:
-
- sess->state = PROXY_STATE_WRITE_REQUEST_HEADER;
-
- /* fall through */
- case PROXY_STATE_WRITE_REQUEST_HEADER:
- /* build the header */
- proxy_get_request_header(srv, con, p, sess);
-
- /* send the header together with the body */
- sess->state = PROXY_STATE_WRITE_REQUEST_BODY;
-
- /* fall through */
- case PROXY_STATE_WRITE_REQUEST_BODY:
- /* do we have a content-body to send up to the backend ? */
-
- switch (proxy_stream_encode_decode(srv, sess)) {
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- /* some backends will send a response before all the request content has been written. */
- if (sess->is_closed || sess->have_response_headers) {
- chunk *c;
- if (sess->is_closed && !sess->have_response_headers) {
- if (sess->p->conf.debug) TRACE("%s", "connection to backend closed when sending request headers/content.");
- }
- if (con->recv->bytes_out < con->recv->bytes_in) {
- /* we have to consume all the request content data. */
- for (c = con->recv->first; c; c = c->next) {
- switch(c->type) {
- case MEM_CHUNK:
- c->offset = c->mem->used - 1;
- break;
- case FILE_CHUNK:
- c->offset = c->file.length;
- break;
- default:
- break;
- }
- }
- con->recv->bytes_out = con->recv->bytes_in;
- con->recv->is_closed = 1;
- }
- break;
- }
- return HANDLER_WAIT_FOR_EVENT;
- case HANDLER_ERROR:
- /* error */
- return HANDLER_ERROR;
- default:
- TRACE("stream-decoder: %s", "foo");
- break;
- }
-
- sess->state = PROXY_STATE_READ_RESPONSE_HEADER;
- /* fall through */
- case PROXY_STATE_READ_RESPONSE_HEADER:
-
- /* decode/encode stream. */
- switch (proxy_stream_encode_decode(srv, sess)) {
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- if (!sess->proxy_con->recv->is_closed && !sess->have_response_headers) {
- return HANDLER_WAIT_FOR_EVENT;
- }
- break;
- case HANDLER_ERROR:
- /* error */
- return HANDLER_ERROR;
- default:
- TRACE("stream-decoder: %s", "foo");
- return HANDLER_ERROR;
- }
-
- if (sess->have_response_headers) {
- /* handle the parsed response headers. */
- switch (proxy_handle_response_headers(srv, con, p, sess, sess->recv)) {
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- break;
- case HANDLER_ERROR:
- /* bad gateway */
- con->http_status = 502;
- return HANDLER_FINISHED;
- default:
- ERROR("%s", "++ oops, something went wrong while parsing response headers");
- con->http_status = 500; /* Internal Server Error */
- return HANDLER_ERROR;
- }
- }
-
- if (!sess->is_closed && !sess->have_response_headers) {
- if (sess->proxy_con->recv->bytes_in == 0) {
- /* the connection went away before we got something back */
- if (p->conf.debug) TRACE("%s", "connection closed while reading the response headers");
-
- if (con->request.content_length <= 0) {
- /**
- * we might run into a 'race-condition'
- *
- * 1. proxy-con is keep-alive, idling and just being closed (FDEVENT_IN) [fd=27]
- * 2. new connection comes in, we use the idling connection [fd=14]
- * 3. we write(), successful [to fd=27]
- * 3. we read() ... and finally receive the close-event for the connection
- */
-
- return HANDLER_COMEBACK;
- } else {
- ERROR("%s", "request content length > 0 can't restart request.");
- }
- } else {
- ERROR("%s", "connection closed after reading part of the response headers.");
- }
-
- con->http_status = 500; /* Internal Server Error */
- return HANDLER_ERROR;
- } else if (sess->do_internal_redirect) {
- /* no more response data to process. do redirect now. */
- if (sess->recv->is_closed) {
- sess->state = PROXY_STATE_FINISHED;
- /* now it becomes tricky
- *
- * mod_staticfile should handle this file for us
- * con->mode = DIRECT is taking us out of the loop */
- con->mode = DIRECT;
- con->http_status = 0;
-
- return HANDLER_COMEBACK;
- } else {
- /* finish processing response data, so we can re-use backend connection. */
- sess->state = PROXY_STATE_READ_RESPONSE_BODY;
- }
- } else {
- con->file_started = 1;
- /* if Status: ... is not set, 200 is our default status-code */
- if (con->http_status == 0) con->http_status = 200;
-
- /* check if all the response content has been read/decoded. */
- if (sess->bytes_read == sess->content_length) {
- sess->is_request_finished = 1;
- /* close response content chunkqueue */
- sess->recv->is_closed = 1;
- }
- /* copy any response content we might have. */
- proxy_copy_response(srv, con, sess);
-
- sess->state = PROXY_STATE_READ_RESPONSE_BODY;
-
- /**
- * set the event to pass the content through to the server
- *
- * this triggers the event-handler
- * @see proxy_handle_fdevent
- */
-
- return HANDLER_GO_ON; /* tell http_response_prepare that we are done with the header */
- }
-
- if (sess->state != PROXY_STATE_READ_RESPONSE_BODY) break;
- case PROXY_STATE_READ_RESPONSE_BODY:
-
- switch (proxy_stream_encode_decode(srv, sess)) {
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- break;
- case HANDLER_ERROR:
- /* error */
- return HANDLER_ERROR;
- default:
- TRACE("stream-decoder: %s", "foo");
- break;
- }
-
- proxy_copy_response(srv, con, sess);
-
- if (!sess->proxy_con->recv->is_closed && !sess->is_request_finished) {
- return HANDLER_WAIT_FOR_EVENT;
- }
-
- if(sess->is_request_finished) {
- sess->recv->is_closed = 1;
- con->send->is_closed = 1;
- /* recycle proxy connection. */
- proxy_recycle_backend_connection(srv, p, sess);
-
- sess->state = PROXY_STATE_FINISHED;
-
- if (sess->do_internal_redirect) {
- /* now it becomes tricky
- *
- * mod_staticfile should handle this file for us
- * con->mode = DIRECT is taking us out of the loop */
- con->send->is_closed = 0;
- con->mode = DIRECT;
- con->http_status = 0;
-
- return HANDLER_COMEBACK;
- }
- }
-
- /* we wrote something into the the send-buffers,
- * call the connection-handler to push it to the client */
- joblist_append(srv, con);
-
- break;
- default:
- break;
- }
-
- return HANDLER_GO_ON;
-}
-
-static proxy_backend *proxy_find_backend(server *srv, connection *con, plugin_data *p, buffer *name) {
- size_t i;
-
- UNUSED(srv);
- UNUSED(con);
-
- for (i = 0; i < p->conf.backends->used; i++) {
- proxy_backend *backend = p->conf.backends->ptr[i];
-
- if (buffer_is_equal(backend->name, name)) {
- return backend;
- }
- }
-
- return NULL;
-}
-
-/**
- * choose an available backend
- *
- */
-static proxy_backend *proxy_backend_balancer(server *srv, connection *con, proxy_session *sess) {
- size_t i;
- plugin_data *p = sess->p;
- proxy_backends *backends = p->conf.backends;
- unsigned long last_max; /* for the HASH balancer */
- proxy_backend *backend = NULL, *cur_backend = NULL;
- int active_backends = 0, rand_ndx;
- size_t min_used;
-
- UNUSED(srv);
-
- /* if we only have one backend just return it. */
- if (backends->used == 1) {
- backend = backends->ptr[0];
-
- return backend->state == PROXY_BACKEND_STATE_ACTIVE ? backend : NULL;
- }
-
- /* frist try to select backend based on sticky session. */
- if (sess->sticky_session) {
- /* find backend */
- backend = proxy_find_backend(srv, con, p, sess->sticky_session);
- if (NULL != backend) return backend;
- }
-
- /* apply balancer algorithm to select backend. */
- switch(p->conf.balancer) {
- case PROXY_BALANCE_CARP:
- /* hash balancing */
-
- for (i = 0, last_max = ULONG_MAX; i < backends->used; i++) {
- unsigned long cur_max;
-
- cur_backend = backends->ptr[i];
-
- if (cur_backend->state != PROXY_BACKEND_STATE_ACTIVE) continue;
-
- cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
- generate_crc32c(CONST_BUF_LEN(cur_backend->name)) + /* we can cache this */
- generate_crc32c(CONST_BUF_LEN(con->uri.authority));
-#if 0
- TRACE("hash-election: %s - %s - %s: %ld",
- con->uri.path->ptr,
- cur_backend->name->ptr,
- con->uri.authority->ptr,
- cur_max);
-#endif
- if (backend == NULL || (cur_max > last_max)) {
- last_max = cur_max;
-
- backend = cur_backend;
- }
- }
-
- break;
- case PROXY_BALANCE_STATIC:
- /* static (only fail-over) */
-
- for (i = 0; i < backends->used; i++) {
- cur_backend = backends->ptr[i];
-
- if (cur_backend->state != PROXY_BACKEND_STATE_ACTIVE) continue;
-
- backend = cur_backend;
- break;
- }
-
- break;
- case PROXY_BALANCE_SQF:
- /* shortest-queue-first balancing */
-
- for (i = 0, min_used = SIZE_MAX; i < backends->used; i++) {
- cur_backend = backends->ptr[i];
-
- if (cur_backend->state != PROXY_BACKEND_STATE_ACTIVE) continue;
-
- /* the backend is up, use it */
- if (cur_backend->pool->used < min_used ) {
- backend = cur_backend;
- min_used = cur_backend->pool->used;
- }
- }
-
- break;
- case PROXY_BALANCE_UNSET: /* if not set, use round-robin as default */
- case PROXY_BALANCE_RR:
- /* round robin */
-
- /**
- * instead of real RoundRobin we just do a RandomSelect
- *
- * it is state-less and has the same distribution
- */
-
- active_backends = 0;
-
- for (i = 0; i < backends->used; i++) {
- cur_backend = backends->ptr[i];
-
- if (cur_backend->state != PROXY_BACKEND_STATE_ACTIVE) continue;
-
- active_backends++;
- }
-
- rand_ndx = (int) (1.0 * active_backends * rand()/(RAND_MAX));
-
- active_backends = 0;
- for (i = 0; i < backends->used; i++) {
- cur_backend = backends->ptr[i];
-
- if (cur_backend->state != PROXY_BACKEND_STATE_ACTIVE) continue;
-
- backend = cur_backend;
-
- if (rand_ndx == active_backends++) break;
- }
-
- break;
- }
-
- return backend;
-}
-
-/**
- * choose an available address from the address-pool
- *
- * the backend has different balancers
- */
-static proxy_address *proxy_address_balancer(server *srv, connection *con, proxy_session *sess) {
- size_t i;
- proxy_backend *backend = sess->proxy_backend;
- proxy_address_pool *address_pool = backend->address_pool;
- unsigned long last_max; /* for the HASH balancer */
- proxy_address *address = NULL, *cur_address = NULL;
- int active_addresses = 0, rand_ndx;
- size_t min_used;
-
- UNUSED(srv);
-
- /* if we only have one address just return it. */
- if (address_pool->used == 1) {
- address = address_pool->ptr[0];
-
- return address->state == PROXY_ADDRESS_STATE_ACTIVE ? address : NULL;
- }
-
- /* apply balancer algorithm to select address. */
- switch(backend->balancer) {
- case PROXY_BALANCE_CARP:
- /* hash balancing */
-
- for (i = 0, last_max = ULONG_MAX; i < address_pool->used; i++) {
- unsigned long cur_max;
-
- cur_address = address_pool->ptr[i];
-
- if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
-
- cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
- generate_crc32c(CONST_BUF_LEN(cur_address->name)) + /* we can cache this */
- generate_crc32c(CONST_BUF_LEN(con->uri.authority));
-#if 0
- TRACE("hash-election: %s - %s - %s: %ld",
- con->uri.path->ptr,
- cur_address->name->ptr,
- con->uri.authority->ptr,
- cur_max);
-#endif
- if (address == NULL || (cur_max > last_max)) {
- last_max = cur_max;
-
- address = cur_address;
- }
- }
-
- break;
- case PROXY_BALANCE_STATIC:
- /* static (only fail-over) */
-
- for (i = 0; i < address_pool->used; i++) {
- cur_address = address_pool->ptr[i];
-
- if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
-
- address = cur_address;
- break;
- }
-
- break;
- case PROXY_BALANCE_SQF:
- /* shortest-queue-first balancing */
-
- for (i = 0, min_used = SIZE_MAX; i < address_pool->used; i++) {
- cur_address = address_pool->ptr[i];
-
- if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
-
- /* the address is up, use it */
- if (cur_address->used < min_used ) {
- address = cur_address;
- min_used = cur_address->used;
- }
- }
-
- break;
- case PROXY_BALANCE_UNSET: /* if not set, use round-robin as default */
- case PROXY_BALANCE_RR:
- /* round robin */
-
- /**
- * instead of real RoundRobin we just do a RandomSelect
- *
- * it is state-less and has the same distribution
- */
-
- active_addresses = 0;
-
- for (i = 0; i < address_pool->used; i++) {
- cur_address = address_pool->ptr[i];
-
- if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
-
- active_addresses++;
- }
-
- rand_ndx = (int) (1.0 * active_addresses * rand()/(RAND_MAX));
-
- active_addresses = 0;
- for (i = 0; i < address_pool->used; i++) {
- cur_address = address_pool->ptr[i];
-
- if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
-
- address = cur_address;
-
- if (rand_ndx == active_addresses++) break;
- }
-
- break;
- }
-
- return address;
-}
-
-static int mod_proxy_core_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- /* global defaults */
- PATCH_OPTION(balancer);
- PATCH_OPTION(debug);
- PATCH_OPTION(backends);
- PATCH_OPTION(backlog);
- PATCH_OPTION(backlog_size);
- PATCH_OPTION(protocol);
- PATCH_OPTION(request_rewrites);
- PATCH_OPTION(response_rewrites);
- PATCH_OPTION(allow_x_sendfile);
- PATCH_OPTION(allow_x_rewrite);
- PATCH_OPTION(max_pool_size);
- PATCH_OPTION(check_local);
- PATCH_OPTION(split_hostnames);
- PATCH_OPTION(max_keep_alive_requests);
- PATCH_OPTION(disable_time);
- PATCH_OPTION(max_backlog_size);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_BACKENDS))) {
- PATCH_OPTION(backends);
- PATCH_OPTION(backlog);
- PATCH_OPTION(backlog_size);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_DEBUG))) {
- PATCH_OPTION(debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_BALANCER))) {
- PATCH_OPTION(balancer);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_PROTOCOL))) {
- PATCH_OPTION(protocol);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_REWRITE_REQUEST))) {
- PATCH_OPTION(request_rewrites);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_REWRITE_RESPONSE))) {
- PATCH_OPTION(response_rewrites);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_ALLOW_X_SENDFILE))) {
- PATCH_OPTION(allow_x_sendfile);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_ALLOW_X_REWRITE))) {
- PATCH_OPTION(allow_x_rewrite);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_MAX_POOL_SIZE))) {
- PATCH_OPTION(max_pool_size);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_CHECK_LOCAL))) {
- PATCH_OPTION(check_local);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_SPLIT_HOSTNAMES))) {
- PATCH_OPTION(split_hostnames);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_MAX_KEEP_ALIVE))) {
- PATCH_OPTION(max_keep_alive_requests);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_DISABLE_TIME))) {
- PATCH_OPTION(disable_time);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_MAX_BACKLOG_SIZE))) {
- PATCH_OPTION(max_backlog_size);
- }
- }
- }
-
- return 0;
-}
-
-static int mod_proxy_core_check_match(server *srv, connection *con, plugin_data *p, int file_match) {
- proxy_session *sess = con->plugin_ctx[p->id];
- buffer *path;
-
- if (sess && !sess->do_new_session) {
- /* if this is the second round, sess is already prepared */
- return HANDLER_GO_ON;
- }
-
- /* check if we have a matching conditional for this request */
- mod_proxy_core_patch_connection(srv, con, p);
-
- /* no proxy backends to handle this request. */
- if (p->conf.backends->used == 0) return HANDLER_GO_ON;
-#if 0
- /* if check_local is enabled, then wait for file match. */
- if (file_match != p->conf.check_local) return HANDLER_GO_ON;
-#endif
- path = file_match ? con->physical.path : con->uri.path;
-#if 0
- if (buffer_is_empty(path)) return HANDLER_GO_ON;
-#endif
- if (sess && sess->do_x_rewrite_backend) {
- proxy_backend *backend;
- buffer *sticky_session = sess->sticky_session;
-
- sess->sticky_session = NULL;
- /* clear old session state */
- proxy_session_reset(sess);
-
- /* find backend */
- backend = proxy_find_backend(srv, con, p, sticky_session);
- if (backend == NULL) {
- backend = proxy_backend_init();
-
- backend->balancer = p->conf.balancer;
- backend->protocol = p->conf.protocol;
-
- buffer_copy_string_buffer(backend->name, sticky_session);
- /* check if the new backend has a valid backend-address */
- if (0 == proxy_address_pool_add_string(backend->address_pool, backend->name)) {
- if (p->conf.max_pool_size) {
- backend->pool->max_size = p->conf.max_pool_size;
- }
-
- proxy_backends_add(p->conf.backends, backend);
- } else {
- proxy_backend_free(backend);
- backend = NULL;
- }
- }
- /* no backend available. */
- if (NULL == backend) {
- buffer_free(sticky_session);
- return HANDLER_GO_ON;
- }
- sess->proxy_backend = backend;
- sess->sticky_session = sticky_session;
- } else if (sess) {
- proxy_session_reset(sess);
- }
-
- /* make sure we have a protocol. */
- if (p->conf.protocol == NULL) {
- con->http_status = 500; /* internal error */
- con->send->is_closed = 1;
-
- TRACE("proxy-core.backends is set, but proxy-core.protocol is not, can't handle '%s' for host '%s'",
- SAFE_BUF_STR(con->uri.path),
- SAFE_BUF_STR(con->uri.authority));
- return HANDLER_FINISHED;
- }
-
- if (!sess) {
- /* a session lives for a single request */
- sess = proxy_session_init();
- }
- /* make sure the state is correct. */
- sess->state = PROXY_STATE_UNSET;
-
- con->plugin_ctx[p->id] = sess;
- con->mode = p->id;
-
- if (con->conf.log_request_handling) {
- TRACE("handling it in mod_proxy_core: %s.path=%s",
- file_match ? "physical" : "uri", SAFE_BUF_STR(path));
- }
- sess->p = p;
- sess->remote_con = con;
-
- return HANDLER_FINISHED;
-}
-
-SUBREQUEST_FUNC(mod_proxy_core_match_url) {
- return mod_proxy_core_check_match(srv, con, p_d, 0);
-}
-
-SUBREQUEST_FUNC(mod_proxy_core_match_local_file) {
- return mod_proxy_core_check_match(srv, con, p_d, 1);
-}
-
-/**
- * end of a request
- */
-REQUESTDONE_FUNC(mod_proxy_connection_close_callback) {
- plugin_data *p = p_d;
- proxy_session *sess = con->plugin_ctx[p->id];
-
- if (!sess) return HANDLER_GO_ON;
-
- /* TODO: copy p->conf into proxy_session when request starts. */
- /* re-patch p->conf */
- mod_proxy_core_patch_connection(srv, con, p);
-
- if (p->conf.debug) TRACE("proxy_connection_reset (%d)", con->sock->fd);
-
- if (sess->proxy_con) {
- proxy_recycle_backend_connection(srv, p, sess);
- } else {
- /* if we have the connection in the backlog, remove it */
- if (0 == proxy_backlog_remove_connection(p->conf.backlog, con)) {
- COUNTER_DEC(p->conf.backlog_size);
- }
- }
-
- /* cleanup proxy session */
- proxy_session_free(sess);
-
- con->plugin_ctx[p->id] = NULL;
-
- return HANDLER_GO_ON;
-}
-
-CONNECTION_FUNC(mod_proxy_core_start_backend) {
- plugin_data *p = p_d;
- proxy_session *sess = con->plugin_ctx[p->id];
-
- if (p->id != con->mode) return HANDLER_GO_ON;
- if (!sess) return HANDLER_GO_ON;
-
- /* TODO: copy p->conf into proxy_session when request starts. */
- /* re-patch p->conf */
- mod_proxy_core_patch_connection(srv, con, p);
-
- /*
- * 0. build session
- * 1. get a proxy connection
- * 2. create the http-request header
- * 3. stream the content to the backend
- * 4. wait for http-response header
- * 5. decode the response + parse the response
- * 6. stream the response-content to the client
- * 7. session finished wait for request close
- * 8. kill session
- * */
-
- if (sess->do_internal_redirect) {
- if (sess->internal_redirect_count > MAX_INTERNAL_REDIRECTS) {
- /* we already handled this request and sent it to the static file handling */
-
- return HANDLER_GO_ON;
- }
- }
-
- switch (sess->state) {
- case PROXY_STATE_FINISHED:
- return HANDLER_GO_ON;
- case PROXY_STATE_CONNECTING:
- /* this connections has waited 10 seconds to connect to the backend
- * and didn't got a successful connection yet, sending timeout */
- if (srv->cur_ts - sess->connect_start_ts > 10) {
- con->http_status = 504; /* gateway timeout */
- con->send->is_closed = 1;
-
- if (sess->proxy_con) {
- TRACE("connect to backend timed out: %s", SAFE_BUF_STR(sess->proxy_con->address->name));
- /* if we are waiting for a proxy-connection right now, close it */
- proxy_remove_backend_connection(srv, sess);
- } else {
- TRACE("%s", "timed out when trying to connect to backend and don't have a connection.");
- }
-
- return HANDLER_FINISHED;
- }
- default:
- /* handle-request-timeout, */
-#if 0
- if (srv->cur_ts - con->request_start > 60) {
- TRACE("request runs longer than 60sec: current state: %d", sess->state);
- }
-#endif
- break;
- }
-
-
- /* if the WRITE fails from the start, restart the connection */
- while (1) {
- if (sess->proxy_con == NULL) {
- proxy_address *address = NULL;
-
- /**
- * ask the balancer for the next address and
- * check the connection pool if we have a connection open
- * for that address
- */
- if (NULL == (sess->proxy_backend = proxy_backend_balancer(srv, con, sess))) {
- if (p->conf.debug) TRACE("backlog: all backends are full or down, putting %s (%d) into the backlog, retry = %d",
- SAFE_BUF_STR(con->uri.path), con->sock->fd, sess->sent_to_backlog + 1);
-
- /* no backends available right now. */
- if (HANDLER_ERROR == mod_proxy_core_backlog_connection(srv, con, p, sess)) {
- con->http_status = 504; /* gateway timeout */
- con->send->is_closed = 1;
-
- TRACE("connecting backends timed out, retry limit reached: %d", sess->sent_to_backlog);
- return HANDLER_FINISHED;
- }
-
- /* no, not really an event,
- * we just want to block the outer loop from stepping forward
- *
- * the trigger will bring this connection back into the game
- */
- return HANDLER_WAIT_FOR_EVENT;
- }
-
- sess->proxy_backend->protocol = p->conf.protocol;
- sess->proxy_backend->balancer = p->conf.balancer;
-
- if (p->conf.debug && sess->proxy_backend) {
- TRACE("selected backend: %s, state: %d", SAFE_BUF_STR(sess->proxy_backend->name), sess->proxy_backend->state);
- }
-
- /**
- * ask the balancer for the next address and
- * check the connection pool if we have a connection open
- * for that address
- */
- if (NULL == (address = proxy_address_balancer(srv, con, sess))) {
- /* no addresses available for this backend right now. */
- sess->proxy_backend->state = PROXY_BACKEND_STATE_DISABLED; /* disable backend */
- TRACE("backlog: all addresses are down, putting %s (%d) into the backlog, retry = %d",
- SAFE_BUF_STR(con->uri.path), con->sock->fd, sess->sent_to_backlog + 1);
-
- if (HANDLER_ERROR == mod_proxy_core_backlog_connection(srv, con, p, sess)) {
- con->http_status = 504; /* gateway timeout */
- con->send->is_closed = 1;
-
- TRACE("connecting backends timed out, retry limit reached: %d", sess->sent_to_backlog);
- return HANDLER_FINISHED;
- }
-
- /* no, not really an event,
- * we just want to block the outer loop from stepping forward
- *
- * the trigger will bring this connection back into the game
- */
-
- return HANDLER_WAIT_FOR_EVENT;
- }
-
- if (PROXY_CONNECTIONPOOL_FULL == proxy_connection_pool_get_connection(
- sess->proxy_backend->pool, address, &(sess->proxy_con))) {
- /* all connections are busy. */
- sess->proxy_backend->state = PROXY_BACKEND_STATE_FULL;
-
- if (p->conf.debug) TRACE("backlog: the con-pool is full, putting %s (%d) into the backlog", SAFE_BUF_STR(con->uri.path), con->sock->fd);
- if (HANDLER_ERROR == mod_proxy_core_backlog_connection(srv, con, p, sess)) {
- con->http_status = 504; /* gateway timeout */
- con->send->is_closed = 1;
-
- TRACE("connecting backends timed out, retry limit reached: %d", sess->sent_to_backlog);
- return HANDLER_FINISHED;
- }
-
- /* no, not really an event,
- * we just want to block the outer loop from stepping forward
- *
- * the trigger will bring this connection back into the game
- */
- return HANDLER_WAIT_FOR_EVENT;
- }
- COUNTER_SET(sess->proxy_backend->pool_size, sess->proxy_backend->pool->used);
- COUNTER_INC(sess->proxy_backend->load);
-
- /* need to reset flags. */
- sess->is_closing = 0;
- sess->is_closed = 0;
- /* a fresh connection, we need address for it */
- if (sess->proxy_con->state == PROXY_CONNECTION_STATE_CONNECTING) {
- sess->state = PROXY_STATE_UNSET;
- sess->bytes_read = 0;
- } else {
- /* we are already connected */
- sess->state = PROXY_STATE_CONNECTED;
-
- /* the connection was idling and using the fdevent_idle-handler
- * switch it back to the normal proxy-event-handler */
- fdevent_event_del(srv->ev, sess->proxy_con->sock);
- fdevent_unregister(srv->ev, sess->proxy_con->sock);
-
- fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess);
- fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
- }
- }
-
-
- switch (proxy_state_engine(srv, con, p, sess)) {
- case HANDLER_WAIT_FOR_EVENT:
- return HANDLER_WAIT_FOR_EVENT;
- case HANDLER_COMEBACK:
-#if 0
- TRACE("%s", "setting PROXY_STATE_FINISHED");
- sess->state = PROXY_STATE_FINISHED;
-#endif
- /* request finished do redirect. */
- if (sess->do_internal_redirect) {
- /* recycle proxy connection. */
- proxy_recycle_backend_connection(srv, p, sess);
- return HANDLER_COMEBACK;
- }
- /* restart the connection to the backend */
- if (p->conf.debug) TRACE("%s", "write failed, restarting request");
- proxy_remove_backend_connection(srv, sess);
- break;
- case HANDLER_WAIT_FOR_FD:
- return HANDLER_WAIT_FOR_FD;
- case HANDLER_GO_ON:
- return HANDLER_GO_ON;
- default:
- TRACE("state: %d (error)", sess->state);
- proxy_remove_backend_connection(srv, sess);
- /* only set 500 if not another error code is already set (like 502) */
- if (con->http_status < 500 || con->http_status > 599) {
- con->http_status = 500; /* Internal Server Error */
- }
- con->mode = DIRECT;
- return HANDLER_GO_ON;
- }
- }
-
- /* should not be reached */
- return HANDLER_ERROR;
-}
-
-CONNECTION_FUNC(mod_proxy_send_request_content) {
- plugin_data *p = p_d;
-
- if (p->id != con->mode) return HANDLER_GO_ON;
-
- /* read all the content before we start our backend */
- if (!con->recv->is_closed) {
- return HANDLER_GO_ON;
- }
-
- /* copy the chunks to our queue and call the state-engine to send it out */
- return mod_proxy_core_start_backend(srv, con, p_d);
-}
-
-/**
- * cleanup dead connections once a second
- *
- * the idling event-handler can't cleanup connections itself and has to wait until the
- * trigger cleans up
- */
-static int mod_proxy_wakeup_connections(server *srv, plugin_data *p, plugin_config *p_conf) {
- size_t i, j;
- proxy_request *req;
- int total_conns_available = 0, backends_available = 0;
- int woken_up;
-
- for (i = 0; i < p_conf->backends->used; i++) {
- proxy_backend *backend = p_conf->backends->ptr[i];
- proxy_connection_pool *pool = backend->pool;
- proxy_address_pool *address_pool = backend->address_pool;
- unsigned int conns_available = 0, addrs_disabled = 0;
- proxy_session *sess = NULL;
-
- conns_available = (pool->max_size - pool->used);
- for (j = 0; j < pool->used; ) {
- proxy_connection *proxy_con = pool->ptr[j];
-
- /* remove-con is removing the current con and moves the good connections to the left
- * no need to increment i */
- switch (proxy_con->state) {
- case PROXY_CONNECTION_STATE_CLOSED:
- proxy_connection_pool_remove_connection(backend->pool, proxy_con);
- COUNTER_SET(backend->pool_size, backend->pool->used);
-
- fdevent_event_del(srv->ev, proxy_con->sock);
- fdevent_unregister(srv->ev, proxy_con->sock);
-
- proxy_connection_free(proxy_con);
-
- conns_available++;
- break;
- case PROXY_CONNECTION_STATE_CONNECTING:
- /* how long are we in this state already ?
- *
- * if the connect() failed with EINPROGRESS we have to wait until we get a POLLOUT
- * if for some reason we don't get that in 4-5 seconds we have to kill the attempt
- *
- * */
-
- if (srv->cur_ts - proxy_con->state_ts < 5) {
- j++;
- break;
- }
-
- TRACE("connect(%s) timed out, closing backend connection",
- SAFE_BUF_STR(proxy_con->address->name));
-
- /** timed out
- *
- * we have to tell the proxy connection to try to connect another backend
- */
-
- proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
-
- sess = proxy_con->proxy_sess;
- joblist_append(srv, sess->remote_con);
-
- j++;
- break;
- case PROXY_CONNECTION_STATE_IDLE:
- conns_available++;
- default:
- j++;
- }
- }
-
- /* active the disabled addresses again */
- for (j = 0; j < address_pool->used; j++) {
- proxy_address *address = address_pool->ptr[j];
-
- if (address->state != PROXY_ADDRESS_STATE_DISABLED) continue;
-
- if (srv->cur_ts > address->disabled_until) {
- address->disabled_until = 0;
- address->state = PROXY_ADDRESS_STATE_ACTIVE;
- } else {
- addrs_disabled++;
- }
- }
-
- total_conns_available += conns_available;
- backend->disabled_addresses = addrs_disabled;
- /* update backend's state */
- if (conns_available == 0) {
- /* connection pool is full and there are no idle connections. */
- backend->state = PROXY_BACKEND_STATE_FULL;
- } else if (addrs_disabled == address_pool->used) {
- /* all addresses are disabled. */
- backend->state = PROXY_BACKEND_STATE_DISABLED;
- } else {
- backend->state = PROXY_BACKEND_STATE_ACTIVE;
- backends_available++;
- }
- }
-
- /* no backends available can't wake any connections. */
- if (backends_available == 0) {
- /* all backends are full or disabled. */
- return 0;
- }
-
- /* wake up the connections from the backlog */
- for (woken_up = 0; woken_up < total_conns_available && (req = proxy_backlog_shift(p_conf->backlog)); woken_up++) {
- connection *con = req->con;
-
- if (p_conf->debug) TRACE("wakeup a connection from backlog: con=%d", con->sock->fd);
- joblist_append(srv, con);
-
- COUNTER_DEC(p->conf.backlog_size);
- proxy_request_free(req);
- }
-
- return woken_up;
-}
-
-TRIGGER_FUNC(mod_proxy_trigger) {
- plugin_data *p = p_d;
- size_t i;
-
- /**
- * walk through all the different address pools and check if they are still alive
- *
- * in case of connect() = -1 -> EINPROGRESS we might have trigger the state-engine
- */
- for (i = 0; i < srv->config_context->used; i++) {
- mod_proxy_wakeup_connections(srv, p, p->config_storage[i]);
- }
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_proxy_core_plugin_init(plugin *p);
-LI_EXPORT int mod_proxy_core_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mod_proxy_core");
-
- p->init = mod_proxy_core_init;
- p->cleanup = mod_proxy_core_free;
- p->set_defaults = mod_proxy_core_set_defaults;
- p->handle_physical = mod_proxy_core_match_url;
- p->handle_start_backend = mod_proxy_core_match_local_file;
- p->handle_send_request_content = mod_proxy_send_request_content;
- p->handle_read_response_content = mod_proxy_core_start_backend;
- p->connection_reset = mod_proxy_connection_close_callback;
- p->handle_connection_close = mod_proxy_connection_close_callback;
- p->handle_trigger = mod_proxy_trigger;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_proxy_core.h b/src/mod_proxy_core.h
deleted file mode 100644
index a3685539..00000000
--- a/src/mod_proxy_core.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef _MOD_PROXY_CORE_H_
-#define _MOD_PROXY_CORE_H_
-
-#include "plugin.h"
-
-#include "mod_proxy_core_pool.h"
-#include "mod_proxy_core_backend.h"
-#include "mod_proxy_core_backlog.h"
-#include "mod_proxy_core_rewrites.h"
-
-#include "buffer.h"
-#include "http_resp.h"
-#include "array.h"
-
-#define MAX_INTERNAL_REDIRECTS 8
-
-struct proxy_protocol;
-
-typedef struct {
- proxy_backends *backends;
-
- proxy_backlog *backlog;
- data_integer *backlog_size;
-
- proxy_rewrites *request_rewrites;
- proxy_rewrites *response_rewrites;
-
- unsigned short allow_x_sendfile;
- unsigned short allow_x_rewrite;
- unsigned short debug;
- unsigned short max_pool_size;
- unsigned short check_local;
- unsigned short split_hostnames;
- unsigned short max_keep_alive_requests;
- unsigned short disable_time;
- unsigned short max_backlog_size;
-
- proxy_balance_t balancer;
- struct proxy_protocol *protocol;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- array *possible_balancers;
- /*array *possible_protocols; */
- struct proxy_protocol *(*proxy_register_protocol) (const char *name); /* register new protocol */
-
- /* statistics counters. */
- data_integer *request_count;
-
- /* for parsing only */
- array *backends_arr;
- buffer *protocol_buf;
- buffer *balance_buf;
-
- buffer *replace_buf;
-
- buffer *tmp_buf; /** a temporary buffer, used by mod_proxy_backend_fastcgi */
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} mod_proxy_core_plugin_data;
-
-#define plugin_data mod_proxy_core_plugin_data
-
-typedef enum {
- PROXY_STATE_UNSET,
- PROXY_STATE_CONNECTING,
- PROXY_STATE_CONNECTED,
- PROXY_STATE_WRITE_REQUEST_HEADER,
- PROXY_STATE_WRITE_REQUEST_BODY,
- PROXY_STATE_READ_RESPONSE_HEADER,
- PROXY_STATE_READ_RESPONSE_BODY,
- PROXY_STATE_FINISHED
-} proxy_state_t;
-
-typedef struct proxy_session {
- proxy_connection *proxy_con;
- proxy_backend *proxy_backend;
-
- connection *remote_con;
-
- buffer *request_uri;
- array *request_headers; /** the con->request.headers without the hop-to-hop headers */
- array *env_headers; /** transformed request-headers for the backend */
-
- http_resp *resp; /** response http headers from backend. */
-
- plugin_data *p; /** used by proxy_xxx_get_request_chunk protocol callbacks */
-
- int is_chunked; /** is the incoming content chunked (for HTTP) */
- int is_closing; /** our connection will close when we are done */
- int is_closed; /** our connection closed. we might have to restart the request. */
- int have_response_headers; /** finished parsing response headers. */
- int is_request_finished; /** encoding/decoding this request is finished. */
- int send_response_content; /** 0 if we have to ignore the content-body */
- int do_internal_redirect; /** 1 if we do a internal redirect to the ->mode = DIRECT */
- int internal_redirect_count; /** protection against infinite loops */
- int do_new_session; /** 1 if we want a new proxy session can be created. */
- int do_x_rewrite_backend; /** 1 if we want to do custom backend balancing */
-
- buffer *sticky_session; /** holds name of backend for custom balancing or sticky sessions */
-
- /**
- * chunkqueues
- * - recv is the decoded response headers and content
- */
- chunkqueue *recv;
-
- off_t bytes_read;
- off_t content_length;
-
- proxy_state_t state;
-
- time_t connect_start_ts;
-
- int sent_to_backlog;
-} proxy_session;
-
-#endif
diff --git a/src/mod_proxy_core_address.c b/src/mod_proxy_core_address.c
deleted file mode 100644
index 0978c9d1..00000000
--- a/src/mod_proxy_core_address.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include "log.h"
-#include "sys-socket.h"
-#include "mod_proxy_core_address.h"
-
-static proxy_address *proxy_address_init(void) {
- proxy_address *address;
-
- address = calloc(1, sizeof(*address));
-
- address->name = buffer_init();
- address->used = 0;
-
- return address;
-}
-
-static void proxy_address_free(proxy_address *address) {
- if (!address) return;
-
- buffer_free(address->name);
-
- free(address);
-}
-
-
-proxy_address_pool *proxy_address_pool_init(void) {
- proxy_address_pool *address_pool;
-
- address_pool = calloc(1, sizeof(*address_pool));
-
- return address_pool;
-}
-
-void proxy_address_pool_free(proxy_address_pool *address_pool) {
- if (!address_pool) return;
-
- ARRAY_STATIC_FREE(address_pool, proxy_address, element, proxy_address_free(element));
-
- free(address_pool);
-}
-
-void proxy_address_pool_add(proxy_address_pool *address_pool, proxy_address *address) {
- size_t i;
-
- /* check if this address is already known */
-
- for (i = 0; i < address_pool->used; i++) {
- proxy_address *pool_address = address_pool->ptr[i];
-
- if (buffer_is_equal(address->name, pool_address->name)) {
- /* TRACE("%s is already in the address-pool", SAFE_BUF_STR(address->name)); */
-
- proxy_address_free(address);
-
- return;
- }
- }
-
- /* TRACE("adding %s to the address-pool", SAFE_BUF_STR(address->name)); */
-
- ARRAY_STATIC_PREPARE_APPEND(address_pool);
-
- address_pool->ptr[address_pool->used++] = address;
-}
-
-int proxy_address_pool_add_string(proxy_address_pool *address_pool, buffer *name) {
- struct addrinfo *res = NULL, pref, *cur;
- int ret;
- buffer *hostname = NULL, *port = NULL;
- char *colon;
-
- pref.ai_flags = 0;
- pref.ai_family = PF_UNSPEC;
- pref.ai_socktype = SOCK_STREAM;
- pref.ai_protocol = 0;
- pref.ai_addrlen = 0;
- pref.ai_addr = NULL;
- pref.ai_canonname = NULL;
- pref.ai_next = NULL;
-
- /* check the address style
- *
- * unix:/tmp/socket
- * www.example.org
- * www.example.org:80
- * 127.0.0.1
- * 127.0.0.1:80
- * [::1]:80
- * [::1]
- */
-
- if (buffer_is_empty(name)) return -1;
-
- if (0 == strncmp(BUF_STR(name), "unix:", 5)) {
- /* a unix domain socket */
-#ifdef HAVE_SYS_UN_H
- proxy_address *a = proxy_address_init();
-
- /* setup AF_UNIX sockaddr */
- a->addr.un.sun_family = AF_UNIX;
- strcpy(a->addr.un.sun_path, BUF_STR(name) + 5);
- a->addrlen = sizeof(a->addr.un);
-/*
-#ifdef SUN_LEN
- a->addrlen = SUN_LEN(&(a->addr.un));
-#else
- a->addrlen = (name->used - 5) + sizeof(a->addr.un.sun_family);
-#endif
-*/
-
- a->state = PROXY_ADDRESS_STATE_ACTIVE;
- buffer_copy_string_buffer(a->name, name);
-
- proxy_address_pool_add(address_pool, a);
- return 0;
-#else
- ERROR("unix: scheme is not supported for %s", SAFE_BUF_STR(name));
- return -1;
-#endif
- } else if (name->ptr[0] == '[') {
- if (name->ptr[name->used - 1] == ']') {
- /* no port-number attached */
-
- hostname = buffer_init();
- buffer_copy_string_len(hostname, BUF_STR(name) + 1, name->used - 3);
- port = buffer_init_string("80");
- } else if (NULL != (colon = strrchr(BUF_STR(name), ':'))) {
- /* with port number */
-
- hostname = buffer_init();
- buffer_copy_string_len(hostname, BUF_STR(name) + 1, colon - BUF_STR(name) - 2);
- port = buffer_init();
- buffer_copy_string(port, colon + 1);
-
- } else {
- ERROR("this is neither [<ipv6-address>] nor [<ipv6-address>]:<port>: %s", SAFE_BUF_STR(name));
-
- return -1;
- }
- } else if (name->ptr[name->used - 1] != ']' &&
- NULL != (colon = strrchr(BUF_STR(name), ':'))) {
-
- hostname = buffer_init();
- buffer_copy_string_len(hostname, BUF_STR(name), colon - BUF_STR(name));
- port = buffer_init();
- buffer_copy_string(port, colon + 1);
- } else {
- /* no colon, just a IPv4 address or a domain name */
-
- hostname = buffer_init_string(BUF_STR(name));
- port = buffer_init_string("80");
- }
-
- /* TRACE("resolving %s on port %s", SAFE_BUF_STR(hostname), SAFE_BUF_STR(port)); */
-
- if (0 != (ret = getaddrinfo(BUF_STR(hostname), BUF_STR(port), &pref, &res))) {
- ERROR("getaddrinfo failed: %s", gai_strerror(ret));
-
- buffer_free(hostname);
- buffer_free(port);
-
- return -1;
- }
-
- buffer_free(hostname);
- buffer_free(port);
-
- for (cur = res; cur; cur = cur->ai_next) {
- proxy_address *a = proxy_address_init();
-
- memcpy(&(a->addr), cur->ai_addr, cur->ai_addrlen);
- a->addrlen = cur->ai_addrlen;
-
- a->state = PROXY_ADDRESS_STATE_ACTIVE;
- buffer_prepare_copy(a->name, 128);
-
- switch (cur->ai_family) {
-#ifdef HAVE_IPV6
- case AF_INET6:
- a->name->ptr[0] = '[';
- inet_ntop(cur->ai_family, &(a->addr.ipv6.sin6_addr), a->name->ptr + 1, a->name->size - 2);
- a->name->used = strlen(a->name->ptr) + 1;
- buffer_append_string_len(a->name, CONST_STR_LEN("]:"));
- buffer_append_long(a->name, ntohs(a->addr.ipv6.sin6_port));
- break;
-#endif
- case AF_INET:
- inet_ntop(cur->ai_family, &(a->addr.ipv4.sin_addr), a->name->ptr, a->name->size - 1);
- a->name->used = strlen(a->name->ptr) + 1;
-
- buffer_append_string_len(a->name, CONST_STR_LEN(":"));
- buffer_append_long(a->name, ntohs(a->addr.ipv4.sin_port));
- break;
- default:
- ERROR("unknown address-family: %d", cur->ai_family);
- return -1;
- }
-
-
- proxy_address_pool_add(address_pool, a);
- }
-
- freeaddrinfo(res);
-
- return 0;
-}
-
-
diff --git a/src/mod_proxy_core_address.h b/src/mod_proxy_core_address.h
deleted file mode 100644
index c7177ca7..00000000
--- a/src/mod_proxy_core_address.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _MOD_PROXY_CORE_ADDRESS_H_
-#define _MOD_PROXY_CORE_ADDRESS_H_
-
-#include <time.h>
-#include "buffer.h"
-#include "sys-socket.h"
-#include "array-static.h"
-
-typedef enum {
- PROXY_ADDRESS_STATE_UNSET,
- PROXY_ADDRESS_STATE_ACTIVE,
- PROXY_ADDRESS_STATE_DISABLED,
-} proxy_address_state_t;
-
-typedef struct {
- sock_addr addr;
- socklen_t addrlen;
-
- buffer *name; /* a inet_ntoa() prepresentation of the address */
-
- time_t last_used;
- time_t disabled_until;
-
- size_t used; /* count of connections currently using this address */
-
- proxy_address_state_t state;
-} proxy_address;
-
-ARRAY_STATIC_DEF(proxy_address_pool, proxy_address, );
-
-proxy_address_pool *proxy_address_pool_init(void);
-void proxy_address_pool_free(proxy_address_pool *address_pool);
-void proxy_address_pool_add(proxy_address_pool *address_pool, proxy_address *address);
-int proxy_address_pool_add_string(proxy_address_pool *address_pool, buffer *address);
-
-#endif
diff --git a/src/mod_proxy_core_backend.c b/src/mod_proxy_core_backend.c
deleted file mode 100644
index 60648f6c..00000000
--- a/src/mod_proxy_core_backend.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <stdlib.h>
-
-#include "mod_proxy_core_backend.h"
-#include "mod_proxy_core_pool.h"
-#include "mod_proxy_core_address.h"
-
-proxy_backend *proxy_backend_init(void) {
- proxy_backend *backend;
-
- backend = calloc(1, sizeof(*backend));
- backend->pool = proxy_connection_pool_init();
- backend->address_pool = proxy_address_pool_init();
- backend->balancer = PROXY_BALANCE_RR;
- backend->name = buffer_init();
- backend->state = PROXY_BACKEND_STATE_ACTIVE;
-
- return backend;
-}
-
-void proxy_backend_free(proxy_backend *backend) {
- if (!backend) return;
-
- proxy_connection_pool_free(backend->pool);
- proxy_address_pool_free(backend->address_pool);
- buffer_free(backend->name);
-
- free(backend);
-}
-
-proxy_backends *proxy_backends_init(void) {
- proxy_backends *backends;
-
- backends = calloc(1, sizeof(*backends));
-
- return backends;
-}
-
-void proxy_backends_free(proxy_backends *backends) {
- if (!backends) return;
-
- ARRAY_STATIC_FREE(backends, proxy_backend, element, proxy_backend_free(element));
-
- free(backends);
-}
-
-void proxy_backends_add(proxy_backends *backends, proxy_backend *backend) {
- ARRAY_STATIC_PREPARE_APPEND(backends);
-
- backends->ptr[backends->used++] = backend;
-}
diff --git a/src/mod_proxy_core_backend.h b/src/mod_proxy_core_backend.h
deleted file mode 100644
index b9fa1c33..00000000
--- a/src/mod_proxy_core_backend.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef _MOD_PROXY_CORE_BACKEND_H_
-#define _MOD_PROXY_CORE_BACKEND_H_
-
-#include "array-static.h"
-#include "array.h"
-#include "buffer.h"
-#include "mod_proxy_core_address.h"
-#include "mod_proxy_core_pool.h"
-#include "sys-socket.h"
-
-/**
- * a single DNS name might explode to several IP addresses
- *
- * url:
- * - http://foo.bar/suburl/
- * - https://foo.bar/suburl/
- * - unix:/tmp/socket
- * - tcp://foobar:1025/
- *
- * backend:
- * - scgi
- * - http
- * - fastcgi
- * - ajp13
- *
- * request-url-rewrite
- * response-url-rewrite
- */
-typedef enum {
- PROXY_BALANCE_UNSET,
- PROXY_BALANCE_SQF,
- PROXY_BALANCE_CARP,
- PROXY_BALANCE_RR,
- PROXY_BALANCE_STATIC
-} proxy_balance_t;
-
-typedef enum {
- PROXY_BACKEND_STATE_UNSET,
- PROXY_BACKEND_STATE_ACTIVE,
- PROXY_BACKEND_STATE_FULL,
- PROXY_BACKEND_STATE_DISABLED,
-} proxy_backend_state_t;
-
-typedef struct {
- buffer *name;
-
- proxy_connection_pool *pool; /* pool of active connections */
- int use_keepalive;
-
- proxy_address_pool *address_pool; /* possible destination-addresses, disabling is done here */
- unsigned int disabled_addresses; /* track how many addresses are disabled. */
- proxy_balance_t balancer; /* how to choose a address from the address-pool */
- struct proxy_protocol *protocol; /* protocol handler */
-
- proxy_backend_state_t state;
-
- /* statistics counters. */
- data_integer *request_count;
- data_integer *load;
- data_integer *pool_size;
- data_integer *requests_failed;
-} proxy_backend;
-
-ARRAY_STATIC_DEF(proxy_backends, proxy_backend, );
-
-proxy_backend *proxy_backend_init(void);
-void proxy_backend_free(proxy_backend *backend);
-
-proxy_backends *proxy_backends_init(void);
-void proxy_backends_free(proxy_backends *backends);
-void proxy_backends_add(proxy_backends *backends, proxy_backend *backend);
-
-#endif
-
diff --git a/src/mod_proxy_core_backlog.c b/src/mod_proxy_core_backlog.c
deleted file mode 100644
index 11a59a59..00000000
--- a/src/mod_proxy_core_backlog.c
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <stdlib.h>
-
-#include "mod_proxy_core_backlog.h"
-#include "array-static.h"
-
-proxy_backlog *proxy_backlog_init(void) {
- STRUCT_INIT(proxy_backlog, backlog);
-
- return backlog;
-}
-
-void proxy_backlog_free(proxy_backlog *backlog) {
- if (!backlog) return;
-
- free(backlog);
-}
-
-int proxy_backlog_push(proxy_backlog *backlog, proxy_request *req) {
- /* first entry */
- if (NULL == backlog->first) {
- backlog->first = backlog->last = req;
- } else {
- backlog->last->next = req;
- backlog->last = req;
- }
- backlog->length++;
-
- return 0;
-}
-
-/**
- * remove the first element from the backlog
- */
-proxy_request *proxy_backlog_shift(proxy_backlog *backlog) {
- proxy_request *req = NULL;
-
- if (!backlog->first) return req;
-
- backlog->length--;
-
- req = backlog->first;
-
- backlog->first = req->next;
-
- /* the backlog is empty */
- if (backlog->first == NULL) backlog->last = NULL;
-
- return req;
-}
-
-int proxy_backlog_remove_connection(proxy_backlog *backlog, void *con) {
- proxy_request *req = NULL;
-
- if (!backlog->first) return -1;
- if (!con) return -1;
-
- /* the first element is what we look for */
- if (backlog->first->con == con) {
- req = backlog->first;
-
- backlog->first = req->next;
- if (backlog->first == NULL) backlog->last = NULL;
-
- backlog->length--;
-
- proxy_request_free(req);
-
- return 0;
- }
-
-
- for (req = backlog->first; req && req->next; req = req->next) {
- proxy_request *cur;
-
- if (req->next->con != con) continue;
-
- backlog->length--;
- /* the next node is our searched connection */
-
- cur = req->next;
- req->next = cur->next;
-
- /* the next node is the last one, make the current the new last */
- if (cur == backlog->last) {
- backlog->last = req;
- }
- cur->next = NULL;
-
- proxy_request_free(cur);
-
- return 0;
- }
-
- return -1;
-}
-
-proxy_request *proxy_request_init(void) {
- STRUCT_INIT(proxy_request, request);
-
- return request;
-}
-
-void proxy_request_free(proxy_request *request) {
- if (!request) return;
-
- free(request);
-}
-
-
diff --git a/src/mod_proxy_core_backlog.h b/src/mod_proxy_core_backlog.h
deleted file mode 100644
index a59141f8..00000000
--- a/src/mod_proxy_core_backlog.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef _MOD_PROXY_CORE_BACKLOG_H_
-#define _MOD_PROXY_CORE_BACKLOG_H_
-
-#include <sys/types.h>
-#ifndef _WIN32
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-
-typedef struct _proxy_request {
- void *con; /* a pointer to the client-connection, (type: connection) */
-
- time_t added_ts; /* when was the entry added (for timeout handling) */
-
- struct _proxy_request *next;
-} proxy_request;
-
-/**
- * a we can't get a connection from the pool, queue the request in the
- * request queue (FIFO)
- *
- * - the queue is infinite
- * - entries are removed after a timeout (status 504)
- */
-typedef struct {
- proxy_request *first; /* pull() does q->first = q->first->next */
- proxy_request *last; /* push() does q->last = r */
-
- size_t length;
-} proxy_backlog;
-
-proxy_backlog *proxy_backlog_init(void);
-void proxy_backlog_free(proxy_backlog *backlog);
-
-/**
- * append a request to the end
- *
- * @return 0 in success, -1 if full
- */
-int proxy_backlog_push(proxy_backlog *backlog, proxy_request *req);
-
-/**
- * remove the first request from the backlog
- *
- * @return NULL if backlog is empty, the request otherwise
- */
-proxy_request *proxy_backlog_shift(proxy_backlog *backlog);
-/**
- * remove the request with the connection 'con' from the backlog
- *
- * @return -1 if not found, 0 otherwise
- */
-int proxy_backlog_remove_connection(proxy_backlog *backlog, void *con);
-
-proxy_request *proxy_request_init(void);
-void proxy_request_free(proxy_request *req);
-
-#endif
-
-
diff --git a/src/mod_proxy_core_pool.c b/src/mod_proxy_core_pool.c
deleted file mode 100644
index 65606fa1..00000000
--- a/src/mod_proxy_core_pool.c
+++ /dev/null
@@ -1,141 +0,0 @@
-
-#include <stdlib.h>
-
-#include "array-static.h"
-#include "sys-files.h"
-#include "log.h"
-#include "mod_proxy_core_pool.h"
-
-proxy_connection * proxy_connection_init(void) {
- proxy_connection *con;
-
- con = calloc(1, sizeof(*con));
-
- con->sock = iosocket_init();
-
- con->send = chunkqueue_init();
- con->recv = chunkqueue_init();
-
- return con;
-}
-
-void proxy_connection_free(proxy_connection *con) {
- if (!con) return;
-
- con->address->used--;
-
- iosocket_free(con->sock);
-
- chunkqueue_free(con->send);
- chunkqueue_free(con->recv);
-
- free(con);
-}
-
-proxy_connection_pool *proxy_connection_pool_init(void) {
- proxy_connection_pool *pool;
-
- pool = calloc(1, sizeof(*pool));
-
- /* default: max parallel connections to the backend
- *
- * this should match max-procs if we manage the procs ourself
- */
-
- pool->max_size = 1;
-
- return pool;
-}
-
-void proxy_connection_pool_free(proxy_connection_pool *pool) {
- size_t i;
-
- if (!pool) return;
-
- for (i = 0; i < pool->used; i++) {
- proxy_connection_free(pool->ptr[i]);
- }
-
- if (pool->size) free(pool->ptr);
-
- free(pool);
-}
-
-static void proxy_connection_pool_add_connection(proxy_connection_pool *pool, proxy_connection *c) {
- ARRAY_STATIC_PREPARE_APPEND(pool);
-
- pool->ptr[pool->used++] = c;
-}
-
-/**
- * remove the connection from the pool
- *
- * usually called on conn-shutdown
- */
-int proxy_connection_pool_remove_connection(proxy_connection_pool *pool, proxy_connection *c) {
- size_t i;
-
- if (pool->used == 0) return -1; /* empty */
-
- for (i = 0; i < pool->used; i++) {
- if (pool->ptr[i] == c) {
- break;
- }
- }
-
- if (i == pool->used) return -1; /* not found */
-
- /**
- * move all elements one to the left
- *
- * if the last element is going to be removed, skip the loop
- */
- for (; i < pool->used - 1; i++) {
- pool->ptr[i] = pool->ptr[i + 1];
- }
-
- pool->used--;
-
- return 0;
-}
-
-proxy_connection_pool_t proxy_connection_pool_get_connection(proxy_connection_pool *pool, proxy_address *address, proxy_connection **rcon) {
- proxy_connection *proxy_con = NULL;
- size_t i;
-
- /* search for a idling proxy connection with the given address */
- for (i = 0; i < pool->used; i++) {
- proxy_con = pool->ptr[i];
-
- if (proxy_con->address == address &&
- proxy_con->state == PROXY_CONNECTION_STATE_IDLE) {
- break;
- }
- }
-
- if (i == pool->used) {
- /* no idling connection found
- *
- * check if we can open another connection to this address
- */
-
- if (pool->used == pool->max_size) return PROXY_CONNECTIONPOOL_FULL;
-
- proxy_con = proxy_connection_init();
-
- proxy_con->state = PROXY_CONNECTION_STATE_CONNECTING;
- proxy_con->address = address;
-
- proxy_connection_pool_add_connection(pool, proxy_con);
- } else {
- proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED;
- }
-
- /* inc. the use-counter of the address */
- proxy_con->address->used++;
-
- *rcon = proxy_con;
-
- return PROXY_CONNECTIONPOOL_GOT_CONNECTION;
-}
-
diff --git a/src/mod_proxy_core_pool.h b/src/mod_proxy_core_pool.h
deleted file mode 100644
index 62040d16..00000000
--- a/src/mod_proxy_core_pool.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef _MOD_PROXY_CORE_POOL_H_
-#define _MOD_PROXY_CORE_POOL_H_
-
-#ifndef _WIN32
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-
-#include "iosocket.h"
-#include "array-static.h"
-#include "mod_proxy_core_address.h"
-#include "chunk.h"
-
-typedef enum {
- PROXY_CONNECTION_STATE_UNSET,
- PROXY_CONNECTION_STATE_CONNECTING,
- PROXY_CONNECTION_STATE_CONNECTED,
- PROXY_CONNECTION_STATE_IDLE,
- PROXY_CONNECTION_STATE_CLOSED,
-} proxy_connection_state_t;
-
-/**
- * a connection to a proxy backend
- *
- * the connection is independent of the incoming request to allow keep-alive
- */
-typedef struct {
- iosocket *sock;
-
- unsigned short request_count; /* used for max-keep-alive-requests */
- time_t last_read; /* timeout handling for keep-alive connections */
- time_t last_write;
-
- proxy_address *address; /* the struct sock_addr for the sock */
-
- struct proxy_protocol *protocol; /* protocol handler */
- void *protocol_data; /** protocol handler's state data for parsing response from backend. */
-
- chunkqueue *send; /* encoded stream data that needs to be send to backend server. */
- chunkqueue *recv; /* encoded stream data received form the backend that needs to be decoded. */
-
- proxy_connection_state_t state;
- time_t state_ts;
-
- void *proxy_sess; /** we are used by this proxy session right now */
-} proxy_connection;
-
-ARRAY_STATIC_DEF(proxy_connection_pool, proxy_connection, size_t max_size;);
-
-typedef enum {
- PROXY_CONNECTIONPOOL_UNSET,
- PROXY_CONNECTIONPOOL_FULL,
- PROXY_CONNECTIONPOOL_GOT_CONNECTION,
-} proxy_connection_pool_t;
-
-proxy_connection_pool *proxy_connection_pool_init(void);
-void proxy_connection_pool_free(proxy_connection_pool *pool);
-
-proxy_connection_pool_t proxy_connection_pool_get_connection(proxy_connection_pool *pool, proxy_address *address, proxy_connection **rcon);
-int proxy_connection_pool_remove_connection(proxy_connection_pool *pool, proxy_connection *c);
-
-proxy_connection * proxy_connection_init(void);
-void proxy_connection_free(proxy_connection *pool);
-
-#endif
-
-
diff --git a/src/mod_proxy_core_protocol.c b/src/mod_proxy_core_protocol.c
deleted file mode 100644
index 66513df5..00000000
--- a/src/mod_proxy_core_protocol.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <stdlib.h>
-
-#include "mod_proxy_core.h"
-#include "mod_proxy_core_protocol.h"
-
-static proxy_protocols *protocols = NULL;
-static buffer *protocol_names = NULL;
-
-proxy_protocol *proxy_protocol_init(void) {
- proxy_protocol *protocol;
-
- protocol = calloc(1, sizeof(*protocol));
-
- return protocol;
-}
-
-void proxy_protocol_free(proxy_protocol *protocol) {
- if (!protocol) return;
-
- buffer_free(protocol->name);
-
- free(protocol);
-}
-
-void proxy_protocols_init(void) {
- if(protocols) return;
- protocols = calloc(1, sizeof(*protocols));
- protocol_names = buffer_init();
-}
-
-void proxy_protocols_free(void) {
- if(!protocols) return;
- ARRAY_STATIC_FREE(protocols, proxy_protocol, element, proxy_protocol_free(element));
-
- free(protocols);
- buffer_free(protocol_names);
-}
-
-void proxy_protocols_register(proxy_protocol *protocol) {
- if(!protocols) return;
- ARRAY_STATIC_PREPARE_APPEND(protocols);
-
- protocols->ptr[protocols->used++] = protocol;
-
- /* append protocol name to list of names. */
- if(!buffer_is_empty(protocol_names)) {
- buffer_append_string_len(protocol_names, CONST_STR_LEN(", '"));
- } else {
- buffer_append_string_len(protocol_names, CONST_STR_LEN("'"));
- }
- buffer_append_string(protocol_names, BUF_STR(protocol->name));
- buffer_append_string_len(protocol_names, CONST_STR_LEN("'"));
-}
-
-proxy_protocol *proxy_get_protocol(buffer *name) {
- if(!protocols) return NULL;
-
- FOREACH(protocols, proxy_protocol, element, if(buffer_is_equal(element->name,name)) return element; );
-
- return NULL;
-}
-
-const char *proxy_available_protocols() {
- return BUF_STR(protocol_names);
-}
-
diff --git a/src/mod_proxy_core_protocol.h b/src/mod_proxy_core_protocol.h
deleted file mode 100644
index e846089f..00000000
--- a/src/mod_proxy_core_protocol.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _MOD_PROXY_CORE_PROTOCOL_H_
-#define _MOD_PROXY_CORE_PROTOCOL_H_
-
-#include "base.h"
-#include "array-static.h"
-#include "buffer.h"
-
-#define PROXY_CONNECTION_FUNC(x) \
- static int x(server *srv, proxy_connection *proxy_con)
-
-#define PROXY_STREAM_DECODER_FUNC(x) \
- static handler_t x(server *srv, proxy_session *sess, chunkqueue *out)
-
-#define PROXY_STREAM_ENCODER_FUNC(x) \
- static handler_t x(server *srv, proxy_session *sess, chunkqueue *in)
-
-typedef struct proxy_protocol {
- buffer *name;
-
- int (*proxy_stream_init) (server *srv, proxy_connection *proxy_con);
- int (*proxy_stream_cleanup) (server *srv, proxy_connection *proxy_con);
- handler_t (*proxy_stream_decoder) (server *srv, proxy_session *sess, chunkqueue *out);
- handler_t (*proxy_stream_encoder) (server *srv, proxy_session *sess, chunkqueue *in);
- handler_t (*proxy_encode_request_headers) (server *srv, proxy_session *sess, chunkqueue *in);
-
-} proxy_protocol;
-
-ARRAY_STATIC_DEF(proxy_protocols, proxy_protocol, );
-
-proxy_protocol *proxy_protocol_init(void);
-void proxy_protocol_free(proxy_protocol *protocol);
-
-void proxy_protocols_init(void);
-void proxy_protocols_free(void);
-void proxy_protocols_register(proxy_protocol *protocol);
-proxy_protocol *proxy_get_protocol(buffer *name);
-const char *proxy_available_protocols(void);
-
-#endif
-
diff --git a/src/mod_proxy_core_rewrites.c b/src/mod_proxy_core_rewrites.c
deleted file mode 100644
index 234f8068..00000000
--- a/src/mod_proxy_core_rewrites.c
+++ /dev/null
@@ -1,127 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "mod_proxy_core_rewrites.h"
-#include "log.h"
-
-proxy_rewrite *proxy_rewrite_init(void) {
- STRUCT_INIT(proxy_rewrite, rewrite);
-
- rewrite->header = buffer_init();
- rewrite->match = buffer_init();
- rewrite->replace = buffer_init();
-
- return rewrite;
-
-}
-void proxy_rewrite_free(proxy_rewrite *rewrite) {
- if (!rewrite) return;
-#ifdef HAVE_PCRE_H
- if (rewrite->regex) pcre_free(rewrite->regex);
-#endif
-
- buffer_free(rewrite->header);
- buffer_free(rewrite->match);
- buffer_free(rewrite->replace);
-
- free(rewrite);
-}
-
-int proxy_rewrite_set_regex(proxy_rewrite *rewrite, buffer *regex) {
- const char *errptr;
- int erroff;
-
-#ifdef HAVE_PCRE_H
- if (NULL == (rewrite->regex = pcre_compile(BUF_STR(regex),
- 0, &errptr, &erroff, NULL))) {
-
- TRACE("regex compilation for %s failed at %s", SAFE_BUF_STR(regex), errptr);
-
- return -1;
- }
-#endif
-
- return 0;
-}
-
-
-proxy_rewrites *proxy_rewrites_init(void) {
- STRUCT_INIT(proxy_rewrites, rewrites);
-
- return rewrites;
-}
-
-void proxy_rewrites_add(proxy_rewrites *rewrites, proxy_rewrite *rewrite) {
- ARRAY_STATIC_PREPARE_APPEND(rewrites);
-
- rewrites->ptr[rewrites->used++] = rewrite;
-}
-
-void proxy_rewrites_free(proxy_rewrites *rewrites) {
- if (!rewrites) return;
-
- ARRAY_STATIC_FREE(rewrites, proxy_rewrite, rewrite, proxy_rewrite_free(rewrite));
-
- free(rewrites);
-}
-
-int pcre_replace(pcre *match, buffer *replace, buffer *match_buf, buffer *result) {
-#ifdef HAVE_PCRE_H
- const char *pattern = replace->ptr;
- size_t pattern_len = replace->used - 1;
-
-# define N 10
- int ovec[N * 3];
- int n;
-
- if ((n = pcre_exec(match, NULL, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
- if (n != PCRE_ERROR_NOMATCH) {
- return n;
- }
- } else {
- const char **list;
- size_t start, end;
- size_t k;
-
- /* it matched */
- pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
-
- /* search for $[0-9] */
-
- buffer_reset(result);
-
- start = 0; end = pattern_len;
- for (k = 0; k < pattern_len; k++) {
- if ((pattern[k] == '$') &&
- isdigit((unsigned char)pattern[k + 1])) {
- /* got one */
-
- size_t num = pattern[k + 1] - '0';
-
- end = k;
-
- buffer_append_string_len(result, pattern + start, end - start);
-
- /* n is always > 0 */
- if (num < (size_t)n) {
- buffer_append_string(result, list[num]);
- }
-
- k++;
- start = k + 1;
- }
- }
-
- buffer_append_string_len(result, pattern + start, pattern_len - start);
-
- pcre_free(list);
- }
-
- return n;
-#else
- return -1;
-#endif
-}
-
-
diff --git a/src/mod_proxy_core_rewrites.h b/src/mod_proxy_core_rewrites.h
deleted file mode 100644
index bd7cc21a..00000000
--- a/src/mod_proxy_core_rewrites.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _MOD_PROXY_CORE_REWRITES_H_
-#define _MOD_PROXY_CORE_REWRITES_H_
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_PCRE_H
-#include <pcre.h>
-#endif
-#include "array-static.h"
-#include "buffer.h"
-
-#ifndef HAVE_PCRE_H
-#define pcre void
-#endif
-
-typedef struct {
- buffer *header;
-
- pcre *regex; /* regex compiled from the <match> */
-
- buffer *match;
- buffer *replace;
-} proxy_rewrite;
-
-ARRAY_STATIC_DEF(proxy_rewrites, proxy_rewrite,);
-
-proxy_rewrite *proxy_rewrite_init(void);
-void proxy_rewrite_free(proxy_rewrite *rewrite);
-int proxy_rewrite_set_regex(proxy_rewrite *rewrite, buffer *regex);
-
-proxy_rewrites *proxy_rewrites_init(void);
-void proxy_rewrites_add(proxy_rewrites *rewrites, proxy_rewrite *rewrite);
-void proxy_rewrites_free(proxy_rewrites *rewrites);
-
-int pcre_replace(pcre *match, buffer *replace, buffer *match_buf, buffer *result);
-
-#endif
-
diff --git a/src/mod_redirect.c b/src/mod_redirect.c
deleted file mode 100644
index ed09f8dc..00000000
--- a/src/mod_redirect.c
+++ /dev/null
@@ -1,229 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-#include "response.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-typedef struct {
- pcre_keyvalue_buffer *redirect;
- data_config *context; /* to which apply me */
-
- unsigned short redirect_code;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
- buffer *match_buf;
- buffer *location;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_redirect_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->match_buf = buffer_init();
- p->location = buffer_init();
-
- return p;
-}
-
-FREE_FUNC(mod_redirect_free) {
- plugin_data *p = p_d;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- pcre_keyvalue_buffer_free(s->redirect);
-
- free(s);
- }
- free(p->config_storage);
- }
-
-
- buffer_free(p->match_buf);
- buffer_free(p->location);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_redirect_set_defaults) {
- plugin_data *p = p_d;
- data_unset *du;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "url.redirect-code", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- /* 0 */
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- size_t j;
- array *ca;
- data_array *da = NULL;
-
- s = calloc(1, sizeof(plugin_config));
- s->redirect = pcre_keyvalue_buffer_init();
-
- cv[0].destination = s->redirect;
- cv[1].destination = &(s->redirect_code);
-
- p->config_storage[i] = s;
- ca = ((data_config *)srv->config_context->data[i])->value;
-
- if (0 != config_insert_values_global(srv, ca, cv)) {
- return HANDLER_ERROR;
- }
-
- if (NULL == (du = array_get_element(ca, CONST_STR_LEN("url.redirect")))) {
- /* no url.redirect defined */
- continue;
- }
-
- if (du->type != TYPE_ARRAY) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "unexpected type for key: ", "url.redirect", "array of strings");
-
- return HANDLER_ERROR;
- }
-
- da = (data_array *)du;
-
- for (j = 0; j < da->value->used; j++) {
- if (da->value->data[j]->type != TYPE_STRING) {
- log_error_write(srv, __FILE__, __LINE__, "sssbs",
- "unexpected type for key: ",
- "url.redirect",
- "[", da->value->data[j]->key, "](string)");
-
- return HANDLER_ERROR;
- }
-
- if (0 != pcre_keyvalue_buffer_append(s->redirect,
- ((data_string *)(da->value->data[j]))->key->ptr,
- ((data_string *)(da->value->data[j]))->value->ptr)) {
-
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "pcre-compile failed for", da->value->data[j]->key);
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-#ifdef HAVE_PCRE_H
-static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(redirect);
- PATCH_OPTION(redirect_code);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect"))) {
- PATCH_OPTION(redirect);
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-code"))) {
- PATCH_OPTION(redirect_code);
- }
- }
- }
-
- return 0;
-}
-#endif
-static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
-#ifdef HAVE_PCRE_H
- plugin_data *p = p_data;
- int i;
-
- /*
- * REWRITE URL
- *
- * e.g. redirect /base/ to /index.php?section=base
- *
- */
-
- mod_redirect_patch_connection(srv, con, p);
-
- buffer_copy_string_buffer(p->match_buf, con->request.uri);
- i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
-
- if (i >= 0) {
- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
-
- con->http_status = p->conf.redirect_code > 99 && p->conf.redirect_code < 1000 ? p->conf.redirect_code : 301;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- }
- else if (i != PCRE_ERROR_NOMATCH) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "execution error while matching", i);
- }
-#undef N
-
-#else
- UNUSED(srv);
- UNUSED(con);
- UNUSED(p_data);
-#endif
-
- return HANDLER_GO_ON;
-}
-
-
-LI_EXPORT int mod_redirect_plugin_init(plugin *p);
-LI_EXPORT int mod_redirect_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("redirect");
-
- p->init = mod_redirect_init;
- p->handle_uri_clean = mod_redirect_uri_handler;
- p->set_defaults = mod_redirect_set_defaults;
- p->cleanup = mod_redirect_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_rewrite.c b/src/mod_rewrite.c
deleted file mode 100644
index 94609300..00000000
--- a/src/mod_rewrite.c
+++ /dev/null
@@ -1,337 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-typedef struct {
- pcre_keyvalue_buffer *rewrite;
- buffer *once;
- data_config *context; /* to which apply me */
-} plugin_config;
-
-typedef struct {
- enum { REWRITE_STATE_UNSET, REWRITE_STATE_FINISHED} state;
- int loops;
-} handler_ctx;
-
-typedef struct {
- PLUGIN_DATA;
- buffer *match_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-static handler_ctx * handler_ctx_init() {
- handler_ctx * hctx;
-
- hctx = calloc(1, sizeof(*hctx));
-
- hctx->state = REWRITE_STATE_UNSET;
- hctx->loops = 0;
-
- return hctx;
-}
-
-static void handler_ctx_free(handler_ctx *hctx) {
- free(hctx);
-}
-
-
-INIT_FUNC(mod_rewrite_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->match_buf = buffer_init();
-
- return p;
-}
-
-FREE_FUNC(mod_rewrite_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- buffer_free(p->match_buf);
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- pcre_keyvalue_buffer_free(s->rewrite);
- buffer_free(s->once);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-static handler_t parse_config_entry(server *UNUSED_PARAM(srv), plugin_config *s, array *ca, const char *option, size_t option_len, int once) {
- data_unset *du;
-
- if (NULL != (du = array_get_element(ca, option, option_len))) {
- data_array *da = (data_array *)du;
- size_t j;
-
- if (du->type != TYPE_ARRAY) {
- ERROR("unexpected type (%d) for key %s, expected 'array of strings'",
- du->type, option);
-
- return HANDLER_ERROR;
- }
-
- da = (data_array *)du;
-
- for (j = 0; j < da->value->used; j++) {
- if (da->value->data[j]->type != TYPE_STRING) {
- ERROR("unexpected type (%d) for value of %s[%s], expected 'string'",
- da->value->data[j]->type, option,
- SAFE_BUF_STR(da->value->data[j]->key));
-
- return HANDLER_ERROR;
- }
-
- if (0 != pcre_keyvalue_buffer_append(s->rewrite,
- ((data_string *)(da->value->data[j]))->key->ptr,
- ((data_string *)(da->value->data[j]))->value->ptr)) {
-#ifdef HAVE_PCRE_H
- ERROR("pcre-compile failed for: %s", SAFE_BUF_STR(da->value->data[j]->key));
-#else
- ERROR("pcre support is missing, please install libpcre and the headers%s", "");
-#endif
- }
-
- if (once) {
- buffer_append_string_len(s->once, CONST_STR_LEN("1"));
- } else {
- buffer_append_string_len(s->once, CONST_STR_LEN("0"));
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
-
- /* old names, still supported
- *
- * url.rewrite remapped to url.rewrite-once
- * url.rewrite-final is url.rewrite-once
- *
- */
- { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- /* 0 */
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
- array *ca;
-
- s = calloc(1, sizeof(plugin_config));
- s->rewrite = pcre_keyvalue_buffer_init();
- s->once = buffer_init();
-
- p->config_storage[i] = s;
- ca = ((data_config *)srv->config_context->data[i])->value;
-
- if (0 != config_insert_values_global(srv, ca, cv)) {
- return HANDLER_ERROR;
- }
-
- if (HANDLER_GO_ON != parse_config_entry(srv, s, ca, CONST_STR_LEN("url.rewrite-once"), 1)) return HANDLER_ERROR;
- if (HANDLER_GO_ON != parse_config_entry(srv, s, ca, CONST_STR_LEN("url.rewrite-final"), 1)) return HANDLER_ERROR;
- if (HANDLER_GO_ON != parse_config_entry(srv, s, ca, CONST_STR_LEN("url.rewrite"), 1)) return HANDLER_ERROR;
- if (HANDLER_GO_ON != parse_config_entry(srv, s, ca, CONST_STR_LEN("url.rewrite-repeat"), 0)) return HANDLER_ERROR;
- }
-
- return HANDLER_GO_ON;
-}
-#ifdef HAVE_PCRE_H
-static int mod_rewrite_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
- p->conf.rewrite = s->rewrite;
- p->conf.once = s->once;
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- if (COMP_HTTP_URL == dc->comp) continue;
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
- p->conf.rewrite = s->rewrite;
- p->conf.once = s->once;
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
- p->conf.rewrite = s->rewrite;
- p->conf.once = s->once;
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
- p->conf.rewrite = s->rewrite;
- p->conf.once = s->once;
- p->conf.context = dc;
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
- p->conf.rewrite = s->rewrite;
- p->conf.once = s->once;
- p->conf.context = dc;
- }
- }
- }
-
- return 0;
-}
-#endif
-URIHANDLER_FUNC(mod_rewrite_con_reset) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (con->plugin_ctx[p->id]) {
- handler_ctx_free(con->plugin_ctx[p->id]);
- con->plugin_ctx[p->id] = NULL;
- }
-
- return HANDLER_GO_ON;
-}
-
-URIHANDLER_FUNC(mod_rewrite_uri_handler) {
-#ifdef HAVE_PCRE_H
- plugin_data *p = p_d;
- int i;
- handler_ctx *hctx = NULL;
-
- /*
- * REWRITE URL
- *
- * e.g. rewrite /base/ to /index.php?section=base
- *
- */
-
- if (con->plugin_ctx[p->id]) {
- hctx = con->plugin_ctx[p->id];
-
- if (hctx->loops++ > 100) {
- ERROR("ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request after %d loops at %s",
- hctx->loops, SAFE_BUF_STR(con->request.uri));
-
- con->http_status = 500;
-
- return HANDLER_FINISHED;
- }
-
- if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
- }
-
- mod_rewrite_patch_connection(srv, con, p);
-
- if (!p->conf.rewrite) return HANDLER_GO_ON;
-
- buffer_copy_string_buffer(p->match_buf, con->request.uri);
- i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
-
- if (i >= 0) {
- if (!hctx) {
- hctx = handler_ctx_init();
-
- con->plugin_ctx[p->id] = hctx;
- }
-
- if (p->conf.once->ptr[i] == '1')
- hctx->state = REWRITE_STATE_FINISHED;
-
- /* looks like we finished the rewrite
- *
- * start the uri-splitting again
- * */
-
- if (con->request.uri->used == 0 ||
- con->request.uri->ptr[0] != '/') {
- con->http_status = 500;
-
- ERROR("url.rewrite contains a regex for '%s' which leads to a URI without a leading slash: %s",
- SAFE_BUF_STR(p->match_buf), SAFE_BUF_STR(con->request.uri));
-
- return HANDLER_FINISHED;
- }
-
- return HANDLER_COMEBACK;
- } else if (i != PCRE_ERROR_NOMATCH) {
- ERROR("execution error while matching '%s' against '%s': %d",
- SAFE_BUF_STR(p->match_buf), SAFE_BUF_STR(con->request.uri), i);
- con->http_status = 500;
-
- return HANDLER_FINISHED;
- }
-#undef N
-
-#else
- UNUSED(srv);
- UNUSED(con);
- UNUSED(p_d);
-#endif
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_rewrite_plugin_init(plugin *p);
-LI_EXPORT int mod_rewrite_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("rewrite");
-
- p->init = mod_rewrite_init;
- /* it has to stay _raw as we are matching on uri + querystring
- */
-
- p->handle_uri_raw = mod_rewrite_uri_handler;
- p->set_defaults = mod_rewrite_set_defaults;
- p->cleanup = mod_rewrite_free;
- p->connection_reset = mod_rewrite_con_reset;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_rrdtool.c b/src/mod_rrdtool.c
deleted file mode 100644
index f7e4fad1..00000000
--- a/src/mod_rrdtool.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/types.h>
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-
-#include "server.h"
-#include "connections.h"
-#include "response.h"
-#include "connections.h"
-#include "log.h"
-
-#include "plugin.h"
-#ifdef HAVE_FORK
-/* no need for waitpid if we don't have fork */
-#include <sys/wait.h>
-#endif
-
-#include "sys-files.h"
-#include "sys-process.h"
-
-typedef struct {
- buffer *path_rrdtool_bin;
- buffer *path_rrd;
-
- double requests, *requests_ptr;
- double bytes_written, *bytes_written_ptr;
- double bytes_read, *bytes_read_ptr;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *cmd;
- buffer *resp;
-
- int read_fd, write_fd;
- pid_t rrdtool_pid;
-
- int rrdtool_running;
-
- plugin_config **config_storage;
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_rrd_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->resp = buffer_init();
- p->cmd = buffer_init();
-
- return p;
-}
-
-FREE_FUNC(mod_rrd_free) {
- plugin_data *p = p_d;
- size_t i;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- buffer_free(s->path_rrdtool_bin);
- buffer_free(s->path_rrd);
-
- free(s);
- }
- }
- buffer_free(p->cmd);
- buffer_free(p->resp);
-
- free(p->config_storage);
-
- if (p->rrdtool_pid) {
- int status;
- close(p->read_fd);
- close(p->write_fd);
-#ifdef HAVE_FORK
- /* collect status */
- waitpid(p->rrdtool_pid, &status, 0);
-#endif
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-static int mod_rrd_create_pipe(server *srv, plugin_data *p) {
-#ifdef HAVE_FORK
- pid_t pid;
-
- int to_rrdtool_fds[2];
- int from_rrdtool_fds[2];
- if (pipe(to_rrdtool_fds)) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "pipe failed: ", strerror(errno));
- return -1;
- }
-
- if (pipe(from_rrdtool_fds)) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "pipe failed: ", strerror(errno));
- return -1;
- }
-
- /* fork, execve */
- switch (pid = fork()) {
- case 0: {
- /* child */
- char **args;
- int argc;
- int i = 0;
- char *dash = "-";
-
- /* move stdout to from_rrdtool_fd[1] */
- dup2(from_rrdtool_fds[1], STDOUT_FILENO);
- close(from_rrdtool_fds[1]);
- /* not needed */
- close(from_rrdtool_fds[0]);
-
- /* move the stdin to to_rrdtool_fd[0] */
- dup2(to_rrdtool_fds[0], STDIN_FILENO);
- close(to_rrdtool_fds[0]);
- /* not needed */
- close(to_rrdtool_fds[1]);
-
- /* set up args */
- argc = 3;
- args = malloc(sizeof(*args) * argc);
- i = 0;
-
- args[i++] = p->conf.path_rrdtool_bin->ptr;
- args[i++] = dash;
- args[i++] = NULL;
-
- /* we don't need the client socket */
- for (i = 3; i < 256; i++) {
- close(i);
- }
-
- /* exec the cgi */
- execv(args[0], args);
-
- /* */
- SEGFAULT("spawing '%s' failed: %s", args[0], strerror(errno));
-
- break;
- }
- case -1:
- /* error */
- ERROR("fork failed: %s", strerror(errno));
- break;
- default: {
- /* father */
-
- close(from_rrdtool_fds[1]);
- close(to_rrdtool_fds[0]);
-
- /* register PID and wait for them asyncronously */
- p->write_fd = to_rrdtool_fds[1];
- p->read_fd = from_rrdtool_fds[0];
- p->rrdtool_pid = pid;
-
-#ifdef FD_CLOEXEC
- fcntl(p->write_fd, F_SETFD, FD_CLOEXEC);
- fcntl(p->read_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- break;
- }
- }
-
- return 0;
-#else
- return -1;
-#endif
-}
-
-/* read/write wrappers to catch EINTR */
-
-/* write to blocking socket; blocks until all data is sent, write returns 0 or an error (apart from EINTR) occurs. */
-static ssize_t safe_write(int fd, const void *buf, size_t count) {
- ssize_t res, sum = 0;
-
- for (;;) {
- res = write(fd, buf, count);
- if (res >= 0) {
- sum += res;
- /* do not try again if res == 0 */
- if (res == 0 || (size_t) res == count) return sum;
- count -= res;
- buf = (const char*) buf + res;
- continue;
- }
- switch (errno) {
- case EINTR:
- continue;
- default:
- return -1;
- }
- }
-}
-
-/* this assumes we get enough data on a successful read */
-static ssize_t safe_read(int fd, void *buf, size_t count) {
- ssize_t res;
-
- for (;;) {
- res = read(fd, buf, count);
- if (res >= 0) return res;
- switch (errno) {
- case EINTR:
- continue;
- default:
- return -1;
- }
- }
-}
-
-static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
- struct stat st;
- int r ;
-
- /* check if DB already exists */
- if (0 == stat(s->path_rrd->ptr, &st)) {
- /* check if it is plain file */
- if (!S_ISREG(st.st_mode)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "not a regular file:", s->path_rrd);
- return HANDLER_ERROR;
- }
- }
-
- /* still create DB if it's empty file */
- if (st.st_size > 0) {
- return HANDLER_GO_ON;
- }
-
- /* create a new one */
- buffer_copy_string_len(p->cmd, CONST_STR_LEN("create "));
- buffer_append_string_buffer(p->cmd, s->path_rrd);
- buffer_append_string_len(p->cmd, CONST_STR_LEN(
- " --step 60 "
- "DS:InOctets:ABSOLUTE:600:U:U "
- "DS:OutOctets:ABSOLUTE:600:U:U "
- "DS:Requests:ABSOLUTE:600:U:U "
- "RRA:AVERAGE:0.5:1:600 "
- "RRA:AVERAGE:0.5:6:700 "
- "RRA:AVERAGE:0.5:24:775 "
- "RRA:AVERAGE:0.5:288:797 "
- "RRA:MAX:0.5:1:600 "
- "RRA:MAX:0.5:6:700 "
- "RRA:MAX:0.5:24:775 "
- "RRA:MAX:0.5:288:797 "
- "RRA:MIN:0.5:1:600 "
- "RRA:MIN:0.5:6:700 "
- "RRA:MIN:0.5:24:775 "
- "RRA:MIN:0.5:288:797\n"));
-
- if (-1 == (r = safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "rrdtool-write: failed", strerror(errno));
-
- return HANDLER_ERROR;
- }
-
- buffer_prepare_copy(p->resp, 4096);
- if (-1 == (r = safe_read(p->read_fd, p->resp->ptr, p->resp->size))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "rrdtool-read: failed", strerror(errno));
-
- return HANDLER_ERROR;
- }
-
- p->resp->used = r;
-
- if (p->resp->ptr[0] != 'O' ||
- p->resp->ptr[1] != 'K') {
- log_error_write(srv, __FILE__, __LINE__, "sbb",
- "rrdtool-response:", p->cmd, p->resp);
-
- return HANDLER_ERROR;
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(path_rrdtool_bin);
- PATCH_OPTION(path_rrd);
-
- p->conf.bytes_written_ptr = &(s->bytes_written);
- p->conf.bytes_read_ptr = &(s->bytes_read);
- p->conf.requests_ptr = &(s->requests);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
- PATCH_OPTION(path_rrd);
- /* get pointers to double values */
-
- p->conf.bytes_written_ptr = &(s->bytes_written);
- p->conf.bytes_read_ptr = &(s->bytes_read);
- p->conf.requests_ptr = &(s->requests);
- }
- }
- }
-
- return 0;
-}
-
-SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
- plugin_data *p = p_d;
- size_t i;
-
- config_values_t cv[] = {
- { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
- { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->path_rrdtool_bin = buffer_init();
- s->path_rrd = buffer_init();
- s->requests = 0;
- s->bytes_written = 0;
- s->bytes_read = 0;
-
- cv[0].destination = s->path_rrdtool_bin;
- cv[1].destination = s->path_rrd;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
- /* path_rrdtool_bin is a global option */
-
- log_error_write(srv, __FILE__, __LINE__, "s",
- "rrdtool.binary can only be set as a global option.");
-
- return HANDLER_ERROR;
- }
-
- }
-
- p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
- p->rrdtool_running = 0;
-
- /* check for dir */
-
- if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "rrdtool.binary has to be set");
- return HANDLER_ERROR;
- }
-
- /* open the pipe to rrdtool */
- if (mod_rrd_create_pipe(srv, p)) {
- return HANDLER_ERROR;
- }
-
- p->rrdtool_running = 1;
-
- return HANDLER_GO_ON;
-}
-
-TRIGGER_FUNC(mod_rrd_trigger) {
- plugin_data *p = p_d;
- size_t i;
-
- if (!p->rrdtool_running) return HANDLER_GO_ON;
- if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
- int r;
-
- if (buffer_is_empty(s->path_rrd)) continue;
-
- /* write the data down every minute */
-
- if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
-
- buffer_copy_string_len(p->cmd, CONST_STR_LEN("update "));
- buffer_append_string_buffer(p->cmd, s->path_rrd);
- buffer_append_string_len(p->cmd, CONST_STR_LEN(" N:"));
- buffer_append_off_t(p->cmd, s->bytes_read);
- buffer_append_string_len(p->cmd, CONST_STR_LEN(":"));
- buffer_append_off_t(p->cmd, s->bytes_written);
- buffer_append_string_len(p->cmd, CONST_STR_LEN(":"));
- buffer_append_long(p->cmd, s->requests);
- buffer_append_string_len(p->cmd, CONST_STR_LEN("\n"));
-
- if (-1 == (r = safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
- p->rrdtool_running = 0;
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "rrdtool-write: failed", strerror(errno));
-
- return HANDLER_ERROR;
- }
-
- buffer_prepare_copy(p->resp, 4096);
- if (-1 == (r = safe_read(p->read_fd, p->resp->ptr, p->resp->size))) {
- p->rrdtool_running = 0;
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "rrdtool-read: failed", strerror(errno));
-
- return HANDLER_ERROR;
- }
-
- p->resp->used = r;
-
- if (p->resp->ptr[0] != 'O' ||
- p->resp->ptr[1] != 'K') {
- /* don't fail on this error if we just started (graceful restart, the old one might have just updated too) */
- if (!(strstr(p->resp->ptr, "(minimum one second step)") && (srv->cur_ts - srv->startup_ts < 3))) {
- p->rrdtool_running = 0;
-
- log_error_write(srv, __FILE__, __LINE__, "sbb",
- "rrdtool-response:", p->cmd, p->resp);
-
- return HANDLER_ERROR;
- }
- }
- s->requests = 0;
- s->bytes_written = 0;
- s->bytes_read = 0;
- }
-
- return HANDLER_GO_ON;
-}
-
-REQUESTDONE_FUNC(mod_rrd_account) {
- plugin_data *p = p_d;
-
- mod_rrd_patch_connection(srv, con, p);
-
- *(p->conf.requests_ptr) += 1;
- *(p->conf.bytes_written_ptr) += con->bytes_written;
- *(p->conf.bytes_read_ptr) += con->bytes_read;
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_rrdtool_plugin_init(plugin *p);
-LI_EXPORT int mod_rrdtool_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("rrd");
-
- p->init = mod_rrd_init;
- p->cleanup = mod_rrd_free;
- p->set_defaults= mod_rrd_set_defaults;
-
- p->handle_trigger = mod_rrd_trigger;
- p->handle_response_done = mod_rrd_account;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_secure_download.c b/src/mod_secure_download.c
deleted file mode 100644
index a5d2b663..00000000
--- a/src/mod_secure_download.c
+++ /dev/null
@@ -1,351 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef USE_OPENSSL
-# include <openssl/md5.h>
-#else
-# include "md5.h"
-
-typedef li_MD5_CTX MD5_CTX;
-#define MD5_Init li_MD5_Init
-#define MD5_Update li_MD5_Update
-#define MD5_Final li_MD5_Final
-
-#endif
-
-#define HASHLEN 16
-typedef unsigned char HASH[HASHLEN];
-#define HASHHEXLEN 32
-typedef char HASHHEX[HASHHEXLEN+1];
-#ifdef USE_OPENSSL
-#define IN const
-#else
-#define IN
-#endif
-#define OUT
-
-
-/* plugin config for all request/connections */
-
-typedef struct {
- buffer *doc_root;
- buffer *secret;
- buffer *uri_prefix;
-
- unsigned int timeout;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *md5;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_secdownload_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->md5 = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_secdownload_free) {
- plugin_data *p = p_d;
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- buffer_free(s->secret);
- buffer_free(s->doc_root);
- buffer_free(s->uri_prefix);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->md5);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { "secdownload.timeout", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->secret = buffer_init();
- s->doc_root = buffer_init();
- s->uri_prefix = buffer_init();
- s->timeout = 60;
-
- cv[0].destination = s->secret;
- cv[1].destination = s->doc_root;
- cv[2].destination = s->uri_prefix;
- cv[3].destination = &(s->timeout);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * checks if the supplied string is a MD5 string
- *
- * @param str a possible MD5 string
- * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
- */
-
-static int is_hex_len(const char *str, size_t len) {
- size_t i;
-
- if (NULL == str) return 0;
-
- for (i = 0; i < len && *str; i++, str++) {
- /* illegal characters */
- if (!((*str >= '0' && *str <= '9') ||
- (*str >= 'a' && *str <= 'f') ||
- (*str >= 'A' && *str <= 'F'))
- ) {
- return 0;
- }
- }
-
- return i == len;
-}
-
-static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(secret);
- PATCH_OPTION(doc_root);
- PATCH_OPTION(uri_prefix);
- PATCH_OPTION(timeout);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
- PATCH_OPTION(secret);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
- PATCH_OPTION(doc_root);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
- PATCH_OPTION(uri_prefix);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
- PATCH_OPTION(timeout);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_secdownload_uri_handler) {
- plugin_data *p = p_d;
- MD5_CTX Md5Ctx;
- HASH HA1;
- const char *rel_uri, *ts_str, *md5_str;
- time_t ts = 0;
- size_t i;
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_secdownload_patch_connection(srv, con, p);
-
- if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
-
- if (buffer_is_empty(p->conf.secret)) {
- ERROR("secdownload.secret has to be set: %s", "");
-
- return HANDLER_ERROR;
- }
-
- if (buffer_is_empty(p->conf.doc_root)) {
- ERROR("secdownload.document-root has to be set: %s", "");
-
- return HANDLER_ERROR;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- handling %s in mod_secdownload", SAFE_BUF_STR(con->uri.path));
- }
-
- /*
- * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
- */
-
- if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) {
- if (con->conf.log_request_handling) {
- TRACE("prefix '%s' didn't matched the url: %s", SAFE_BUF_STR(p->conf.uri_prefix), SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
-
- if (!is_hex_len(md5_str, 32)) {
- if (con->conf.log_request_handling) {
- TRACE("expected a 32-char hex-val as md5-hash: %s", SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
- if (*(md5_str + 32) != '/') {
- if (con->conf.log_request_handling) {
- TRACE("missing a / after the md5-hash: %s", SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- ts_str = md5_str + 32 + 1;
-
- if (!is_hex_len(ts_str, 8)) {
- if (con->conf.log_request_handling) {
- TRACE("expected a 8-char hex-val after md5-hash: %s", SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
- if (*(ts_str + 8) != '/') {
- if (con->conf.log_request_handling) {
- TRACE("missing a / after the timestamp: %s", SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- for (i = 0; i < 8; i++) {
- ts = (ts << 4) + hex2int(*(ts_str + i));
- }
-
- /* timed-out */
- if ( (srv->cur_ts > ts && (unsigned int) (srv->cur_ts - ts) > p->conf.timeout) ||
- (srv->cur_ts < ts && (unsigned int) (ts - srv->cur_ts) > p->conf.timeout) ) {
- if (con->conf.log_request_handling) {
- TRACE("timestamp is too old: %ld, timeout: %d", (long int) ts, p->conf.timeout);
- }
-
- /* "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;
- }
-
- rel_uri = ts_str + 8;
-
- /* checking MD5
- *
- * <secret><rel-path><timestamp-hex>
- */
-
- buffer_copy_string_buffer(p->md5, p->conf.secret);
- buffer_append_string(p->md5, rel_uri);
- buffer_append_string_len(p->md5, ts_str, 8);
-
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
- MD5_Final(HA1, &Md5Ctx);
-
- buffer_copy_string_hex(p->md5, (char *)HA1, 16);
-
- if (0 != strncasecmp(md5_str, p->md5->ptr, 32)) {
- con->http_status = 403;
-
- TRACE("MD5 didn't matched: %s == %s", md5_str, SAFE_BUF_STR(p->md5));
-
- return HANDLER_FINISHED;
- }
-
- /* starting with the last / we should have relative-path to the docroot
- */
-
- buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
- buffer_copy_string(con->physical.rel_path, rel_uri);
- buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
- buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
-
- if (con->conf.log_request_handling) {
- TRACE("MD5 matched, timestamp is ok, sending %s", SAFE_BUF_STR(con->physical.path));
- }
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_secdownload_plugin_init(plugin *p);
-LI_EXPORT int mod_secdownload_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("secdownload");
-
- p->init = mod_secdownload_init;
- p->handle_physical = mod_secdownload_uri_handler;
- p->set_defaults = mod_secdownload_set_defaults;
- p->cleanup = mod_secdownload_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_setenv.c b/src/mod_setenv.c
deleted file mode 100644
index 026adb16..00000000
--- a/src/mod_setenv.c
+++ /dev/null
@@ -1,254 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "response.h"
-
-/* plugin config for all request/connections */
-
-typedef struct {
- int handled; /* make sure that we only apply the headers once */
-} handler_ctx;
-
-typedef struct {
- array *request_header;
- array *response_header;
-
- array *environment;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-static handler_ctx * handler_ctx_init() {
- handler_ctx * hctx;
-
- hctx = calloc(1, sizeof(*hctx));
-
- hctx->handled = 0;
-
- return hctx;
-}
-
-static void handler_ctx_free(handler_ctx *hctx) {
- free(hctx);
-}
-
-
-/* init the plugin data */
-INIT_FUNC(mod_setenv_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_setenv_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- array_free(s->request_header);
- array_free(s->response_header);
- array_free(s->environment);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->request_header = array_init();
- s->response_header = array_init();
- s->environment = array_init();
-
- cv[0].destination = s->request_header;
- cv[1].destination = s->response_header;
- cv[2].destination = s->environment;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(request_header);
- PATCH_OPTION(response_header);
- PATCH_OPTION(environment);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
- PATCH_OPTION(request_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
- PATCH_OPTION(response_header);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
- PATCH_OPTION(environment);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_setenv_uri_handler) {
- plugin_data *p = p_d;
- size_t k;
- handler_ctx *hctx;
-
- mod_setenv_patch_connection(srv, con, p);
-
- if (p->conf.request_header->used == 0 &&
- p->conf.environment->used == 0 &&
- p->conf.response_header->used == 0) {
- return HANDLER_GO_ON;
- }
-
- if (con->plugin_ctx[p->id]) {
- hctx = con->plugin_ctx[p->id];
- } else {
- hctx = handler_ctx_init();
-
- con->plugin_ctx[p->id] = hctx;
- }
-
- if (hctx->handled) {
- return HANDLER_GO_ON;
- }
-
- hctx->handled = 1;
-
- for (k = 0; k < p->conf.request_header->used; k++) {
- data_string *ds = (data_string *)p->conf.request_header->data[k];
- data_string *ds_dst;
-
- if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
- ds_dst = data_string_init();
- }
-
- buffer_copy_string_buffer(ds_dst->key, ds->key);
- buffer_copy_string_buffer(ds_dst->value, ds->value);
-
- array_insert_unique(con->request.headers, (data_unset *)ds_dst);
- }
-
- for (k = 0; k < p->conf.environment->used; k++) {
- data_string *ds = (data_string *)p->conf.environment->data[k];
- data_string *ds_dst;
-
- if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
- ds_dst = data_string_init();
- }
-
- buffer_copy_string_buffer(ds_dst->key, ds->key);
- buffer_copy_string_buffer(ds_dst->value, ds->value);
-
- array_insert_unique(con->environment, (data_unset *)ds_dst);
- }
-
- for (k = 0; k < p->conf.response_header->used; k++) {
- data_string *ds = (data_string *)p->conf.response_header->data[k];
-
- response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-REQUESTDONE_FUNC(mod_setenv_reset) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (con->plugin_ctx[p->id]) {
- handler_ctx_free(con->plugin_ctx[p->id]);
- con->plugin_ctx[p->id] = NULL;
- }
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_setenv_plugin_init(plugin *p);
-LI_EXPORT int mod_setenv_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("setenv");
-
- p->init = mod_setenv_init;
- p->handle_uri_clean = mod_setenv_uri_handler;
- p->handle_start_backend = mod_setenv_uri_handler;
- p->set_defaults = mod_setenv_set_defaults;
- p->cleanup = mod_setenv_free;
-
- p->connection_reset = mod_setenv_reset;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_simple_vhost.c b/src/mod_simple_vhost.c
deleted file mode 100644
index eb100e1b..00000000
--- a/src/mod_simple_vhost.c
+++ /dev/null
@@ -1,282 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "stat_cache.h"
-
-#include "plugin.h"
-
-#include "sys-files.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-typedef struct {
- buffer *server_root;
- buffer *default_host;
- buffer *document_root;
-
- buffer *docroot_cache_key;
- buffer *docroot_cache_value;
- buffer *docroot_cache_servername;
-
- unsigned short debug;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *doc_root;
-
- plugin_config **config_storage;
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_simple_vhost_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->doc_root = buffer_init();
-
- return p;
-}
-
-FREE_FUNC(mod_simple_vhost_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- buffer_free(s->document_root);
- buffer_free(s->default_host);
- buffer_free(s->server_root);
-
- buffer_free(s->docroot_cache_key);
- buffer_free(s->docroot_cache_value);
- buffer_free(s->docroot_cache_servername);
-
- free(s);
- }
-
- free(p->config_storage);
- }
-
- buffer_free(p->doc_root);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
- plugin_data *p = p_d;
- size_t i;
-
- config_values_t cv[] = {
- { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
-
- s->server_root = buffer_init();
- s->default_host = buffer_init();
- s->document_root = buffer_init();
-
- s->docroot_cache_key = buffer_init();
- s->docroot_cache_value = buffer_init();
- s->docroot_cache_servername = buffer_init();
-
- s->debug = 0;
-
- cv[0].destination = s->server_root;
- cv[1].destination = s->default_host;
- cv[2].destination = s->document_root;
- cv[3].destination = &(s->debug);
-
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
- stat_cache_entry *sce = NULL;
-
- buffer_prepare_copy(out, 128);
-
- if (p->conf.server_root->used) {
- buffer_copy_string_buffer(out, p->conf.server_root);
-
- if (host->used) {
- /* a hostname has to start with a alpha-numerical character
- * and must not contain a slash "/"
- */
- char *dp;
-
- PATHNAME_APPEND_SLASH(out);
-
- if (NULL == (dp = strchr(host->ptr, ':'))) {
- buffer_append_string_buffer(out, host);
- } else {
- buffer_append_string_len(out, host->ptr, dp - host->ptr);
- }
- }
- PATHNAME_APPEND_SLASH(out);
-
- if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
- buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
- } else {
- buffer_append_string_buffer(out, p->conf.document_root);
- PATHNAME_APPEND_SLASH(out);
- }
- } else {
- buffer_copy_string_buffer(out, con->conf.document_root);
- PATHNAME_APPEND_SLASH(out);
- }
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), out);
- }
- return -1;
- } else if (!S_ISDIR(sce->st.st_mode)) {
- return -1;
- }
-
- return 0;
-}
-
-static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(server_root);
- PATCH_OPTION(default_host);
- PATCH_OPTION(document_root);
-
- PATCH_OPTION(docroot_cache_key);
- PATCH_OPTION(docroot_cache_value);
- PATCH_OPTION(docroot_cache_servername);
-
- PATCH_OPTION(debug);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
- PATCH_OPTION(server_root);
- PATCH_OPTION(docroot_cache_key);
- PATCH_OPTION(docroot_cache_value);
- PATCH_OPTION(docroot_cache_servername);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
- PATCH_OPTION(default_host);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
- PATCH_OPTION(document_root);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
- PATCH_OPTION(debug);
- }
- }
- }
-
- return 0;
-}
-
-static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
- plugin_data *p = p_data;
-
- /*
- * cache the last successfull translation from hostname (authority) to docroot
- * - this saves us a stat() call
- *
- */
-
- mod_simple_vhost_patch_connection(srv, con, p);
-
- if (p->conf.docroot_cache_key->used &&
- con->uri.authority->used &&
- buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
- /* cache hit */
- buffer_copy_string_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
- buffer_copy_string_buffer(con->server_name, p->conf.docroot_cache_servername);
- } else {
- /* build document-root */
- if ((con->uri.authority->used == 0) ||
- build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
- /* not found, fallback the default-host */
- if (build_doc_root(srv, con, p,
- p->doc_root,
- p->conf.default_host)) {
- return HANDLER_GO_ON;
- } else {
- buffer_copy_string_buffer(con->server_name, p->conf.default_host);
- }
- } else {
- buffer_copy_string_buffer(con->server_name, con->uri.authority);
- }
-
- /* copy to cache */
- buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
- buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
- buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
-
- buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
- }
-
- return HANDLER_GO_ON;
-}
-
-
-LI_EXPORT int mod_simple_vhost_plugin_init(plugin *p);
-LI_EXPORT int mod_simple_vhost_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("simple_vhost");
-
- p->init = mod_simple_vhost_init;
- p->set_defaults = mod_simple_vhost_set_defaults;
- p->handle_docroot = mod_simple_vhost_docroot;
- p->cleanup = mod_simple_vhost_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_skeleton.c b/src/mod_skeleton.c
deleted file mode 100644
index d79b08e9..00000000
--- a/src/mod_skeleton.c
+++ /dev/null
@@ -1,207 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/**
- * this is a skeleton for a lighttpd plugin
- *
- * just replaces every occurance of 'skeleton' by your plugin name
- *
- * e.g. in vim:
- *
- * :%s/skeleton/myhandler/
- *
- */
-
-
-
-/* plugin config for all request/connections */
-
-typedef struct {
- array *match;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *match_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-typedef struct {
- size_t foo;
-} handler_ctx;
-
-static handler_ctx * handler_ctx_init() {
- handler_ctx * hctx;
-
- hctx = calloc(1, sizeof(*hctx));
-
- return hctx;
-}
-
-static void handler_ctx_free(handler_ctx *hctx) {
-
- free(hctx);
-}
-
-/* init the plugin data */
-INIT_FUNC(mod_skeleton_init) {
- plugin_data *p;
-
- p = calloc(1, sizeof(*p));
-
- p->match_buf = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_skeleton_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- array_free(s->match);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->match_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->match = array_init();
-
- cv[0].destination = s->match;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(match);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
- PATCH_OPTION(match);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_skeleton_uri_handler) {
- plugin_data *p = p_d;
- int s_len;
- size_t k, i;
-
- UNUSED(srv);
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_skeleton_patch_connection(srv, con, p);
-
- s_len = con->uri.path->used - 1;
-
- for (k = 0; k < p->conf.match->used; k++) {
- data_string *ds = (data_string *)p->conf.match->data[k];
- int ct_len = ds->value->used - 1;
-
- if (ct_len > s_len) continue;
- if (ds->value->used == 0) continue;
-
- if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
- con->http_status = 403;
-
- return HANDLER_FINISHED;
- }
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-int mod_skeleton_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("skeleton");
-
- p->init = mod_skeleton_init;
- p->handle_uri_clean = mod_skeleton_uri_handler;
- p->set_defaults = mod_skeleton_set_defaults;
- p->cleanup = mod_skeleton_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_sql_vhost_core.c b/src/mod_sql_vhost_core.c
deleted file mode 100644
index 8cef1c8b..00000000
--- a/src/mod_sql_vhost_core.c
+++ /dev/null
@@ -1,384 +0,0 @@
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "plugin.h"
-#include "log.h"
-#include "sys-files.h"
-
-#include "stat_cache.h"
-
-#include "mod_sql_vhost_core.h"
-
-#define plugin_data mod_sql_vhost_core_plugin_data
-#define plugin_config mod_sql_vhost_core_plugin_config
-
-typedef struct {
- buffer *docroot;
- time_t added_ts;
-
- time_t ttl;
-} cached_vhost;
-
-/* init the plugin data */
-INIT_FUNC(mod_sql_vhost_core_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->docroot = buffer_init();
- p->host = buffer_init();
-
- return p;
-}
-
-/* cleanup the plugin data */
-SERVER_FUNC(mod_sql_vhost_core_cleanup) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- buffer_free(s->db);
- buffer_free(s->user);
- buffer_free(s->pass);
- buffer_free(s->sock);
- buffer_free(s->backend);
- buffer_free(s->hostname);
- buffer_free(s->select_vhost);
-#ifdef HAVE_GLIB_H
- g_hash_table_destroy(s->vhost_table);
-#endif
-
- free(s);
- }
- free(p->config_storage);
- }
- buffer_free(p->docroot);
- buffer_free(p->host);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-#ifdef HAVE_GLIB_H
-#if 0
-static cached_vhost *cached_vhost_init(void) {
- cached_vhost *vhost;
-
- vhost = g_new0(cached_vhost, 1);
-
- return vhost;
-}
-#endif
-
-static void cached_vhost_free(cached_vhost *vhost) {
- if (!vhost) return;
-
- if (vhost->docroot) buffer_free(vhost->docroot);
-
- g_free(vhost);
-}
-
-static void cached_vhost_free_hash(gpointer vhost) {
- cached_vhost_free(vhost);
-}
-
-static uint buffer_hash(gconstpointer key) {
- buffer *b = (buffer *)key;
-
- return g_str_hash(b->ptr);
-}
-
-static gboolean buffer_hash_equal(gconstpointer _a, gconstpointer _b) {
- buffer *a = (buffer *)_a;
- buffer *b = (buffer *)_b;
-
- return buffer_is_equal(a, b);
-}
-
-static void buffer_hash_free(gpointer d) {
- buffer *b = d;
-
- buffer_free(b);
-}
-#endif
-
-#define CONFIG_CACHE_TTL "sql-vhost.cache-ttl"
-#define CONFIG_DEBUG "sql-vhost.debug"
-
-/* set configuration values */
-SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
- plugin_data *p = p_d;
-
- size_t i = 0;
-
- config_values_t cv[] = {
- { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
- { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
- { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
- { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
- { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
- { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
- { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
- { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
-
- /* backward compat */
- { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
- { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
- { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
- { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
- { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
- { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
- { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
-
- { CONFIG_CACHE_TTL, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 15 * 60 */
- { CONFIG_DEBUG, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 15 * 60 */
-
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->db = buffer_init();
- s->user = buffer_init();
- s->pass = buffer_init();
- s->sock = buffer_init();
- s->hostname = buffer_init();
- s->backend = buffer_init();
- s->port = 0; /* default port for mysql */
- s->select_vhost = buffer_init();
- s->backend_data = NULL;
-#ifdef HAVE_GLIB_H
- s->vhost_table = g_hash_table_new_full(buffer_hash, buffer_hash_equal, buffer_hash_free, cached_vhost_free_hash);
-#endif
- s->cache_ttl = 60;
- s->debug = 0;
-
- cv[0].destination = s->db;
- cv[1].destination = s->user;
- cv[2].destination = s->pass;
- cv[3].destination = s->sock;
- cv[4].destination = s->select_vhost;
- cv[5].destination = s->hostname;
- cv[6].destination = &(s->port);
- cv[7].destination = s->backend;
-
- /* backend compat */
- cv[8].destination = cv[0].destination;
- cv[9].destination = cv[1].destination;
- cv[10].destination = cv[2].destination;
- cv[11].destination = cv[3].destination;
- cv[12].destination = cv[4].destination;
- cv[13].destination = cv[5].destination;
- cv[14].destination = cv[6].destination;
-
- cv[15].destination = &(s->cache_ttl);
- cv[16].destination = &(s->debug);
-
- p->config_storage[i] = s;
-
- if (config_insert_values_global(srv,
- ((data_config *)srv->config_context->data[i])->value,
- cv)) return HANDLER_ERROR;
-
- /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(backend_data);
- PATCH_OPTION(get_vhost);
-#ifdef HAVE_GLIB_H
- PATCH_OPTION(vhost_table);
-#endif
- PATCH_OPTION(cache_ttl);
- PATCH_OPTION(debug);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- if (s->backend_data) {
- PATCH_OPTION(backend_data);
- PATCH_OPTION(get_vhost);
-#ifdef HAVE_GLIB_H
- PATCH_OPTION(vhost_table);
-#endif
- }
-
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_CACHE_TTL))) {
- PATCH_OPTION(cache_ttl);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DEBUG))) {
- PATCH_OPTION(debug);
- }
- }
- }
-
- return 0;
-}
-
-/* handle document root request
- *
- * glib: if available we cache the entries
- *
- * */
-CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
- plugin_data *p = p_d;
- stat_cache_entry *sce;
-#ifdef HAVE_GLIB_H
- cached_vhost *vhost = NULL;
-#endif
-
- /* no host specified? */
- if (!con->uri.authority->used) return HANDLER_GO_ON;
-
- mod_sql_vhost_core_patch_connection(srv, con, p);
-
- /* do we have backend ? */
- if (!p->conf.get_vhost) return HANDLER_GO_ON;
-
-#ifdef HAVE_GLIB_H
- if (p->conf.cache_ttl == 0 || /* 1. we don't cache */
- NULL == (vhost = g_hash_table_lookup(p->conf.vhost_table, con->uri.authority)) || /* 2. check if the host is already known */
- srv->cur_ts - vhost->added_ts >= p->conf.cache_ttl
- ) { /* 3. the cache value is old */
- /* ask the backend for the data */
- if (p->conf.debug) TRACE("cache-miss for %s", SAFE_BUF_STR(con->uri.authority));
-
- if (HANDLER_GO_ON != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
- return HANDLER_GO_ON;
- }
-
- if (p->conf.cache_ttl > 0) {
- /* check if the cache-ttl is > 0, otherwise we would always trash the cache-entry */
- if (vhost) {
- if (p->conf.debug) TRACE("refreshing %s: %s", SAFE_BUF_STR(con->uri.authority), SAFE_BUF_STR(p->docroot));
- buffer_copy_string_buffer(vhost->docroot, p->docroot);
- vhost->added_ts = srv->cur_ts;
- } else {
- buffer *key;
-
- vhost = g_new0(cached_vhost, 1);
- vhost->docroot = buffer_init_buffer(p->docroot);
- vhost->added_ts = srv->cur_ts;
- vhost->ttl = p->conf.cache_ttl;
-
- key = buffer_init_buffer(con->uri.authority);
-
- if (p->conf.debug) TRACE("adding %s: %s", SAFE_BUF_STR(key), SAFE_BUF_STR(vhost->docroot));
-
- g_hash_table_insert(p->conf.vhost_table, key, vhost);
-
- g_assert(g_hash_table_lookup(p->conf.vhost_table, key));
- }
- }
- } else {
- if (p->conf.debug) TRACE("cache-hit for %s: %s", SAFE_BUF_STR(vhost->docroot), SAFE_BUF_STR(con->uri.authority));
-
- buffer_copy_string_buffer(p->docroot, vhost->docroot);
- }
-#else
- if (HANDLER_GO_ON != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
- return HANDLER_GO_ON;
- }
-#endif
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
- ERROR("stat_cache_get_entry(%s) failed: %s", SAFE_BUF_STR(p->docroot), strerror(errno));
-
- return HANDLER_GO_ON;
- }
- if (!S_ISDIR(sce->st.st_mode)) {
- ERROR("%s is not a dir", SAFE_BUF_STR(p->docroot));
-
- return HANDLER_GO_ON;
- }
-
- buffer_copy_string_buffer(con->server_name, p->host);
- buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
-
- return HANDLER_GO_ON;
-}
-
-#if 0
-#ifdef HAVE_GLIB_H
-static gboolean cached_vhost_remove_expired(gpointer _key, gpointer _val, gpointer data) {
-// buffer *key = _key;
- cached_vhost *val = _val;
- server *srv = data;
- UNUSED(_key);
-
- return (srv->cur_ts - val->added_ts > val->ttl);
-}
-#endif
-
-TRIGGER_FUNC(mod_sql_vhost_core_trigger) {
- plugin_data *p = p_d;
- size_t i;
-
- /* test once every 10 seconds */
- if (srv->cur_ts % 10 != 0) return HANDLER_GO_ON;
-
-#ifdef HAVE_GLIB_H
- /* cleanup all caches */
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (s->vhost_table) {
- g_hash_table_foreach_remove(s->vhost_table, cached_vhost_remove_expired, srv);
- }
- }
-#endif
-
- return HANDLER_GO_ON;
-}
-#endif
-
-/* this function is called at dlopen() time and inits the callbacks */
-LI_EXPORT int mod_sql_vhost_core_plugin_init(plugin *p);
-LI_EXPORT int mod_sql_vhost_core_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("mod_sql_vhost_core");
-
- p->init = mod_sql_vhost_core_init;
- p->cleanup = mod_sql_vhost_core_cleanup;
-
- p->set_defaults = mod_sql_vhost_core_set_defaults;
- p->handle_docroot = mod_sql_vhost_core_handle_docroot;
-
- return 0;
-}
-
diff --git a/src/mod_sql_vhost_core.h b/src/mod_sql_vhost_core.h
deleted file mode 100644
index 2d70f62d..00000000
--- a/src/mod_sql_vhost_core.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef _MOD_SQL_VHOST_CORE_H_
-#define _MOD_SQL_VHOST_CORE_H_
-
-#include "buffer.h"
-#include "plugin.h"
-
-#ifdef HAVE_GLIB_H
-#include <glib.h>
-#endif
-
-#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
- (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
-
-#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
-
-#define SQLVHOST_BACKEND_GETVHOST(name) \
- SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
-
-#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
- SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
-
-typedef struct {
- buffer *db;
- buffer *user;
- buffer *pass;
- buffer *sock;
-
- buffer *hostname;
- unsigned short port;
-
- buffer *backend;
- void *backend_data;
-
- buffer *select_vhost;
-
- unsigned short cache_ttl;
- unsigned short debug;
-
-#ifdef HAVE_GLIB_H
- GHashTable *vhost_table;
-#endif
-
- SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
-} mod_sql_vhost_core_plugin_config;
-
-/* global plugin data */
-typedef struct {
- PLUGIN_DATA;
-
- buffer *docroot;
- buffer *host;
-
- mod_sql_vhost_core_plugin_config **config_storage;
-
- mod_sql_vhost_core_plugin_config conf;
-} mod_sql_vhost_core_plugin_data;
-
-
-
-#endif
diff --git a/src/mod_ssi.c b/src/mod_ssi.c
deleted file mode 100644
index 91370e01..00000000
--- a/src/mod_ssi.c
+++ /dev/null
@@ -1,1095 +0,0 @@
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "stat_cache.h"
-
-#include "plugin.h"
-#include "stream.h"
-
-#include "response.h"
-
-#include "mod_ssi.h"
-
-#include "inet_ntop_cache.h"
-
-#include "sys-socket.h"
-#include "sys-strings.h"
-#include "sys-files.h"
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-#ifdef HAVE_FORK
-#include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>
-#endif
-
-/* init the plugin data */
-INIT_FUNC(mod_ssi_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->timefmt = buffer_init();
- p->stat_fn = buffer_init();
-
- p->ssi_vars = array_init();
- p->ssi_cgi_env = array_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_ssi_free) {
- plugin_data *p = p_d;
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- array_free(s->ssi_extension);
- buffer_free(s->content_type);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- array_free(p->ssi_vars);
- array_free(p->ssi_cgi_env);
-#ifdef HAVE_PCRE_H
- pcre_free(p->ssi_regex);
-#endif
- buffer_free(p->timefmt);
- buffer_free(p->stat_fn);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_ssi_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-#ifdef HAVE_PCRE_H
- const char *errptr;
- int erroff;
-#endif
-
- config_values_t cv[] = {
- { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "ssi.content-type", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->ssi_extension = array_init();
- s->content_type = buffer_init();
-
- cv[0].destination = s->ssi_extension;
- cv[1].destination = s->content_type;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
-#ifdef HAVE_PCRE_H
- /* allow 2 params */
- if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "ssi: pcre ",
- erroff, errptr);
- return HANDLER_ERROR;
- }
-#else
- log_error_write(srv, __FILE__, __LINE__, "s",
- "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
- return HANDLER_ERROR;
-#endif
-
- return HANDLER_GO_ON;
-}
-
-static int ssi_env_add(array *env, const char *key, const char *val) {
- data_string *ds;
-
- if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
- ds = data_string_init();
- }
- buffer_copy_string(ds->key, key);
- buffer_copy_string(ds->value, val);
-
- array_insert_unique(env, (data_unset *)ds);
-
- return 0;
-}
-
-/**
- *
- * the next two functions are take from fcgi.c
- *
- */
-
-static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
- size_t i;
-
- for (i = 0; i < con->request.headers->used; i++) {
- data_string *ds;
-
- ds = (data_string *)con->request.headers->data[i];
-
- if (ds->value->used && ds->key->used) {
- size_t j;
- buffer_reset(srv->tmp_buf);
-
- /* don't forward the Authorization: Header */
- if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
- continue;
- }
-
- if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
- buffer_copy_string_len(srv->tmp_buf, CONST_STR_LEN("HTTP_"));
- srv->tmp_buf->used--;
- }
-
- buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
- for (j = 0; j < ds->key->used - 1; j++) {
- char c = '_';
- if (light_isalpha(ds->key->ptr[j])) {
- /* upper-case */
- c = ds->key->ptr[j] & ~32;
- } else if (light_isdigit(ds->key->ptr[j])) {
- /* copy */
- c = ds->key->ptr[j];
- }
- srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
- }
- srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
-
- ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
- }
- }
-
- return 0;
-}
-
-static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
- char buf[32];
-
- server_socket *srv_sock = con->srv_socket;
-
-#ifdef HAVE_IPV6
- char b2[INET6_ADDRSTRLEN + 1];
-#endif
-
-#define CONST_STRING(x) \
- x
-
- array_reset(p->ssi_cgi_env);
-
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
-#ifdef HAVE_IPV6
- inet_ntop(srv_sock->addr.plain.sa_family,
- srv_sock->addr.plain.sa_family == AF_INET6 ?
- (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
- (const void *) &(srv_sock->addr.ipv4.sin_addr),
- b2, sizeof(b2)-1)
-#else
- inet_ntoa(srv_sock->addr.ipv4.sin_addr)
-#endif
- );
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
-
- LI_ltostr(buf,
-#ifdef HAVE_IPV6
- ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
-#else
- ntohs(srv_sock->addr.ipv4.sin_port)
-#endif
- );
-
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
-
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
- inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
-
- if (con->authed_user->used) {
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
- con->authed_user->ptr);
- }
-
- if (con->request.content_length > 0) {
- /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
-
- /* request.content_length < SSIZE_MAX, see request.c */
- LI_ltostr(buf, con->request.content_length);
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
- }
-
- /*
- * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
- * http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
- * (6.1.14, 6.1.6, 6.1.7)
- */
-
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_NAME"), con->uri.path->ptr);
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), "");
-
- /*
- * SCRIPT_FILENAME and DOCUMENT_ROOT for php. The PHP manual
- * http://www.php.net/manual/en/reserved.variables.php
- * treatment of PATH_TRANSLATED is different from the one of CGI specs.
- * TODO: this code should be checked against cgi.fix_pathinfo php
- * parameter.
- */
-
- if (con->request.pathinfo->used) {
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
- }
-
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
-
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
- ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
-
- ssi_env_add_request_headers(srv, con, p);
-
- return 0;
-}
-
-static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
- const char **l, size_t n) {
- size_t i, ssicmd = 0;
- char buf[255];
- buffer *b = NULL;
-
- struct {
- const char *var;
- enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
- SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
- SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
- } ssicmds[] = {
- { "echo", SSI_ECHO },
- { "include", SSI_INCLUDE },
- { "flastmod", SSI_FLASTMOD },
- { "fsize", SSI_FSIZE },
- { "config", SSI_CONFIG },
- { "printenv", SSI_PRINTENV },
- { "set", SSI_SET },
- { "if", SSI_IF },
- { "elif", SSI_ELIF },
- { "endif", SSI_ENDIF },
- { "else", SSI_ELSE },
- { "exec", SSI_EXEC },
-
- { NULL, SSI_UNSET }
- };
-
- for (i = 0; ssicmds[i].var; i++) {
- if (0 == strcmp(l[1], ssicmds[i].var)) {
- ssicmd = ssicmds[i].type;
- break;
- }
- }
-
- switch(ssicmd) {
- case SSI_ECHO: {
- /* echo */
- int var = 0, enc = 0;
- const char *var_val = NULL;
- stat_cache_entry *sce = NULL;
-
- struct {
- const char *var;
- enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
- SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
- } echovars[] = {
- { "DATE_GMT", SSI_ECHO_DATE_GMT },
- { "DATE_LOCAL", SSI_ECHO_DATE_LOCAL },
- { "DOCUMENT_NAME", SSI_ECHO_DOCUMENT_NAME },
- { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
- { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
- { "USER_NAME", SSI_ECHO_USER_NAME },
-
- { NULL, SSI_ECHO_UNSET }
- };
-
- struct {
- const char *var;
- enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
- } encvars[] = {
- { "url", SSI_ENC_URL },
- { "none", SSI_ENC_NONE },
- { "entity", SSI_ENC_ENTITY },
-
- { NULL, SSI_ENC_UNSET }
- };
-
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "var")) {
- int j;
-
- var_val = l[i+1];
-
- for (j = 0; echovars[j].var; j++) {
- if (0 == strcmp(l[i+1], echovars[j].var)) {
- var = echovars[j].type;
- break;
- }
- }
- } else if (0 == strcmp(l[i], "encoding")) {
- int j;
-
- for (j = 0; encvars[j].var; j++) {
- if (0 == strcmp(l[i+1], encvars[j].var)) {
- enc = encvars[j].type;
- break;
- }
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
-
- if (p->if_is_false) break;
-
- if (!var_val) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: ",
- l[1], "var is missing");
- break;
- }
-
- stat_cache_get_entry(srv, con, con->physical.path, &sce);
-
- switch(var) {
- case SSI_ECHO_USER_NAME: {
- struct passwd *pw;
-
- b = chunkqueue_get_append_buffer(con->send);
-#ifdef HAVE_PWD_H
- if (NULL == (pw = getpwuid(sce->st.st_uid))) {
- buffer_copy_long(b, sce->st.st_uid);
- } else {
- buffer_copy_string(b, pw->pw_name);
- }
-#else
- buffer_copy_long(b, sce->st.st_uid);
-#endif
- break;
- }
- case SSI_ECHO_LAST_MODIFIED: {
- time_t t = sce->st.st_mtime;
-
- b = chunkqueue_get_append_buffer(con->send);
- if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
- buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
- } else {
- buffer_copy_string(b, buf);
- }
- break;
- }
- case SSI_ECHO_DATE_LOCAL: {
- time_t t = time(NULL);
-
- b = chunkqueue_get_append_buffer(con->send);
- if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
- buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
- } else {
- buffer_copy_string(b, buf);
- }
- break;
- }
- case SSI_ECHO_DATE_GMT: {
- time_t t = time(NULL);
-
- b = chunkqueue_get_append_buffer(con->send);
- if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
- buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
- } else {
- buffer_copy_string(b, buf);
- }
- break;
- }
- case SSI_ECHO_DOCUMENT_NAME: {
- char *sl;
-
- b = chunkqueue_get_append_buffer(con->send);
- if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
- buffer_copy_string_buffer(b, con->physical.path);
- } else {
- buffer_copy_string(b, sl + 1);
- }
- break;
- }
- case SSI_ECHO_DOCUMENT_URI: {
- b = chunkqueue_get_append_buffer(con->send);
- buffer_copy_string_buffer(b, con->uri.path);
- break;
- }
- default: {
- data_string *ds;
- /* check if it is a cgi-var */
-
- b = chunkqueue_get_append_buffer(con->send);
-
- if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val, strlen(var_val)))) {
- buffer_copy_string_buffer(b, ds->value);
- } else {
- buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
- }
-
- break;
- }
- }
- break;
- }
- case SSI_INCLUDE:
- case SSI_FLASTMOD:
- case SSI_FSIZE: {
- const char * file_path = NULL, *virt_path = NULL;
- struct stat st;
- char *sl;
-
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "file")) {
- file_path = l[i+1];
- } else if (0 == strcmp(l[i], "virtual")) {
- virt_path = l[i+1];
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
-
- if (!file_path && !virt_path) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: ",
- l[1], "file or virtual are missing");
- break;
- }
-
- if (file_path && virt_path) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: ",
- l[1], "only one of file and virtual is allowed here");
- break;
- }
-
-
- if (p->if_is_false) break;
-
- if (file_path) {
- /* current doc-root */
- if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
- buffer_copy_string_len(p->stat_fn, CONST_STR_LEN("/"));
- } else {
- buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
- }
-
- buffer_copy_string(srv->tmp_buf, file_path);
- buffer_urldecode_path(srv->tmp_buf);
- buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
- buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
- } else {
- /* virtual */
-
- if (virt_path[0] == '/') {
- buffer_copy_string(p->stat_fn, virt_path);
- } else {
- /* there is always a / */
- sl = strrchr(con->uri.path->ptr, '/');
-
- buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
- buffer_append_string(p->stat_fn, virt_path);
- }
-
- buffer_urldecode_path(p->stat_fn);
- buffer_path_simplify(srv->tmp_buf, p->stat_fn);
-
- /* we have an uri */
-
- buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
- buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
- }
-
- if (0 == stat(p->stat_fn->ptr, &st)) {
- time_t t = st.st_mtime;
-
- switch (ssicmd) {
- case SSI_FSIZE:
- b = chunkqueue_get_append_buffer(con->send);
- if (p->sizefmt) {
- int j = 0;
- const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
-
- off_t s = st.st_size;
-
- for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
-
- buffer_copy_off_t(b, s);
- buffer_append_string(b, abr[j]);
- } else {
- buffer_copy_off_t(b, st.st_size);
- }
- break;
- case SSI_FLASTMOD:
- b = chunkqueue_get_append_buffer(con->send);
- if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
- buffer_copy_string_len(b, CONST_STR_LEN("(none)"));
- } else {
- buffer_copy_string(b, buf);
- }
- break;
- case SSI_INCLUDE:
- chunkqueue_append_file(con->send, p->stat_fn, 0, st.st_size);
- break;
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "ssi: stating failed ",
- p->stat_fn, strerror(errno));
- }
- break;
- }
- case SSI_SET: {
- const char *key = NULL, *val = NULL;
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "var")) {
- key = l[i+1];
- } else if (0 == strcmp(l[i], "value")) {
- val = l[i+1];
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
-
- if (p->if_is_false) break;
-
- if (key && val) {
- data_string *ds;
-
- if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
- ds = data_string_init();
- }
- buffer_copy_string(ds->key, key);
- buffer_copy_string(ds->value, val);
-
- array_insert_unique(p->ssi_vars, (data_unset *)ds);
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: var and value have to be set in",
- l[0], l[1]);
- }
- break;
- }
- case SSI_CONFIG:
- if (p->if_is_false) break;
-
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "timefmt")) {
- buffer_copy_string(p->timefmt, l[i+1]);
- } else if (0 == strcmp(l[i], "sizefmt")) {
- if (0 == strcmp(l[i+1], "abbrev")) {
- p->sizefmt = 1;
- } else if (0 == strcmp(l[i+1], "abbrev")) {
- p->sizefmt = 0;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sssss",
- "ssi: unknow value for attribute '",
- l[i],
- "' for ",
- l[1], l[i+1]);
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
- break;
- case SSI_PRINTENV:
- if (p->if_is_false) break;
-
- b = chunkqueue_get_append_buffer(con->send);
- buffer_copy_string_len(b, CONST_STR_LEN("<pre>"));
- for (i = 0; i < p->ssi_vars->used; i++) {
- data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
-
- buffer_append_string_buffer(b, ds->key);
- buffer_append_string_len(b, CONST_STR_LEN(": "));
- buffer_append_string_buffer(b, ds->value);
- buffer_append_string_len(b, CONST_STR_LEN("<br />"));
-
- }
- buffer_append_string_len(b, CONST_STR_LEN("</pre>"));
-
- break;
- case SSI_EXEC: {
-#ifndef _WIN32
-
- const char *cmd = NULL;
- pid_t pid;
- int from_exec_fds[2];
-
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "cmd")) {
- cmd = l[i+1];
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
-
- if (p->if_is_false) break;
-
- /* create a return pipe and send output to the html-page
- *
- * as exec is assumed evil it is implemented synchronously
- */
-
- if (!cmd) break;
-
- if (pipe(from_exec_fds)) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "pipe failed: ", strerror(errno));
- return -1;
- }
-
- /* fork, execve */
- switch (pid = fork()) {
- case 0: {
- /* move stdout to from_rrdtool_fd[1] */
- close(STDOUT_FILENO);
- dup2(from_exec_fds[1], STDOUT_FILENO);
- close(from_exec_fds[1]);
- /* not needed */
- close(from_exec_fds[0]);
-
- /* close stdin */
- close(STDIN_FILENO);
-
- execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
-
- /* */
- SEGFAULT("spawing '%s' failed: %s", cmd, strerror(errno));
- break;
- }
- case -1:
- /* error */
- log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
- break;
- default: {
- /* father */
- int status;
- ssize_t r;
-
- close(from_exec_fds[1]);
-
- /* wait for the client to end */
- 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;
- }
-
- if (toread > 0) {
- b = chunkqueue_get_append_buffer(con->send);
-
- 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 {
- break;
- }
- }
- } else {
- log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
- }
- close(from_exec_fds[0]);
-
- break;
- }
- }
-#else
- return -1;
-#endif
-
- break;
- }
- case SSI_IF: {
- const char *expr = NULL;
-
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "expr")) {
- expr = l[i+1];
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
-
- if (!expr) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: ",
- l[1], "expr missing");
- break;
- }
-
- if ((!p->if_is_false) &&
- ((p->if_is_false_level == 0) ||
- (p->if_level < p->if_is_false_level))) {
- switch (ssi_eval_expr(srv, con, p, expr)) {
- case -1:
- case 0:
- p->if_is_false = 1;
- p->if_is_false_level = p->if_level;
- break;
- case 1:
- p->if_is_false = 0;
- break;
- }
- }
-
- p->if_level++;
-
- break;
- }
- case SSI_ELSE:
- p->if_level--;
-
- if (p->if_is_false) {
- if ((p->if_level == p->if_is_false_level) &&
- (p->if_is_false_endif == 0)) {
- p->if_is_false = 0;
- }
- } else {
- p->if_is_false = 1;
-
- p->if_is_false_level = p->if_level;
- }
- p->if_level++;
-
- break;
- case SSI_ELIF: {
- const char *expr = NULL;
- for (i = 2; i < n; i += 2) {
- if (0 == strcmp(l[i], "expr")) {
- expr = l[i+1];
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: unknow attribute for ",
- l[1], l[i]);
- }
- }
-
- if (!expr) {
- log_error_write(srv, __FILE__, __LINE__, "sss",
- "ssi: ",
- l[1], "expr missing");
- break;
- }
-
- p->if_level--;
-
- if (p->if_level == p->if_is_false_level) {
- if ((p->if_is_false) &&
- (p->if_is_false_endif == 0)) {
- switch (ssi_eval_expr(srv, con, p, expr)) {
- case -1:
- case 0:
- p->if_is_false = 1;
- p->if_is_false_level = p->if_level;
- break;
- case 1:
- p->if_is_false = 0;
- break;
- }
- } else {
- p->if_is_false = 1;
- p->if_is_false_level = p->if_level;
- p->if_is_false_endif = 1;
- }
- }
-
- p->if_level++;
-
- break;
- }
- case SSI_ENDIF:
- p->if_level--;
-
- if (p->if_level == p->if_is_false_level) {
- p->if_is_false = 0;
- p->if_is_false_endif = 0;
- }
-
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "ssi: unknow ssi-command:",
- l[1]);
- break;
- }
-
- return 0;
-
-}
-
-static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
- stream s;
-#ifdef HAVE_PCRE_H
- int i, n;
-
-#define N 10
- int ovec[N * 3];
-#endif
-
- /* get a stream to the file */
-
- array_reset(p->ssi_vars);
- array_reset(p->ssi_cgi_env);
- buffer_copy_string_len(p->timefmt, CONST_STR_LEN("%a, %d %b %Y %H:%M:%S %Z"));
- p->sizefmt = 0;
- build_ssi_cgi_vars(srv, con, p);
- p->if_is_false = 0;
-
- if (-1 == stream_open(&s, con->physical.path)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "stream-open: ", con->physical.path);
- return -1;
- }
-
-
- /**
- * <!--#element attribute=value attribute=value ... -->
- *
- * config DONE
- * errmsg -- missing
- * sizefmt DONE
- * timefmt DONE
- * echo DONE
- * var DONE
- * encoding -- missing
- * exec DONE
- * cgi -- never
- * cmd DONE
- * fsize DONE
- * file DONE
- * virtual DONE
- * flastmod DONE
- * file DONE
- * virtual DONE
- * include DONE
- * file DONE
- * virtual DONE
- * printenv DONE
- * set DONE
- * var DONE
- * value DONE
- *
- * if DONE
- * elif DONE
- * else DONE
- * endif DONE
- *
- *
- * expressions
- * AND, OR DONE
- * comp DONE
- * ${...} -- missing
- * $... DONE
- * '...' DONE
- * ( ... ) DONE
- *
- *
- *
- * ** all DONE **
- * DATE_GMT
- * The current date in Greenwich Mean Time.
- * DATE_LOCAL
- * The current date in the local time zone.
- * DOCUMENT_NAME
- * The filename (excluding directories) of the document requested by the user.
- * DOCUMENT_URI
- * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document.
- * LAST_MODIFIED
- * The last modification date of the document requested by the user.
- * USER_NAME
- * Contains the owner of the file which included it.
- *
- */
-#ifdef HAVE_PCRE_H
- for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
- const char **l;
- /* take everything from last offset to current match pos */
-
- if (!p->if_is_false) chunkqueue_append_file(con->send, con->physical.path, i, ovec[0] - i);
-
- pcre_get_substring_list(s.start, ovec, n, &l);
- process_ssi_stmt(srv, con, p, l, n);
- pcre_free_substring_list(l);
- }
-
- switch(n) {
- case PCRE_ERROR_NOMATCH:
- /* copy everything/the rest */
- chunkqueue_append_file(con->send, con->physical.path, i, s.size - i);
-
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "execution error while matching: ", n);
- break;
- }
-#endif
-
-
- stream_close(&s);
-
- con->file_started = 1;
- con->send->is_closed = 1;
-
- if (p->conf.content_type->used <= 1) {
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
- } else {
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->conf.content_type));
- }
-
- /* reset physical.path */
- buffer_reset(con->physical.path);
-
- return 0;
-}
-
-static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(ssi_extension);
- PATCH_OPTION(content_type);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
- PATCH_OPTION(ssi_extension);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.content-type"))) {
- PATCH_OPTION(content_type);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_ssi_physical_path) {
- plugin_data *p = p_d;
- size_t k;
-
- if (con->physical.path->used == 0) return HANDLER_GO_ON;
-
- mod_ssi_patch_connection(srv, con, p);
-
- for (k = 0; k < p->conf.ssi_extension->used; k++) {
- data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
-
- if (ds->value->used == 0) continue;
-
- if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
- /* handle ssi-request */
-
- if (mod_ssi_handle_request(srv, con, p)) {
- /* on error */
- con->http_status = 500;
- }
-
- return HANDLER_FINISHED;
- }
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_ssi_plugin_init(plugin *p);
-LI_EXPORT int mod_ssi_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("ssi");
-
- p->init = mod_ssi_init;
- p->handle_start_backend = mod_ssi_physical_path;
- p->set_defaults = mod_ssi_set_defaults;
- p->cleanup = mod_ssi_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_ssi.h b/src/mod_ssi.h
deleted file mode 100644
index 241e8320..00000000
--- a/src/mod_ssi.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _MOD_SSI_H_
-#define _MOD_SSI_H_
-
-#include "base.h"
-#include "buffer.h"
-#include "array.h"
-
-#include "plugin.h"
-
-#ifdef HAVE_PCRE_H
-#include <pcre.h>
-#endif
-
-/* plugin config for all request/connections */
-
-typedef struct {
- array *ssi_extension;
- buffer *content_type;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
-#ifdef HAVE_PCRE_H
- pcre *ssi_regex;
-#endif
- buffer *timefmt;
- int sizefmt;
-
- buffer *stat_fn;
-
- array *ssi_vars;
- array *ssi_cgi_env;
-
- int if_level, if_is_false_level, if_is_false, if_is_false_endif;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
-
-#endif
diff --git a/src/mod_ssi_expr.c b/src/mod_ssi_expr.c
deleted file mode 100644
index 0766e50d..00000000
--- a/src/mod_ssi_expr.c
+++ /dev/null
@@ -1,325 +0,0 @@
-#include <ctype.h>
-#include <string.h>
-
-#include "mod_ssi.h"
-#include "mod_ssi_expr.h"
-#include "mod_ssi_exprparser.h"
-
-#include "buffer.h"
-#include "log.h"
-
-typedef struct {
- const char *input;
- size_t offset;
- size_t size;
-
- int line_pos;
-
- int in_key;
- int in_brace;
- int in_cond;
-} ssi_tokenizer_t;
-
-ssi_val_t *ssi_val_init() {
- ssi_val_t *s;
-
- s = calloc(1, sizeof(*s));
-
- return s;
-}
-
-void ssi_val_free(ssi_val_t *s) {
- if (s->str) buffer_free(s->str);
-
- free(s);
-}
-
-int ssi_val_tobool(ssi_val_t *B) {
- if (B->type == SSI_TYPE_STRING) {
- return B->str->used > 1 ? 1 : 0;
- } else {
- return B->bo;
- }
-}
-
-static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p,
- ssi_tokenizer_t *t, int *token_id, buffer *token) {
- int tid = 0;
- size_t i;
-
- UNUSED(con);
-
- for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
- char c = t->input[t->offset];
- data_string *ds;
-
- switch (c) {
- case '=':
- tid = TK_EQ;
-
- t->offset++;
- t->line_pos++;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(=)"));
-
- break;
- case '>':
- if (t->input[t->offset + 1] == '=') {
- t->offset += 2;
- t->line_pos += 2;
-
- tid = TK_GE;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(>=)"));
- } else {
- t->offset += 1;
- t->line_pos += 1;
-
- tid = TK_GT;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(>)"));
- }
-
- break;
- case '<':
- if (t->input[t->offset + 1] == '=') {
- t->offset += 2;
- t->line_pos += 2;
-
- tid = TK_LE;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(<=)"));
- } else {
- t->offset += 1;
- t->line_pos += 1;
-
- tid = TK_LT;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(<)"));
- }
-
- break;
-
- case '!':
- if (t->input[t->offset + 1] == '=') {
- t->offset += 2;
- t->line_pos += 2;
-
- tid = TK_NE;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(!=)"));
- } else {
- t->offset += 1;
- t->line_pos += 1;
-
- tid = TK_NOT;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(!)"));
- }
-
- break;
- case '&':
- if (t->input[t->offset + 1] == '&') {
- t->offset += 2;
- t->line_pos += 2;
-
- tid = TK_AND;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(&&)"));
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "pos:", t->line_pos,
- "missing second &");
- return -1;
- }
-
- break;
- case '|':
- if (t->input[t->offset + 1] == '|') {
- t->offset += 2;
- t->line_pos += 2;
-
- tid = TK_OR;
-
- buffer_copy_string_len(token, CONST_STR_LEN("(||)"));
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "pos:", t->line_pos,
- "missing second |");
- return -1;
- }
-
- break;
- case '\t':
- case ' ':
- t->offset++;
- t->line_pos++;
- break;
-
- case '\'':
- /* search for the terminating " */
- for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
-
- if (t->input[t->offset + i]) {
- tid = TK_VALUE;
-
- buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
-
- t->offset += i + 1;
- t->line_pos += i + 1;
- } else {
- /* ERROR */
-
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "pos:", t->line_pos,
- "missing closing quote");
-
- return -1;
- }
-
- break;
- case '(':
- t->offset++;
- t->in_brace++;
-
- tid = TK_LPARAN;
-
- buffer_copy_string_len(token, CONST_STR_LEN("("));
- break;
- case ')':
- t->offset++;
- t->in_brace--;
-
- tid = TK_RPARAN;
-
- buffer_copy_string_len(token, CONST_STR_LEN(")"));
- break;
- case '$':
- if (t->input[t->offset + 1] == '{') {
- for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
-
- if (t->input[t->offset + i] != '}') {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "pos:", t->line_pos,
- "missing closing quote");
-
- return -1;
- }
-
- buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
- } else {
- for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
-
- buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
- }
-
- tid = TK_VALUE;
-
- if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, CONST_BUF_LEN(token)))) {
- buffer_copy_string_buffer(token, ds->value);
- } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, CONST_BUF_LEN(token)))) {
- buffer_copy_string_buffer(token, ds->value);
- } else {
- buffer_copy_string_len(token, CONST_STR_LEN(""));
- }
-
- t->offset += i;
- t->line_pos += i;
-
- break;
- default:
- for (i = 0; isgraph(t->input[t->offset + i]); i++) {
- char d = t->input[t->offset + i];
- switch(d) {
- case ' ':
- case '\t':
- case ')':
- case '(':
- case '\'':
- case '=':
- case '!':
- case '<':
- case '>':
- case '&':
- case '|':
- break;
- }
- }
-
- tid = TK_VALUE;
-
- buffer_copy_string_len(token, t->input + t->offset, i);
-
- t->offset += i;
- t->line_pos += i;
-
- break;
- }
- }
-
- if (tid) {
- *token_id = tid;
-
- return 1;
- } else if (t->offset < t->size) {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "pos:", t->line_pos,
- "foobar");
- }
- return 0;
-}
-
-int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr) {
- ssi_tokenizer_t t;
- void *pParser;
- int token_id;
- buffer *token;
- ssi_ctx_t context;
- int ret;
-
- t.input = expr;
- t.offset = 0;
- t.size = strlen(expr);
- t.line_pos = 1;
-
- t.in_key = 1;
- t.in_brace = 0;
- t.in_cond = 0;
-
- context.ok = 1;
- context.srv = srv;
-
- /* default context */
-
- pParser = ssiexprparserAlloc( malloc );
- token = buffer_init();
- while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
- ssiexprparser(pParser, token_id, token, &context);
-
- token = buffer_init();
- }
- ssiexprparser(pParser, 0, token, &context);
- ssiexprparserFree(pParser, free );
-
- buffer_free(token);
-
- if (ret == -1) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "expr parser failed");
- return -1;
- }
-
- if (context.ok == 0) {
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "pos:", t.line_pos,
- "parser failed somehow near here");
- return -1;
- }
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "expr: ",
- expr,
- context.val.bo);
-#endif
- return context.val.bo;
-}
diff --git a/src/mod_ssi_expr.h b/src/mod_ssi_expr.h
deleted file mode 100644
index 2d3ae8bb..00000000
--- a/src/mod_ssi_expr.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _MOD_SSI_EXPR_H_
-#define _MOD_SSI_EXPR_H_
-
-#include "buffer.h"
-
-typedef struct {
- enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
-
- buffer *str;
- int bo;
-} ssi_val_t;
-
-typedef struct {
- int ok;
-
- ssi_val_t val;
-
- void *srv;
-} ssi_ctx_t;
-
-typedef enum { SSI_COND_UNSET, SSI_COND_LE, SSI_COND_GE, SSI_COND_EQ, SSI_COND_NE, SSI_COND_LT, SSI_COND_GT } ssi_expr_cond;
-
-void *ssiexprparserAlloc(void *(*mallocProc)(size_t));
-void ssiexprparserFree(void *p, void (*freeProc)(void*));
-void ssiexprparser(void *yyp, int yymajor, buffer *yyminor, ssi_ctx_t *ctx);
-
-int ssi_val_tobool(ssi_val_t *B);
-ssi_val_t *ssi_val_init();
-void ssi_val_free(ssi_val_t *s);
-
-#endif
diff --git a/src/mod_ssi_exprparser.y b/src/mod_ssi_exprparser.y
deleted file mode 100644
index ffaafd05..00000000
--- a/src/mod_ssi_exprparser.y
+++ /dev/null
@@ -1,122 +0,0 @@
-%token_prefix TK_
-%token_type {buffer *}
-%extra_argument {ssi_ctx_t *ctx}
-%name ssiexprparser
-
-%include {
-#include <assert.h>
-#include <string.h>
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "mod_ssi_expr.h"
-#include "buffer.h"
-}
-
-%parse_failure {
- ctx->ok = 0;
-}
-
-%type expr { ssi_val_t * }
-%type value { buffer * }
-%type exprline { ssi_val_t * }
-%type cond { int }
-%token_destructor { buffer_free($$); }
-
-%left AND.
-%left OR.
-%nonassoc EQ NE GT GE LT LE.
-%right NOT.
-
-input ::= exprline(B). {
- ctx->val.bo = ssi_val_tobool(B);
- ctx->val.type = SSI_TYPE_BOOL;
-
- ssi_val_free(B);
-}
-
-exprline(A) ::= expr(B) cond(C) expr(D). {
- int cmp;
-
- if (B->type == SSI_TYPE_STRING &&
- D->type == SSI_TYPE_STRING) {
- cmp = strcmp(B->str->ptr, D->str->ptr);
- } else {
- cmp = ssi_val_tobool(B) - ssi_val_tobool(D);
- }
-
- A = B;
-
- switch(C) {
- case SSI_COND_EQ: A->bo = (cmp == 0) ? 1 : 0; break;
- case SSI_COND_NE: A->bo = (cmp != 0) ? 1 : 0; break;
- case SSI_COND_GE: A->bo = (cmp >= 0) ? 1 : 0; break;
- case SSI_COND_GT: A->bo = (cmp > 0) ? 1 : 0; break;
- case SSI_COND_LE: A->bo = (cmp <= 0) ? 1 : 0; break;
- case SSI_COND_LT: A->bo = (cmp < 0) ? 1 : 0; break;
- }
-
- A->type = SSI_TYPE_BOOL;
-
- ssi_val_free(D);
-}
-exprline(A) ::= expr(B). {
- A = B;
-}
-expr(A) ::= expr(B) AND expr(C). {
- int e;
-
- e = ssi_val_tobool(B) && ssi_val_tobool(C);
-
- A = B;
- A->bo = e;
- A->type = SSI_TYPE_BOOL;
- ssi_val_free(C);
-}
-
-expr(A) ::= expr(B) OR expr(C). {
- int e;
-
- e = ssi_val_tobool(B) || ssi_val_tobool(C);
-
- A = B;
- A->bo = e;
- A->type = SSI_TYPE_BOOL;
- ssi_val_free(C);
-}
-
-expr(A) ::= NOT expr(B). {
- int e;
-
- e = !ssi_val_tobool(B);
-
- A = B;
- A->bo = e;
- A->type = SSI_TYPE_BOOL;
-}
-expr(A) ::= LPARAN exprline(B) RPARAN. {
- A = B;
-}
-
-expr(A) ::= value(B). {
- A = ssi_val_init();
- A->str = B;
- A->type = SSI_TYPE_STRING;
-}
-
-value(A) ::= VALUE(B). {
- A = B;
-}
-
-value(A) ::= value(B) VALUE(C). {
- A = B;
- buffer_append_string_buffer(A, C);
- buffer_free(C);
-}
-
-cond(A) ::= EQ. { A = SSI_COND_EQ; }
-cond(A) ::= NE. { A = SSI_COND_NE; }
-cond(A) ::= LE. { A = SSI_COND_LE; }
-cond(A) ::= GE. { A = SSI_COND_GE; }
-cond(A) ::= LT. { A = SSI_COND_LT; }
-cond(A) ::= GT. { A = SSI_COND_GT; }
diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c
deleted file mode 100644
index 1be1d594..00000000
--- a/src/mod_staticfile.c
+++ /dev/null
@@ -1,552 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "stat_cache.h"
-#include "etag.h"
-#include "response.h"
-
-#include "sys-files.h"
-#include "sys-strings.h"
-
-#include "http_req_range.h"
-/**
- * this is a staticfile for a lighttpd plugin
- *
- */
-
-
-
-/* plugin config for all request/connections */
-
-typedef struct {
- array *exclude_ext;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *range_buf;
-
- http_req_range *ranges;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_staticfile_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->range_buf = buffer_init();
-
- p->ranges = http_request_range_init();
-
- return p;
-}
-
-/* destroy the plugin data */
-FREE_FUNC(mod_staticfile_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- array_free(s->exclude_ext);
-
- free(s);
- }
- free(p->config_storage);
- }
- buffer_free(p->range_buf);
-
- http_request_range_free(p->ranges);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->exclude_ext = array_init();
-
- cv[0].destination = s->exclude_ext;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(exclude_ext);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
- PATCH_OPTION(exclude_ext);
- }
- }
- }
-
- return 0;
-}
-
-static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
- int multipart = 0;
- char *boundary = "fkj49sn38dcn3";
- data_string *ds;
- stat_cache_entry *sce = NULL;
- buffer *content_type = NULL;
- buffer *range = NULL;
- http_req_range *ranges, *r;
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Range")))) {
- range = ds->value;
- } else {
- /* we don't have a Range header */
-
- return -1;
- }
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- SEGFAULT("stat_cache_get_entry(%s) returned %d", SAFE_BUF_STR(con->physical.path), HANDLER_ERROR);
- }
-
- con->response.content_length = 0;
-
- if (NULL != (ds = (data_string *)array_get_element(con->response.headers, CONST_STR_LEN("Content-Type")))) {
- content_type = ds->value;
- }
-
- /* start the range-header parser
- * bytes=<num> */
-
- ranges = p->ranges;
- http_request_range_reset(ranges);
- switch (http_request_range_parse(range, ranges)) {
- case PARSE_ERROR:
- return -1; /* no range valid Range Header */
- case PARSE_SUCCESS:
- break;
- default:
- TRACE("%s", "foobar");
- return -1;
- }
-
- if (ranges->next) {
- multipart = 1;
- }
-
- /* patch the '-1' */
- for (r = ranges; r; r = r->next) {
- if (r->start == -1) {
- /* -<end>
- *
- * the last <end> bytes */
- r->start = sce->st.st_size - r->end;
- r->end = sce->st.st_size - 1;
- }
- if (r->end == -1) {
- /* <start>-
- * all but the first <start> bytes */
-
- r->end = sce->st.st_size - 1;
- }
-
- if (r->end > sce->st.st_size - 1) {
- /* RFC 2616 - 14.35.1
- *
- * if last-byte-pos not present or > size-of-file
- * take the size-of-file
- *
- * */
- r->end = sce->st.st_size - 1;
- }
-
- if (r->start > sce->st.st_size - 1) {
- /* RFC 2616 - 14.35.1
- *
- * if first-byte-pos > file-size, 416
- */
-
- con->http_status = 416;
- return -1;
- }
-
- if (r->start > r->end) {
- /* RFC 2616 - 14.35.1
- *
- * if last-byte-pos is present, it has to be >= first-byte-pos
- *
- * invalid ranges have to be handle as no Range specified
- * */
-
- return -1;
- }
- }
-
- if (r) {
- /* we ran into an range violation */
- return -1;
- }
-
- if (multipart) {
- buffer *b;
- for (r = ranges; r; r = r->next) {
- /* write boundary-header */
-
- b = chunkqueue_get_append_buffer(con->send);
-
- buffer_copy_string_len(b, CONST_STR_LEN("\r\n--"));
- buffer_append_string(b, boundary);
-
- /* write Content-Range */
- buffer_append_string_len(b, CONST_STR_LEN("\r\nContent-Range: bytes "));
- buffer_append_off_t(b, r->start);
- buffer_append_string_len(b, CONST_STR_LEN("-"));
- buffer_append_off_t(b, r->end);
- buffer_append_string_len(b, CONST_STR_LEN("/"));
- buffer_append_off_t(b, sce->st.st_size);
-
- buffer_append_string_len(b, CONST_STR_LEN("\r\nContent-Type: "));
- buffer_append_string_buffer(b, content_type);
-
- /* write END-OF-HEADER */
- buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
-
- con->response.content_length += b->used - 1;
- con->send->bytes_in += b->used - 1;
-
- chunkqueue_append_file(con->send, con->physical.path, r->start, r->end - r->start + 1);
- con->response.content_length += r->end - r->start + 1;
- con->send->bytes_in += r->end - r->start + 1;
- }
-
- /* add boundary end */
- b = chunkqueue_get_append_buffer(con->send);
-
- buffer_copy_string_len(b, "\r\n--", 4);
- buffer_append_string(b, boundary);
- buffer_append_string_len(b, "--\r\n", 4);
-
- con->response.content_length += b->used - 1;
- con->send->bytes_in += b->used - 1;
-
- /* set header-fields */
-
- buffer_copy_string_len(p->range_buf, CONST_STR_LEN("multipart/byteranges; boundary="));
- buffer_append_string(p->range_buf, boundary);
-
- /* overwrite content-type */
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
-
- } else {
- r = ranges;
-
- chunkqueue_append_file(con->send, con->physical.path, r->start, r->end - r->start + 1);
- con->response.content_length += r->end - r->start + 1;
- con->send->bytes_in += r->end - r->start + 1;
-
- buffer_copy_string_len(p->range_buf, CONST_STR_LEN("bytes "));
- buffer_append_off_t(p->range_buf, r->start);
- buffer_append_string_len(p->range_buf, CONST_STR_LEN("-"));
- buffer_append_off_t(p->range_buf, r->end);
- buffer_append_string_len(p->range_buf, CONST_STR_LEN("/"));
- buffer_append_off_t(p->range_buf, sce->st.st_size);
-
- response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
- }
-
- /* ok, the file is set-up */
- return 0;
-}
-
-URIHANDLER_FUNC(mod_staticfile_subrequest) {
- plugin_data *p = p_d;
- size_t k;
- int s_len;
- stat_cache_entry *sce = NULL;
- buffer *mtime;
- data_string *ds;
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "checking file for static file");
- }
-
-
- /* someone else has done a decision for us */
- if (con->http_status != 0) return HANDLER_GO_ON;
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
- if (con->physical.path->used == 0) return HANDLER_GO_ON;
-
- /* someone else has handled this request */
- if (con->mode != DIRECT) return HANDLER_GO_ON;
-
- /* we only handle GET, POST and HEAD */
- switch(con->request.http_method) {
- case HTTP_METHOD_GET:
- case HTTP_METHOD_POST:
- case HTTP_METHOD_HEAD:
- break;
- default:
- return HANDLER_GO_ON;
- }
-
- mod_staticfile_patch_connection(srv, con, p);
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "handling file as static file");
- }
-
-
- s_len = con->uri.path->used - 1;
-
- /* ignore certain extensions */
- for (k = 0; k < p->conf.exclude_ext->used; k++) {
- ds = (data_string *)p->conf.exclude_ext->data[k];
-
- if (ds->value->used == 0) continue;
-
- if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
- if (con->conf.log_request_handling) {
- TRACE("'%s' matched exclude(%s), sending 403",
- SAFE_BUF_STR(con->physical.path),
- SAFE_BUF_STR(ds->value));
- }
-
- con->http_status = 403;
-
- return HANDLER_FINISHED;
- }
- }
-
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- con->http_status = 403;
-
- log_error_write(srv, __FILE__, __LINE__, "sbsb",
- "not a regular file:", con->uri.path,
- "->", con->physical.path);
-
- return HANDLER_FINISHED;
- }
-
- /* we only handle regular files */
-#ifdef HAVE_LSTAT
- if ((sce->is_symlink == 1) && !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
- if (!S_ISREG(sce->st.st_mode)) {
- con->http_status = 404;
-
- if (con->conf.log_file_not_found) {
- log_error_write(srv, __FILE__, __LINE__, "sbsb",
- "not a regular file:", con->uri.path,
- "->", sce->name);
- }
-
- return HANDLER_FINISHED;
- }
-
- /* mod_compress might set several parameters directly; don't overwrite them */
-
- /* set response content-type, if not set already */
-
- if (NULL == array_get_element(con->response.headers, CONST_STR_LEN("Content-Type"))) {
- if (buffer_is_empty(sce->content_type)) {
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("application/octet-stream"));
- } else {
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
- }
- }
-
- if (NULL == array_get_element(con->response.headers, CONST_STR_LEN("ETag"))) {
- /* generate e-tag */
- etag_mutate(con->physical.etag, sce->etag);
-
- response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
- }
- if (con->conf.range_requests) {
- response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
- }
-
- /* prepare header */
- if (NULL == (ds = (data_string *)array_get_element(con->response.headers, CONST_STR_LEN("Last-Modified")))) {
- mtime = strftime_cache_get(srv, sce->st.st_mtime);
- response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
- } else {
- mtime = ds->value;
- }
-
- if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
- return HANDLER_FINISHED;
- } else if (con->conf.range_requests &&
- NULL != array_get_element(con->request.headers, CONST_STR_LEN("Range"))) {
- int do_range_request = 1;
- /* check if we have a conditional GET */
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("If-Range")))) {
- /* 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)) {
- do_range_request = 0;
- }
- }
-
- if (do_range_request) {
- /* content prepared, I'm done */
- con->send->is_closed = 1;
-
- if (0 == http_response_parse_range(srv, con, p)) {
- con->http_status = 206;
- }
- return HANDLER_FINISHED;
- }
- }
-
- /* if we are still here, prepare body */
-
- /* we add it here for all requests
- * the HEAD request will drop it afterwards again
- */
- chunkqueue_append_file(con->send, con->physical.path, 0, sce->st.st_size);
-
- con->send->is_closed = 1;
- con->send->bytes_in = sce->st.st_size;
-
- return HANDLER_FINISHED;
-}
-
-/**
- * mark all the content as read
- */
-CONNECTION_FUNC(mod_staticfile_dev_null) {
- chunk *c;
- chunkqueue *in = con->recv;
-
- UNUSED(srv);
- UNUSED(p_d);
-
- if (con->mode != DIRECT) return HANDLER_GO_ON;
-
- /* there is nothing that we have to send out anymore */
- if (in->bytes_in == in->bytes_out &&
- in->is_closed) return HANDLER_GO_ON;
-
- for (c = in->first; in->bytes_out < in->bytes_in; c = c->next) {
- off_t weWant = in->bytes_in - in->bytes_out;
- off_t weHave = 0;
-
- /* we announce toWrite octects
- * now take all the request_content chunk that we need to fill this request
- */
-
- switch (c->type) {
- case FILE_CHUNK:
- weHave = c->file.length - c->offset;
-
- if (weHave > weWant) weHave = weWant;
-
- c->offset += weHave;
- in->bytes_out += weHave;
-
- break;
- case MEM_CHUNK:
- /* append to the buffer */
- weHave = c->mem->used - 1 - c->offset;
-
- if (weHave > weWant) weHave = weWant;
-
- c->offset += weHave;
- in->bytes_out += weHave;
-
- break;
- default:
- break;
- }
- }
-
- return HANDLER_GO_ON;
-
-}
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_staticfile_plugin_init(plugin *p);
-LI_EXPORT int mod_staticfile_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("staticfile");
-
- p->init = mod_staticfile_init;
- p->handle_start_backend = mod_staticfile_subrequest;
- p->handle_send_request_content = mod_staticfile_dev_null;
- p->set_defaults = mod_staticfile_set_defaults;
- p->cleanup = mod_staticfile_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_status.c b/src/mod_status.c
deleted file mode 100644
index 459db41c..00000000
--- a/src/mod_status.c
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined.
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#include <sys/types.h>
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <stdio.h>
-
-#include "server.h"
-#include "connections.h"
-#include "response.h"
-#include "connections.h"
-#include "log.h"
-#include "status_counter.h"
-#include "network_backends.h"
-
-#include "plugin.h"
-
-#include "inet_ntop_cache.h"
-
-typedef struct {
- buffer *config_url;
- buffer *status_url;
- buffer *statistics_url;
-
- int sort;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- double traffic_out;
- double requests;
-
- double mod_5s_traffic_out[5];
- double mod_5s_requests[5];
- size_t mod_5s_ndx;
-
- double rel_traffic_out;
- double rel_requests;
-
- double abs_traffic_out;
- double abs_requests;
-
- double bytes_written;
-
- buffer *tmp_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-INIT_FUNC(mod_status_init) {
- plugin_data *p;
- size_t i;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->traffic_out = p->requests = 0;
- p->rel_traffic_out = p->rel_requests = 0;
- p->abs_traffic_out = p->abs_requests = 0;
- p->bytes_written = 0;
- p->tmp_buf = buffer_init();
-
- for (i = 0; i < 5; i++) {
- p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
- }
-
- return p;
-}
-
-FREE_FUNC(mod_status_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- buffer_free(p->tmp_buf);
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- buffer_free(s->status_url);
- buffer_free(s->statistics_url);
- buffer_free(s->config_url);
-
- free(s);
- }
- free(p->config_storage);
- }
-
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-SETDEFAULTS_FUNC(mod_status_set_defaults) {
- plugin_data *p = p_d;
- size_t i;
-
- config_values_t cv[] = {
- { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
- { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->config_url = buffer_init();
- s->status_url = buffer_init();
- s->sort = 1;
- s->statistics_url = buffer_init();
-
- cv[0].destination = s->status_url;
- cv[1].destination = s->config_url;
- cv[2].destination = &(s->sort);
- cv[3].destination = s->statistics_url;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-
-
-static int mod_status_row_append(buffer *b, const char *key, const char *value) {
- buffer_append_string_len(b, CONST_STR_LEN(" <tr>\n"));
- buffer_append_string_len(b, CONST_STR_LEN(" <td><b>"));
- buffer_append_string(b, key);
- buffer_append_string_len(b, CONST_STR_LEN("</b></td>\n"));
- buffer_append_string_len(b, CONST_STR_LEN(" <td>"));
- buffer_append_string(b, value);
- buffer_append_string_len(b, CONST_STR_LEN("</td>\n"));
- buffer_append_string_len(b, CONST_STR_LEN(" </tr>\n"));
-
- return 0;
-}
-
-static int mod_status_header_append(buffer *b, const char *key) {
- buffer_append_string_len(b, CONST_STR_LEN(" <tr>\n"));
- buffer_append_string_len(b, CONST_STR_LEN(" <th colspan=\"2\">"));
- buffer_append_string(b, key);
- buffer_append_string_len(b, CONST_STR_LEN("</th>\n"));
- buffer_append_string_len(b, CONST_STR_LEN(" </tr>\n"));
-
- return 0;
-}
-
-static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
- plugin_data *p = p_d;
-
- if (p->conf.sort) {
- buffer_append_string_len(b, CONST_STR_LEN("<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">"));
- buffer_append_string(b, key);
- buffer_append_string_len(b, CONST_STR_LEN("<span class=\"sortarrow\">:</span></a></th>\n"));
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("<th class=\"status\">"));
- buffer_append_string(b, key);
- buffer_append_string_len(b, CONST_STR_LEN("</th>\n"));
- }
-
- return 0;
-}
-
-static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
- *multiplier = ' ';
-
- if (*avg > size) { *avg /= size; *multiplier = 'k'; }
- if (*avg > size) { *avg /= size; *multiplier = 'M'; }
- if (*avg > size) { *avg /= size; *multiplier = 'G'; }
- if (*avg > size) { *avg /= size; *multiplier = 'T'; }
- if (*avg > size) { *avg /= size; *multiplier = 'P'; }
- if (*avg > size) { *avg /= size; *multiplier = 'E'; }
- if (*avg > size) { *avg /= size; *multiplier = 'Z'; }
- if (*avg > size) { *avg /= size; *multiplier = 'Y'; }
-
- return 0;
-}
-
-static handler_t mod_status_handle_server_status_html(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
- buffer *b;
- size_t j;
- double avg;
- char multiplier = '\0';
- char buf[128];
- time_t ts;
-
- int days, hours, mins, seconds;
-
- b = chunkqueue_get_append_buffer(con->send);
-
- buffer_copy_string_len(b, CONST_STR_LEN(
- "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
- " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
- "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
- " <head>\n"
- " <title>Status</title>\n"
-
- " <style type=\"text/css\">\n"
- " table.status { border: black solid thin; }\n"
- " td { white-space: nowrap; }\n"
- " td.int { background-color: #f0f0f0; text-align: right }\n"
- " td.string { background-color: #f0f0f0; text-align: left }\n"
- " th.status { background-color: black; color: white; font-weight: bold; }\n"
- " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
- " span.sortarrow { color: white; text-decoration: none; }\n"
- " </style>\n"));
-
- if (p->conf.sort) {
- buffer_append_string_len(b, CONST_STR_LEN(
- "<script type=\"text/javascript\">\n"
- "// <!--\n"
- "var sort_column;\n"
- "var prev_span = null;\n"
-
- "function get_inner_text(el) {\n"
- " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
- " return el;\n"
- " if(el.innerText)\n"
- " return el.innerText;\n"
- " else {\n"
- " var str = \"\";\n"
- " var cs = el.childNodes;\n"
- " var l = cs.length;\n"
- " for (i=0;i<l;i++) {\n"
- " if (cs[i].nodeType==1) str += get_inner_text(cs[i]);\n"
- " else if (cs[i].nodeType==3) str += cs[i].nodeValue;\n"
- " }\n"
- " }\n"
- " return str;\n"
- "}\n"
-
- "function sortfn(a,b) {\n"
- " var at = get_inner_text(a.cells[sort_column]);\n"
- " var bt = get_inner_text(b.cells[sort_column]);\n"
- " if (a.cells[sort_column].className == 'int') {\n"
- " return parseInt(at)-parseInt(bt);\n"
- " } else {\n"
- " aa = at.toLowerCase();\n"
- " bb = bt.toLowerCase();\n"
- " if (aa==bb) return 0;\n"
- " else if (aa<bb) return -1;\n"
- " else return 1;\n"
- " }\n"
- "}\n"
-
- "function resort(lnk) {\n"
- " var span = lnk.childNodes[1];\n"
- " var table = lnk.parentNode.parentNode.parentNode.parentNode;\n"
- " var rows = new Array();\n"
- " for (j=1;j<table.rows.length;j++)\n"
- " rows[j-1] = table.rows[j];\n"
- " sort_column = lnk.parentNode.cellIndex;\n"
- " rows.sort(sortfn);\n"
-
- " if (prev_span != null) prev_span.innerHTML = '';\n"
- " if (span.getAttribute('sortdir')=='down') {\n"
- " span.innerHTML = '&uarr;';\n"
- " span.setAttribute('sortdir','up');\n"
- " rows.reverse();\n"
- " } else {\n"
- " span.innerHTML = '&darr;';\n"
- " span.setAttribute('sortdir','down');\n"
- " }\n"
- " for (i=0;i<rows.length;i++)\n"
- " table.tBodies[0].appendChild(rows[i]);\n"
- " prev_span = span;\n"
- "}\n"
- "// -->\n"
- "</script>\n"));
- }
-
- buffer_append_string_len(b, CONST_STR_LEN(
- " </head>\n"
- " <body>\n"));
-
-
-
- /* connection listing */
- buffer_append_string_len(b, CONST_STR_LEN("<h1>Server-Status</h1>"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<table class=\"status\" id=\"status\" summary=\"Server Status\">"));
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">"));
- buffer_append_string_buffer(b, con->uri.authority);
- buffer_append_string_len(b, CONST_STR_LEN("</span> (<span id=\"host_name\">"));
- buffer_append_string_buffer(b, con->server_name);
- buffer_append_string_len(b, CONST_STR_LEN("</span>)</td></tr>\n"));
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">"));
-
- ts = srv->cur_ts - srv->startup_ts;
-
- days = ts / (60 * 60 * 24);
- ts %= (60 * 60 * 24);
-
- hours = ts / (60 * 60);
- ts %= (60 * 60);
-
- mins = ts / (60);
- ts %= (60);
-
- seconds = ts;
-
- if (days) {
- buffer_append_long(b, days);
- buffer_append_string_len(b, CONST_STR_LEN(" days "));
- }
-
- if (hours) {
- buffer_append_long(b, hours);
- buffer_append_string_len(b, CONST_STR_LEN(" hours "));
- }
-
- if (mins) {
- buffer_append_long(b, mins);
- buffer_append_string_len(b, CONST_STR_LEN(" min "));
- }
-
- buffer_append_long(b, seconds);
- buffer_append_string_len(b, CONST_STR_LEN(" s"));
-
- buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Started at</td><td class=\"string\">"));
-
- ts = srv->startup_ts;
-
- strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
- buffer_append_string(b, buf);
- buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
-
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">absolute (since start)</th></tr>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">"));
- avg = p->abs_requests;
-
- mod_status_get_multiplier(&avg, &multiplier, 1000);
-
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("</span> <span id=\"requests_mult\">"));
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
- buffer_append_string_len(b, CONST_STR_LEN("</span>req</td></tr>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">"));
- avg = p->abs_traffic_out;
-
- mod_status_get_multiplier(&avg, &multiplier, 1024);
-
- sprintf(buf, "%.2f", avg);
- buffer_append_string(b, buf);
- buffer_append_string_len(b, CONST_STR_LEN("</span> <span id=\"traffic_mult\">"));
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
- buffer_append_string_len(b, CONST_STR_LEN("</span>byte</td></tr>\n"));
-
-
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">average (since start)</th></tr>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">"));
- avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
-
- mod_status_get_multiplier(&avg, &multiplier, 1000);
-
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("</span> <span id=\"requests_avg_mult\">"));
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
- buffer_append_string_len(b, CONST_STR_LEN("</span>req/s</td></tr>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">"));
- avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
-
- mod_status_get_multiplier(&avg, &multiplier, 1024);
-
- sprintf(buf, "%.2f", avg);
- buffer_append_string(b, buf);
- buffer_append_string_len(b, CONST_STR_LEN("</span> <span id=\"traffic_avg_mult\">"));
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
- buffer_append_string_len(b, CONST_STR_LEN("</span>byte/s</td></tr>\n"));
-
-
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n"));
- for (j = 0, avg = 0; j < 5; j++) {
- avg += p->mod_5s_requests[j];
- }
-
- avg /= 5;
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">"));
-
- mod_status_get_multiplier(&avg, &multiplier, 1000);
-
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("</span> <span id=\"requests_sliding_avg_mult\">"));
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
-
- buffer_append_string_len(b, CONST_STR_LEN("</span>req/s</td></tr>\n"));
-
- for (j = 0, avg = 0; j < 5; j++) {
- avg += p->mod_5s_traffic_out[j];
- }
-
- avg /= 5;
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">"));
-
- mod_status_get_multiplier(&avg, &multiplier, 1024);
-
- sprintf(buf, "%.2f", avg);
- buffer_append_string(b, buf);
- buffer_append_string_len(b, CONST_STR_LEN("</span> <span id=\"requests_sliding_traffic_mult\">"));
- if (multiplier) buffer_append_string_len(b, &multiplier, 1);
- buffer_append_string_len(b, CONST_STR_LEN("</span>byte/s</td></tr>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("</table>\n"));
-
-
- buffer_append_string_len(b, CONST_STR_LEN("<hr />\n<pre><b>legend</b>\n"));
- buffer_append_string_len(b, CONST_STR_LEN(". = connect, C = close, E = hard error\n"));
- buffer_append_string_len(b, CONST_STR_LEN("r = read, R = read-POST, W = write, h = handle-request\n"));
- buffer_append_string_len(b, CONST_STR_LEN("q = request-start, Q = request-end\n"));
- buffer_append_string_len(b, CONST_STR_LEN("s = response-start, S = response-end\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<strong><span id=\"connections\">"));
- buffer_append_long(b, srv->conns->used);
- buffer_append_string_len(b, CONST_STR_LEN("</span> connections</strong>\n"));
-
- for (j = 0; j < srv->conns->used; j++) {
- connection *c = srv->conns->ptr[j];
- const char *state = connection_get_short_state(c->state);
-
- buffer_append_string_len(b, state, 1);
-
- if (((j + 1) % 50) == 0) {
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
- }
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("\n</pre><hr />\n<h2>Connections</h2>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n"));
- buffer_append_string_len(b, CONST_STR_LEN("<tr>"));
- mod_status_header_append_sort(b, p_d, "Client IP");
- mod_status_header_append_sort(b, p_d, "Read");
- mod_status_header_append_sort(b, p_d, "Written");
- mod_status_header_append_sort(b, p_d, "State");
- mod_status_header_append_sort(b, p_d, "Time");
- mod_status_header_append_sort(b, p_d, "Host");
- mod_status_header_append_sort(b, p_d, "URI");
- mod_status_header_append_sort(b, p_d, "File");
- buffer_append_string_len(b, CONST_STR_LEN("</tr>\n"));
-
- for (j = 0; j < srv->conns->used; j++) {
- connection *c = srv->conns->ptr[j];
-
- buffer_append_string_len(b, CONST_STR_LEN("<tr><td class=\"string ip\">"));
-
- buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
-
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int bytes_read\">"));
-
- if (c->request.content_length != -1) {
- buffer_append_long(b, c->recv->bytes_in);
- buffer_append_string_len(b, CONST_STR_LEN("/"));
- buffer_append_long(b, c->request.content_length);
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("0/0"));
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int bytes_written\">"));
-
- buffer_append_off_t(b, c->send_raw->bytes_out);
- buffer_append_string_len(b, CONST_STR_LEN("/"));
- buffer_append_off_t(b, c->send_raw->bytes_in);
-
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string state\">"));
-
- buffer_append_string(b, connection_get_state(c->state));
-
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"int time\">"));
-
- buffer_append_long(b, srv->cur_ts - c->request_start);
-
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string host\">"));
-
- if (buffer_is_empty(c->server_name)) {
- buffer_append_string_buffer(b, c->uri.authority);
- }
- else {
- buffer_append_string_buffer(b, c->server_name);
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string uri\">"));
-
- if (!buffer_is_empty(c->uri.path)) {
- buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
- }
-
- if (!buffer_is_empty(c->uri.query)) {
- buffer_append_string_len(b, CONST_STR_LEN("?"));
- buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.query), ENCODING_HTML);
- }
-
- if (!buffer_is_empty(c->request.orig_uri)) {
- buffer_append_string_len(b, CONST_STR_LEN(" ("));
- buffer_append_string_encoded(b, CONST_BUF_LEN(c->request.orig_uri), ENCODING_HTML);
- buffer_append_string_len(b, CONST_STR_LEN(")"));
- }
- buffer_append_string_len(b, CONST_STR_LEN("</td><td class=\"string file\">"));
-
- buffer_append_string_buffer(b, c->physical.path);
-
- buffer_append_string_len(b, CONST_STR_LEN("</td></tr>\n"));
- }
-
-
- buffer_append_string_len(b, CONST_STR_LEN(
- "</table>\n"
-
- " </body>\n"
- "</html>\n"
- ));
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
- con->send->bytes_in += b->used-1;
-
- return 0;
-}
-
-
-static handler_t mod_status_handle_server_status_text(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
- buffer *b;
- double avg;
- time_t ts;
- size_t j;
- unsigned int k;
- unsigned int l;
-
- b = chunkqueue_get_append_buffer(con->send);
-
- /* output total number of requests */
- buffer_append_string_len(b, CONST_STR_LEN("Total Accesses: "));
- avg = p->abs_requests;
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* output total traffic out in kbytes */
- buffer_append_string_len(b, CONST_STR_LEN("Total kBytes: "));
- avg = p->abs_traffic_out / 1024;
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* output uptime */
- buffer_append_string_len(b, CONST_STR_LEN("Uptime: "));
- ts = srv->cur_ts - srv->startup_ts;
- buffer_append_long(b, ts);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* output busy servers */
- buffer_append_string_len(b, CONST_STR_LEN("BusyServers: "));
- buffer_append_long(b, srv->conns->used);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN("IdleServers: "));
- buffer_append_long(b, srv->conns->size - srv->conns->used);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* output traffic */
- buffer_append_string_len(b, CONST_STR_LEN("Traffic: "));
- avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* output traffic 5s */
- buffer_append_string_len(b, CONST_STR_LEN("Traffic5s: "));
- for (j = 0, avg = 0; j < 5; j++) {
- avg += p->mod_5s_traffic_out[j];
- }
- avg /= 5;
- buffer_append_long(b, avg);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* output scoreboard */
- buffer_append_string_len(b, CONST_STR_LEN("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_len(b, CONST_STR_LEN("_"));
- }
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
-
- /* set text/plain output */
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
- con->send->bytes_in += b->used-1;
-
- return 0;
-}
-
-static handler_t mod_status_handle_server_statistics(server *srv, connection *con, void *p_d) {
- buffer *b;
- size_t i;
- array *st = status_counter_get_array();
-
- UNUSED(p_d);
-
- if (0 == st->used) {
- /* we have nothing to send */
- con->http_status = 204;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- }
-
- b = chunkqueue_get_append_buffer(con->send);
-
- for (i = 0; i < st->used; i++) {
- size_t ndx = st->sorted[i];
-
- buffer_append_string_buffer(b, st->data[ndx]->key);
- buffer_append_string_len(b, CONST_STR_LEN(": "));
- buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
- buffer_append_string_len(b, CONST_STR_LEN("\n"));
- }
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
-
- con->http_status = 200;
- con->send->bytes_in += b->used-1;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
-}
-
-
-static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
-
- if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
- mod_status_handle_server_status_text(srv, con, p_d);
- } else {
- mod_status_handle_server_status_html(srv, con, p_d);
- }
-
- con->http_status = 200;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
-}
-
-
-static handler_t mod_status_handle_server_config(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
- buffer *b, *tmp_buf = p->tmp_buf;
- size_t i;
- const fdevent_handler_info_t *handler;
- const network_backend_info_t *backend;
-
- b = chunkqueue_get_append_buffer(con->send);
-
- BUFFER_COPY_STRING_CONST(b,
- "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
- " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
- "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
- " <head>\n"
- " <title>Status</title>\n"
- " </head>\n"
- " <body>\n"
- " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
- " <table summary=\"status\" border=\"1\">\n");
-
- mod_status_header_append(b, "Server-Features");
-#ifdef HAVE_PCRE_H
- mod_status_row_append(b, "RegEx Conditionals", "enabled");
-#else
- mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
-#endif
- mod_status_header_append(b, "Network Engine");
-
- mod_status_row_append(b, "fd-Event-Handler", fdevent_get_handler_info_by_type(srv->event_handler)->name);
- buffer_reset(tmp_buf);
- for (handler = fdevent_get_handlers(); handler->name; handler++) {
- if (handler->init) {
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("+ "));
- } else {
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("- "));
- }
-
- buffer_append_string(tmp_buf, handler->name);
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("<br />"));
- }
- mod_status_row_append(b, "Supported fd-Event-Handlers", tmp_buf->ptr);
-
- mod_status_row_append(b, "Network-Backend", network_get_backend_info_by_type(srv->network_backend)->name);
- buffer_reset(tmp_buf);
- for (backend = network_get_backends(); backend->name; backend++) {
- if (backend->write_handler) {
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("+ "));
- } else {
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("- "));
- }
-
- buffer_append_string(tmp_buf, backend->name);
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("<br />"));
- }
-#ifdef USE_MMAP
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("+ (mmap)<br />"));
-#else
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("- (mmap)<br />"));
-#endif
- mod_status_row_append(b, "Supported Network-Backends", tmp_buf->ptr);
-
- mod_status_header_append(b, "Config-File-Settings");
-
- buffer_reset(tmp_buf);
- for (i = 0; i < srv->plugins.used; i++) {
- plugin **ps = srv->plugins.ptr;
-
- plugin *pl = ps[i];
-
- if (i == 0) {
- buffer_copy_string_buffer(tmp_buf, pl->name);
- } else {
- buffer_append_string_len(tmp_buf, CONST_STR_LEN("<br />"));
- buffer_append_string_buffer(tmp_buf, pl->name);
- }
- }
-
- mod_status_row_append(b, "Loaded Modules", tmp_buf->ptr);
-
- buffer_append_string_len(b, CONST_STR_LEN(" </table>\n"));
-
- buffer_append_string_len(b, CONST_STR_LEN(
- " </body>\n"
- "</html>\n"
- ));
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
-
- con->http_status = 200;
- con->send->bytes_in += b->used-1;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
-}
-
-static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(status_url);
- PATCH_OPTION(config_url);
- PATCH_OPTION(sort);
- PATCH_OPTION(statistics_url);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
- PATCH_OPTION(status_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
- PATCH_OPTION(config_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
- PATCH_OPTION(sort);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
- PATCH_OPTION(statistics_url);
- }
- }
- }
-
- return 0;
-}
-
-static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
- plugin_data *p = p_d;
-
- mod_status_patch_connection(srv, con, p);
-
- if (!buffer_is_empty(p->conf.status_url) &&
- buffer_is_equal(p->conf.status_url, con->uri.path)) {
- return mod_status_handle_server_status(srv, con, p_d);
- } else if (!buffer_is_empty(p->conf.config_url) &&
- buffer_is_equal(p->conf.config_url, con->uri.path)) {
- return mod_status_handle_server_config(srv, con, p_d);
- } else if (!buffer_is_empty(p->conf.statistics_url) &&
- buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
- return mod_status_handle_server_statistics(srv, con, p_d);
- }
-
- return HANDLER_GO_ON;
-}
-
-TRIGGER_FUNC(mod_status_trigger) {
- plugin_data *p = p_d;
- size_t i;
-
- /* check all connections */
- for (i = 0; i < srv->conns->used; i++) {
- connection *c = srv->conns->ptr[i];
-
- p->bytes_written += c->bytes_written_cur_second;
- }
-
- /* a sliding average */
- p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
- p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
-
- p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
-
- p->abs_traffic_out += p->bytes_written;
- p->rel_traffic_out += p->bytes_written;
-
- p->bytes_written = 0;
-
- /* reset storage - second */
- p->traffic_out = 0;
- p->requests = 0;
-
- return HANDLER_GO_ON;
-}
-
-REQUESTDONE_FUNC(mod_status_account) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- p->requests++;
- p->rel_requests++;
- p->abs_requests++;
-
- p->bytes_written += con->bytes_written_cur_second;
-
- return HANDLER_GO_ON;
-}
-
-LI_EXPORT int mod_status_plugin_init(plugin *p);
-LI_EXPORT int mod_status_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("status");
-
- p->init = mod_status_init;
- p->cleanup = mod_status_free;
- p->set_defaults= mod_status_set_defaults;
-
- p->handle_uri_clean = mod_status_handler;
- p->handle_trigger = mod_status_trigger;
- p->handle_response_done = mod_status_account;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_trigger_b4_dl.c b/src/mod_trigger_b4_dl.c
deleted file mode 100644
index 2ef3b49f..00000000
--- a/src/mod_trigger_b4_dl.c
+++ /dev/null
@@ -1,589 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-#include "response.h"
-#include "inet_ntop_cache.h"
-
-#if defined(HAVE_GDBM_H)
-#include <gdbm.h>
-#endif
-
-#if defined(HAVE_PCRE_H)
-#include <pcre.h>
-#endif
-
-#if defined(HAVE_MEMCACHE_H)
-#include <memcache.h>
-#endif
-
-/**
- * this is a trigger_b4_dl for a lighttpd plugin
- *
- */
-
-/* plugin config for all request/connections */
-
-typedef struct {
- buffer *db_filename;
-
- buffer *trigger_url;
- buffer *download_url;
- buffer *deny_url;
-
- array *mc_hosts;
- buffer *mc_namespace;
-#if defined(HAVE_PCRE_H)
- pcre *trigger_regex;
- pcre *download_regex;
-#endif
-#if defined(HAVE_GDBM_H)
- GDBM_FILE db;
-#endif
-
-#if defined(HAVE_MEMCACHE_H)
- struct memcache *mc;
-#endif
-
- unsigned short trigger_timeout;
- unsigned short debug;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *tmp_buf;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_trigger_b4_dl_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_trigger_b4_dl_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- buffer_free(s->db_filename);
- buffer_free(s->download_url);
- buffer_free(s->trigger_url);
- buffer_free(s->deny_url);
-
- buffer_free(s->mc_namespace);
- array_free(s->mc_hosts);
-
-#if defined(HAVE_PCRE_H)
- if (s->trigger_regex) pcre_free(s->trigger_regex);
- if (s->download_regex) pcre_free(s->download_regex);
-#endif
-#if defined(HAVE_GDBM_H)
- if (s->db) gdbm_close(s->db);
-#endif
-#if defined(HAVE_MEMCACHE_H)
- if (s->mc) mc_free(s->mc);
-#endif
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
-
- config_values_t cv[] = {
- { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { "trigger-before-download.deny-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { "trigger-before-download.trigger-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
- { "trigger-before-download.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
- { "trigger-before-download.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
- { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-#if defined(HAVE_PCRE_H)
- const char *errptr;
- int erroff;
-#endif
-
- s = calloc(1, sizeof(plugin_config));
- s->db_filename = buffer_init();
- s->download_url = buffer_init();
- s->trigger_url = buffer_init();
- s->deny_url = buffer_init();
- s->mc_hosts = array_init();
- s->mc_namespace = buffer_init();
-
- cv[0].destination = s->db_filename;
- cv[1].destination = s->trigger_url;
- cv[2].destination = s->download_url;
- cv[3].destination = s->deny_url;
- cv[4].destination = &(s->trigger_timeout);
- cv[5].destination = s->mc_hosts;
- cv[6].destination = s->mc_namespace;
- cv[7].destination = &(s->debug);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-#if defined(HAVE_GDBM_H)
- if (!buffer_is_empty(s->db_filename)) {
- if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "gdbm-open failed");
- return HANDLER_ERROR;
- }
- }
-#endif
-#if defined(HAVE_PCRE_H)
- if (!buffer_is_empty(s->download_url)) {
- if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
- 0, &errptr, &erroff, NULL))) {
-
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "compiling regex for download-url failed:",
- s->download_url, "pos:", erroff);
- return HANDLER_ERROR;
- }
- }
-
- if (!buffer_is_empty(s->trigger_url)) {
- if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
- 0, &errptr, &erroff, NULL))) {
-
- log_error_write(srv, __FILE__, __LINE__, "sbss",
- "compiling regex for trigger-url failed:",
- s->trigger_url, "pos:", erroff);
-
- return HANDLER_ERROR;
- }
- }
-#endif
-
- if (s->mc_hosts->used) {
-#if defined(HAVE_MEMCACHE_H)
- size_t k;
- s->mc = mc_new();
-
- for (k = 0; k < s->mc_hosts->used; k++) {
- data_string *ds = (data_string *)s->mc_hosts->data[k];
-
- if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "connection to host failed:",
- ds->value);
-
- return HANDLER_ERROR;
- }
- }
-#else
- log_error_write(srv, __FILE__, __LINE__, "s",
- "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
- return HANDLER_ERROR;
-#endif
- }
-
-
-#if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
- log_error_write(srv, __FILE__, __LINE__, "s",
- "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
- return HANDLER_ERROR;
-#endif
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
-#if defined(HAVE_GDBM)
- PATCH_OPTION(db);
-#endif
-#if defined(HAVE_PCRE_H)
- PATCH_OPTION(download_regex);
- PATCH_OPTION(trigger_regex);
-#endif
- PATCH_OPTION(trigger_timeout);
- PATCH_OPTION(deny_url);
- PATCH_OPTION(mc_namespace);
- PATCH_OPTION(debug);
-#if defined(HAVE_MEMCACHE_H)
- PATCH_OPTION(mc);
-#endif
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
-#if defined(HAVE_PCRE_H)
- PATCH_OPTION(download_regex);
-#endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
-# if defined(HAVE_PCRE_H)
- PATCH_OPTION(trigger_regex);
-# endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
-#if defined(HAVE_GDBM_H)
- PATCH_OPTION(db);
-#endif
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
- PATCH_OPTION(trigger_timeout);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
- PATCH_OPTION(debug);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
- PATCH_OPTION(deny_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
- PATCH_OPTION(mc_namespace);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
-#if defined(HAVE_MEMCACHE_H)
- PATCH_OPTION(mc);
-#endif
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
- plugin_data *p = p_d;
- const char *remote_ip;
- data_string *ds;
-
-#if defined(HAVE_PCRE_H)
- int n;
-# define N 10
- int ovec[N * 3];
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_trigger_b4_dl_patch_connection(srv, con, p);
-
- if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
-
-# if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
- return HANDLER_GO_ON;
-# elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
- if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
- if (p->conf.db && p->conf.mc) {
- /* can't decide which one */
-
- return HANDLER_GO_ON;
- }
-# elif defined(HAVE_GDBM_H)
- if (!p->conf.db) return HANDLER_GO_ON;
-# else
- if (!p->conf.mc) return HANDLER_GO_ON;
-# endif
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("X-Forwarded-For")))) {
- /* X-Forwarded-For contains the ip behind the proxy */
-
- remote_ip = ds->value->ptr;
-
- /* memcache can't handle spaces */
- } else {
- remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
- }
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
- }
-
- /* check if URL is a trigger -> insert IP into DB */
- if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
- if (n != PCRE_ERROR_NOMATCH) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "execution error while matching:", n);
-
- return HANDLER_ERROR;
- }
- } else {
-# if defined(HAVE_GDBM_H)
- if (p->conf.db) {
- /* the trigger matched */
- datum key, val;
-
- key.dptr = (char *)remote_ip;
- key.dsize = strlen(remote_ip);
-
- val.dptr = (char *)&(srv->cur_ts);
- val.dsize = sizeof(srv->cur_ts);
-
- if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "insert failed");
- }
- }
-# endif
-# if defined(HAVE_MEMCACHE_H)
- if (p->conf.mc) {
- size_t i;
- buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
- buffer_append_string(p->tmp_buf, remote_ip);
-
- for (i = 0; i < p->tmp_buf->used - 1; i++) {
- if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
- }
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
- }
-
- if (0 != mc_set(p->conf.mc,
- CONST_BUF_LEN(p->tmp_buf),
- (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
- p->conf.trigger_timeout, 0)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "insert failed");
- }
- }
-# endif
- }
-
- /* check if URL is a download -> check IP in DB, update timestamp */
- if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
- if (n != PCRE_ERROR_NOMATCH) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "execution error while matching: ", n);
- return HANDLER_ERROR;
- }
- } else {
- /* the download uri matched */
-# if defined(HAVE_GDBM_H)
- if (p->conf.db) {
- datum key, val;
- time_t last_hit;
-
- key.dptr = (char *)remote_ip;
- key.dsize = strlen(remote_ip);
-
- val = gdbm_fetch(p->conf.db, key);
-
- if (val.dptr == NULL) {
- /* not found, redirect */
-
- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
-
- con->http_status = 307;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- }
-
- last_hit = *(time_t *)(val.dptr);
-
- free(val.dptr);
-
- if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
- /* found, but timeout, redirect */
-
- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
- con->http_status = 307;
- con->send->is_closed = 1;
-
- if (p->conf.db) {
- if (0 != gdbm_delete(p->conf.db, key)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "delete failed");
- }
- }
-
- return HANDLER_FINISHED;
- }
-
- val.dptr = (char *)&(srv->cur_ts);
- val.dsize = sizeof(srv->cur_ts);
-
- if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "insert failed");
- }
- }
-# endif
-
-# if defined(HAVE_MEMCACHE_H)
- if (p->conf.mc) {
- void *r;
- size_t i;
-
- buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
- buffer_append_string(p->tmp_buf, remote_ip);
-
- for (i = 0; i < p->tmp_buf->used - 1; i++) {
- if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
- }
-
- if (p->conf.debug) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
- }
-
- /**
- *
- * memcached is do expiration for us, as long as we can fetch it every thing is ok
- * and the timestamp is updated
- *
- */
- if (NULL == (r = mc_aget(p->conf.mc,
- CONST_BUF_LEN(p->tmp_buf)
- ))) {
-
- response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
-
- con->http_status = 307;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- }
-
- free(r);
-
- /* set a new timeout */
- if (0 != mc_set(p->conf.mc,
- CONST_BUF_LEN(p->tmp_buf),
- (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
- p->conf.trigger_timeout, 0)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "insert failed");
- }
- }
-# endif
- }
-
-#else
- UNUSED(srv);
- UNUSED(con);
- UNUSED(p_d);
-#endif
-
- return HANDLER_GO_ON;
-}
-
-#if defined(HAVE_GDBM_H)
-TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
- plugin_data *p = p_d;
- size_t i;
-
- /* check DB each minute */
- if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
-
- /* cleanup */
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
- datum key, val, okey;
-
- if (!s->db) continue;
-
- okey.dptr = NULL;
-
- /* according to the manual this loop + delete does delete all entries on its way
- *
- * we don't care as the next round will remove them. We don't have to perfect here.
- */
- for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
- time_t last_hit;
- if (okey.dptr) {
- free(okey.dptr);
- okey.dptr = NULL;
- }
-
- val = gdbm_fetch(s->db, key);
-
- last_hit = *(time_t *)(val.dptr);
-
- free(val.dptr);
-
- if (srv->cur_ts - last_hit > s->trigger_timeout) {
- gdbm_delete(s->db, key);
- }
-
- okey = key;
- }
- if (okey.dptr) free(okey.dptr);
-
- /* reorg once a day */
- if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
- }
- return HANDLER_GO_ON;
-}
-#endif
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_trigger_b4_dl_plugin_init(plugin *p);
-LI_EXPORT int mod_trigger_b4_dl_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("trigger_b4_dl");
-
- p->init = mod_trigger_b4_dl_init;
- p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
- p->set_defaults = mod_trigger_b4_dl_set_defaults;
-#if defined(HAVE_GDBM_H)
- p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
-#endif
- p->cleanup = mod_trigger_b4_dl_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_uploadprogress.c b/src/mod_uploadprogress.c
deleted file mode 100644
index 56423680..00000000
--- a/src/mod_uploadprogress.c
+++ /dev/null
@@ -1,638 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#include "response.h"
-#include "stat_cache.h"
-
-#define CONFIG_UPLOAD_PROGRESS_URL "upload-progress.progress-url"
-#define CONFIG_UPLOAD_PROGRESS_TIMEOUT "upload-progress.remove-timeout"
-#define CONFIG_UPLOAD_PROGRESS_DEBUG "upload-progress.debug"
-
-/**
- * uploadprogress for lighttpd
- *
- * Initial: Jan Kneschke <jan@kneschke.de>
- * Timeout+Status addon: Bjoern Kalkbrenner <terminar@cyberphoria.org> [20070112]
- *
- * the timeout is used to keep in the status information intact even if the parent
- * connection is gone already
- */
-
-typedef struct {
- buffer *tracking_id;
- connection *con;
-
- time_t timeout;
- int status;
- off_t size;
-} connection_map_entry;
-
-typedef struct {
- connection_map_entry **ptr;
-
- size_t used;
- size_t size;
-} connection_map;
-
-/* plugin config for all request/connections */
-
-typedef struct {
- buffer *progress_url;
- unsigned short debug;
- unsigned short remove_timeout;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- connection_map *con_map;
-
- buffer *tmp_buf; /** used as temporary buffer for extracting the tracking id */
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/**
- *
- * connection maps
- *
- */
-
-/* init the plugin data */
-static connection_map *connection_map_init() {
- connection_map *cm;
-
- cm = calloc(1, sizeof(*cm));
-
- return cm;
-}
-
-static void connection_map_free(connection_map *cm) {
- size_t i;
- for (i = 0; i < cm->size; i++) {
- connection_map_entry *cme = cm->ptr[i];
-
- if (!cme) break;
-
- if (cme->tracking_id) {
- buffer_free(cme->tracking_id);
- }
- free(cme);
- }
-
- free(cm);
-}
-
-static connection_map_entry *connection_map_insert(connection_map *cm, buffer *tracking_id, connection *con) {
- connection_map_entry *cme;
- size_t i;
-
- if (cm->size == 0) {
- cm->size = 16;
- cm->ptr = malloc(cm->size * sizeof(*(cm->ptr)));
- for (i = 0; i < cm->size; i++) {
- cm->ptr[i] = NULL;
- }
- } else if (cm->used == cm->size) {
- cm->size += 16;
- cm->ptr = realloc(cm->ptr, cm->size * sizeof(*(cm->ptr)));
- for (i = cm->used; i < cm->size; i++) {
- cm->ptr[i] = NULL;
- }
- }
-
- if (cm->ptr[cm->used]) {
- /* is already alloced, just reuse it */
- cme = cm->ptr[cm->used];
- } else {
- cme = malloc(sizeof(*cme));
- cme->tracking_id = buffer_init();
- }
- cme->timeout = 0;
- cme->status = 0;
- buffer_copy_string_buffer(cme->tracking_id, tracking_id);
- cme->con = con;
-
- cm->ptr[cm->used++] = cme;
-
- return cme;
-}
-
-static connection_map_entry *connection_map_get_connection_entry(connection_map *cm, buffer *tracking_id) {
- size_t i;
-
- for (i = 0; i < cm->used; i++) {
- connection_map_entry *cme = cm->ptr[i];
-
- if (buffer_is_equal(cme->tracking_id, tracking_id)) {
- /* found connection */
- return cme;
- }
- }
- return NULL;
-}
-
-static void connection_map_remove_connection(connection_map *cm, size_t i) {
- connection_map_entry *cme = cm->ptr[i];
-
- buffer_reset(cme->tracking_id);
- cme->timeout=0;
- cme->status=0;
-
- cm->used--;
-
- /* swap positions with the last entry */
- if (cm->used) {
- cm->ptr[i] = cm->ptr[cm->used];
- cm->ptr[cm->used] = cme;
- }
-}
-
-/**
- * remove dead tracking IDs
- *
- * uploadprogress.remove-timeout sets a grace-period in which the
- * connection status is still known even of the connection is already
- * being removed
- *
- */
-static void connection_map_clear_timeout_connections(connection_map *cm) {
- size_t i;
- time_t now_t = time(NULL);
-
- for (i = 0; i < cm->used; i++) {
- connection_map_entry *cme = cm->ptr[i];
-
- if (cme->timeout != 0 && cme->timeout < now_t) {
- /* found connection */
- connection_map_remove_connection(cm, i);
- }
- }
-}
-
-/**
- * extract the tracking-id from the parameters
- *
- * for POST requests it is part of the request headers
- * for GET requests ... too
- */
-static buffer *get_tracking_id(plugin_data *p, connection *con) {
- data_string *ds;
- buffer *b = NULL;
- char *qstr=NULL;
- size_t i;
-
- /* the request has to contain a 32byte ID */
- if (NULL == (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("X-Progress-ID")))) {
- char *amp = NULL;
-
- /* perhaps the POST request is using the querystring to pass the X-Progress-ID */
- if (buffer_is_empty(con->uri.query)) {
- /*
- * con->uri.query will not be parsed out if a 413 error happens
- */
- if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
- /** extract query string from request.uri */
- buffer_copy_string(con->uri.query, qstr + 1);
- } else {
- return NULL;
- }
- }
-
- /** split the query-string and extract the X-Progress-ID */
- do {
- char *eq = NULL;
- char *start = amp ? amp + 1 : con->uri.query->ptr;
-
- amp = strchr(start, '&');
-
- /* check the string between start and amp for = */
-
- if (amp) {
- buffer_copy_string_len(p->tmp_buf, start, amp - start);
- } else {
- buffer_copy_string(p->tmp_buf, start);
- }
-
- eq = strchr(p->tmp_buf->ptr, '=');
-
- if (eq) {
- *eq = '\0';
-
- if (0 == strcmp(p->tmp_buf->ptr, "X-Progress-ID")) {
- size_t key_len = sizeof("X-Progress-ID") - 1;
- size_t var_len = p->tmp_buf->used - 1;
- /* found */
-
- buffer_copy_string_len(p->tmp_buf, start + key_len + 1, var_len - key_len - 1);
-
- b = p->tmp_buf;
-
- break;
- }
- }
- } while (amp);
-
- if (!b) return NULL;
- } else {
- /* request header was found, use it */
- b = ds->value;
- }
-
- if (b->used != 32 + 1) {
- if (p->conf.debug) ERROR("the Progress-ID has to be 32 characters long, got %zd characters", b->used - 1);
- return NULL;
- }
-
- for (i = 0; i < b->used - 1; i++) {
- char c = b->ptr[i];
-
- if (!light_isxdigit(c)) {
- if (p->conf.debug) ERROR("only hex-digits are allowed (0-9 + a-f): (ascii: %d)", c);
- return NULL;
- }
- }
-
- return b;
-}
-
-/* init the plugin data */
-INIT_FUNC(mod_uploadprogress_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->con_map = connection_map_init();
- p->tmp_buf = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_uploadprogress_free) {
- plugin_data *p = p_d;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- buffer_free(s->progress_url);
- s->remove_timeout=0;
-
- free(s);
- }
- free(p->config_storage);
- }
-
- connection_map_free(p->con_map);
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_uploadprogress_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { CONFIG_UPLOAD_PROGRESS_URL, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { CONFIG_UPLOAD_PROGRESS_TIMEOUT, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { CONFIG_UPLOAD_PROGRESS_DEBUG, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->progress_url = buffer_init();
- s->remove_timeout = 60;
- s->debug = 0;
-
- cv[0].destination = s->progress_url;
- cv[1].destination = &(s->remove_timeout);
- cv[2].destination = &(s->debug);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_uploadprogress_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(progress_url);
- PATCH_OPTION(remove_timeout);
- PATCH_OPTION(debug);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_UPLOAD_PROGRESS_URL))) {
- PATCH_OPTION(progress_url);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_UPLOAD_PROGRESS_TIMEOUT))) {
- PATCH_OPTION(remove_timeout);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_UPLOAD_PROGRESS_DEBUG))) {
- PATCH_OPTION(debug);
- }
- }
- }
-
- return 0;
-}
-
-/**
- *
- * the idea:
- *
- * for the first request we check if it is a post-request
- *
- * if no, move out, don't care about them
- *
- * if yes, take the connection structure and register it locally
- * in the progress-struct together with an session-id (md5 ... )
- *
- * if the connections closes, cleanup the entry in the progress-struct
- *
- * a second request can now get the info about the size of the upload,
- * the received bytes
- *
- */
-
-URIHANDLER_FUNC(mod_uploadprogress_uri_handler) {
- plugin_data *p = p_d;
- buffer *tracking_id;
- buffer *b;
- connection_map_entry *post_con_entry = NULL;
- connection_map_entry *map_con_entry = NULL;
-
- if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
-
- mod_uploadprogress_patch_connection(srv, con, p);
-
- /* no progress URL set, ignore request */
- if (buffer_is_empty(p->conf.progress_url)) return HANDLER_GO_ON;
-
- switch(con->request.http_method) {
- case HTTP_METHOD_POST:
- /**
- * a POST request is the UPLOAD itself
- *
- * get the unique tracker id
- */
- if (NULL == (tracking_id = get_tracking_id(p, con))) {
- return HANDLER_GO_ON;
- }
-
- if (NULL == (map_con_entry = connection_map_get_connection_entry(p->con_map, tracking_id))) {
- connection_map_insert(p->con_map, tracking_id, con);
-
- if (p->conf.debug) TRACE("POST: connection is new, registered: %s", SAFE_BUF_STR(tracking_id));
- } else {
- map_con_entry->timeout = 0;
- map_con_entry->status = 0;
-
- if (p->conf.debug) TRACE("POST: connection is known, id: %s", SAFE_BUF_STR(tracking_id));
- }
-
- return HANDLER_GO_ON;
- case HTTP_METHOD_GET:
- /**
- * the status request for the current connection
- */
- if (p->conf.debug) TRACE("(uploadprogress) urls %s == %s", SAFE_BUF_STR(con->uri.path), SAFE_BUF_STR(p->conf.progress_url));
-
- if (!buffer_is_equal(con->uri.path, p->conf.progress_url)) {
- return HANDLER_GO_ON;
- }
-
- /* get the tracker id */
- if (NULL == (tracking_id = get_tracking_id(p, con))) {
- return HANDLER_GO_ON;
- }
-
- buffer_reset(con->physical.path);
-
- con->file_started = 1;
- con->http_status = 200;
- con->send->is_closed = 1;
-
- /* send JSON content */
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/javascript"));
-
- /* just an attempt the force the IE/proxies to NOT cache the request */
- response_header_overwrite(srv, con, CONST_STR_LEN("Pragma"), CONST_STR_LEN("no-cache"));
- response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_STR_LEN("Thu, 19 Nov 1981 08:52:00 GMT"));
- response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"),
- CONST_STR_LEN("no-store, no-cache, must-revalidate, post-check=0, pre-check=0"));
-
- b = chunkqueue_get_append_buffer(con->send);
-
- /* get the connection */
- if (NULL == (post_con_entry = connection_map_get_connection_entry(p->con_map, tracking_id))) {
- /**
- * looks like we don't know the tracking id yet, GET and POST out of sync ? */
- buffer_append_string_len(b, CONST_STR_LEN("new Object({ 'state' : 'starting' })\r\n"));
- con->send->bytes_in += b->used-1;
-
- if (p->conf.debug) TRACE("connection unknown: %s, sending: %s", SAFE_BUF_STR(tracking_id), SAFE_BUF_STR(b));
-
- return HANDLER_FINISHED;
- }
-
- buffer_copy_string_len(b, CONST_STR_LEN("new Object({ 'state' : "));
-
- if (post_con_entry->status == 413) {
- /* the upload was too large */
- buffer_append_string_len(b, CONST_STR_LEN("'error', 'status' : 413"));
- } else if (post_con_entry->con == NULL) {
- /* the connection is already gone */
- buffer_append_string_len(b, CONST_STR_LEN("'done', 'size' : "));
- buffer_append_off_t(b, post_con_entry->size);
- } else {
- /* the upload is already done, but the connection might be still open */
- buffer_append_string(b, post_con_entry->con->recv->is_closed ? "'done'" : "'uploading'");
- buffer_append_string_len(b, CONST_STR_LEN(", 'received' : "));
- buffer_append_off_t(b, post_con_entry->con->recv->bytes_in);
- buffer_append_string_len(b, CONST_STR_LEN(", 'size' : "));
- buffer_append_off_t(b, post_con_entry->con->request.content_length == -1 ? 0 : post_con_entry->con->request.content_length);
- }
- buffer_append_string_len(b, CONST_STR_LEN("})\r\n"));
- con->send->bytes_in += b->used-1;
-
- if (p->conf.debug) TRACE("connection is known: %s, sending: %s", SAFE_BUF_STR(tracking_id), SAFE_BUF_STR(b));
-
- return HANDLER_FINISHED;
- default:
- break;
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * check if request parser sent 413 for our POST request
- */
-URIHANDLER_FUNC(mod_uploadprogress_response_header) {
- plugin_data *p = p_d;
-
- buffer *tracking_id;
- connection_map_entry *map_con_entry = NULL;
-
- UNUSED(srv);
-
- /*
- * we only want to process an 413 (Bad length) error for the upload (POST request)
- */
- if (con->request.http_method != HTTP_METHOD_POST || con->http_status != 413) {
- return HANDLER_GO_ON;
- }
-
- if (p->conf.debug) {
- TRACE("response_header: con=%p, http_method=%d, http_status=%d", (void*) con,
- con->request.http_method, con->http_status);
- }
-
- /* get the tracker id */
- if (NULL == (tracking_id = get_tracking_id(p, con))) {
- return HANDLER_GO_ON;
- }
-
- if (NULL == (map_con_entry = connection_map_get_connection_entry(p->con_map, tracking_id))) {
- /**
- * in case the request parser meant the request was too large the URI handler won't
- * get called. Insert the connection mapping here
- */
- if (NULL == (map_con_entry = connection_map_insert(p->con_map, tracking_id, con))) {
- return HANDLER_GO_ON;
- }
- }
-
- /* ok, found our entries, setting 413 here for status */
- map_con_entry->status = 413;
-
- return HANDLER_GO_ON;
-}
-
-/**
- * remove the parent connection from the connection mapping
- * when it got closed
- *
- * keep the mapping active for a while to send a valid final status
- */
-REQUESTDONE_FUNC(mod_uploadprogress_request_done) {
- plugin_data *p = p_d;
- buffer *tracking_id;
- connection_map_entry *cm = NULL;
-
- UNUSED(srv);
-
- if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
-
- /*
- * only need to handle the upload request.
- */
- if (con->request.http_method != HTTP_METHOD_POST) {
- return HANDLER_GO_ON;
- }
-
- if (NULL == (tracking_id = get_tracking_id(p, con))) {
- return HANDLER_GO_ON;
- }
-
- if (p->conf.debug) {
- TRACE("upload is done, moving tracking-id to backlog: tracking-id=%s, http_status=%d",
- SAFE_BUF_STR(tracking_id),
- con->http_status);
- }
-
- /*
- * set timeout on the upload's connection_map_entry.
- */
- if (NULL == (cm = connection_map_get_connection_entry(p->con_map, tracking_id))) {
- if (p->conf.debug) {
- TRACE("tracking ID %s not found, can't set timeout", SAFE_BUF_STR(tracking_id));
- }
- return HANDLER_GO_ON;
- }
-
- /* save request size to be able to report it even when cm->con == NULL */
- cm->size = con->request.content_length;
-
- cm->timeout = time(NULL) + p->conf.remove_timeout;
- cm->con = NULL; /* con becomes invalid very soon */
-
- return HANDLER_GO_ON;
-}
-
-/**
- * remove dead connections once in while
- */
-TRIGGER_FUNC(mod_uploadprogress_trigger) {
- plugin_data *p = p_d;
-
- if ((srv->cur_ts % 10) != 0) return HANDLER_GO_ON;
-
- connection_map_clear_timeout_connections(p->con_map);
-
- return HANDLER_GO_ON;
-}
-
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_uploadprogress_plugin_init(plugin *p);
-LI_EXPORT int mod_uploadprogress_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("uploadprogress");
-
- p->init = mod_uploadprogress_init;
- p->handle_uri_clean = mod_uploadprogress_uri_handler;
- p->handle_response_done = mod_uploadprogress_request_done;
- p->set_defaults = mod_uploadprogress_set_defaults;
- p->cleanup = mod_uploadprogress_free;
- p->handle_trigger = mod_uploadprogress_trigger;
- p->handle_response_header = mod_uploadprogress_response_header;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_userdir.c b/src/mod_userdir.c
deleted file mode 100644
index 8ee91295..00000000
--- a/src/mod_userdir.c
+++ /dev/null
@@ -1,325 +0,0 @@
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "response.h"
-
-#include "plugin.h"
-#include "sys-files.h"
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-/* plugin config for all request/connections */
-typedef struct {
- array *exclude_user;
- array *include_user;
- buffer *path;
- buffer *basepath;
- unsigned short letterhomes;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *username;
- buffer *temp_path;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_userdir_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->username = buffer_init();
- p->temp_path = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_userdir_free) {
- plugin_data *p = p_d;
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- array_free(s->include_user);
- array_free(s->exclude_user);
- buffer_free(s->path);
- buffer_free(s->basepath);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->username);
- buffer_free(p->temp_path);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
- plugin_data *p = p_d;
- size_t i;
-
- config_values_t cv[] = {
- { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "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 }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->exclude_user = array_init();
- 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;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(path);
- PATCH_OPTION(exclude_user);
- PATCH_OPTION(include_user);
- PATCH_OPTION(basepath);
- PATCH_OPTION(letterhomes);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
- PATCH_OPTION(path);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
- PATCH_OPTION(exclude_user);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
- PATCH_OPTION(include_user);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
- PATCH_OPTION(basepath);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.letterhomes"))) {
- PATCH_OPTION(letterhomes);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_userdir_docroot_handler) {
- plugin_data *p = p_d;
- int uri_len;
- size_t k;
- char *rel_url;
-#ifdef HAVE_PWD_H
- struct passwd *pwd = NULL;
-#endif
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_userdir_patch_connection(srv, con, p);
-
- uri_len = con->uri.path->used - 1;
-
- /* /~user/foo.html -> /home/user/public_html/foo.html */
-
- if (con->uri.path->ptr[0] != '/' ||
- con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
-
- if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
- /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
- http_response_redirect_to_directory(srv, con);
-
- return HANDLER_FINISHED;
- }
-
- /* /~/ is a empty username, catch it directly */
- if (0 == rel_url - (con->uri.path->ptr + 2)) {
- return HANDLER_GO_ON;
- }
-
- buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
-
- if (buffer_is_empty(p->conf.basepath)
-#ifdef HAVE_PWD_H
- && NULL == (pwd = getpwnam(p->username->ptr))
-#endif
- ) {
- /* user not found */
- return HANDLER_GO_ON;
- }
-
-
- for (k = 0; k < p->conf.exclude_user->used; k++) {
- data_string *ds = (data_string *)p->conf.exclude_user->data[k];
-
- if (buffer_is_equal(ds->value, p->username)) {
- /* user in exclude list */
- return HANDLER_GO_ON;
- }
- }
-
- if (p->conf.include_user->used) {
- int found_user = 0;
- for (k = 0; k < p->conf.include_user->used; k++) {
- data_string *ds = (data_string *)p->conf.include_user->data[k];
-
- if (buffer_is_equal(ds->value, p->username)) {
- /* user in include list */
- found_user = 1;
- break;
- }
- }
-
- if (!found_user) return HANDLER_GO_ON;
- }
-
- /* we build the physical path */
-
- if (buffer_is_empty(p->conf.basepath)) {
-#ifdef HAVE_PWD_H
- buffer_copy_string(p->temp_path, pwd->pw_dir);
-#endif
- } else {
- char *cp;
- /* check if the username is valid
- * a request for /~../ should lead to a directory traversal
- * limiting to [-_a-z0-9.] should fix it */
-
- for (cp = p->username->ptr; *cp; cp++) {
- char c = *cp;
-
- if (!(c == '-' ||
- c == '_' ||
- c == '.' ||
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9'))) {
-
- return HANDLER_GO_ON;
- }
- }
- if (con->conf.force_lowercase_filenames) {
- buffer_to_lower(p->username);
- }
-
- buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
- PATHNAME_APPEND_SLASH(p->temp_path);
- if (p->conf.letterhomes) {
- buffer_append_string_len(p->temp_path, p->username->ptr, 1);
- PATHNAME_APPEND_SLASH(p->temp_path);
- }
- buffer_append_string_buffer(p->temp_path, p->username);
- }
- PATHNAME_APPEND_SLASH(p->temp_path);
- buffer_append_string_buffer(p->temp_path, p->conf.path);
-
- if (buffer_is_empty(p->conf.basepath)) {
- struct stat st;
- int ret;
-
- ret = stat(p->temp_path->ptr, &st);
- if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
- return HANDLER_GO_ON;
- }
- }
-
- /* the physical rel_path is basically the same as uri.path;
- * but it is converted to lowercase in case of force_lowercase_filenames and some special handling
- * for trailing '.', ' ' and '/' on windows
- * we assume that no docroot/physical handler changed this
- * (docroot should only set the docroot/server name, phyiscal should only change the phyiscal.path;
- * the exception mod_secure_download doesn't work with userdir anyway)
- */
- PATHNAME_APPEND_SLASH(p->temp_path);
- /* if no second '/' is found, we assume that it was stripped from the uri.path for the special handling
- * on windows.
- * we do not care about the trailing slash here on windows, as we already ensured it is a directory
- *
- * TODO: what to do with trailing dots in usernames on windows? they may result in the same directory
- * as a username without them.
- */
- if (NULL != (rel_url = strchr(con->physical.rel_path->ptr + 2, '/'))) {
- buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
- }
- buffer_copy_string_buffer(con->physical.path, p->temp_path);
-
- buffer_reset(p->temp_path);
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_userdir_plugin_init(plugin *p);
-LI_EXPORT int mod_userdir_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("userdir");
-
- p->init = mod_userdir_init;
- p->handle_physical = mod_userdir_docroot_handler;
- p->set_defaults = mod_userdir_set_defaults;
- p->cleanup = mod_userdir_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_usertrack.c b/src/mod_usertrack.c
deleted file mode 100644
index b0275107..00000000
--- a/src/mod_usertrack.c
+++ /dev/null
@@ -1,277 +0,0 @@
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-
-#include "plugin.h"
-
-#ifdef USE_OPENSSL
-# include <openssl/md5.h>
-#else
-# include "md5.h"
-
-typedef li_MD5_CTX MD5_CTX;
-#define MD5_Init li_MD5_Init
-#define MD5_Update li_MD5_Update
-#define MD5_Final li_MD5_Final
-
-#endif
-
-/* plugin config for all request/connections */
-
-typedef struct {
- buffer *cookie_name;
- buffer *cookie_domain;
- unsigned short cookie_max_age;
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_usertrack_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_usertrack_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- buffer_free(s->cookie_name);
- buffer_free(s->cookie_domain);
-
- free(s);
- }
- free(p->config_storage);
- }
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
-
- { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->cookie_name = buffer_init();
- s->cookie_domain = buffer_init();
- s->cookie_max_age = 0;
-
- cv[0].destination = s->cookie_name;
- cv[1].destination = &(s->cookie_max_age);
- cv[2].destination = s->cookie_domain;
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (buffer_is_empty(s->cookie_name)) {
- buffer_copy_string_len(s->cookie_name, CONST_STR_LEN("TRACKID"));
- } else {
- size_t j;
- for (j = 0; j < s->cookie_name->used - 1; j++) {
- char c = s->cookie_name->ptr[j] | 32;
- if (c < 'a' || c > 'z') {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "invalid character in usertrack.cookie-name:",
- s->cookie_name);
-
- return HANDLER_ERROR;
- }
- }
- }
-
- if (!buffer_is_empty(s->cookie_domain)) {
- size_t j;
- for (j = 0; j < s->cookie_domain->used - 1; j++) {
- char c = s->cookie_domain->ptr[j];
- if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "invalid character in usertrack.cookie-domain:",
- s->cookie_domain);
-
- return HANDLER_ERROR;
- }
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(cookie_name);
- PATCH_OPTION(cookie_domain);
- PATCH_OPTION(cookie_max_age);
-
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
- PATCH_OPTION(cookie_name);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
- PATCH_OPTION(cookie_max_age);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
- PATCH_OPTION(cookie_domain);
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_usertrack_uri_handler) {
- plugin_data *p = p_d;
- data_string *ds;
- unsigned char h[16];
- MD5_CTX Md5Ctx;
- char hh[32];
-
- if (con->uri.path->used == 0) return HANDLER_GO_ON;
-
- mod_usertrack_patch_connection(srv, con, p);
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Cookie")))) {
- char *g;
- /* we have a cookie, does it contain a valid name ? */
-
- /* parse the cookie
- *
- * check for cookiename + (WS | '=')
- *
- */
-
- if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
- char *nc;
-
- /* skip WS */
- for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
-
- if (*nc == '=') {
- /* ok, found the key of our own cookie */
-
- if (strlen(nc) > 32) {
- /* i'm lazy */
- return HANDLER_GO_ON;
- }
- }
- }
- }
-
- /* set a cookie */
- if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
- ds = data_response_init();
- }
- buffer_copy_string_len(ds->key, CONST_STR_LEN("Set-Cookie"));
- buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
- buffer_append_string_len(ds->value, CONST_STR_LEN("="));
-
-
- /* taken from mod_auth.c */
-
- /* generate shared-secret */
- MD5_Init(&Md5Ctx);
- MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
- MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
-
- /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
- LI_ltostr(hh, srv->cur_ts);
- MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
- MD5_Update(&Md5Ctx, (unsigned char *)srv->entropy, sizeof(srv->entropy));
- LI_ltostr(hh, rand());
- MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
-
- MD5_Final(h, &Md5Ctx);
-
- buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
- buffer_append_string_len(ds->value, CONST_STR_LEN("; Path=/"));
- buffer_append_string_len(ds->value, CONST_STR_LEN("; Version=1"));
-
- if (!buffer_is_empty(p->conf.cookie_domain)) {
- buffer_append_string_len(ds->value, CONST_STR_LEN("; Domain="));
- buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
- }
-
- if (p->conf.cookie_max_age) {
- buffer_append_string_len(ds->value, CONST_STR_LEN("; max-age="));
- buffer_append_long(ds->value, p->conf.cookie_max_age);
- }
-
- array_insert_unique(con->response.headers, (data_unset *)ds);
-
- return HANDLER_GO_ON;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_usertrack_plugin_init(plugin *p);
-LI_EXPORT int mod_usertrack_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("usertrack");
-
- p->init = mod_usertrack_init;
- p->handle_uri_clean = mod_usertrack_uri_handler;
- p->set_defaults = mod_usertrack_set_defaults;
- p->cleanup = mod_usertrack_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/mod_webdav.c b/src/mod_webdav.c
deleted file mode 100644
index 49de74a5..00000000
--- a/src/mod_webdav.c
+++ /dev/null
@@ -1,2688 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <assert.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H)
-#define USE_PROPPATCH
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-
-#include <sqlite3.h>
-#endif
-
-#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
-#define USE_LOCKS
-#include <uuid/uuid.h>
-#endif
-
-#include "base.h"
-#include "log.h"
-#include "buffer.h"
-#include "response.h"
-
-#include "plugin.h"
-
-#include "stream.h"
-#include "stat_cache.h"
-
-#include "sys-files.h"
-#include "sys-mmap.h"
-#include "sys-strings.h"
-
-/**
- * this is a webdav for a lighttpd plugin
- *
- * at least a very basic one.
- * - for now it is read-only and we only support PROPFIND
- *
- */
-#ifdef _WIN32
-#define WEBDAV_FILE_MODE _S_IREAD | _S_IWRITE
-#define WEBDAV_DIR_MODE _S_IREAD | _S_IWRITE
-#else
-#define WEBDAV_FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
-#define WEBDAV_DIR_MODE S_IRWXU | S_IRWXG | S_IRWXO
-#endif
-
-/* plugin config for all request/connections */
-
-typedef struct {
- unsigned short enabled;
- unsigned short is_readonly;
- unsigned short log_xml;
-
- buffer *sqlite_db_name;
-#ifdef USE_PROPPATCH
- sqlite3 *sql;
- sqlite3_stmt *stmt_update_prop;
- sqlite3_stmt *stmt_delete_prop;
- sqlite3_stmt *stmt_select_prop;
- sqlite3_stmt *stmt_select_propnames;
-
- sqlite3_stmt *stmt_delete_uri;
- sqlite3_stmt *stmt_move_uri;
- sqlite3_stmt *stmt_copy_uri;
-
- sqlite3_stmt *stmt_remove_lock;
- sqlite3_stmt *stmt_create_lock;
- sqlite3_stmt *stmt_read_lock;
- sqlite3_stmt *stmt_read_lock_by_uri;
- sqlite3_stmt *stmt_refresh_lock;
-#endif
-} plugin_config;
-
-typedef struct {
- PLUGIN_DATA;
-
- buffer *tmp_buf;
- request_uri uri;
- physical physical;
-
- plugin_config **config_storage;
-
- plugin_config conf;
-} plugin_data;
-
-/* init the plugin data */
-INIT_FUNC(mod_webdav_init) {
- plugin_data *p;
-
- UNUSED(srv);
-
- p = calloc(1, sizeof(*p));
-
- p->tmp_buf = buffer_init();
-
- p->uri.scheme = buffer_init();
- p->uri.path_raw = buffer_init();
- p->uri.path = buffer_init();
- p->uri.authority = buffer_init();
-
- p->physical.path = buffer_init();
- p->physical.rel_path = buffer_init();
- p->physical.doc_root = buffer_init();
- p->physical.basedir = buffer_init();
-
- return p;
-}
-
-/* detroy the plugin data */
-FREE_FUNC(mod_webdav_free) {
- plugin_data *p = p_d;
-
- UNUSED(srv);
-
- if (!p) return HANDLER_GO_ON;
-
- if (p->config_storage) {
- size_t i;
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s = p->config_storage[i];
-
- if (!s) continue;
-
- buffer_free(s->sqlite_db_name);
-#ifdef USE_PROPPATCH
- if (s->sql) {
- sqlite3_finalize(s->stmt_delete_prop);
- sqlite3_finalize(s->stmt_delete_uri);
- sqlite3_finalize(s->stmt_copy_uri);
- sqlite3_finalize(s->stmt_move_uri);
- sqlite3_finalize(s->stmt_update_prop);
- sqlite3_finalize(s->stmt_select_prop);
- sqlite3_finalize(s->stmt_select_propnames);
-
- sqlite3_finalize(s->stmt_read_lock);
- sqlite3_finalize(s->stmt_read_lock_by_uri);
- sqlite3_finalize(s->stmt_create_lock);
- sqlite3_finalize(s->stmt_remove_lock);
- sqlite3_finalize(s->stmt_refresh_lock);
- sqlite3_close(s->sql);
- }
-#endif
- free(s);
- }
- free(p->config_storage);
- }
-
- buffer_free(p->uri.scheme);
- buffer_free(p->uri.path_raw);
- buffer_free(p->uri.path);
- buffer_free(p->uri.authority);
-
- buffer_free(p->physical.path);
- buffer_free(p->physical.rel_path);
- buffer_free(p->physical.doc_root);
- buffer_free(p->physical.basedir);
-
- buffer_free(p->tmp_buf);
-
- free(p);
-
- return HANDLER_GO_ON;
-}
-
-/* handle plugin config and check values */
-
-SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
- plugin_data *p = p_d;
- size_t i = 0;
-
- config_values_t cv[] = {
- { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
- { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
- { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
- { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
- };
-
- if (!p) return HANDLER_ERROR;
-
- p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
- for (i = 0; i < srv->config_context->used; i++) {
- plugin_config *s;
-
- s = calloc(1, sizeof(plugin_config));
- s->sqlite_db_name = buffer_init();
-
- cv[0].destination = &(s->enabled);
- cv[1].destination = &(s->is_readonly);
- cv[2].destination = s->sqlite_db_name;
- cv[3].destination = &(s->log_xml);
-
- p->config_storage[i] = s;
-
- if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
- return HANDLER_ERROR;
- }
-
- if (!buffer_is_empty(s->sqlite_db_name)) {
-#ifdef USE_PROPPATCH
- const char *next_stmt;
- char *err;
-
- if (SQLITE_OK != sqlite3_open(s->sqlite_db_name->ptr, &(s->sql))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs", "sqlite3_open failed for",
- s->sqlite_db_name,
- sqlite3_errmsg(s->sql));
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_exec(s->sql,
- "CREATE TABLE properties ("
- " resource TEXT NOT NULL,"
- " prop TEXT NOT NULL,"
- " ns TEXT NOT NULL,"
- " value TEXT NOT NULL,"
- " PRIMARY KEY(resource, prop, ns))",
- NULL, NULL, &err)) {
-
- if (0 != strcmp(err, "table properties already exists")) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
- sqlite3_free(err);
-
- return HANDLER_ERROR;
- }
- sqlite3_free(err);
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
- &(s->stmt_select_prop), &next_stmt)) {
- /* prepare failed */
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
- &(s->stmt_select_propnames), &next_stmt)) {
- /* prepare failed */
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
- return HANDLER_ERROR;
- }
-
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
- &(s->stmt_update_prop), &next_stmt)) {
- /* prepare failed */
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
- &(s->stmt_delete_prop), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
- &(s->stmt_delete_uri), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
- &(s->stmt_copy_uri), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
- &(s->stmt_move_uri), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- /* LOCKS */
-
- if (SQLITE_OK != sqlite3_exec(s->sql,
- "CREATE TABLE locks ("
- " locktoken TEXT NOT NULL,"
- " resource TEXT NOT NULL,"
- " lockscope TEXT NOT NULL,"
- " locktype TEXT NOT NULL,"
- " owner TEXT NOT NULL,"
- " depth INT NOT NULL,"
- " timeout TIMESTAMP NOT NULL,"
- " PRIMARY KEY(locktoken))",
- NULL, NULL, &err)) {
-
- if (0 != strcmp(err, "table locks already exists")) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
- sqlite3_free(err);
-
- return HANDLER_ERROR;
- }
- sqlite3_free(err);
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
- &(s->stmt_create_lock), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
- &(s->stmt_remove_lock), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
- &(s->stmt_read_lock), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
- &(s->stmt_read_lock_by_uri), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
- if (SQLITE_OK != sqlite3_prepare(s->sql,
- CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
- &(s->stmt_refresh_lock), &next_stmt)) {
- /* prepare failed */
- log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
-
- return HANDLER_ERROR;
- }
-
-
-#else
- log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
- return HANDLER_ERROR;
-#endif
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
- size_t i, j;
- plugin_config *s = p->config_storage[0];
-
- PATCH_OPTION(enabled);
- PATCH_OPTION(is_readonly);
- PATCH_OPTION(log_xml);
-
-#ifdef USE_PROPPATCH
- PATCH_OPTION(sql);
- PATCH_OPTION(stmt_update_prop);
- PATCH_OPTION(stmt_delete_prop);
- PATCH_OPTION(stmt_select_prop);
- PATCH_OPTION(stmt_select_propnames);
-
- PATCH_OPTION(stmt_delete_uri);
- PATCH_OPTION(stmt_move_uri);
- PATCH_OPTION(stmt_copy_uri);
-
- PATCH_OPTION(stmt_remove_lock);
- PATCH_OPTION(stmt_refresh_lock);
- PATCH_OPTION(stmt_create_lock);
- PATCH_OPTION(stmt_read_lock);
- PATCH_OPTION(stmt_read_lock_by_uri);
-#endif
- /* skip the first, the global context */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- s = p->config_storage[i];
-
- /* condition didn't match */
- if (!config_check_cond(srv, con, dc)) continue;
-
- /* merge config */
- for (j = 0; j < dc->value->used; j++) {
- data_unset *du = dc->value->data[j];
-
- if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
- PATCH_OPTION(enabled);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
- PATCH_OPTION(is_readonly);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
- PATCH_OPTION(log_xml);
- } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
-#ifdef USE_PROPPATCH
- PATCH_OPTION(sql);
- PATCH_OPTION(stmt_update_prop);
- PATCH_OPTION(stmt_delete_prop);
- PATCH_OPTION(stmt_select_prop);
- PATCH_OPTION(stmt_select_propnames);
-
- PATCH_OPTION(stmt_delete_uri);
- PATCH_OPTION(stmt_move_uri);
- PATCH_OPTION(stmt_copy_uri);
-
- PATCH_OPTION(stmt_remove_lock);
- PATCH_OPTION(stmt_refresh_lock);
- PATCH_OPTION(stmt_create_lock);
- PATCH_OPTION(stmt_read_lock);
- PATCH_OPTION(stmt_read_lock_by_uri);
-#endif
- }
- }
- }
-
- return 0;
-}
-
-URIHANDLER_FUNC(mod_webdav_uri_handler) {
- plugin_data *p = p_d;
-
- if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
-
- mod_webdav_patch_connection(srv, con, p);
-
- if (!p->conf.enabled) {
- if (con->conf.log_request_handling) {
- TRACE("-- skipping %s in mod_webdav, not enabled",
- SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- handling request in mod_webdav: %s",
- SAFE_BUF_STR(con->uri.path));
- }
-
- switch (con->request.http_method) {
- case HTTP_METHOD_OPTIONS:
- /* we fake a little bit but it makes MS W2k happy and it let's us mount the volume */
- response_header_overwrite(srv, con, CONST_STR_LEN("DAV"), CONST_STR_LEN("1,2"));
- response_header_overwrite(srv, con, CONST_STR_LEN("MS-Author-Via"), CONST_STR_LEN("DAV"));
-
- if (p->conf.is_readonly) {
- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
- } else {
- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
- }
-
- if (con->conf.log_request_handling) {
- TRACE("sending OPTIONS response for: %s",
- SAFE_BUF_STR(con->uri.path));
- }
-
- break;
- default:
- break;
- }
-
- return HANDLER_GO_ON;
-}
-
-PHYSICALPATH_FUNC(mod_webdav_physical_handler) {
- plugin_data *p = p_d;
-
- if (con->mode != DIRECT) return HANDLER_GO_ON;
-
- mod_webdav_patch_connection(srv, con, p);
-
- if (!p->conf.enabled) {
- if (con->conf.log_request_handling) {
- TRACE("-- skipping %s in mod_webdav, not enabled",
- SAFE_BUF_STR(con->uri.path));
- }
-
- return HANDLER_GO_ON;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- handling request in mod_webdav: %s",
- SAFE_BUF_STR(con->uri.path));
- }
-
- /* physical path is setup */
- if (con->physical.path->used == 0) {
- TRACE("-- missing con->physical.path: %s",
- SAFE_BUF_STR(con->uri.path));
- return HANDLER_GO_ON;
- }
-
- switch (con->request.http_method) {
- case HTTP_METHOD_OPTIONS:
- /* already handled */
- break;
- case HTTP_METHOD_PROPFIND:
- case HTTP_METHOD_MKCOL:
- case HTTP_METHOD_DELETE:
- case HTTP_METHOD_PUT:
- case HTTP_METHOD_MOVE:
- case HTTP_METHOD_COPY:
- case HTTP_METHOD_PROPPATCH:
- case HTTP_METHOD_LOCK:
- case HTTP_METHOD_UNLOCK:
- con->mode = p->id;
- return HANDLER_FINISHED;
- default: break;
- }
-
- return HANDLER_GO_ON;
-}
-
-
-static int webdav_gen_prop_tag(server *srv, connection *con,
- char *prop_name,
- char *prop_ns,
- char *value,
- buffer *b) {
-
- UNUSED(srv);
- UNUSED(con);
-
- if (value) {
- buffer_append_string_len(b,CONST_STR_LEN("<"));
- buffer_append_string(b, prop_name);
- buffer_append_string_len(b, CONST_STR_LEN(" xmlns=\""));
- buffer_append_string(b, prop_ns);
- buffer_append_string_len(b, CONST_STR_LEN("\">"));
-
- buffer_append_string(b, value);
-
- buffer_append_string_len(b,CONST_STR_LEN("</"));
- buffer_append_string(b, prop_name);
- buffer_append_string_len(b, CONST_STR_LEN(">"));
- } else {
- buffer_append_string_len(b,CONST_STR_LEN("<"));
- buffer_append_string(b, prop_name);
- buffer_append_string_len(b, CONST_STR_LEN(" xmlns=\""));
- buffer_append_string(b, prop_ns);
- buffer_append_string_len(b, CONST_STR_LEN("\"/>"));
- }
-
- return 0;
-}
-
-
-static int webdav_gen_response_status_tag(server *srv, connection *con, physical *dst, int status, buffer *b) {
- UNUSED(srv);
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:response xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:href>\n"));
- buffer_append_string_buffer(b, dst->rel_path);
- buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:status>\n"));
-
- if (con->request.http_version == HTTP_VERSION_1_1) {
- buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 "));
- } else {
- buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.0 "));
- }
- buffer_append_long(b, status);
- buffer_append_string_len(b, CONST_STR_LEN(" "));
- buffer_append_string(b, get_http_status_name(status));
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:status>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n"));
-
- return 0;
-}
-
-static int webdav_delete_file(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) {
- int status = 0;
-
- UNUSED(p);
-
- /* try to unlink it */
- if (-1 == unlink(dst->path->ptr)) {
- switch(errno) {
- case EACCES:
- case EPERM:
- /* 403 */
- status = 403;
- break;
- default:
- status = 501;
- break;
- }
- webdav_gen_response_status_tag(srv, con, dst, status, b);
- } else {
-#ifdef USE_PROPPATCH
- sqlite3_stmt *stmt = p->conf.stmt_delete_uri;
-
- if (stmt) {
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
-
- sqlite3_bind_text(stmt, 1,
- dst->rel_path->ptr,
- dst->rel_path->used - 1,
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- /* */
- }
- }
-#endif
- }
-
- return (status != 0);
-}
-
-static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) {
- DIR *dir;
- int have_multi_status = 0;
- physical d;
-
- d.path = buffer_init();
- d.rel_path = buffer_init();
-
- if (NULL != (dir = opendir(dst->path->ptr))) {
- struct dirent *de;
-
- while(NULL != (de = readdir(dir))) {
- struct stat st;
- int status = 0;
-
- if ((de->d_name[0] == '.' && de->d_name[1] == '\0') ||
- (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
- continue;
- /* ignore the parent dir */
- }
-
- buffer_copy_string_buffer(d.path, dst->path);
- PATHNAME_APPEND_SLASH(d.path);
- buffer_append_string(d.path, de->d_name);
-
- buffer_copy_string_buffer(d.rel_path, dst->rel_path);
- PATHNAME_APPEND_SLASH(d.rel_path);
- buffer_append_string(d.rel_path, de->d_name);
-
- /* stat and unlink afterwards */
- if (-1 == stat(d.path->ptr, &st)) {
- /* don't about it yet, rmdir will fail too */
- } else if (S_ISDIR(st.st_mode)) {
- have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
-
- /* try to unlink it */
- if (-1 == rmdir(d.path->ptr)) {
- switch(errno) {
- case EACCES:
- case EPERM:
- /* 403 */
- status = 403;
- break;
- default:
- status = 501;
- break;
- }
- have_multi_status = 1;
-
- webdav_gen_response_status_tag(srv, con, &d, status, b);
- } else {
-#ifdef USE_PROPPATCH
- sqlite3_stmt *stmt = p->conf.stmt_delete_uri;
-
- status = 0;
-
- if (stmt) {
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
-
- sqlite3_bind_text(stmt, 1,
- d.rel_path->ptr,
- d.rel_path->used - 1,
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- /* */
- }
- }
-#endif
- }
- } else {
- have_multi_status = webdav_delete_file(srv, con, p, &d, b);
- }
- }
- closedir(dir);
-
- buffer_free(d.path);
- buffer_free(d.rel_path);
- }
-
- return have_multi_status;
-}
-
-static int webdav_copy_file(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) {
- stream s;
- int status = 0, ofd;
-
- UNUSED(con);
- UNUSED(srv);
- UNUSED(p);
-
- if (stream_open(&s, src->path)) {
- return 403;
- }
-
- if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), WEBDAV_FILE_MODE))) {
- /* opening the destination failed for some reason */
- switch(errno) {
- case EEXIST:
- status = 412;
- break;
- case EISDIR:
- status = 409;
- break;
- case ENOENT:
- /* at least one part in the middle wasn't existing */
- status = 409;
- break;
- default:
- status = 403;
- break;
- }
- stream_close(&s);
- return status;
- }
-
- if (-1 == write(ofd, s.start, s.size)) {
- switch(errno) {
- case ENOSPC:
- status = 507;
- break;
- default:
- status = 403;
- break;
- }
- }
-
- stream_close(&s);
- close(ofd);
-
-#ifdef USE_PROPPATCH
- if (0 == status) {
- /* copy worked fine, copy connected properties */
- sqlite3_stmt *stmt = p->conf.stmt_copy_uri;
-
- if (stmt) {
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
- sqlite3_bind_text(stmt, 1,
- dst->rel_path->ptr,
- dst->rel_path->used - 1,
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 2,
- src->rel_path->ptr,
- src->rel_path->used - 1,
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- /* */
- }
- }
- }
-#endif
- return status;
-}
-
-static int webdav_copy_dir(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) {
- DIR *srcdir;
- int status = 0;
-
- if (NULL != (srcdir = opendir(src->path->ptr))) {
- struct dirent *de;
- physical s, d;
-
- s.path = buffer_init();
- s.rel_path = buffer_init();
-
- d.path = buffer_init();
- d.rel_path = buffer_init();
-
- while (NULL != (de = readdir(srcdir))) {
- struct stat st;
-
- if ((de->d_name[0] == '.' && de->d_name[1] == '\0') ||
- (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
- continue;
- }
-
- buffer_copy_string_buffer(s.path, src->path);
- PATHNAME_APPEND_SLASH(s.path);
- buffer_append_string(s.path, de->d_name);
-
- buffer_copy_string_buffer(d.path, dst->path);
- PATHNAME_APPEND_SLASH(d.path);
- buffer_append_string(d.path, de->d_name);
-
- buffer_copy_string_buffer(s.rel_path, src->rel_path);
- PATHNAME_APPEND_SLASH(s.rel_path);
- buffer_append_string(s.rel_path, de->d_name);
-
- buffer_copy_string_buffer(d.rel_path, dst->rel_path);
- PATHNAME_APPEND_SLASH(d.rel_path);
- buffer_append_string(d.rel_path, de->d_name);
-
- if (-1 == stat(s.path->ptr, &st)) {
- /* why ? */
- } else if (S_ISDIR(st.st_mode)) {
- /* a directory */
- if (-1 == mkdir(d.path->ptr, WEBDAV_DIR_MODE) &&
- errno != EEXIST) {
- /* WTH ? */
- } else {
-#ifdef USE_PROPPATCH
- sqlite3_stmt *stmt = p->conf.stmt_copy_uri;
-
- if (0 != (status = webdav_copy_dir(srv, con, p, &s, &d, overwrite))) {
- break;
- }
- /* directory is copied, copy the properties too */
-
- if (stmt) {
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
- sqlite3_bind_text(stmt, 1,
- dst->rel_path->ptr,
- dst->rel_path->used - 1,
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 2,
- src->rel_path->ptr,
- src->rel_path->used - 1,
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- /* */
- }
- }
-#endif
- }
- } else if (S_ISREG(st.st_mode)) {
- /* a plain file */
- if (0 != (status = webdav_copy_file(srv, con, p, &s, &d, overwrite))) {
- break;
- }
- }
- }
-
- buffer_free(s.path);
- buffer_free(s.rel_path);
- buffer_free(d.path);
- buffer_free(d.rel_path);
-
- closedir(srcdir);
- }
-
- return status;
-}
-
-static int webdav_get_live_property(server *srv, connection *con, plugin_data *p, physical *dst, char *prop_name, buffer *b) {
- stat_cache_entry *sce = NULL;
- int found = 0;
-
- UNUSED(p);
-
- if (HANDLER_ERROR != (stat_cache_get_entry(srv, con, dst->path, &sce))) {
- char ctime_buf[] = "2005-08-18T07:27:16Z";
- char mtime_buf[] = "Thu, 18 Aug 2005 07:27:16 GMT";
- size_t k;
-
- if (0 == strcmp(prop_name, "resourcetype")) {
- if (S_ISDIR(sce->st.st_mode)) {
- buffer_append_string_len(b, CONST_STR_LEN("<D:resourcetype><D:collection/></D:resourcetype>"));
- found = 1;
- }
- } else if (0 == strcmp(prop_name, "getcontenttype")) {
- if (S_ISDIR(sce->st.st_mode)) {
- buffer_append_string_len(b, CONST_STR_LEN("<D:getcontenttype>httpd/unix-directory</D:getcontenttype>"));
- found = 1;
- } else if(S_ISREG(sce->st.st_mode)) {
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
-
- if (ds->key->used == 0) continue;
-
- if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:getcontenttype>"));
- buffer_append_string_buffer(b, ds->value);
- buffer_append_string_len(b, CONST_STR_LEN("</D:getcontenttype>"));
- found = 1;
-
- break;
- }
- }
- }
- } else if (0 == strcmp(prop_name, "creationdate")) {
- buffer_append_string_len(b, CONST_STR_LEN("<D:creationdate ns0:dt=\"dateTime.tz\">"));
- strftime(ctime_buf, sizeof(ctime_buf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&(sce->st.st_ctime)));
- buffer_append_string(b, ctime_buf);
- buffer_append_string_len(b, CONST_STR_LEN("</D:creationdate>"));
- found = 1;
- } else if (0 == strcmp(prop_name, "getlastmodified")) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:getlastmodified ns0:dt=\"dateTime.rfc1123\">"));
- strftime(mtime_buf, sizeof(mtime_buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(sce->st.st_mtime)));
- buffer_append_string(b, mtime_buf);
- buffer_append_string_len(b, CONST_STR_LEN("</D:getlastmodified>"));
- found = 1;
- } else if (0 == strcmp(prop_name, "getcontentlength")) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:getcontentlength>"));
- buffer_append_off_t(b, sce->st.st_size);
- buffer_append_string_len(b, CONST_STR_LEN("</D:getcontentlength>"));
- found = 1;
- } else if (0 == strcmp(prop_name, "getcontentlanguage")) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:getcontentlanguage>"));
- buffer_append_string_len(b, CONST_STR_LEN("en"));
- buffer_append_string_len(b, CONST_STR_LEN("</D:getcontentlanguage>"));
- found = 1;
- }
- }
-
- return found ? 0 : -1;
-}
-
-static int webdav_get_property(server *srv, connection *con, plugin_data *p, physical *dst, char *prop_name, char *prop_ns, buffer *b) {
- if (0 == strcmp(prop_ns, "DAV:")) {
- /* a local 'live' property */
- return webdav_get_live_property(srv, con, p, dst, prop_name, b);
- } else {
- int found = 0;
-#ifdef USE_PROPPATCH
- sqlite3_stmt *stmt = p->conf.stmt_select_prop;
-
- if (stmt) {
- /* perhaps it is in sqlite3 */
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
-
- sqlite3_bind_text(stmt, 1,
- dst->rel_path->ptr,
- dst->rel_path->used - 1,
- SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2,
- prop_name,
- strlen(prop_name),
- SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 3,
- prop_ns,
- strlen(prop_ns),
- SQLITE_TRANSIENT);
-
- /* it is the PK */
- while (SQLITE_ROW == sqlite3_step(stmt)) {
- /* there is a row for us, we only expect a single col 'value' */
- webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
- found = 1;
- }
- }
-#endif
- return found ? 0 : -1;
- }
-
- /* not found */
- return -1;
-}
-
-typedef struct {
- char *ns;
- char *prop;
-} webdav_property;
-
-webdav_property live_properties[] = {
- { "DAV:", "creationdate" },
- { "DAV:", "displayname" },
- { "DAV:", "getcontentlanguage" },
- { "DAV:", "getcontentlength" },
- { "DAV:", "getcontenttype" },
- { "DAV:", "getetag" },
- { "DAV:", "getlastmodified" },
- { "DAV:", "resourcetype" },
- { "DAV:", "lockdiscovery" },
- { "DAV:", "source" },
- { "DAV:", "supportedlock" },
-
- { NULL, NULL }
-};
-
-typedef struct {
- webdav_property **ptr;
-
- size_t used;
- size_t size;
-} webdav_properties;
-
-static int webdav_get_props(server *srv, connection *con, plugin_data *p, physical *dst, webdav_properties *props, buffer *b_200, buffer *b_404) {
- size_t i;
-
- if (props) {
- for (i = 0; i < props->used; i++) {
- webdav_property *prop;
-
- prop = props->ptr[i];
-
- if (0 != webdav_get_property(srv, con, p,
- dst, prop->prop, prop->ns, b_200)) {
- webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
- }
- }
- } else {
- for (i = 0; live_properties[i].prop; i++) {
- /* a local 'live' property */
- webdav_get_live_property(srv, con, p, dst, live_properties[i].prop, b_200);
- }
- }
-
- return 0;
-}
-
-#ifdef USE_PROPPATCH
-static int webdav_parse_chunkqueue(server *srv, connection *con, plugin_data *p, chunkqueue *cq, xmlDoc **ret_xml) {
- xmlParserCtxtPtr ctxt;
- xmlDoc *xml;
- int res = 0;
- int err;
-
- chunk *c;
-
- UNUSED(con);
-
- /* read the chunks in to the XML document */
- ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
-
- for (c = cq->first; cq->bytes_out != cq->bytes_in; c = cq->first) {
- size_t weWant = cq->bytes_out - cq->bytes_in;
- size_t weHave;
-
- switch(c->type) {
- case FILE_CHUNK:
- weHave = c->file.length - c->offset;
-
- if (weHave > weWant) weHave = weWant;
-
- /* xml chunks are always memory, mmap() is our friend */
- if (c->file.mmap.start == MAP_FAILED) {
- if (-1 == c->file.fd && /* open the file if not already open */
- -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
- ERROR("open(%s) failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return -1;
- }
-
- if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
- ERROR("mmap(%s) failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return -1;
- }
-
- close(c->file.fd);
- c->file.fd = -1;
-
- c->file.mmap.length = c->file.length;
-
- /* chunk_reset() or chunk_free() will cleanup for us */
- }
-
- if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
- ERROR("xmlParseChunk() failed: %d", err);
- log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
- }
-
- c->offset += weHave;
- cq->bytes_out += weHave;
-
- break;
- case MEM_CHUNK:
- /* append to the buffer */
- weHave = c->mem->used - 1 - c->offset;
-
- if (weHave > weWant) weHave = weWant;
-
- if (p->conf.log_xml) {
- TRACE("XML-request-body: %s", c->mem->ptr + c->offset);
- }
-
- if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
- ERROR("xmlParseChunk(%s) failed: %d", c->mem->ptr + c->offset, err);
- }
-
- c->offset += weHave;
- cq->bytes_out += weHave;
-
- break;
- case UNUSED_CHUNK:
- break;
- }
- chunkqueue_remove_finished_chunks(cq);
- }
-
- switch ((err = xmlParseChunk(ctxt, 0, 0, 1))) {
- case XML_ERR_DOCUMENT_END:
- case XML_ERR_OK:
- break;
- default:
- ERROR("xmlParseChunk() failed: %d", err);
- break;
- }
-
- xml = ctxt->myDoc;
- res = ctxt->wellFormed;
- xmlFreeParserCtxt(ctxt);
-
- if (res == 0) {
- xmlFreeDoc(xml);
- } else {
- *ret_xml = xml;
- }
-
- return res;
-}
-#endif
-
-#ifdef USE_LOCKS
-static int webdav_lockdiscovery(server *srv, connection *con,
- buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
-
- buffer *b;
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
-
- response_header_overwrite(srv, con,
- CONST_STR_LEN("Content-Type"),
- CONST_STR_LEN("text/xml; charset=\"utf-8\""));
-
- b = chunkqueue_get_append_buffer(con->send);
-
- buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:lockdiscovery>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:activelock>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:lockscope>"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:"));
- buffer_append_string(b, lockscope);
- buffer_append_string_len(b, CONST_STR_LEN("/>"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:lockscope>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:locktype>"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:"));
- buffer_append_string(b, locktype);
- buffer_append_string_len(b, CONST_STR_LEN("/>"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:locktype>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:depth>"));
- buffer_append_string(b, depth == 0 ? "0" : "infinity");
- buffer_append_string_len(b,CONST_STR_LEN("</D:depth>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:timeout>"));
- buffer_append_string_len(b, CONST_STR_LEN("Second-600"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:timeout>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:owner>"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:owner>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:locktoken>"));
- buffer_append_string_len(b, CONST_STR_LEN("<D:href>"));
- buffer_append_string_buffer(b, locktoken);
- buffer_append_string_len(b, CONST_STR_LEN("</D:href>"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:locktoken>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:activelock>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:lockdiscovery>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n"));
-
- con->send->bytes_in += b->used-1;
-
- return 0;
-}
-#endif
-
-/**
- * check if resource is having the right locks to access to resource
- *
- *
- *
- */
-static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
- int has_lock = 1;
-
-#ifdef USE_LOCKS
- data_string *ds;
-
- UNUSED(srv);
-
- /**
- * This implementation is more fake than real
- * we need a parser for the If: header to really handle the full scope
- *
- * X-Litmus: locks: 11 (owner_modify)
- * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
- * - a tagged check:
- * if http://127.0.0.1:1025/dav/litmus/lockme is locked with
- * opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1, go on
- *
- * X-Litmus: locks: 16 (fail_cond_put)
- * If: (<DAV:no-lock> ["-1622396671"])
- * - untagged:
- * go on if the resource has the etag [...] and the lock
- */
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("If")))) {
- /* Ooh, ooh. A if tag, now the fun begins.
- *
- * this can only work with a real parser
- **/
- } else {
- /* we didn't provided a lock-token -> */
- /* if the resource is locked -> 423 */
-
- sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
-
- sqlite3_reset(stmt);
-
- sqlite3_bind_text(stmt, 1,
- CONST_BUF_LEN(uri),
- SQLITE_TRANSIENT);
-
- while (SQLITE_ROW == sqlite3_step(stmt)) {
- has_lock = 0;
- }
- }
-#else
- UNUSED(srv);
- UNUSED(uri);
- UNUSED(con);
- UNUSED(p);
-#endif
-
- return has_lock;
-}
-
-URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
- plugin_data *p = p_d;
- buffer *b;
- DIR *dir;
- data_string *ds;
- int depth = -1;
- struct stat st;
- buffer *prop_200;
- buffer *prop_404;
- webdav_properties *req_props;
- stat_cache_entry *sce = NULL;
-
- if (con->conf.log_request_handling) {
- TRACE("-- handling request in mod_webdav: %s",
- SAFE_BUF_STR(con->uri.path));
- }
-
- /* PROPFIND need them */
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Depth")))) {
- depth = strtol(ds->value->ptr, NULL, 10);
- }
-
- if (con->conf.log_request_handling) {
- TRACE("depth for %s: %d",
- SAFE_BUF_STR(con->uri.path), depth);
- }
-
- if (con->conf.log_request_handling) {
- TRACE("method for %s: %s",
- SAFE_BUF_STR(con->uri.path), get_http_method_name(con->request.http_method));
- }
-
- switch (con->request.http_method) {
- case HTTP_METHOD_PROPFIND:
- /* they want to know the properties of the directory */
- req_props = NULL;
-
- /* is there a content-body ? */
- if (con->conf.log_request_handling) {
- TRACE("path-name: %s",
- SAFE_BUF_STR(con->physical.path));
- }
-
- switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- case HANDLER_ERROR:
- if (errno == ENOENT) {
- if (con->conf.log_request_handling) {
- TRACE("path-name: %s ... not found",
- SAFE_BUF_STR(con->physical.path));
- }
-
- con->http_status = 404;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- break;
- default:
- break;
- }
-
-
-#ifdef USE_PROPPATCH
- /* any special requests or just allprop ? */
- if (p->conf.sql && con->request.content_length > 0) {
- xmlDocPtr xml;
-
- if (1 == webdav_parse_chunkqueue(srv, con, p, con->recv, &xml)) {
- xmlNode *rootnode = xmlDocGetRootElement(xml);
-
- assert(rootnode);
-
- if (0 == xmlStrcmp(rootnode->name, BAD_CAST "propfind")) {
- xmlNode *cmd;
-
- req_props = calloc(1, sizeof(*req_props));
-
- for (cmd = rootnode->children; cmd; cmd = cmd->next) {
-
- if (0 == xmlStrcmp(cmd->name, BAD_CAST "prop")) {
- /* get prop by name */
- xmlNode *prop;
-
- for (prop = cmd->children; prop; prop = prop->next) {
- if (prop->type == XML_TEXT_NODE) continue; /* ignore WS */
-
- if (prop->ns &&
- (0 == xmlStrcmp(prop->ns->href, BAD_CAST "")) &&
- (0 != xmlStrcmp(prop->ns->prefix, BAD_CAST ""))) {
- size_t i;
-
- ERROR("no name space for: %s", prop->name);
-
- xmlFreeDoc(xml);
-
- for (i = 0; i < req_props->used; i++) {
- free(req_props->ptr[i]->ns);
- free(req_props->ptr[i]->prop);
- free(req_props->ptr[i]);
- }
- free(req_props->ptr);
- free(req_props);
-
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* add property to requested list */
- if (req_props->size == 0) {
- req_props->size = 16;
- req_props->ptr = malloc(sizeof(*(req_props->ptr)) * req_props->size);
- } else if (req_props->used == req_props->size) {
- req_props->size += 16;
- req_props->ptr = realloc(req_props->ptr, sizeof(*(req_props->ptr)) * req_props->size);
- }
-
- req_props->ptr[req_props->used] = malloc(sizeof(webdav_property));
- req_props->ptr[req_props->used]->ns = (char *)xmlStrdup(prop->ns ? prop->ns->href : (xmlChar *)"");
- req_props->ptr[req_props->used]->prop = (char *)xmlStrdup(prop->name);
- req_props->used++;
- }
- } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "propname")) {
- sqlite3_stmt *stmt = p->conf.stmt_select_propnames;
-
- if (stmt) {
- /* get all property names (EMPTY) */
- sqlite3_reset(stmt);
- /* bind the values to the insert */
-
- sqlite3_bind_text(stmt, 1,
- con->uri.path->ptr,
- con->uri.path->used - 1,
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- }
- }
- } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "allprop")) {
- /* get all properties (EMPTY) */
- }
- }
- }
-
- xmlFreeDoc(xml);
- } else {
- ERROR("webdav_parse_chunkqueue() failed: %s", "");
-
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- }
-#endif
- con->http_status = 207;
-
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
-
- b = chunkqueue_get_append_buffer(con->send);
-
- buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n"));
-
- /* allprop */
-
- prop_200 = buffer_init();
- prop_404 = buffer_init();
-
- switch(depth) {
- case 0:
- /* Depth: 0 */
- webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:response>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:href>"));
- buffer_append_string_buffer(b, con->uri.scheme);
- buffer_append_string_len(b,CONST_STR_LEN("://"));
- buffer_append_string_buffer(b, con->uri.authority);
- buffer_append_string_encoded(b, CONST_BUF_LEN(con->uri.path), ENCODING_REL_URI);
- buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n"));
-
- if (!buffer_is_empty(prop_200)) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n"));
-
- buffer_append_string_buffer(b, prop_200);
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 200 OK</D:status>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n"));
- }
- if (!buffer_is_empty(prop_404)) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n"));
-
- buffer_append_string_buffer(b, prop_404);
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 404 Not Found</D:status>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n"));
- }
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n"));
-
- break;
- case 1:
- if (NULL != (dir = opendir(con->physical.path->ptr))) {
- struct dirent *de;
- physical d;
- physical *dst = &(con->physical);
-
- d.path = buffer_init();
- d.rel_path = buffer_init();
-
- while(NULL != (de = readdir(dir))) {
- if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
- continue;
- /* ignore the parent dir */
- }
-
- buffer_copy_string_buffer(d.path, dst->path);
- PATHNAME_APPEND_SLASH(d.path);
-
- buffer_copy_string_buffer(d.rel_path, dst->rel_path);
- PATHNAME_APPEND_SLASH(d.rel_path);
-
- if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
- /* don't append the . */
- } else {
- buffer_append_string(d.path, de->d_name);
- buffer_append_string(d.rel_path, de->d_name);
- }
-
- buffer_reset(prop_200);
- buffer_reset(prop_404);
-
- webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:response>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:href>"));
- buffer_append_string_buffer(b, con->uri.scheme);
- buffer_append_string_len(b,CONST_STR_LEN("://"));
- buffer_append_string_buffer(b, con->uri.authority);
- buffer_append_string_encoded(b, CONST_BUF_LEN(d.rel_path), ENCODING_REL_URI);
- buffer_append_string_len(b,CONST_STR_LEN("</D:href>\n"));
-
- if (!buffer_is_empty(prop_200)) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n"));
-
- buffer_append_string_buffer(b, prop_200);
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 200 OK</D:status>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n"));
- }
- if (!buffer_is_empty(prop_404)) {
- buffer_append_string_len(b,CONST_STR_LEN("<D:propstat>\n"));
- buffer_append_string_len(b,CONST_STR_LEN("<D:prop>\n"));
-
- buffer_append_string_buffer(b, prop_404);
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:prop>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:status>HTTP/1.1 404 Not Found</D:status>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:propstat>\n"));
- }
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:response>\n"));
- }
- closedir(dir);
- buffer_free(d.path);
- buffer_free(d.rel_path);
- }
- break;
- }
-
- if (req_props) {
- size_t i;
- for (i = 0; i < req_props->used; i++) {
- free(req_props->ptr[i]->ns);
- free(req_props->ptr[i]->prop);
- free(req_props->ptr[i]);
- }
- free(req_props->ptr);
- free(req_props);
- }
-
- buffer_free(prop_200);
- buffer_free(prop_404);
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:multistatus>\n"));
-
- if (con->conf.log_request_handling) {
- TRACE("sending XML: %s",
- SAFE_BUF_STR(b));
- }
-
- if (p->conf.log_xml) {
- TRACE("XML-response-body: %s", SAFE_BUF_STR(b));
- }
- con->send->bytes_in += b->used-1;
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- case HTTP_METHOD_MKCOL:
- if (p->conf.is_readonly) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- if (con->request.content_length > 0) {
- /* we don't support MKCOL with a body */
- con->http_status = 415;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- /* let's create the directory */
-
- if (-1 == mkdir(con->physical.path->ptr, WEBDAV_DIR_MODE)) {
- switch(errno) {
- case EPERM:
- con->http_status = 403;
- break;
- case ENOENT:
- case ENOTDIR:
- con->http_status = 409;
- break;
- case EEXIST:
- default:
- con->http_status = 405; /* not allowed */
- break;
- }
- con->mode = DIRECT;
- } else {
- con->http_status = 201;
- con->send->is_closed = 1;
- }
-
- return HANDLER_FINISHED;
- case HTTP_METHOD_DELETE:
- if (p->conf.is_readonly) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* does the client have a lock for this connection ? */
- if (!webdav_has_lock(srv, con, p, con->uri.path)) {
- con->http_status = 423;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* stat and unlink afterwards */
- if (-1 == stat(con->physical.path->ptr, &st)) {
- /* don't about it yet, unlink will fail too */
- switch(errno) {
- case ENOENT:
- con->http_status = 404;
- break;
- default:
- con->http_status = 403;
- break;
- }
- con->mode = DIRECT;
- } else if (S_ISDIR(st.st_mode)) {
- buffer *multi_status_resp = buffer_init();
-
- if (webdav_delete_dir(srv, con, p, &(con->physical), multi_status_resp)) {
- /* we got an error somewhere in between, build a 207 */
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
-
- b = chunkqueue_get_append_buffer(con->send);
-
- buffer_copy_string_len(b, CONST_STR_LEN("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
-
- buffer_append_string_len(b,CONST_STR_LEN("<D:multistatus xmlns:D=\"DAV:\">\n"));
-
- buffer_append_string_buffer(b, multi_status_resp);
-
- buffer_append_string_len(b,CONST_STR_LEN("</D:multistatus>\n"));
-
- if (p->conf.log_xml) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
- }
-
- con->http_status = 207;
- con->send->bytes_in += b->used-1;
- con->send->is_closed = 1;
- } else {
- /* everything went fine, remove the directory */
-
- if (-1 == rmdir(con->physical.path->ptr)) {
- switch(errno) {
- case ENOENT:
- con->http_status = 404;
- break;
- default:
- con->http_status = 501;
- break;
- }
- con->mode = DIRECT;
- } else {
- con->http_status = 204;
- con->send->is_closed = 1;
- }
- }
-
- buffer_free(multi_status_resp);
- } else if (-1 == unlink(con->physical.path->ptr)) {
- switch(errno) {
- case EPERM:
- con->http_status = 403;
- break;
- case ENOENT:
- con->http_status = 404;
- break;
- default:
- con->http_status = 501;
- break;
- }
- con->mode = DIRECT;
- } else {
- con->http_status = 204;
- con->send->is_closed = 1;
- }
- return HANDLER_FINISHED;
- case HTTP_METHOD_PUT: {
- int fd;
- chunkqueue *cq = con->recv;
- chunk *c;
- data_string *ds_range;
-
- if (p->conf.is_readonly) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* is a exclusive lock set on the source */
- if (!webdav_has_lock(srv, con, p, con->uri.path)) {
- con->http_status = 423;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
-
- if (chunkqueue_length(cq) != (off_t)con->request.content_length) {
- ERROR("%s", "chunkqueue_length didn't match request.content_length");
- con->http_status = 500;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
- * - most important Content-Range
- *
- *
- * Example: Content-Range: bytes 100-1037/1038 */
-
- if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Content-Range")))) {
- const char *num = ds_range->value->ptr;
- off_t offset;
- char *err = NULL;
-
- if (0 != strncmp(num, "bytes ", 6)) {
- con->http_status = 501; /* not implemented */
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- /* we only support <num>- ... */
-
- num += 6;
-
- /* skip WS */
- while (*num == ' ' || *num == '\t') num++;
-
- if (*num == '\0') {
- con->http_status = 501; /* not implemented */
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- offset = str_to_off_t(num, &err, 10);
-
- if (offset == STR_OFF_T_MAX ||
- offset == STR_OFF_T_MIN) {
- /**
- * conversion did a over- or underrun
- */
- con->http_status = 501; /* not implemented */
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- if (*err != '-' || offset < 0) {
- con->http_status = 501; /* not implemented */
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, WEBDAV_FILE_MODE))) {
- switch (errno) {
- case ENOENT:
- con->http_status = 404; /* not found */
- break;
- default:
- con->http_status = 403; /* not found */
- break;
- }
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- if (-1 == lseek(fd, offset, SEEK_SET)) {
- con->http_status = 501; /* not implemented */
- con->mode = DIRECT;
-
- close(fd);
-
- return HANDLER_FINISHED;
- }
- con->http_status = 200; /* modified */
- } else {
- /* take what we have in the request-body and write it to a file */
-
- /* if the file doesn't exist, create it */
- if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, WEBDAV_FILE_MODE))) {
- if (errno == ENOENT &&
- -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, WEBDAV_FILE_MODE))) {
- /* we can't open the file */
- con->http_status = 403;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- } else {
- con->http_status = 201; /* created */
- }
- } else {
- con->http_status = 200; /* modified */
- }
- }
-
- con->send->is_closed = 1;
-
- for (c = cq->first; c; c = cq->first) {
- int r = 0;
-
- /* copy all chunks */
- switch(c->type) {
- case FILE_CHUNK:
-
- if (c->file.mmap.start == MAP_FAILED) {
- if (-1 == c->file.fd && /* open the file if not already open */
- -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
-
- return HANDLER_ERROR;
- }
-
- if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
- strerror(errno), c->file.name, c->file.fd);
-
- return HANDLER_ERROR;
- }
-
- c->file.mmap.length = c->file.length;
-
- close(c->file.fd);
- c->file.fd = -1;
-
- /* chunk_reset() or chunk_free() will cleanup for us */
- }
-
- if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
- switch(errno) {
- case ENOSPC:
- con->http_status = 507;
-
- break;
- default:
- con->http_status = 403;
- break;
- }
- }
- break;
- case MEM_CHUNK:
- if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
- switch(errno) {
- case ENOSPC:
- con->http_status = 507;
-
- break;
- default:
- con->http_status = 403;
- break;
- }
- }
- break;
- case UNUSED_CHUNK:
- break;
- }
-
- if (r > 0) {
- c->offset += r;
- cq->bytes_out += r;
- } else {
- break;
- }
- chunkqueue_remove_finished_chunks(cq);
- }
- close(fd);
-
- return HANDLER_FINISHED;
- }
- case HTTP_METHOD_MOVE:
- case HTTP_METHOD_COPY: {
- buffer *destination = NULL;
- char *sep, *start;
- int overwrite = 1;
-
- if (p->conf.is_readonly) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* is a exclusive lock set on the source */
- if (con->request.http_method == HTTP_METHOD_MOVE) {
- if (!webdav_has_lock(srv, con, p, con->uri.path)) {
- con->http_status = 423;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- }
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Destination")))) {
- destination = ds->value;
- } else {
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Overwrite")))) {
- if (ds->value->used != 2 ||
- (ds->value->ptr[0] != 'F' &&
- ds->value->ptr[0] != 'T') ) {
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- overwrite = (ds->value->ptr[0] == 'F' ? 0 : 1);
- }
- /* let's parse the Destination
- *
- * http://127.0.0.1:1025/dav/litmus/copydest
- *
- * - host has to be the same as the Host: header we got
- * - we have to stay inside the document root
- * - the query string is thrown away
- * */
-
- buffer_reset(p->uri.scheme);
- buffer_reset(p->uri.path_raw);
- buffer_reset(p->uri.authority);
-
- start = destination->ptr;
-
- if (NULL == (sep = strstr(start, "://"))) {
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- buffer_copy_string_len(p->uri.scheme, start, sep - start);
-
- start = sep + 3;
-
- if (NULL == (sep = strchr(start, '/'))) {
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- buffer_copy_string_len(p->uri.authority, start, sep - start);
-
- start = sep + 1;
-
- if (NULL == (sep = strchr(start, '?'))) {
- /* no query string, good */
- buffer_copy_string(p->uri.path_raw, start);
- } else {
- buffer_copy_string_len(p->uri.path_raw, start, sep - start);
- }
-
- if (!buffer_is_equal(p->uri.authority, con->uri.authority)) {
- /* not the same host */
- con->http_status = 502;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- buffer_copy_string_buffer(p->tmp_buf, p->uri.path_raw);
- buffer_urldecode_path(p->tmp_buf);
- buffer_path_simplify(p->uri.path, p->tmp_buf);
-
- /* we now have a URI which is clean. transform it into a physical path */
- buffer_copy_string_buffer(p->physical.doc_root, con->physical.doc_root);
- buffer_copy_string_buffer(p->physical.rel_path, p->uri.path);
-
- if (con->conf.force_lowercase_filenames) {
- buffer_to_lower(p->physical.rel_path);
- }
-
- buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
- PATHNAME_APPEND_SLASH(p->physical.path);
- buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
-
- /* don't add a second / */
- if (p->physical.rel_path->ptr[0] == '/') {
- buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
- } else {
- buffer_append_string_buffer(p->physical.path, p->physical.rel_path);
- }
-
- /* let's see if the source is a directory
- * if yes, we fail with 501 */
-
- if (-1 == stat(con->physical.path->ptr, &st)) {
- /* don't about it yet, unlink will fail too */
- switch(errno) {
- case ENOENT:
- con->http_status = 404;
- break;
- default:
- con->http_status = 403;
- break;
- }
- con->mode = DIRECT;
- } else if (S_ISDIR(st.st_mode)) {
- int r;
- /* src is a directory */
-
- con->http_status = 204;
- con->send->is_closed = 1;
- if (-1 == stat(p->physical.path->ptr, &st)) {
- if (-1 == mkdir(p->physical.path->ptr, WEBDAV_DIR_MODE)) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- con->http_status = 201;
- } else if (!S_ISDIR(st.st_mode)) {
- if (overwrite == 0) {
- /* copying into a non-dir ? */
- con->http_status = 409;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- } else {
- unlink(p->physical.path->ptr);
- if (-1 == mkdir(p->physical.path->ptr, WEBDAV_DIR_MODE)) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- }
- }
-
- /* copy the content of src to dest */
- if (0 != (r = webdav_copy_dir(srv, con, p, &(con->physical), &(p->physical), overwrite))) {
- con->http_status = r;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- if (con->request.http_method == HTTP_METHOD_MOVE) {
- b = buffer_init();
- webdav_delete_dir(srv, con, p, &(con->physical), b); /* content */
- buffer_free(b);
-
- rmdir(con->physical.path->ptr);
- }
- } else {
- /* it is just a file, good */
- int r;
-
- /* does the client have a lock for this connection ? */
- if (!webdav_has_lock(srv, con, p, p->uri.path)) {
- con->http_status = 423;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* destination exists */
- if (0 == (r = stat(p->physical.path->ptr, &st))) {
- if (S_ISDIR(st.st_mode)) {
- /* file to dir/
- * append basename to physical path */
-
- if (NULL != (sep = strrchr(con->physical.path->ptr, '/'))) {
- buffer_append_string(p->physical.path, sep);
- r = stat(p->physical.path->ptr, &st);
- }
- }
- }
-
- if (-1 == r) {
- con->http_status = 201; /* we will create a new one */
- con->send->is_closed = 1;
-
- switch(errno) {
- case ENOTDIR:
- con->http_status = 409;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- } else if (overwrite == 0) {
- /* destination exists, but overwrite is not set */
- con->http_status = 412;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- } else {
- con->http_status = 204; /* resource already existed */
- con->send->is_closed = 1;
- }
-
- if (con->request.http_method == HTTP_METHOD_MOVE) {
- /* try a rename */
-
- if (0 == rename(con->physical.path->ptr, p->physical.path->ptr)) {
-#ifdef USE_PROPPATCH
- sqlite3_stmt *stmt = p->conf.stmt_move_uri;
-
- if (stmt) {
-
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
- sqlite3_bind_text(stmt, 1,
- p->uri.path->ptr,
- p->uri.path->used - 1,
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 2,
- con->uri.path->ptr,
- con->uri.path->used - 1,
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
- }
- }
-#endif
- return HANDLER_FINISHED;
- }
-
- /* rename failed, fall back to COPY + DELETE */
- }
-
- if (0 != (r = webdav_copy_file(srv, con, p, &(con->physical), &(p->physical), overwrite))) {
- con->http_status = r;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- if (con->request.http_method == HTTP_METHOD_MOVE) {
- b = buffer_init();
- webdav_delete_file(srv, con, p, &(con->physical), b);
- buffer_free(b);
- }
- }
-
- return HANDLER_FINISHED;
- }
- case HTTP_METHOD_PROPPATCH:
- if (p->conf.is_readonly) {
- con->http_status = 403;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- if (!webdav_has_lock(srv, con, p, con->uri.path)) {
- con->http_status = 423;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
-
- /* check if destination exists */
- if (-1 == stat(con->physical.path->ptr, &st)) {
- switch(errno) {
- case ENOENT:
- con->http_status = 404;
- con->mode = DIRECT;
- break;
- }
- }
-
-#ifdef USE_PROPPATCH
- if (p->conf.sql && con->request.content_length > 0) {
- xmlDocPtr xml;
-
- if (1 == webdav_parse_chunkqueue(srv, con, p, con->recv, &xml)) {
- xmlNode *rootnode = xmlDocGetRootElement(xml);
-
- if (0 == xmlStrcmp(rootnode->name, BAD_CAST "propertyupdate")) {
- xmlNode *cmd;
- char *err = NULL;
- int empty_ns = 0; /* send 400 on a empty namespace attribute */
-
- /* start response */
-
- if (SQLITE_OK != sqlite3_exec(p->conf.sql, "BEGIN TRANSACTION", NULL, NULL, &err)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
- sqlite3_free(err);
-
- goto propmatch_cleanup;
- }
-
- /* a UPDATE request, we know 'set' and 'remove' */
- for (cmd = rootnode->children; cmd; cmd = cmd->next) {
- xmlNode *props;
- /* either set or remove */
-
- if ((0 == xmlStrcmp(cmd->name, BAD_CAST "set")) ||
- (0 == xmlStrcmp(cmd->name, BAD_CAST "remove"))) {
-
- sqlite3_stmt *stmt;
-
- stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
- p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
-
- for (props = cmd->children; props; props = props->next) {
- if (0 == xmlStrcmp(props->name, BAD_CAST "prop")) {
- xmlNode *prop;
- int r;
-
- prop = props->children;
-
- if (prop->ns &&
- (0 == xmlStrcmp(prop->ns->href, BAD_CAST "")) &&
- (0 != xmlStrcmp(prop->ns->prefix, BAD_CAST ""))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "no name space for:",
- prop->name);
-
- empty_ns = 1;
- break;
- }
-
- sqlite3_reset(stmt);
-
- /* bind the values to the insert */
-
- sqlite3_bind_text(stmt, 1,
- con->uri.path->ptr,
- con->uri.path->used - 1,
- SQLITE_TRANSIENT);
- sqlite3_bind_text(stmt, 2,
- (char *)prop->name,
- strlen((char *)prop->name),
- SQLITE_TRANSIENT);
- if (prop->ns) {
- sqlite3_bind_text(stmt, 3,
- (char *)prop->ns->href,
- strlen((char *)prop->ns->href),
- SQLITE_TRANSIENT);
- } else {
- sqlite3_bind_text(stmt, 3,
- "",
- 0,
- SQLITE_TRANSIENT);
- }
- if (stmt == p->conf.stmt_update_prop) {
- sqlite3_bind_text(stmt, 4,
- (char *)xmlNodeGetContent(prop),
- strlen((char *)xmlNodeGetContent(prop)),
- SQLITE_TRANSIENT);
- }
-
- if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "sql-set failed:", sqlite3_errmsg(p->conf.sql));
- }
- }
- }
- if (empty_ns) break;
- }
- }
-
- if (empty_ns) {
- if (SQLITE_OK != sqlite3_exec(p->conf.sql, "ROLLBACK", NULL, NULL, &err)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't rollback transaction:", err);
- sqlite3_free(err);
-
- goto propmatch_cleanup;
- }
-
- con->http_status = 400;
- con->mode = DIRECT;
- } else {
- if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't commit transaction:", err);
- sqlite3_free(err);
-
- goto propmatch_cleanup;
- }
- con->http_status = 200;
- }
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- }
-
-propmatch_cleanup:
-
- xmlFreeDoc(xml);
- } else {
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- }
-#endif
- con->http_status = 501;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- case HTTP_METHOD_LOCK:
- /**
- * a mac wants to write
- *
- * LOCK /dav/expire.txt HTTP/1.1\r\n
- * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
- * Accept: * / *\r\n
- * Depth: 0\r\n
- * Timeout: Second-600\r\n
- * Content-Type: text/xml; charset=\"utf-8\"\r\n
- * Content-Length: 229\r\n
- * Connection: keep-alive\r\n
- * Host: 192.168.178.23:1025\r\n
- * \r\n
- * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
- * <D:lockinfo xmlns:D=\"DAV:\">\n
- * <D:lockscope><D:exclusive/></D:lockscope>\n
- * <D:locktype><D:write/></D:locktype>\n
- * <D:owner>\n
- * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
- * </D:owner>\n
- * </D:lockinfo>\n
- */
-
- if (depth != 0 && depth != -1) {
- con->http_status = 400;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
-#ifdef USE_LOCKS
- if (p->conf.sql && con->request.content_length > 0) {
- xmlDocPtr xml;
- buffer *hdr_if = NULL;
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("If")))) {
- hdr_if = ds->value;
- }
-
- /* we don't support Depth: Infinity on locks */
- if (hdr_if == NULL && depth == -1) {
- con->http_status = 409; /* Conflict */
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- if (1 == webdav_parse_chunkqueue(srv, con, p, con->recv, &xml)) {
- xmlNode *rootnode = xmlDocGetRootElement(xml);
-
- assert(rootnode);
-
- if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
- xmlNode *lockinfo;
- const xmlChar *lockscope = NULL, *locktype = NULL; /* unused variable: , *owner = NULL; */
-
- for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
- if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
- xmlNode *value;
- for (value = lockinfo->children; value; value = value->next) {
- if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
- (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
- lockscope = value->name;
- } else {
- con->http_status = 400;
- con->mode = DIRECT;
-
- xmlFreeDoc(xml);
- return HANDLER_FINISHED;
- }
- }
- } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
- xmlNode *value;
- for (value = lockinfo->children; value; value = value->next) {
- if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
- locktype = value->name;
- } else {
- con->http_status = 400;
- con->mode = DIRECT;
-
- xmlFreeDoc(xml);
- return HANDLER_FINISHED;
- }
- }
-
- } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
- }
- }
-
- if (lockscope && locktype) {
- sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
-
- /* is this resourse already locked ? */
-
- /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
- * FROM locks
- * WHERE resource = ? */
-
- if (stmt) {
-
- sqlite3_reset(stmt);
-
- sqlite3_bind_text(stmt, 1,
- p->uri.path->ptr,
- p->uri.path->used - 1,
- SQLITE_TRANSIENT);
-
- /* it is the PK */
- while (SQLITE_ROW == sqlite3_step(stmt)) {
- /* we found a lock
- * 1. is it compatible ?
- * 2. is it ours */
- char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
-
- if (strcmp(sql_lockscope, "exclusive")) {
- con->http_status = 423;
- con->mode = DIRECT;
- } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
- /* resourse is locked with a shared lock
- * client wants exclusive */
- con->http_status = 423;
- con->mode = DIRECT;
- }
- }
- if (con->http_status == 423) {
- xmlFreeDoc(xml);
- return HANDLER_FINISHED;
- }
- }
-
- stmt = p->conf.stmt_create_lock;
- if (stmt) {
- /* create a lock-token */
- uuid_t id;
- char uuid[37] /* 36 + \0 */;
-
- uuid_generate(id);
- uuid_unparse(id, uuid);
-
- buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("opaquelocktoken:"));
- buffer_append_string(p->tmp_buf, uuid);
-
- /* "CREATE TABLE locks ("
- * " locktoken TEXT NOT NULL,"
- * " resource TEXT NOT NULL,"
- * " lockscope TEXT NOT NULL,"
- * " locktype TEXT NOT NULL,"
- * " owner TEXT NOT NULL,"
- * " depth INT NOT NULL,"
- */
-
- sqlite3_reset(stmt);
-
- sqlite3_bind_text(stmt, 1,
- CONST_BUF_LEN(p->tmp_buf),
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 2,
- CONST_BUF_LEN(con->uri.path),
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 3,
- (const char *)lockscope,
- xmlStrlen(lockscope),
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 4,
- (const char *)locktype,
- +xmlStrlen(locktype),
- SQLITE_TRANSIENT);
-
- /* owner */
- sqlite3_bind_text(stmt, 5,
- "",
- 0,
- SQLITE_TRANSIENT);
-
- /* depth */
- sqlite3_bind_int(stmt, 6,
- depth);
-
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "create lock:", sqlite3_errmsg(p->conf.sql));
- }
-
- /* looks like we survived */
- webdav_lockdiscovery(srv, con, p->tmp_buf, (const char *)lockscope, (const char *)locktype, depth);
-
- con->http_status = 201;
- con->send->is_closed = 1;
- }
- }
- }
-
- xmlFreeDoc(xml);
- return HANDLER_FINISHED;
- } else {
- con->http_status = 400;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
- }
- } else {
-
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("If")))) {
- buffer *locktoken = ds->value;
- sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
-
- /* remove the < > around the token */
- if (locktoken->used < 6) {
- con->http_status = 400;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
-
- sqlite3_reset(stmt);
-
- sqlite3_bind_text(stmt, 1,
- CONST_BUF_LEN(p->tmp_buf),
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- TRACE("refresh lock failed: %s", sqlite3_errmsg(p->conf.sql));
- }
-
- webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
-
- con->http_status = 200;
- con->send->is_closed = 1;
- return HANDLER_FINISHED;
- } else {
- /* we need a lock-token to refresh */
- con->http_status = 400;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
- }
- break;
-#else
- con->http_status = 501;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
-#endif
- case HTTP_METHOD_UNLOCK:
-#ifdef USE_LOCKS
- if (NULL != (ds = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("Lock-Token")))) {
- buffer *locktoken = ds->value;
- sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
-
- /* remove the < > around the token */
- if (locktoken->used < 4) {
- con->http_status = 400;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
-
- /**
- * FIXME:
- *
- * if the resourse is locked:
- * - by us: unlock
- * - by someone else: 401
- * if the resource is not locked:
- * - 412
- * */
-
- buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
-
- sqlite3_reset(stmt);
-
- sqlite3_bind_text(stmt, 1,
- CONST_BUF_LEN(p->tmp_buf),
- SQLITE_TRANSIENT);
-
- sqlite3_bind_text(stmt, 2,
- CONST_BUF_LEN(con->uri.path),
- SQLITE_TRANSIENT);
-
- if (SQLITE_DONE != sqlite3_step(stmt)) {
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "remove lock:", sqlite3_errmsg(p->conf.sql));
- }
-
- if (0 == sqlite3_changes(p->conf.sql)) {
- con->http_status = 401;
- con->mode = DIRECT;
- } else {
- con->http_status = 204;
- con->send->is_closed = 1;
- }
- return HANDLER_FINISHED;
- } else {
- /* we need a lock-token to unlock */
- con->http_status = 400;
- con->mode = DIRECT;
-
- return HANDLER_FINISHED;
- }
- break;
-#else
- con->http_status = 501;
- con->mode = DIRECT;
- return HANDLER_FINISHED;
-#endif
- default:
- break;
- }
-
- /* not found */
- return HANDLER_GO_ON;
-}
-
-/**
- * calls the request-handler if we have received all the content
- */
-CONNECTION_FUNC(mod_webdav_recv_request_content) {
- chunkqueue *in = con->recv;
- plugin_data *p = p_d;
- handler_t res;
-
- /**
- * is the content for webdav
- */
- if (con->mode != p->id) return HANDLER_GO_ON;
-
- if (!in->is_closed) return HANDLER_GO_ON;
-
- /* we received all the content, let's call the webdav handler */
-
- res = mod_webdav_subrequest_handler(srv, con, p_d);
-
- /* mark body as read */
- con->recv->bytes_out += chunkqueue_skip(con->recv, con->recv->bytes_in - con->recv->bytes_out);
- chunkqueue_remove_finished_chunks(con->recv);
-
- return res;
-}
-
-/* this function is called at dlopen() time and inits the callbacks */
-
-LI_EXPORT int mod_webdav_plugin_init(plugin *p);
-LI_EXPORT int mod_webdav_plugin_init(plugin *p) {
- p->version = LIGHTTPD_VERSION_ID;
- p->name = buffer_init_string("webdav");
-
- p->init = mod_webdav_init;
- p->handle_uri_clean = mod_webdav_uri_handler; /* check if we handle this URL */
-#if 0
- /* will get called when the content is received */
-#endif
- p->handle_physical = mod_webdav_physical_handler;
- p->handle_send_request_content = mod_webdav_recv_request_content; /* check if we received all the content */
- p->set_defaults = mod_webdav_set_defaults;
- p->cleanup = mod_webdav_free;
-
- p->data = NULL;
-
- return 0;
-}
diff --git a/src/network.c b/src/network.c
deleted file mode 100644
index 988dc940..00000000
--- a/src/network.c
+++ /dev/null
@@ -1,891 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include <stdio.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "connections.h"
-#include "plugin.h"
-#include "joblist.h"
-
-#include "network_backends.h"
-#include "sys-mmap.h"
-#include "sys-socket.h"
-#include "sys-files.h"
-
-#ifdef USE_OPENSSL
-# include <openssl/ssl.h>
-# include <openssl/err.h>
-# include <openssl/rand.h>
-#endif
-
-#define BACKEND_HANDLERS(read, write) network_read_chunkqueue_##read, network_write_chunkqueue_##write
-static network_backend_info_t network_backends[] = {
- /* lowest id wins */
- {
- NETWORK_BACKEND_LINUX_SENDFILE,
- "linux-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_LINUX_SENDFILE
- BACKEND_HANDLERS(read, linuxsendfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_LINUX_AIO_SENDFILE,
- "linux-aio-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_LINUX_AIO_SENDFILE
- BACKEND_HANDLERS(read, linuxaiosendfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_FREEBSD_SENDFILE,
- "freebsd-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_FREEBSD_SENDFILE
- BACKEND_HANDLERS(read, freebsdsendfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_SOLARIS_SENDFILEV,
- "solaris-sendfilev",
- NULL,
-#if defined USE_WRITE && defined USE_SOLARIS_SENDFILEV
- BACKEND_HANDLERS(read, solarissendfilev)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_POSIX_AIO,
- "posix-aio",
- NULL,
-#if defined USE_WRITE && defined USE_POSIX_AIO
- BACKEND_HANDLERS(read, posixaio)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_GTHREAD_AIO,
- "gthread-aio",
- NULL,
-#if defined USE_WRITE && defined USE_GTHREAD_AIO
- BACKEND_HANDLERS(read, gthreadaio)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_GTHREAD_SENDFILE,
- "gthread-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_GTHREAD_AIO && defined USE_GTHREAD_SENDFILE
- BACKEND_HANDLERS(read, gthreadsendfile)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_GTHREAD_FREEBSD_SENDFILE,
- "gthread-freebsd-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_GTHREAD_AIO && defined USE_GTHREAD_FREEBSD_SENDFILE
- BACKEND_HANDLERS(read, gthreadfreebsdsendfile)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_WRITEV,
- "writev",
- NULL,
-#if defined USE_WRITE && defined USE_WRITEV
- BACKEND_HANDLERS(read, writev)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_WRITE,
- "write",
- NULL,
-#if defined USE_WRITE
- BACKEND_HANDLERS(read, write)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_WIN32_TRANSMITFILE,
- "win32-transmitfile",
- NULL,
-#if defined USE_WIN32_TRANSMITFILE
- BACKEND_HANDLERS(win32recv, win32transmitfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_WIN32_SEND,
- "win32-send",
- NULL,
-#if defined USE_WIN32_SEND && defined USE_WIN32_SEND
- BACKEND_HANDLERS(win32recv, win32send)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_UNSET,
- NULL,
- NULL,
- NULL, NULL
- }
-};
-
-const network_backend_info_t *network_get_backends() {
- return network_backends;
-}
-
-const network_backend_info_t *network_get_defaultbackend() {
- const network_backend_info_t *backend = network_get_backends();
-
- while (backend->name) {
- if (backend->write_handler) {
- return backend;
- }
- backend ++;
- }
-
- return NULL;
-}
-
-const network_backend_info_t *network_get_backend_info_by_type(network_backend_t type) {
- const network_backend_info_t *backend = network_get_backends();
-
- while (backend->name) {
- if (type == backend->type) {
- return backend;
- }
- backend ++;
- }
-
- return NULL;
-}
-
-const network_backend_info_t *network_get_backend_info_by_name(const char *name) {
- const network_backend_info_t *backend = network_get_backends();
-
- while (backend->name) {
- if (strcmp(name, backend->name) == 0) {
- return backend;
- }
- backend ++;
- }
-
- return NULL;
-}
-
-handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
- server *srv = (server *)s;
- server_socket *srv_socket = (server_socket *)context;
- connection *con;
- int loops = 0;
-
- UNUSED(context);
-
- if (revents != FDEVENT_IN) {
- log_error_write(srv, __FILE__, __LINE__, "sdd",
- "strange event for server socket",
- srv_socket->sock->fd,
- revents);
- return HANDLER_ERROR;
- }
-
- /* accept()s at most 100 connections directly
- *
- * we jump out after 100 to give the waiting connections a chance */
- for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
- joblist_append(srv, con);
- }
- return HANDLER_GO_ON;
-}
-
-#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
-static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) {
- const char *servername;
- connection *con = (connection *) SSL_get_app_data(ssl);
-
- UNUSED(al);
-
- buffer_copy_string(con->uri.scheme, "https");
-
- if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
-#if 0
- /* this "error" just means the client didn't support it */
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "failed to get TLS server name");
-#endif
- return SSL_TLSEXT_ERR_NOACK;
- }
- buffer_copy_string(con->sock->tlsext_server_name, servername);
- buffer_to_lower(con->sock->tlsext_server_name);
-
- config_patch_connection(srv, con, COMP_SERVER_SOCKET);
- config_patch_connection(srv, con, COMP_HTTP_SCHEME);
- config_patch_connection(srv, con, COMP_HTTP_HOST);
-
- if (NULL == con->conf.ssl_ctx) {
- /* ssl_ctx <=> pemfile was set <=> ssl_ctx got patched: so this should never happen */
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- "null SSL_CTX for TLS server name", con->sock->tlsext_server_name);
- return SSL_TLSEXT_ERR_ALERT_FATAL;
- }
-
- /* switch to new SSL_CTX in reaction to a client's server_name extension */
- if (con->conf.ssl_ctx != SSL_set_SSL_CTX(ssl, con->conf.ssl_ctx)) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- "failed to set SSL_CTX for TLS server name", con->sock->tlsext_server_name);
- return SSL_TLSEXT_ERR_ALERT_FATAL;
- }
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif
-
-static int network_server_init(server *srv, buffer *host_token, specific_config *s) {
- int val;
- socklen_t addr_len;
- server_socket *srv_socket;
- char *sp;
- unsigned int port = 0;
- const char *host;
- buffer *b;
- int is_unix_domain_socket = 0;
- int fd;
-
-#ifdef SO_ACCEPTFILTER
- struct accept_filter_arg afa;
-#endif
-
-#ifdef _WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-
- wVersionRequested = MAKEWORD( 2, 2 );
-
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 ) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- return -1;
- }
-#endif
-
- srv_socket = calloc(1, sizeof(*srv_socket));
- srv_socket->sock = iosocket_init();
-
- srv_socket->srv_token = buffer_init();
- buffer_copy_string_buffer(srv_socket->srv_token, host_token);
-
- b = buffer_init();
- buffer_copy_string_buffer(b, host_token);
-
- /* ipv4:port
- * [ipv6]:port
- */
- if (NULL == (sp = strrchr(b->ptr, ':'))) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
-
- goto error_free_socket;
- }
-
- host = b->ptr;
-
- /* check for [ and ] */
- if (b->ptr[0] == '[' && *(sp-1) == ']') {
- *(sp-1) = '\0';
- host++;
-
- s->use_ipv6 = 1;
- }
-
- *(sp++) = '\0';
-
- port = strtol(sp, NULL, 10);
-
- if (host[0] == '/') {
- /* host is a unix-domain-socket */
- is_unix_domain_socket = 1;
- } else if (port == 0 || port > 65535) {
- log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
-
- goto error_free_socket;
- }
-
- if (*host == '\0') host = NULL;
-
- if (is_unix_domain_socket) {
-#ifdef HAVE_SYS_UN_H
-
- srv_socket->addr.plain.sa_family = AF_UNIX;
-
- if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
- goto error_free_socket;
- }
-#else
- log_error_write(srv, __FILE__, __LINE__, "s",
- "ERROR: Unix Domain sockets are not supported.");
- goto error_free_socket;
-#endif
- }
-
-#ifdef HAVE_IPV6
- if (s->use_ipv6) {
- srv_socket->addr.plain.sa_family = AF_INET6;
-
- if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
- goto error_free_socket;
- }
- srv_socket->use_ipv6 = 1;
- }
-#endif
-
- if (srv_socket->sock->fd == -1) {
- srv_socket->addr.plain.sa_family = AF_INET;
- if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
- goto error_free_socket;
- }
- }
-
- val = 1;
- if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
- goto error_free_socket;
- }
-
- switch(srv_socket->addr.plain.sa_family) {
-#ifdef HAVE_IPV6
- case AF_INET6:
- memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in6));
- srv_socket->addr.ipv6.sin6_family = AF_INET6;
- if (host == NULL) {
- srv_socket->addr.ipv6.sin6_addr = in6addr_any;
- } else {
- struct addrinfo hints, *res;
- int r;
-
- memset(&hints, 0, sizeof(hints));
-
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
- log_error_write(srv, __FILE__, __LINE__,
- "sssss", "getaddrinfo failed: ",
- gai_strerror(r), "'", host, "'");
-
- goto error_free_socket;
- }
-
- memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
-
- freeaddrinfo(res);
- }
- srv_socket->addr.ipv6.sin6_port = htons(port);
- addr_len = sizeof(struct sockaddr_in6);
- break;
-#endif
- case AF_INET:
- memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in));
- srv_socket->addr.ipv4.sin_family = AF_INET;
- if (host == NULL) {
- srv_socket->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
- } else {
- struct hostent *he;
- if (NULL == (he = gethostbyname(host))) {
- log_error_write(srv, __FILE__, __LINE__,
- "sds", "gethostbyname failed: ",
- h_errno, host);
- goto error_free_socket;
- }
-
- if (he->h_addrtype != AF_INET) {
- log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
- goto error_free_socket;
- }
-
- if (he->h_length != sizeof(struct in_addr)) {
- log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
- goto error_free_socket;
- }
-
- memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
- }
- srv_socket->addr.ipv4.sin_port = htons(port);
-
- addr_len = sizeof(struct sockaddr_in);
-
- break;
-#ifndef _WIN32
- case AF_UNIX:
- srv_socket->addr.un.sun_family = AF_UNIX;
- strcpy(srv_socket->addr.un.sun_path, host);
-
-#ifdef SUN_LEN
- addr_len = SUN_LEN(&srv_socket->addr.un);
-#else
- /* stevens says: */
- addr_len = strlen(host) + 1 + sizeof(srv_socket->addr.un.sun_family);
-#endif
-
- /* check if the socket exists and try to connect to it. */
- if (-1 != (fd = connect(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
- close(fd);
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "server socket is still in use:",
- host);
-
-
- goto error_free_socket;
- }
-
- /* connect failed */
- switch(errno) {
- case ECONNREFUSED:
- unlink(host);
- break;
- case ENOENT:
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "testing socket failed:",
- host, strerror(errno));
-
- goto error_free_socket;
- }
-
- break;
-#endif
- default:
- addr_len = 0;
-
- goto error_free_socket;
- }
-
- if (0 != bind(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
- switch(srv_socket->addr.plain.sa_family) {
- case AF_UNIX:
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "can't bind to socket:",
- host, strerror(errno));
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssds",
- "can't bind to port:",
- host, port, strerror(errno));
- break;
- }
- goto error_free_socket;
- }
-
- if (-1 == listen(srv_socket->sock->fd, 128 * 8)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
- goto error_free_socket;
- }
-
- if (s->is_ssl) {
-#ifdef USE_OPENSSL
- if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
- goto error_free_socket;
- }
-#else
-
- buffer_free(srv_socket->srv_token);
- free(srv_socket);
-
- buffer_free(b);
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "ssl requested but openssl support is not compiled in");
-
- goto error_free_socket;
-#endif
- } else {
-#ifdef SO_ACCEPTFILTER
- /*
- * FreeBSD accf_http filter
- *
- */
- memset(&afa, 0, sizeof(afa));
- strcpy(afa.af_name, "httpready");
- if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
- if (errno != ENOENT) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't set accept-filter 'httpready': ", strerror(errno));
- }
- }
-#endif
- }
-
-#ifdef FD_CLOEXEC
- /* set FD_CLOEXEC now, fdevent_fcntl_set is called later; needed for pipe-logger forks */
- fcntl(srv_socket->sock->fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- srv_socket->is_ssl = s->is_ssl;
-
- if (srv->srv_sockets.size == 0) {
- srv->srv_sockets.size = 4;
- srv->srv_sockets.used = 0;
- srv->srv_sockets.ptr = malloc(srv->srv_sockets.size * sizeof(server_socket));
- } else if (srv->srv_sockets.used == srv->srv_sockets.size) {
- srv->srv_sockets.size += 4;
- srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
- }
-
- srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
- buffer_free(b);
-
- return 0;
-
-error_free_socket:
- iosocket_free(srv_socket->sock);
- buffer_free(srv_socket->srv_token);
- free(srv_socket);
-
- return -1;
-}
-
-int network_close(server *srv) {
- size_t i;
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
-
- if (srv_socket->sock->fd != -1) {
- /* check if server fd are already registered */
- if (srv_socket->sock->fde_ndx != -1) {
- fdevent_event_del(srv->ev, srv_socket->sock);
- fdevent_unregister(srv->ev, srv_socket->sock);
- }
- }
-
- iosocket_free(srv_socket->sock);
-
- buffer_free(srv_socket->srv_token);
-
- free(srv_socket);
- }
-
-#ifdef USE_OPENSSL
- ERR_free_strings();
-#endif
- free(srv->srv_sockets.ptr);
-
- return 0;
-}
-
-int network_init(server *srv) {
- buffer *b;
- size_t i;
- const network_backend_info_t *backend;
-
-#ifdef USE_OPENSSL
- /* load SSL certificates */
- for (i = 0; i < srv->config_context->used; i++) {
- specific_config *s = srv->config_storage[i];
-
- if (buffer_is_empty(s->ssl_pemfile)) continue;
-
-#ifdef OPENSSL_NO_TLSEXT
- {
- data_config *dc = (data_config *)srv->config_context->data[i];
- if (COMP_HTTP_HOST == dc->comp) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
- return -1;
- }
- }
-#endif
-
- if (srv->ssl_is_init == 0) {
- SSL_load_error_strings();
- SSL_library_init();
- srv->ssl_is_init = 1;
-
- if (0 == RAND_status()) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "not enough entropy in the pool");
- return -1;
- }
- }
-
- if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
-
- if (!s->ssl_use_sslv2) {
- /* disable SSLv2 */
- if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
- }
-
- if (!buffer_is_empty(s->ssl_cipher_list)) {
- if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
- }
-
- if (!buffer_is_empty(s->ssl_ca_file)) {
- if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
- return -1;
- }
- if (s->ssl_verifyclient) {
- STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
- if (!certs) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
- }
- if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
- SSL_CTX_set_client_CA_list(s->ssl_ctx, certs);
- SSL_CTX_set_verify(
- s->ssl_ctx,
- SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
- NULL
- );
- SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
- }
- } else if (s->ssl_verifyclient) {
- log_error_write(
- srv, __FILE__, __LINE__, "s",
- "SSL: You specified ssl.verifyclient.activate but no ca_file"
- );
- }
-
- if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
- return -1;
- }
-
- if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
- return -1;
- }
-
- if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
- "Private key does not match the certificate public key, reason:",
- ERR_error_string(ERR_get_error(), NULL),
- s->ssl_pemfile);
- return -1;
- }
-
-#ifndef OPENSSL_NO_TLSEXT
- if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
- !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
- return -1;
- }
-#endif
- }
-#endif
-
- b = buffer_init();
-
- buffer_copy_string_buffer(b, srv->srvconf.bindhost);
- buffer_append_string_len(b, CONST_STR_LEN(":"));
- buffer_append_long(b, srv->srvconf.port);
-
- if (0 != network_server_init(srv, b, srv->config_storage[0])) {
- return -1;
- }
- buffer_free(b);
-
-#ifdef USE_OPENSSL
- srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
-#endif
-
- backend = network_get_backend_info_by_type(srv->network_backend);
- assert(backend && backend->read_handler);
- srv->network_backend_read = backend->read_handler;
- srv->network_backend_write = backend->write_handler;
-
-#ifdef USE_OPENSSL
- srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
- srv->network_ssl_backend_read = network_read_chunkqueue_openssl;
-#endif
-
- /* check for $SERVER["socket"] */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- specific_config *s = srv->config_storage[i];
- size_t j;
-
- /* not our stage */
- if (COMP_SERVER_SOCKET != dc->comp) continue;
-
- if (dc->cond != CONFIG_COND_EQ) continue;
-
- /* check if we already know this socket,
- * if yes, don't init it */
- for (j = 0; j < srv->srv_sockets.used; j++) {
- if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
- break;
- }
- }
-
- if (j == srv->srv_sockets.used) {
- if (0 != network_server_init(srv, dc->string, s)) return -1;
- }
- }
-
- return 0;
-}
-
-int network_register_fdevents(server *srv) {
- size_t i;
- if (-1 == fdevent_reset(srv->ev)) {
- return -1;
- }
- /* register fdevents after reset */
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
- fdevent_register(srv->ev, srv_socket->sock, network_server_handle_fdevent, srv_socket);
- fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN);
- }
- return 0;
-}
-
-network_status_t network_read(server *srv, connection *con, iosocket *sock, chunkqueue *cq) {
- server_socket *srv_socket = con->srv_socket;
- network_status_t ret = NETWORK_STATUS_UNSET;
- off_t start_bytes_in = cq->bytes_in;
-
- if (srv_socket->is_ssl) {
-#ifdef USE_OPENSSL
- ret = srv->network_ssl_backend_read(srv, con, sock, cq);
-#else
- ret = NETWORK_STATUS_FATAL_ERROR;
-#endif
- } else {
- ret = srv->network_backend_read(srv, con, sock, cq);
- }
-
- con->bytes_read += cq->bytes_in - start_bytes_in;
-
- return ret;
-}
-
-network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
- network_status_t ret = NETWORK_STATUS_UNSET;
- off_t written = 0;
-#ifdef TCP_CORK
- int corked = 0;
-#endif
- server_socket *srv_socket = con->srv_socket;
-
- if (con->conf.global_kbytes_per_second &&
- *(con->conf.global_bytes_per_second_cnt_ptr) > con->conf.global_kbytes_per_second * 1024) {
- /* we reached the global traffic limit */
-
- con->traffic_limit_reached = 1;
- joblist_append(srv, con);
-
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- }
-
- written = cq->bytes_out;
-
-#ifdef TCP_CORK
- /* Linux: put a cork into the socket as we want to combine the write() calls
- * but only if we really have multiple chunks
- */
- if (cq->first && cq->first->next) {
- corked = 1;
- setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
- }
-#endif
-
- if (srv_socket->is_ssl) {
-#ifdef USE_OPENSSL
- ret = srv->network_ssl_backend_write(srv, con, con->sock, cq);
-#endif
- } else {
- ret = srv->network_backend_write(srv, con, con->sock, cq);
- }
-
- switch (ret) {
- case NETWORK_STATUS_WAIT_FOR_FD:
- case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- case NETWORK_STATUS_SUCCESS:
- chunkqueue_remove_finished_chunks(cq);
-
- break;
- default:
- break;
- }
-
-#ifdef TCP_CORK
- if (corked) {
- corked = 0;
- setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
- }
-#endif
-
- written = cq->bytes_out - written;
- con->bytes_written += written;
- con->bytes_written_cur_second += written;
-
- *(con->conf.global_bytes_per_second_cnt_ptr) += written;
-
- if (con->conf.kbytes_per_second &&
- (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
- /* we reached the traffic limit */
-
- con->traffic_limit_reached = 1;
- joblist_append(srv, con);
- }
- return ret;
-}
diff --git a/src/network.h b/src/network.h
deleted file mode 100644
index 1e3016f3..00000000
--- a/src/network.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _NETWORK_H_
-#define _NETWORK_H_
-
-#include "settings.h"
-#include "server.h"
-
-LI_API network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
-LI_API network_status_t network_read(server *srv, connection *con, iosocket *sock, chunkqueue *c);
-
-LI_API int network_init(server *srv);
-LI_API int network_close(server *srv);
-
-LI_API int network_register_fdevents(server *srv);
-LI_API handler_t network_server_handle_fdevent(void *s, void *context, int revents);
-
-#endif
diff --git a/src/network_backends.h b/src/network_backends.h
deleted file mode 100644
index 4f99a663..00000000
--- a/src/network_backends.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef _NETWORK_BACKENDS_H_
-#define _NETWORK_BACKENDS_H_
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-
-#include "settings.h"
-#include "base.h"
-#include "network.h"
-
-#define NETWORK_BACKEND_WRITE_CHUNK(x) \
- network_status_t network_write_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq, chunk *c)
-
-#define NETWORK_BACKEND_WRITE(x) \
- network_status_t network_write_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq)
-#define NETWORK_BACKEND_READ(x) \
- network_status_t network_read_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq)
-
-LI_API NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
-
-LI_API NETWORK_BACKEND_WRITE(write);
-LI_API NETWORK_BACKEND_WRITE(writev);
-LI_API NETWORK_BACKEND_WRITE(linuxsendfile);
-LI_API NETWORK_BACKEND_WRITE(linuxaiosendfile);
-LI_API NETWORK_BACKEND_WRITE(posixaio);
-LI_API NETWORK_BACKEND_WRITE(gthreadaio);
-LI_API NETWORK_BACKEND_WRITE(gthreadsendfile);
-LI_API NETWORK_BACKEND_WRITE(gthreadfreebsdsendfile);
-LI_API NETWORK_BACKEND_WRITE(freebsdsendfile);
-LI_API NETWORK_BACKEND_WRITE(solarissendfilev);
-
-LI_API NETWORK_BACKEND_WRITE(win32transmitfile);
-LI_API NETWORK_BACKEND_WRITE(win32send);
-
-LI_API NETWORK_BACKEND_READ(read);
-LI_API NETWORK_BACKEND_READ(win32recv);
-
-#ifdef USE_OPENSSL
-LI_API NETWORK_BACKEND_WRITE(openssl);
-LI_API NETWORK_BACKEND_READ(openssl);
-#endif
-
-typedef struct {
- network_backend_t type;
- const char *name;
- const char *description;
- network_status_t (*read_handler)(server *srv, connection *con, iosocket *sock, chunkqueue *cq);
- network_status_t (*write_handler)(server *srv, connection *con, iosocket *sock, chunkqueue *cq);
-} network_backend_info_t;
-
-LI_API const network_backend_info_t *network_get_backends();
-LI_API const network_backend_info_t *network_get_defaultbackend();
-LI_API const network_backend_info_t *network_get_backend_info_by_type(network_backend_t type);
-LI_API const network_backend_info_t *network_get_backend_info_by_name(const char *name);
-
-#endif
diff --git a/src/network_freebsd_sendfile.c b/src/network_freebsd_sendfile.c
deleted file mode 100644
index 446e1fe7..00000000
--- a/src/network_freebsd_sendfile.c
+++ /dev/null
@@ -1,157 +0,0 @@
-#include "network_backends.h"
-
-#ifdef USE_FREEBSD_SENDFILE
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-
-
-#ifndef UIO_MAXIOV
-# if defined(__FreeBSD__) || defined(__DragonFly__)
-/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
-# define UIO_MAXIOV 1024
-# endif
-#endif
-
-NETWORK_BACKEND_WRITE(freebsdsendfile) {
- chunk *c;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- chunk *tc;
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc; tc = tc->next) {
- /* finished the chunk */
- if (tc->offset == tc->mem->used - 1) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- } else {
- break;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- off_t offset, r;
- size_t toSend;
- stat_cache_entry *sce = NULL;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- offset = c->file.start + c->offset;
- /* limit the toSend to 2^31-1 bytes in a chunk */
- toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
- ((1 << 30) - 1) : c->file.length - c->offset;
-
- if (-1 == c->file.fd) {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
- switch (errno) {
- case EMFILE:
- return NETWORK_STATUS_WAIT_FOR_FD;
- default:
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- r = 0;
-
- /* FreeBSD sendfile() */
- if (-1 == sendfile(c->file.fd, sock->fd, offset, toSend, NULL, &r, 0)) {
- switch(errno) {
- case EAGAIN:
- break;
- case ENOTCONN:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- /* We got an event to write but we wrote nothing
- *
- * - the file shrinked -> error
- * - the remote side closed inbetween -> remote-close */
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- /* file is gone ? */
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (offset > sce->st.st_size) {
- /* file shrinked, close the connection */
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- return NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
- c->offset += r;
- cq->bytes_out += r;
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
- }
-
- break;
- }
- default:
- ERROR("chunk-type '%d' not known", c->type);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/network_gthread_aio.c b/src/network_gthread_aio.c
deleted file mode 100644
index 42a2f3bd..00000000
--- a/src/network_gthread_aio.c
+++ /dev/null
@@ -1,481 +0,0 @@
-/**
- * - MAP_ANON needs _BSD_SOURCE | _SVID_SOURCE
- * - pread() needs _XOPEN_SOURCE 500 on Linux
- * - _XOPEN_SOURCE breaks the compile on FreeBSD (see #1240, #1251)
- *
- */
-#ifndef _GNU_SOURCE
-# ifndef _BSD_SOURCE
-# define _BSD_SOURCE 1
-# endif
-#endif
-
-#ifdef linux
-/* For pread()/pwrite() */
-#define _XOPEN_SOURCE 500
-#endif
-
-#include "settings.h"
-#include "network_backends.h"
-#ifdef USE_GTHREAD_AIO
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "joblist.h"
-#include "timing.h"
-
-#include "sys-files.h"
-#include "sys-socket.h"
-
-typedef struct {
- chunk *c;
-
- void *con;
-
- int sock_fd;
-} write_job;
-
-static write_job *write_job_init() {
- write_job *wj = calloc(1, sizeof(*wj));
-
- return wj;
-}
-
-static void write_job_free(write_job *wj) {
- if (!wj) return;
-
- free(wj);
-}
-
-#define kByte * (1024)
-#define MByte * (1024 kByte)
-
-/**
- * log the time-stamps of the different stages
- */
-static void timing_print(server *srv, connection *con) {
- if (!srv->srvconf.log_timing) return;
-
- TRACE("write-start: %ld.%06ld "
- "read-queue-wait: %ld ms "
- "read-time: %ld ms "
- "write-time: %ld ms ",
- con->timestamps[TIME_SEND_WRITE_START].tv_sec,
- con->timestamps[TIME_SEND_WRITE_START].tv_usec,
-
- TIME_DIFF(TIME_SEND_ASYNC_READ_START, TIME_SEND_ASYNC_READ_QUEUED),
- TIME_DIFF(TIME_SEND_ASYNC_READ_END, TIME_SEND_ASYNC_READ_START),
- TIME_DIFF(TIME_SEND_WRITE_END, TIME_SEND_ASYNC_READ_END_QUEUED)
- );
-}
-
-gpointer network_gthread_aio_read_thread(gpointer _srv) {
- server *srv = (server *)_srv;
-
- GAsyncQueue * inq;
-
- int fadvise_is_enosys = 0;
-
- g_async_queue_ref(srv->aio_write_queue);
-
- inq = srv->aio_write_queue;
-
- /* */
- while (!srv->is_shutdown) {
- write_job *wj = NULL;
-
- if ((wj = g_async_queue_pop(inq))) {
- /* let's see what we have to stat */
- ssize_t r;
- off_t offset;
- size_t toSend;
- chunk *c;
- connection *con;
- off_t max_toSend = 64 kByte; /** should be larger than the send buffer */
-
- int fadvise_fd = 0;
- off_t fadvise_offset = 0;
- off_t fadvise_len = 0;
-
- if(wj == (write_job *) 1)
- continue; /* just notifying us that srv->is_shutdown changed */
-
- c = wj->c;
- con = wj->con;
-
-#if 0
- /* try to be adaptive */
- int snd_buf_size = 0;
- socklen_t snd_buf_size_size = sizeof(snd_buf_size);
-
- if (0 == getsockopt(con->sock->fd, SOL_SOCKET, SO_SNDBUF, &snd_buf_size, &snd_buf_size_size)) {
- /* adjust the read-data to the send-buffer */
- if (snd_buf_size * 4 > max_toSend) {
- max_toSend = snd_buf_size * 4;
- }
- }
-#endif
-
- offset = c->file.start + c->offset;
-
- toSend = c->file.length - c->offset > max_toSend ?
- max_toSend : c->file.length - c->offset;
-
- c->file.copy.offset = 0;
- c->file.copy.length = 0;
-
- /* open a file in /dev/shm to write to */
- if (c->file.mmap.start == MAP_FAILED) {
-#if defined(HAVE_MEM_MMAP_ZERO)
- int mmap_fd;
- if (-1 == (mmap_fd = open("/dev/zero", O_RDWR))) {
- if (errno != EMFILE) {
- TRACE("open(/dev/zero) returned: %d (%s)",
- errno, strerror(errno));
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- } else {
- c->async.ret_val = NETWORK_STATUS_WAIT_FOR_FD;
- }
- } else {
- c->file.mmap.offset = 0;
- c->file.mmap.length = toSend;
-
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, 0);
- if (c->file.mmap.start == MAP_FAILED) {
- TRACE("mmap(/dev/zero) returned: %d (%s)",
- errno, strerror(errno));
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- }
-
- close(mmap_fd);
- mmap_fd = -1;
- }
-#elif defined(HAVE_MEM_MMAP_ANON)
- c->file.mmap.offset = 0;
- c->file.mmap.length = toSend; /* align to page-size */
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
-
- if (c->file.mmap.start == MAP_FAILED) {
- TRACE("mmap(MAP_ANON) returned: %d (%s)",
- errno, strerror(errno));
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- }
-#else
-#error hmm, does your system support mmap(/dev/zero) or mmap(MAP_ANON)
-#endif
- }
- if (c->file.mmap.start != MAP_FAILED) {
- timing_log(srv, con, TIME_SEND_ASYNC_READ_START);
-
- if (-1 == (r = pread(c->file.fd, c->file.mmap.start, toSend, c->file.start + c->offset))) {
- switch(errno) {
- default:
- ERROR("reading file failed: %d (%s)", errno, strerror(errno));
-
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- }
- } else if (r == 0) {
- ERROR("pread(%s) returned 0 ... not good", SAFE_BUF_STR(c->file.name));
-
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- } else {
- timing_log(srv, con, TIME_SEND_ASYNC_READ_END);
- c->file.copy.length = r;
- }
- }
-
- if (c->file.copy.length && !fadvise_is_enosys) {
- fadvise_fd = c->file.fd;
- fadvise_offset = c->file.start + c->offset + c->file.copy.length;
- fadvise_len = c->file.length - c->offset - c->file.copy.length;
-
- if (fadvise_len > max_toSend) {
- fadvise_len = max_toSend;
- }
- }
- timing_log(srv, con, TIME_SEND_ASYNC_READ_END_QUEUED);
- /* read async, write as usual */
- joblist_async_append(srv, wj->con);
-
-#if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
- /* read ahead */
- if (c->file.copy.length && !fadvise_is_enosys && fadvise_len) {
- /* let's hope that the fd is still valid when we try to read ahead */
- if (-1 == posix_fadvise(fadvise_fd, fadvise_offset, fadvise_len, POSIX_FADV_WILLNEED)) {
- if (ENOSYS != errno) {
- ERROR("posix_fadvise(%d) failed: %s (%d)", fadvise_fd, strerror(errno), errno);
- } else {
- /* don't try again as we don't support it */
- fadvise_is_enosys = 1;
- }
- }
- }
-#endif
- write_job_free(wj);
- }
- }
-
- g_async_queue_unref(srv->aio_write_queue);
-
- return NULL;
-
-}
-
-
-NETWORK_BACKEND_WRITE(gthreadaio) {
- chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc && chunk_is_done(tc); tc = tc->next) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- ssize_t r;
-
- /* we might be on our way back from the async request and have a status-code */
- if (c->async.ret_val != NETWORK_STATUS_UNSET) {
- ret = c->async.ret_val;
-
- c->async.ret_val = NETWORK_STATUS_UNSET;
-
- ERROR("thread returned: %d", ret);
-
- return ret;
- }
-
- /* open file if not already opened */
- if (-1 == c->file.fd) {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY /* | O_DIRECT */ | (srv->srvconf.use_noatime ? O_NOATIME : 0)))) {
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
-#if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_SEQUENTIAL)
- /* tell the kernel that we want to stream the file
- *
- * - POSIX_FADV_SEQUENTIAL doubles the read-ahead on Linux
- *
- * */
- if (-1 == posix_fadvise(c->file.fd, c->file.start, c->file.length, POSIX_FADV_SEQUENTIAL)) {
- if (ENOSYS != errno) {
- ERROR("posix_fadvise(%s) failed: %s (%d)", c->file.name->ptr, strerror(errno), errno);
- }
- }
-#endif
- }
- /* check if we have content */
- if (c->file.copy.length == 0) {
- const off_t max_toSend = 64 kByte; /** should be larger than the send buffer */
- size_t toSend;
- off_t offset;
-
- /* start to write a block out the to net work */
- timing_log(srv, con, TIME_SEND_WRITE_START);
-
- offset = c->file.start + c->offset;
-
- toSend = c->file.length - c->offset > max_toSend ?
- max_toSend : c->file.length - c->offset;
-
- /* we small files don't take the overhead of a full async-loop */
- if (toSend < 4 * 1024) {
-
- c->file.copy.offset = 0;
- c->file.copy.length = toSend;
-
- /* open a file in /dev/shm to write to */
- if (c->file.mmap.start == MAP_FAILED) {
-#if defined(HAVE_MEM_MMAP_ZERO)
- int mmap_fd;
-
- if (-1 == (mmap_fd = open("/dev/zero", O_RDWR))) {
- if (errno != EMFILE) {
- TRACE("open(/dev/zero) returned: %d (%s), open fds: %d",
- errno, strerror(errno));
- return NETWORK_STATUS_FATAL_ERROR;
- } else {
- return NETWORK_STATUS_WAIT_FOR_FD;
- }
- } else {
- c->file.mmap.offset = 0;
- c->file.mmap.length = c->file.copy.length; /* align to page-size */
-
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, 0);
- if (c->file.mmap.start == MAP_FAILED) {
- ERROR("mmap(%s) failed: %s (%d)", c->file.name->ptr, strerror(errno), errno);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- close(mmap_fd);
- mmap_fd = -1;
- }
-#elif defined(HAVE_MEM_MMAP_ANON)
- c->file.mmap.offset = 0;
- c->file.mmap.length = c->file.copy.length; /* align to page-size */
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
-
- if (c->file.mmap.start == MAP_FAILED) {
- TRACE("mmap(MAP_ANON) returned: %d (%s)",
- errno, strerror(errno));
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#else
-#error hmm, does your system support mmap(/dev/zero) or mmap(MAP_ANON)
-#endif
-
- }
-
- if (c->file.mmap.start != MAP_FAILED) {
- lseek(c->file.fd, c->file.start + c->offset, SEEK_SET);
-
- if (-1 == (r = read(c->file.fd, c->file.mmap.start, c->file.copy.length))) {
- switch(errno) {
- default:
- ERROR("reading file failed: %d (%s)", errno, strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- } else if (r == 0) {
- ERROR("read() returned 0 ... not good: %s", "");
-
- return NETWORK_STATUS_FATAL_ERROR;
- } else if (r != c->file.copy.length) {
- ERROR("read() returned %zd instead of %jd", r, (intmax_t) c->file.copy.length);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- } else {
- return NETWORK_STATUS_FATAL_ERROR;
- }
- } else {
- write_job *wj;
-
- wj = write_job_init();
- wj->c = c;
- wj->con = con;
- wj->sock_fd = sock->fd;
-
- c->async.written = -1;
- c->async.ret_val = NETWORK_STATUS_UNSET;
-
- g_async_queue_push(srv->aio_write_queue, wj);
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_QUEUED);
-
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- }
- }
-
- if (-1 == (r = write(sock->fd, c->file.mmap.start + c->file.copy.offset, c->file.copy.length - c->file.copy.offset))) {
- switch (errno) {
- case EINTR:
- case EAGAIN:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("write failed: %d (%s) [%jd, %p, %jd]",
- errno, strerror(errno), (intmax_t) c->file.copy.length,
- c->file.mmap.start, (intmax_t) c->file.copy.offset);
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- return NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
- c->file.copy.offset += r; /* offset in the copy-chunk */
-
- c->offset += r; /* global offset in the file */
- cq->bytes_out += r;
-
- if (c->file.copy.offset == (off_t) c->file.mmap.length) {
- /* this block is sent, get a new one */
- timing_log(srv, con, TIME_SEND_WRITE_END);
-
- timing_print(srv, con);
-
- c->file.copy.length = 0;
- }
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
-
- if (c->file.copy.fd != -1) {
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
- }
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/network_gthread_freebsd_sendfile.c b/src/network_gthread_freebsd_sendfile.c
deleted file mode 100644
index 639eda67..00000000
--- a/src/network_gthread_freebsd_sendfile.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#include "settings.h"
-#include "network_backends.h"
-#if defined(USE_GTHREAD_FREEBSD_SENDFILE)
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "joblist.h"
-#include "timing.h"
-
-#include "sys-files.h"
-#include "sys-socket.h"
-
-typedef struct {
- chunk *c;
-
- void *con;
-
- int sock_fd;
-} write_job;
-
-static write_job *write_job_init() {
- write_job *wj = calloc(1, sizeof(*wj));
-
- return wj;
-}
-
-static void write_job_free(write_job *wj) {
- if (!wj) return;
-
- free(wj);
-}
-
-#define kByte * (1024)
-#define MByte * (1024 kByte)
-
-/**
- * log the time-stamps of the different stages
- */
-static void timing_print(server *srv, connection *con) {
- if (!srv->srvconf.log_timing) return;
-
- TRACE("write-start: %ld.%06ld "
- "read-queue-wait: %ld ms "
- "read-time: %ld ms "
- "write-time: %ld ms ",
- con->timestamps[TIME_SEND_WRITE_START].tv_sec,
- con->timestamps[TIME_SEND_WRITE_START].tv_usec,
-
- TIME_DIFF(TIME_SEND_ASYNC_READ_START, TIME_SEND_ASYNC_READ_QUEUED),
- TIME_DIFF(TIME_SEND_ASYNC_READ_END, TIME_SEND_ASYNC_READ_START),
- TIME_DIFF(TIME_SEND_WRITE_END, TIME_SEND_ASYNC_READ_END_QUEUED)
- );
-}
-
-/**
- * a backend which calls sendfile() in a thread
- */
-
-gpointer network_gthread_freebsd_sendfile_read_thread(gpointer _srv) {
- server *srv = (server *)_srv;
-
- GAsyncQueue * inq;
-
- g_async_queue_ref(srv->aio_write_queue);
-
- inq = srv->aio_write_queue;
-
- /* */
- while (!srv->is_shutdown) {
- write_job *wj = NULL;
-
- if ((wj = g_async_queue_pop(inq))) {
- /* let's see what we have to stat */
- off_t r;
- off_t offset;
- size_t toSend;
- chunk *c;
- connection *con;
- off_t max_toSend = 512 kByte; /** should be larger than the send buffer */
-
- if(wj == (write_job *) 1)
- continue; /* just notifying us that srv->is_shutdown changed */
-
- c = wj->c;
- con = wj->con;
- offset = c->file.start + c->offset;
-
- toSend = c->file.length - c->offset > max_toSend ?
- max_toSend : c->file.length - c->offset;
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_START);
-
- r = 0;
- if (-1 == sendfile(c->file.fd, wj->sock_fd, offset, toSend, NULL, &r, 0)) {
- switch (errno) {
- case EAGAIN:
- case EINTR:
- c->async.ret_val = NETWORK_STATUS_WAIT_FOR_EVENT;
- break;
- case ENOTCONN:
- c->async.ret_val = NETWORK_STATUS_CONNECTION_CLOSE;
- break;
- default:
- ERROR("sendfile(%s) failed: %s (%d)",
- SAFE_BUF_STR(c->file.name),
- strerror(errno), errno);
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- break;
- }
- } else if (r == 0) {
- c->async.ret_val = NETWORK_STATUS_CONNECTION_CLOSE;
- } else {
- c->async.written = r;
- }
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_END);
- timing_log(srv, con, TIME_SEND_ASYNC_READ_END_QUEUED);
-
- /* read async, write as usual */
- joblist_async_append(srv, wj->con);
-
- write_job_free(wj);
- }
- }
-
- g_async_queue_unref(srv->aio_write_queue);
-
- return NULL;
-
-}
-
-
-NETWORK_BACKEND_WRITE(gthreadfreebsdsendfile) {
- chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc && chunk_is_done(tc); tc = tc->next) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- /* we might be on our way back from the async request and have a status-code */
- if (c->async.ret_val != NETWORK_STATUS_UNSET) {
- ret = c->async.ret_val;
-
- c->async.ret_val = NETWORK_STATUS_UNSET;
-
- return ret;
- }
-
- /* open file if not already opened */
- if (-1 == c->file.fd) {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY /* | O_DIRECT */ | (srv->srvconf.use_noatime ? O_NOATIME : 0)))) {
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
-#if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_SEQUENTIAL)
- /* tell the kernel that we want to stream the file */
- if (-1 == posix_fadvise(c->file.fd, c->file.start, c->file.length, POSIX_FADV_SEQUENTIAL)) {
- if (ENOSYS != errno) {
- ERROR("posix_fadvise(%s) failed: %s (%d)", c->file.name->ptr, strerror(errno), errno);
- }
- }
-#endif
- }
-
- if (c->async.written > 0) {
- /* the backend has written something */
-
- c->offset += c->async.written; /* global offset in the file */
- cq->bytes_out += c->async.written;
-
- /* this block is sent, get a new one */
- timing_log(srv, con, TIME_SEND_WRITE_END);
-
- timing_print(srv, con);
-
- c->async.written = -1;
- }
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
- } else {
- /* start this write */
- write_job *wj;
-
- timing_log(srv, con, TIME_SEND_WRITE_START);
- wj = write_job_init();
- wj->c = c;
- wj->con = con;
- wj->sock_fd = sock->fd;
-
- c->async.written = -1;
- c->async.ret_val = NETWORK_STATUS_UNSET;
-
- g_async_queue_push(srv->aio_write_queue, wj);
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_QUEUED);
-
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- }
-
- break;
- }
- case UNUSED_CHUNK:
- continue;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
-
diff --git a/src/network_gthread_sendfile.c b/src/network_gthread_sendfile.c
deleted file mode 100644
index b39a082d..00000000
--- a/src/network_gthread_sendfile.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#include "settings.h"
-#include "network_backends.h"
-#if defined(USE_GTHREAD_SENDFILE)
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "joblist.h"
-#include "timing.h"
-
-#include "sys-files.h"
-#include "sys-socket.h"
-
-typedef struct {
- chunk *c;
-
- void *con;
-
- int sock_fd;
-} write_job;
-
-static write_job *write_job_init() {
- write_job *wj = calloc(1, sizeof(*wj));
-
- return wj;
-}
-
-static void write_job_free(write_job *wj) {
- if (!wj) return;
-
- free(wj);
-}
-
-#define kByte * (1024)
-#define MByte * (1024 kByte)
-
-/**
- * log the time-stamps of the different stages
- */
-static void timing_print(server *srv, connection *con) {
- if (!srv->srvconf.log_timing) return;
-
- TRACE("write-start: %ld.%06ld "
- "read-queue-wait: %ld ms "
- "read-time: %ld ms "
- "write-time: %ld ms ",
- con->timestamps[TIME_SEND_WRITE_START].tv_sec,
- con->timestamps[TIME_SEND_WRITE_START].tv_usec,
-
- TIME_DIFF(TIME_SEND_ASYNC_READ_START, TIME_SEND_ASYNC_READ_QUEUED),
- TIME_DIFF(TIME_SEND_ASYNC_READ_END, TIME_SEND_ASYNC_READ_START),
- TIME_DIFF(TIME_SEND_WRITE_END, TIME_SEND_ASYNC_READ_END_QUEUED)
- );
-}
-
-/**
- * a backend which calls sendfile() in a thread
- */
-
-gpointer network_gthread_sendfile_read_thread(gpointer _srv) {
- server *srv = (server *)_srv;
-
- GAsyncQueue * inq;
-
- g_async_queue_ref(srv->aio_write_queue);
-
- inq = srv->aio_write_queue;
-
- /* */
- while (!srv->is_shutdown) {
- write_job *wj = NULL;
-
- if ((wj = g_async_queue_pop(inq))) {
- /* let's see what we have to stat */
- ssize_t r;
- off_t offset;
- size_t toSend;
- chunk *c;
- connection *con;
- off_t max_toSend = 512 kByte; /** should be larger than the send buffer */
-
- if(wj == (write_job *) 1)
- continue; /* just notifying us that srv->is_shutdown changed */
-
- c = wj->c;
- con = wj->con;
- offset = c->file.start + c->offset;
-
- toSend = c->file.length - c->offset > max_toSend ?
- max_toSend : c->file.length - c->offset;
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_START);
-
- if (-1 == (r = sendfile(wj->sock_fd, c->file.fd, &offset, toSend))) {
- switch (errno) {
- case EAGAIN:
- case EINTR:
- c->async.ret_val = NETWORK_STATUS_WAIT_FOR_EVENT;
- break;
- case EPIPE:
- case ECONNRESET:
- c->async.ret_val = NETWORK_STATUS_CONNECTION_CLOSE;
- break;
- case ENOSYS:
- ERROR("sendfile(%s) is not implemented, use server.network-backend = \"writev\"",
- SAFE_BUF_STR(c->file.name));
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- break;
- default:
- ERROR("sendfile(%s) failed: %s (%d)",
- SAFE_BUF_STR(c->file.name),
- strerror(errno), errno);
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- break;
- }
- } else if (r == 0) {
- c->async.ret_val = NETWORK_STATUS_CONNECTION_CLOSE;
- } else {
- c->async.written = r;
- }
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_END);
- timing_log(srv, con, TIME_SEND_ASYNC_READ_END_QUEUED);
-
- /* read async, write as usual */
- joblist_async_append(srv, wj->con);
-
- write_job_free(wj);
- }
- }
-
- g_async_queue_unref(srv->aio_write_queue);
-
- return NULL;
-
-}
-
-
-NETWORK_BACKEND_WRITE(gthreadsendfile) {
- chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc && chunk_is_done(tc); tc = tc->next) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- /* we might be on our way back from the async request and have a status-code */
- if (c->async.ret_val != NETWORK_STATUS_UNSET) {
- ret = c->async.ret_val;
-
- c->async.ret_val = NETWORK_STATUS_UNSET;
-
- return ret;
- }
-
- /* open file if not already opened */
- if (-1 == c->file.fd) {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY /* | O_DIRECT */ | (srv->srvconf.use_noatime ? O_NOATIME : 0)))) {
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
-#if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_SEQUENTIAL)
- /* tell the kernel that we want to stream the file */
- if (-1 == posix_fadvise(c->file.fd, c->file.start, c->file.length, POSIX_FADV_SEQUENTIAL)) {
- if (ENOSYS != errno) {
- ERROR("posix_fadvise(%s) failed: %s (%d)", c->file.name->ptr, strerror(errno), errno);
- }
- }
-#endif
- }
-
- if (c->async.written > 0) {
- /* the backend has written something */
-
- c->offset += c->async.written; /* global offset in the file */
- cq->bytes_out += c->async.written;
-
- /* this block is sent, get a new one */
- timing_log(srv, con, TIME_SEND_WRITE_END);
-
- timing_print(srv, con);
-
- c->async.written = -1;
- }
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
- } else {
- /* start this write */
- write_job *wj;
-
- timing_log(srv, con, TIME_SEND_WRITE_START);
- wj = write_job_init();
- wj->c = c;
- wj->con = con;
- wj->sock_fd = sock->fd;
-
- c->async.written = -1;
- c->async.ret_val = NETWORK_STATUS_UNSET;
-
- g_async_queue_push(srv->aio_write_queue, wj);
-
- timing_log(srv, con, TIME_SEND_ASYNC_READ_QUEUED);
-
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- }
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/network_linux_aio.c b/src/network_linux_aio.c
deleted file mode 100644
index 23f64160..00000000
--- a/src/network_linux_aio.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* we need O_DIRECT */
-#endif
-
-#include "network_backends.h"
-
-#ifdef USE_LINUX_AIO_SENDFILE
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include <libaio.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "joblist.h"
-#include "status_counter.h"
-
-#include "sys-files.h"
-
-/* the completion handler */
-gpointer linux_aio_read_thread(gpointer _srv) {
- server *srv = (server *)_srv;
-
- /* */
- while (!srv->is_shutdown) {
- /* let's see what we have to stat */
- struct io_event event[16];
- struct timespec io_ts;
- int res;
-
- io_ts.tv_sec = 1;
- io_ts.tv_nsec = 0;
-
- if ((res = io_getevents(srv->linux_io_ctx, 1, 16, event, &io_ts)) > 0) {
- int i;
- for (i = 0; i < res; i++) {
- connection *con = event[i].data;
-
- if ((long)event[i].res <= 0) {
- TRACE("async-read failed with %d (%s), was asked for %s (fd = %d)",
- (int) event[i].res, strerror(-event[i].res), SAFE_BUF_STR(con->uri.path), con->sock->fd);
- }
-
- /* free the iocb */
- event[i].obj->data = NULL;
-
- joblist_async_append(srv, con);
- }
- } else if (res < 0) {
- TRACE("getevents - failed: %d: %s", res, strerror(-res));
- }
- }
-
- return NULL;
-}
-
-
-NETWORK_BACKEND_WRITE(linuxaiosendfile) {
- chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc; tc = tc->next) {
- /* finished the chunk */
- if (tc->offset == (off_t) tc->mem->used - 1) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- } else {
- break;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- ssize_t r;
- int rounds = 8;
-
- /* open file if not already opened */
- if (-1 == c->file.fd) {
- mode_t mode = O_RDONLY;
- /*
- * Note: can't use O_DIRECT on files in "/dev/shm/". I hope all tempfiles
- * will be in shared memory filesystem. Also use O_NOATIME on tempfiles
- * since they will be deleted anyways.
- */
- if(c->file.is_temp) {
- mode |= O_NOATIME;
- } else {
- mode |= (O_DIRECT | (srv->srvconf.use_noatime ? O_NOATIME : 0));
- }
- if (-1 == (c->file.fd = open(c->file.name->ptr, mode))) {
- if (errno == EMFILE) return NETWORK_STATUS_WAIT_FOR_FD;
-
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
- }
-
- do {
- size_t toSend;
- const off_t max_toSend = 4 * 256 * 1024; /** should be larger than the send buffer */
- int file_fd;
- off_t offset;
-
- offset = c->file.start + c->offset;
-
- toSend = c->file.length - c->offset > max_toSend ?
- max_toSend : c->file.length - c->offset;
-
- if (!c->file.is_temp && (-1 == c->file.copy.fd || 0 == c->file.copy.length)) {
- long page_size = sysconf(_SC_PAGESIZE);
-
- int res;
- int async_error = 0;
-
- size_t iocb_ndx;
- struct iocb *iocb = NULL;
-
- c->file.copy.offset = 0;
- c->file.copy.length = toSend - (toSend % page_size); /* align to page-size */
-
- if (c->file.copy.length == 0) {
- async_error = 1;
- }
-
- /* if we reused the previous tmp-file we get overlaps
- *
- * 1 ... 3904 are ok
- * 3905 ... 4096 are replaces by 8001 ... 8192
- *
- * somehow the second read writes into the mmap() before
- * the sendfile is finished which is very strange.
- *
- * if someone finds the reason for this, feel free to remove
- * this if again and number of reduce the syscalls a bit.
- */
- if (-1 != c->file.copy.fd) {
- munmap(c->file.mmap.start, c->file.mmap.length);
-
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- /* do we have a IOCB we can use ? */
-
- for (iocb_ndx = 0; async_error == 0 && iocb_ndx < srv->srvconf.max_read_threads; iocb_ndx++) {
- if (NULL == srv->linux_io_iocbs[iocb_ndx].data) {
- iocb = &srv->linux_io_iocbs[iocb_ndx];
- break;
- }
- }
-
- if (iocb_ndx == srv->srvconf.max_read_threads) {
- async_error = 1;
- }
-
-
- /* get mmap()ed mem-block in /dev/shm */
- if (async_error == 0 && -1 == c->file.copy.fd ) {
- char tmpfile_name[sizeof("/dev/shm/l-XXXXXX")];
-
- /* open a file in /dev/shm to write to */
- strcpy(tmpfile_name, "/dev/shm/l-XXXXXX");
- if (-1 == (c->file.copy.fd = mkstemp(tmpfile_name))) {
- async_error = 1;
-
- if (errno != EMFILE) {
- TRACE("mkstemp returned: %d (%s) for %s, falling back to sync-io",
- errno, strerror(errno), tmpfile_name);
- }
- }
-
- c->file.mmap.offset = 0;
- c->file.mmap.length = c->file.copy.length; /* align to page-size */
-
- if (!async_error) {
- unlink(tmpfile_name); /* remove the file again, we still keep it open */
- if (0 != ftruncate(c->file.copy.fd, c->file.mmap.length)) {
- /* disk full ... */
- async_error = 1;
-
- TRACE("ftruncate returned: %d (%s), falling back to sync-io",
- errno, strerror(errno));
- }
- }
-
- if (!async_error) {
-
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED, c->file.copy.fd, 0);
- if (c->file.mmap.start == MAP_FAILED) {
- async_error = 1;
- }
- }
- }
-
- /* can we be sure that offset is always aligned ? */
- if (async_error == 0 &&
- (((intptr_t)c->file.mmap.start) % page_size != 0 ||
- c->file.copy.length % page_size != 0 ||
- ((intptr_t)(c->file.start + c->offset)) % page_size != 0)) {
- /**
- * after a fallback to sendfile() the offset might be unaligned
- */
-
- async_error = 1;
- }
-
-
- /* looks like we couldn't get a temp-file [disk-full] */
- if (async_error == 0 && -1 != c->file.copy.fd) {
- struct iocb *iocbs[] = { iocb };
-
- assert(c->file.copy.length > 0);
-
- io_prep_pread(iocb, c->file.fd, c->file.mmap.start, c->file.copy.length, c->file.start + c->offset);
- iocb->data = con;
-
- if (1 == (res = io_submit(srv->linux_io_ctx, 1, iocbs))) {
- status_counter_inc(CONST_STR_LEN("server.io.linux-aio.async-read"));
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- } else {
- iocb->data = NULL;
-
- if (-res != EAGAIN) {
- TRACE("io_submit returned: %d (%s), falling back to sync-io",
- res, strerror(-res));
- } else {
- TRACE("io_submit returned EAGAIN on (%d - %d), -> sync-io", c->file.fd, c->file.copy.fd);
- }
- }
- }
-
- /* oops, looks like the IO-queue is full
- *
- * fall-back to blocking sendfile()
- */
-
- if (c->file.mmap.start != MAP_FAILED) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
- }
- if (c->file.copy.fd != -1) {
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- c->file.copy.length = 0;
- c->file.copy.offset = 0;
- } else if (c->file.copy.offset == 0) {
- /* we are finished */
- }
-
- if (c->file.copy.fd == -1) {
- status_counter_inc(CONST_STR_LEN("server.io.linux-aio.sync-read"));
-
- file_fd = c->file.fd;
- } else {
- file_fd = c->file.copy.fd;
-
- offset = c->file.copy.offset;
- toSend = c->file.copy.length - offset;
- }
-
- /* send the tmp-file from /dev/shm/ */
- if (-1 == (r = sendfile(sock->fd, file_fd, &offset, toSend))) {
- switch (errno) {
- case EAGAIN:
- case EINTR:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "sendfile failed:", strerror(errno), sock->fd);
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- /* ... ooops */
- return NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
- c->offset += r; /* global offset in the file */
- cq->bytes_out += r;
-
- if (c->file.copy.fd == -1) {
- /* ... */
- } else {
- c->file.copy.offset += r; /* local offset in the mmap file */
-
- if (c->file.copy.offset == c->file.copy.length) {
- c->file.copy.length = 0; /* reset the length and let the next round fetch a new item */
- }
- }
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- if (c->file.copy.fd != -1) {
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
- }
-
- /* the chunk is larger and the current snippet is finished */
- } while (c->file.copy.length == 0 && chunk_finished == 0 && rounds-- > 0);
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
-#if 0
-network_linuxsendfile_init(void) {
- p->write = network_linuxsendfile_write_chunkset;
-}
-#endif
diff --git a/src/network_linux_sendfile.c b/src/network_linux_sendfile.c
deleted file mode 100644
index 290f0304..00000000
--- a/src/network_linux_sendfile.c
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* we need O_DIRECT */
-#endif
-
-#include "network_backends.h"
-
-#ifdef USE_LINUX_SENDFILE
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "sys-files.h"
-
-/* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
-#undef HAVE_POSIX_FADVISE
-
-NETWORK_BACKEND_WRITE(linuxsendfile) {
- chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc && chunk_is_done(tc); tc = tc->next) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- ssize_t r;
- off_t offset;
- size_t toSend;
- stat_cache_entry *sce = NULL;
-
- offset = c->file.start + c->offset;
- /* limit the toSend to 2^31-1 bytes in a chunk */
- toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
- ((1 << 30) - 1) : c->file.length - c->offset;
-
- /* open file if not already opened */
- if (-1 == c->file.fd) {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY | (srv->srvconf.use_noatime ? O_NOATIME : 0)))) {
- switch (errno) {
- case EMFILE:
- return NETWORK_STATUS_WAIT_FOR_FD;
- default:
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- return -1;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
-#ifdef HAVE_POSIX_FADVISE
- /* tell the kernel that we want to stream the file */
- if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
- if (ENOSYS != errno) {
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "posix_fadvise failed:", strerror(errno), c->file.fd);
- }
- }
-#endif
- }
-
- if (-1 == (r = sendfile(sock->fd, c->file.fd, &offset, toSend))) {
- switch (errno) {
- case EAGAIN:
- case EINTR:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- case ENOSYS:
- ERROR("sendfile(%s) is not implemented, use server.network-backend = \"writev\"",
- SAFE_BUF_STR(c->file.name));
- return NETWORK_STATUS_FATAL_ERROR;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "sendfile failed:", strerror(errno), sock->fd);
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- /* We got an event to write but we wrote nothing
- *
- * - the file shrinked -> error
- * - the remote side closed inbetween -> remote-close */
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- /* file is gone ? */
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (offset > sce->st.st_size) {
- /* file shrinked, close the connection */
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- return NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
-#ifdef HAVE_POSIX_FADVISE
-#if 0
-#define K * 1024
-#define M * 1024 K
-#define READ_AHEAD 4 M
- /* check if we need a new chunk */
- if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
- /* tell the kernel that we want to stream the file */
- if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "posix_fadvise failed:", strerror(errno), c->file.fd);
- }
- }
-#endif
-#endif
-
- c->offset += r;
- cq->bytes_out += r;
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- /* chunk_free() / chunk_reset() will cleanup for us but it is a ok to be faster :) */
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
- }
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
-#if 0
-network_linuxsendfile_init(void) {
- p->write = network_linuxsendfile_write_chunkset;
-}
-#endif
diff --git a/src/network_openssl.c b/src/network_openssl.c
deleted file mode 100644
index 7ffc8c47..00000000
--- a/src/network_openssl.c
+++ /dev/null
@@ -1,402 +0,0 @@
-#include "network_backends.h"
-
-#ifdef USE_OPENSSL
-#include <sys/types.h>
-#include "sys-socket.h"
-#include <sys/stat.h>
-#include <sys/time.h>
-#ifndef _WIN32
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <unistd.h>
-#include <netdb.h>
-#else
-#include <sys/types.h>
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-
-# include <openssl/ssl.h>
-# include <openssl/err.h>
-
-NETWORK_BACKEND_READ(openssl) {
- buffer *b;
- off_t len;
- int read_something = 0;
- off_t max_read = 256 * 1024;
- off_t start_bytes_in = cq->bytes_in;
- network_status_t res;
- int toread, read_offset;
-
- UNUSED(srv);
- UNUSED(con);
-
- /* use a chunk-size of 4k, append to last buffer if it has >= 1kb free */
-#define TOREAD 4096
-
- do {
- int oerrno;
-
- b = (cq->last) ? cq->last->mem : NULL;
-
- if (NULL == b || b->size - b->used < 1024) {
- b = chunkqueue_get_append_buffer(cq);
- buffer_prepare_copy(b, TOREAD+1);
- }
-
- read_offset = (b->used == 0) ? 0 : b->used - 1;
- toread = b->size - 1 - read_offset;
-
- ERR_clear_error();
- len = SSL_read(sock->ssl, b->ptr + read_offset, toread);
-
- /**
- * man SSL_read:
- *
- * >0 is success
- * 0 is connection close
- * <0 is error
- */
- if (len <= 0) {
- int r, ssl_err;
-
- oerrno = errno; /* store the errno for SSL_ERROR_SYSCALL */
- chunkqueue_remove_empty_last_chunk(cq);
-
- switch ((r = SSL_get_error(sock->ssl, len))) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_WAIT_FOR_EVENT;
- case SSL_ERROR_SYSCALL:
- /**
- * man SSL_get_error()
- *
- * SSL_ERROR_SYSCALL
- * Some I/O error occurred. The OpenSSL error queue may contain more
- * information on the error. If the error queue is empty (i.e.
- * ERR_get_error() returns 0), ret can be used to find out more about
- * the error: If ret == 0, an EOF was observed that violates the
- * protocol. If ret == -1, the underlying BIO reported an I/O error
- * (for socket I/O on Unix systems, consult errno for details).
- *
- */
- while((ssl_err = ERR_get_error())) {
- /* get all errors from the error-queue */
- ERROR("ssl-errors: %s", ERR_error_string(ssl_err, NULL));
- }
-
- if (len == 0) {
- return NETWORK_STATUS_CONNECTION_CLOSE;
- } else {
- switch(oerrno) {
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("last-errno: (%d) %s", oerrno, strerror(oerrno));
- break;
- }
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- case SSL_ERROR_ZERO_RETURN:
- if (len == 0) {
- /* clean shutdown on the remote side */
- return NETWORK_STATUS_CONNECTION_CLOSE;
- }
- /* fall through otherwise */
- default:
- res = NETWORK_STATUS_CONNECTION_CLOSE;
- while((ssl_err = ERR_get_error())) {
- switch (ERR_GET_REASON(ssl_err)) {
- case SSL_R_SSL_HANDSHAKE_FAILURE:
- case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
- case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
- case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
- if (!con->conf.log_ssl_noise) continue;
- break;
- default:
- res = NETWORK_STATUS_FATAL_ERROR;
- break;
- }
- /* get all errors from the error-queue */
- ERROR("ssl-errors: %s", ERR_error_string(ssl_err, NULL));
- }
-
- return res;
- }
- } else {
- if (b->used > 0) b->used--;
- b->used += len;
- b->ptr[b->used++] = '\0';
-
- read_something = 1;
- cq->bytes_in += len;
- }
-
- if (cq->bytes_in - start_bytes_in > max_read) break;
- } while (len == toread);
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-
-NETWORK_BACKEND_WRITE(openssl) {
- int ssl_r;
- chunk *c;
-
- /* this is a 64k sendbuffer
- *
- * it has to stay at the same location all the time to satisfy the needs
- * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
- *
- * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
- * -> we expect a 64k block to 'leak' in valgrind
- *
- *
- * In reality we would like to use mmap() but we don't have a guarantee that
- * we get the same mmap() address for each call. On openbsd the mmap() address
- * even randomized.
- * That means either we keep the mmap() open or we do a read() into a
- * constant buffer
- * */
-#define LOCAL_SEND_BUFSIZE (64 * 1024)
- static char *local_send_buffer = NULL;
-
- /* the remote side closed the connection before without shutdown request
- * - IE
- * - wget
- * if keep-alive is disabled */
-
- if (con->keep_alive == 0) {
- SSL_set_shutdown(sock->ssl, SSL_RECEIVED_SHUTDOWN);
- }
-
- for(c = cq->first; c; c = c->next) {
- int chunk_finished = 0;
-
- switch(c->type) {
- case MEM_CHUNK: {
- char * offset;
- size_t toSend;
- ssize_t r = 0;
-
- if (c->mem->used == 0) {
- chunk_finished = 1;
- break;
- }
-
- offset = c->mem->ptr + c->offset;
- toSend = c->mem->used - 1 - c->offset;
-
- /**
- * SSL_write man-page
- *
- * WARNING
- * When an SSL_write() operation has to be repeated because of
- * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
- * repeated with the same arguments.
- *
- * SSL_write(..., 0) return 0 which is handle as an error (Success)
- * checking toSend and not calling SSL_write() is simpler
- */
-
- ERR_clear_error();
- if (toSend != 0 && (r = SSL_write(sock->ssl, offset, toSend)) <= 0) {
- unsigned long err;
-
- switch ((ssl_r = SSL_get_error(sock->ssl, r))) {
- case SSL_ERROR_WANT_WRITE:
- break;
- case SSL_ERROR_SYSCALL:
- /* perhaps we have error waiting in our error-queue */
- if (0 != (err = ERR_get_error())) {
- do {
- ERROR("SSL_write(): SSL_get_error() = %d, SSL_write() = %zd, msg = %s",
- ssl_r, r,
- ERR_error_string(err, NULL));
- } while((err = ERR_get_error()));
- } else if (r == -1) {
- /* no, but we have errno */
- switch(errno) {
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("SSL_write(): SSL_get_error() = %d, SSL_write() = %zd, errmsg = %s (%d)",
- ssl_r, r,
- strerror(errno), errno);
- break;
- }
- } else {
- /* neither error-queue nor errno ? */
- ERROR("SSL_write(): SSL_get_error() = %d, SSL_write() = %zd, errmsg = %s (%d)",
- ssl_r, r,
- strerror(errno), errno);
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- case SSL_ERROR_ZERO_RETURN:
- /* clean shutdown on the remote side */
-
- if (r == 0) return NETWORK_STATUS_CONNECTION_CLOSE;
-
- /* fall through */
- default:
- while((err = ERR_get_error())) {
- ERROR("SSL_write(): SSL_get_error() = %d, SSL_write() = %zd, msg = %s",
- ssl_r, r,
- ERR_error_string(err, NULL));
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- } else {
- c->offset += r;
- cq->bytes_out += r;
- }
-
- if (c->offset == (off_t)c->mem->used - 1) {
- chunk_finished = 1;
- }
-
- break;
- }
- case FILE_CHUNK: {
- char *s;
- ssize_t r;
- stat_cache_entry *sce = NULL;
- int ifd;
- int write_wait = 0;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- ERROR("stat_cache_get_entry(%s) failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (NULL == local_send_buffer) {
- local_send_buffer = malloc(LOCAL_SEND_BUFSIZE);
- assert(local_send_buffer);
- }
-
- do {
- off_t offset = c->file.start + c->offset;
- off_t toSend = c->file.length - c->offset;
-
- if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
-
- if (-1 == (ifd = open(BUF_STR(c->file.name), O_RDONLY))) {
- ERROR("open(%s) failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
-
- lseek(ifd, offset, SEEK_SET);
- if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) {
- close(ifd);
-
- ERROR("read(%s) failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- s = local_send_buffer;
-
- close(ifd);
-
- ERR_clear_error();
- if ((r = SSL_write(sock->ssl, s, toSend)) <= 0) {
- unsigned long err;
-
- switch ((ssl_r = SSL_get_error(sock->ssl, r))) {
- case SSL_ERROR_WANT_WRITE:
- write_wait = 1;
- break;
- case SSL_ERROR_SYSCALL:
- /* perhaps we have error waiting in our error-queue */
- if (0 != (err = ERR_get_error())) {
- do {
- ERROR("SSL_write(): ssl-error: %d (ret = %zd): %s",
- ssl_r, r,
- ERR_error_string(err, NULL));
- } while((err = ERR_get_error()));
- } else if (r == -1) {
- /* no, but we have errno */
- switch(errno) {
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("SSL_write(): ssl-error: %d (ret = %zd). errno=%d, %s",
- ssl_r, r, errno,
- strerror(errno));
- break;
- }
- } else {
- ERROR("SSL_write(): ssl-error: %d (ret = %zd). errno=%d, %s",
- ssl_r, r, errno,
- strerror(errno));
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- case SSL_ERROR_ZERO_RETURN:
- /* clean shutdown on the remote side */
-
- if (r == 0) return NETWORK_STATUS_CONNECTION_CLOSE;
-
- /* fall thourgh */
- default:
- while((err = ERR_get_error())) {
- ERROR("SSL_write(): ssl-error: %d (ret = %zd), %s",
- ssl_r, r,
- ERR_error_string(err, NULL));
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- } else {
- c->offset += r;
- cq->bytes_out += r;
- }
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
- }
- } while(!chunk_finished && !write_wait);
-
- break;
- }
- default:
- ERROR("type not known: %d", c->type);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-#endif
-
-#if 0
-network_openssl_init(void) {
- p->write_ssl = network_openssl_write_chunkset;
-}
-#endif
diff --git a/src/network_posix_aio.c b/src/network_posix_aio.c
deleted file mode 100644
index b77abb22..00000000
--- a/src/network_posix_aio.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* we need O_DIRECT */
-#endif
-
-#include "network_backends.h"
-
-#ifdef USE_POSIX_AIO
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include <aio.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "joblist.h"
-
-#include "sys-files.h"
-#include "status_counter.h"
-
-typedef struct {
- server *srv;
- connection *con;
-
- struct aiocb *iocb;
-
- chunk *c;
-} write_job;
-
-static write_job *write_job_init() {
- write_job *wj = calloc(1, sizeof(*wj));
-
- return wj;
-}
-
-static void write_job_free(write_job *wj) {
- if (!wj) return;
-
- free(wj);
-}
-
-#if (defined(__FreeBSD__) || defined(__DragonFly__))
-/* someone is wrong here, both (MacOS X and FreeBSD) reference POSIX 1003.1b but have
- * different names (in /usr/include/sys/signal.h) */
-#define sival_ptr sigval_ptr
-#endif
-
-/**
- * handle the completion of a AIO-read() operation
- *
- * Linux has 'union sigval' and 'sigval_t'
- * MacOS X and FreeBSD only 'union sigval'
- * */
-static void posix_aio_completion_handler(union sigval foo) {
- write_job *wj = (write_job *)foo.sival_ptr;
- server *srv = wj->srv;
- connection *con = wj->con;
- struct aiocb *iocb = wj->iocb;
- chunk *c = wj->c;
- int res;
-
- if (srv->is_shutdown) {
- write_job_free(wj);
-
- return;
- }
-
- res = aio_error(iocb);
-
- if (res != EINPROGRESS) {
- switch (res) {
- case ECANCELED:
- TRACE("aio-op was canceled, was asked for %s (fd = %d)",
- SAFE_BUF_STR(con->uri.path), con->sock->fd);
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- break;
- case 0:
- break;
- default:
- TRACE("aio-op failed with %d (%s), was asked for %s (fd = %d)",
- res, strerror(res), SAFE_BUF_STR(con->uri.path), con->sock->fd);
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- break;
- }
-
- if ((res = aio_return(iocb)) < 0) {
- /* we have an error */
-
- TRACE("aio-return returned %d (%s), was asked for %s (fd = %d)",
- res, strerror(res), SAFE_BUF_STR(con->uri.path), con->sock->fd);
-
- c->async.ret_val = NETWORK_STATUS_FATAL_ERROR;
- }
-
- joblist_async_append(srv, con);
-
- iocb->aio_nbytes = 0; /* mark the entry as unused */
- }
-
- write_job_free(wj);
-}
-
-NETWORK_BACKEND_WRITE(posixaio) {
- chunk *c, *tc;
-
- for(c = cq->first; c; c = c->next) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc && chunk_is_done(tc); tc = tc->next) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- ssize_t r;
- int rounds = 8;
-
- /* open file if not already opened */
- if (-1 == c->file.fd) {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY | /* O_DIRECT | */ (srv->srvconf.use_noatime ? O_NOATIME : 0)))) {
- if (errno == EMFILE) return NETWORK_STATUS_WAIT_FOR_FD;
-
- ERROR("opening '%s' failed: %s", SAFE_BUF_STR(c->file.name), strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
- }
-
- do {
- size_t toSend;
- const off_t max_toSend = 4 * 256 * 1024; /** should be larger than the send buffer */
- off_t offset;
-
- offset = c->file.start + c->offset;
-
- toSend = c->file.length - c->offset > max_toSend ?
- max_toSend : c->file.length - c->offset;
-
- if (0 == c->file.copy.length) {
- int async_error = 0;
-
- size_t iocb_ndx;
-
- c->file.copy.offset = 0;
- c->file.copy.length = 0;
-
- /* if we reused the previous tmp-file we get overlaps
- *
- * 1 ... 3904 are ok
- * 3905 ... 4096 are replaces by 8001 ... 8192
- *
- * somehow the second read writes into the mmap() before
- * the sendfile is finished which is very strange.
- *
- * if someone finds the reason for this, feel free to remove
- * this if again and number of reduce the syscalls a bit.
- */
- if (c->file.mmap.start) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
- }
-
- if (-1 != c->file.copy.fd) {
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- /* do we have a IOCB we can use ? */
-
- for (iocb_ndx = 0; async_error == 0 && iocb_ndx < srv->srvconf.max_read_threads; iocb_ndx++) {
- if (0 == srv->posix_aio_iocbs[iocb_ndx].aio_nbytes) {
- break;
- }
- }
-
- if (iocb_ndx == srv->srvconf.max_read_threads) {
- async_error = 1;
- }
-
-
- /* get mmap()ed mem-block in /dev/shm
- *
- * in case we don't have a iocb available, we still need the mmap() for the blocking
- * read()
- * */
-#if defined(HAVE_MEM_MMAP_ZERO)
- if (-1 == c->file.copy.fd ) {
- int mmap_fd = -1;
-
- /* open a file in /dev/shm to write to */
- if (-1 == (mmap_fd = open("/dev/zero", O_RDWR))) {
- async_error = 1;
-
- if (errno != EMFILE) {
- TRACE("open(/dev/zero) returned: %d (%s), falling back to sync-io",
- errno, strerror(errno));
- } else {
- return NETWORK_STATUS_WAIT_FOR_FD;
- }
- } else {
- c->file.mmap.offset = 0;
- c->file.mmap.length = toSend;
-
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED, mmap_fd, 0);
- if (c->file.mmap.start == MAP_FAILED) {
- async_error = 1;
- } else {
- c->file.copy.length = toSend;
- }
-
- close(mmap_fd);
- mmap_fd = -1;
-
- }
- }
-#elif defined(HAVE_MEM_MMAP_ANON)
- c->file.mmap.offset = 0;
- c->file.mmap.length = c->file.copy.length; /* align to page-size */
- c->file.mmap.start = mmap(0, c->file.mmap.length,
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
-
- if (c->file.mmap.start == MAP_FAILED) {
- async_error = 1;
- }
-#else
-#error hmm, does your system support mmap(/dev/zero) or mmap(MAP_ANON)
-#endif
-
- /* looks like we couldn't get a temp-file [disk-full]
- *
- * if we only have 4k to send we can fall back to sync-read as either the read-ahead
- * or the stat() has put the data into the fs-buffers
- *
- * the 4kbyte are guessed ... someone should benchmark it.
- *
- * */
- if (async_error == 0 && c->file.mmap.start != MAP_FAILED && c->file.length > 4 * 1024) {
- struct aiocb *iocb = NULL;
- write_job *wj;
-
- assert(c->file.copy.length > 0);
-
- iocb = &srv->posix_aio_iocbs[iocb_ndx];
-
- memset(iocb, 0, sizeof(*iocb));
-
- iocb->aio_fildes = c->file.fd;
- iocb->aio_buf = c->file.mmap.start;
- iocb->aio_nbytes = c->file.copy.length;
- iocb->aio_offset = c->file.start + c->offset;
-
- wj = write_job_init();
- wj->srv = srv;
- wj->con = con;
- wj->iocb = iocb;
-
- iocb->aio_sigevent.sigev_notify_function = posix_aio_completion_handler;
- iocb->aio_sigevent.sigev_notify_attributes = NULL;
- iocb->aio_sigevent.sigev_value.sival_ptr = wj;
- iocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
-
- if (0 == aio_read(iocb)) {
- status_counter_inc(CONST_STR_LEN("server.io.posix-aio.async-read"));
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- } else {
- if (errno != EAGAIN) {
- TRACE("aio_read returned: %d (%s), falling back to sync-io",
- errno, strerror(errno));
- } else {
- TRACE("aio_read returned EAGAIN on (%d - %d), -> sync-io", c->file.fd, c->file.copy.fd);
- }
- }
- }
-
- /* fall back to a blocking read */
-
- if (c->file.mmap.start != MAP_FAILED) {
- status_counter_inc(CONST_STR_LEN("server.io.posix-aio.sync-read"));
-
- assert(c->file.copy.length > 0);
-
- lseek(c->file.fd, c->file.start + c->offset, SEEK_SET);
-
- if (-1 == (r = read(c->file.fd, c->file.mmap.start, c->file.copy.length))) {
- switch(errno) {
- default:
- ERROR("reading file failed: %d (%s)", errno, strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- ERROR("read() returned 0 ... not good: %s", "");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (r != c->file.copy.length) {
- ERROR("read() returned %zd instead of %jd", r, (intmax_t) c->file.copy.length);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- } else {
- ERROR("the mmap() failed, no way for a fallback: %s", "");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- } else if (c->file.copy.offset == 0) {
-#if 0
- /**
- * aio_write only creates extra-trouble
- *
- * instead we use the classic non-blocking-io write() call on the socket
- */
- size_t iocb_ndx;
- struct aiocb *iocb = NULL;
-
- /* the aio_read() is finished, send it */
-
- /* do we have a IOCB we can use ? */
-
- for (iocb_ndx = 0; iocb_ndx < POSIX_AIO_MAX_IOCBS; iocb_ndx++) {
- if (NULL == srv->posix_aio_data[iocb_ndx]) {
- break;
- }
- }
-
- assert(iocb_ndx != POSIX_AIO_MAX_IOCBS);
-
- iocb = &srv->posix_aio_iocbs[iocb_ndx];
- memset(iocb, 0, sizeof(*iocb));
-
- iocb->aio_fildes = sock->fd;
- iocb->aio_buf = c->file.mmap.start;
- iocb->aio_nbytes = c->file.copy.length;
- iocb->aio_offset = 0;
-
- /* the write should only return when it is finished */
- fcntl(sock->fd, F_SETFL, fcntl(sock->fd, F_GETFL) & ~O_NONBLOCK);
-
- if (0 != aio_write(iocb)) {
- TRACE("aio-write failed: %d (%s)", errno, strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- srv->have_aio_waiting++;
-
- srv->posix_aio_iocbs_watch[iocb_ndx] = iocb;
- srv->posix_aio_data[iocb_ndx] = con;
-
- /* in case we come back: we have written everything */
- c->file.copy.offset = c->file.copy.length;
-
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
-#endif
- }
-
- if (-1 == (r = write(sock->fd, c->file.mmap.start + c->file.copy.offset, c->file.copy.length - c->file.copy.offset))) {
- switch (errno) {
- case EINTR:
- case EAGAIN:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("write failed: %d (%s) [%jd, %p, %jd]",
- errno, strerror(errno), (intmax_t) c->file.copy.length,
- c->file.mmap.start, (intmax_t) c->file.copy.offset);
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- return NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
- c->file.copy.offset += r; /* offset in the copy-chunk */
-
- c->offset += r; /* global offset in the file */
- cq->bytes_out += r;
-
- if ((off_t) c->file.mmap.length == c->file.copy.offset) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
- c->file.copy.length = 0;
- }
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- if (c->file.copy.fd != -1) {
- close(c->file.copy.fd);
- c->file.copy.fd = -1;
- }
-
- if (c->file.fd != -1) {
- close(c->file.fd);
- c->file.fd = -1;
- }
- }
-
- /* the chunk is larger and the current snippet is finished */
- } while (c->file.copy.length == 0 && chunk_finished == 0 && rounds-- > 0);
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
-
diff --git a/src/network_solaris_sendfilev.c b/src/network_solaris_sendfilev.c
deleted file mode 100644
index 1a0aa965..00000000
--- a/src/network_solaris_sendfilev.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include "network_backends.h"
-
-#ifdef USE_SOLARIS_SENDFILEV
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-
-#ifndef UIO_MAXIOV
-#define UIO_MAXIOV IOV_MAX
-#endif
-
-/**
- * a very simple sendfilev() interface for solaris which can be optimised a lot more
- * as solaris sendfilev() supports 'sending everythin in one syscall()'
- *
- * If you want such an interface and need the performance, just give me an account on
- * a solaris box.
- * - jan@kneschke.de
- */
-
-
-NETWORK_BACKEND_WRITE(solarissendfilev) {
- chunk *c, *tc;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next, chunks_written++) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc; tc = tc->next) {
- /* finished the chunk */
- if (tc->offset == tc->mem->used - 1) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- } else {
- break;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- ssize_t r;
- off_t offset;
- size_t toSend, written = 0;
- sendfilevec_t fvec;
- stat_cache_entry *sce = NULL;
- int ifd;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
- return -1;
- }
-
- offset = c->file.start + c->offset;
- toSend = c->file.length - c->offset;
-
- if (offset > sce->st.st_size) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
-
- return -1;
- }
-
- if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
-
- return -1;
- }
-
- fvec.sfv_fd = ifd;
- fvec.sfv_flag = 0;
- fvec.sfv_off = offset;
- fvec.sfv_len = toSend;
-
- /* Solaris sendfilev() */
- if (-1 == (r = sendfilev(sock->fd, &fvec, 1, &written))) {
- switch (errno) {
- case EAGAIN:
- case EINTR:
- break;
- default:
- ERROR("sendfilev() failed: %s (errno=%d)", strerror(errno), errno);
-
- close(ifd);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- r = 0;
- }
-
- close(ifd);
- c->offset += written;
- cq->bytes_out += written;
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
- }
-
- break;
- }
- default:
- ERROR("chunk-type '%s' is not known", c->type);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/network_win32_send.c b/src/network_win32_send.c
deleted file mode 100644
index 0ee3f4aa..00000000
--- a/src/network_win32_send.c
+++ /dev/null
@@ -1,265 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-
-#include "sys-socket.h"
-#include "sys-files.h"
-
-#include "network_backends.h"
-
-#ifdef USE_WIN32_SEND
-/**
-* fill the chunkqueue will all the data that we can get
-*
-* this might be optimized into a readv() which uses the chunks
-* as vectors
-*
-* - This is pretty much a copy of the generic network_read receiver.
-*
-*/
-NETWORK_BACKEND_READ(win32recv)
-{
- int toread, read_offset;
- buffer *b;
- off_t r, start_bytes_in;
- off_t max_read = 256 * 1024;
-
- /**
- * a EAGAIN is a successful read if we already read something to the chunkqueue
- */
- int read_something = 0;
-
- UNUSED(srv);
- UNUSED(con);
-
- start_bytes_in = cq->bytes_in;
-
- /* use a chunk-size of 4k, append to last buffer if it has >= 1kb free */
-#define TOREAD 4096
-
- do {
- b = (cq->last) ? cq->last->mem : NULL;
-
- if (NULL == b || b->size - b->used < 1024) {
- b = chunkqueue_get_append_buffer(cq);
- buffer_prepare_copy(b, TOREAD+1);
- }
-
- read_offset = (b->used == 0) ? 0 : b->used - 1;
- toread = b->size - 1 - read_offset;
-
- if (-1 == (r = recv(sock->fd, b->ptr + read_offset, toread, 0))) {
- switch (light_sock_errno()) {
- case EAGAIN:
- case EWOULDBLOCK:
- /* remove the last chunk from the chunkqueue */
- chunkqueue_remove_empty_last_chunk(cq);
- return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_WAIT_FOR_EVENT;
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("oops, read from fd=%d failed: %s (%d)", sock->fd, strerror(errno), errno );
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- chunkqueue_remove_empty_last_chunk(cq);
- return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
- read_something = 1;
-
- if (b->used > 0) b->used--;
- b->used += r;
- b->ptr[b->used++] = '\0';
-
- cq->bytes_in += r;
-
- if (cq->bytes_in - start_bytes_in > max_read) break;
- } while (r == toread);
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-NETWORK_BACKEND_WRITE(win32send)
-{
- chunk *c;
- size_t chunks_written = 0;
-
- for(c = cq->first; c; c = c->next)
- {
- int chunk_finished = 0;
-
- switch(c->type)
- {
- case MEM_CHUNK:
- {
- char * offset;
- size_t toSend;
- ssize_t r;
-
- if (c->mem->used == 0) {
- chunk_finished = 1;
- break;
- }
-
- offset = c->mem->ptr + c->offset;
- toSend = c->mem->used - 1 - c->offset;
-
- if ((r = send(sock->fd, offset, toSend, 0)) < 0)
- {
- errno = WSAGetLastError();
-
- switch(errno)
- {
- case WSAEWOULDBLOCK:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case WSAECONNABORTED:
- case WSAECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "sdd", "send to socket:", errno, sock->fd);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- c->offset += r;
- cq->bytes_out += r;
-
- if (c->offset == (off_t)c->mem->used - 1) {
- chunk_finished = 1;
- }
-
- break;
- }
- case FILE_CHUNK:
- {
- ssize_t r;
- off_t offset;
-
- stat_cache_entry *sce = NULL;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce))
- {
- log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- offset = c->file.start + c->offset;
-
- if (offset > sce->st.st_size)
- {
- log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
-
- if (-1 == c->file.fd)
- {
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY|O_BINARY|O_SEQUENTIAL)))
- {
- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (-1 == lseek(c->file.fd, offset, SEEK_SET))
- {
- log_error_write(srv, __FILE__, __LINE__, "ss", "lseek failed: ", strerror(errno));
- }
-
- while(1)
- {
- off_t haveRead = 0;
- int finished = 0;
- int toSend;
-
- /* only send 64k blocks */
- toSend = c->file.length - c->offset > 256 * 1024 ? 256 * 1024 : c->file.length - c->offset;
-
- /* BMH. Not 100% sure about this */
- if ( toSend == 0 )
- break;
-
- buffer_prepare_copy(srv->tmp_buf, toSend);
-
- if (-1 == (haveRead = read(c->file.fd, srv->tmp_buf->ptr, toSend)))
- {
- log_error_write(srv, __FILE__, __LINE__, "ss", "read from file: ", strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (-1 == (r = send(sock->fd, srv->tmp_buf->ptr, haveRead, 0)))
- {
- errno = WSAGetLastError();
-
- switch(errno)
- {
- case WSAEWOULDBLOCK:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case WSAECONNABORTED:
- case WSAECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "sd", "send to socket:", errno);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- c->offset += r;
- cq->bytes_out += r;
-
- /* BMH: I don't understand this */
- if (r != haveRead)
- {
- break;
- }
- }
-
- if (c->offset == c->file.length)
- {
- chunk_finished = 1;
- }
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished)
- {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
-
- chunks_written++;
- }
- /* fprintf(stderr, "%s.%d: chunks_written: %d\r\n", __FILE__, __LINE__, chunks_written); */
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/network_write.c b/src/network_write.c
deleted file mode 100644
index 5de91927..00000000
--- a/src/network_write.c
+++ /dev/null
@@ -1,227 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-
-#include "sys-socket.h"
-#include "sys-files.h"
-
-#include "network_backends.h"
-
-#ifdef USE_WRITE
-
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-
-/**
-* fill the chunkqueue will all the data that we can get
-*
-* this might be optimized into a readv() which uses the chunks
-* as vectors
-*/
-NETWORK_BACKEND_READ(read) {
- int toread, read_offset;
- buffer *b;
- off_t r, start_bytes_in;
- off_t max_read = 256 * 1024;
-
- /**
- * a EAGAIN is a successful read if we already read something to the chunkqueue
- */
- int read_something = 0;
-
- UNUSED(srv);
- UNUSED(con);
-
- start_bytes_in = cq->bytes_in;
-
- /* use a chunk-size of 4k, append to last buffer if it has >= 1kb free */
-#define TOREAD 4096
-
- do {
- b = (cq->last) ? cq->last->mem : NULL;
-
- if (NULL == b || b->size - b->used < 1024) {
- b = chunkqueue_get_append_buffer(cq);
- buffer_prepare_copy(b, TOREAD+1);
- }
-
- read_offset = (b->used == 0) ? 0 : b->used - 1;
- toread = b->size - 1 - read_offset;
-
- if (-1 == (r = read(sock->fd, b->ptr + read_offset, toread))) {
- switch (errno) {
- case EAGAIN:
- /* remove the last chunk from the chunkqueue */
- chunkqueue_remove_empty_last_chunk(cq);
- return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_WAIT_FOR_EVENT;
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- ERROR("oops, read from fd=%d failed: %s (%d)", sock->fd, strerror(errno), errno );
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- if (r == 0) {
- chunkqueue_remove_empty_last_chunk(cq);
- return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_CONNECTION_CLOSE;
- }
-
- read_something = 1;
-
- if (b->used > 0) b->used--;
- b->used += r;
- b->ptr[b->used++] = '\0';
-
- cq->bytes_in += r;
-
- if (cq->bytes_in - start_bytes_in > max_read) break;
- } while (r == toread);
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-NETWORK_BACKEND_WRITE(write) {
- chunk *c;
-
- for(c = cq->first; c; c = c->next) {
- int chunk_finished = 0;
-
- switch(c->type) {
- case MEM_CHUNK: {
- char * offset;
- size_t toSend;
- ssize_t r;
-
- if (c->mem->used == 0) {
- chunk_finished = 1;
- break;
- }
-
- offset = c->mem->ptr + c->offset;
- toSend = c->mem->used - 1 - c->offset;
-
- if ((r = write(sock->fd, offset, toSend)) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), sock->fd);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- c->offset += r;
- cq->bytes_out += r;
-
- if (c->offset == (off_t)c->mem->used - 1) {
- chunk_finished = 1;
- }
-
- break;
- }
- case FILE_CHUNK: {
-#ifdef USE_MMAP
- char *p = NULL;
-#endif
- ssize_t r;
- off_t offset;
- size_t toSend;
- stat_cache_entry *sce = NULL;
- int ifd;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- offset = c->file.start + c->offset;
- toSend = c->file.length - c->offset;
-
- if (offset > sce->st.st_size) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
-#if defined USE_MMAP
- if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
-
- close(ifd);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- close(ifd);
-
- if ((r = write(sock->fd, p + offset, toSend)) <= 0) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
- munmap(p, sce->st.st_size);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- munmap(p, sce->st.st_size);
-#else
- buffer_prepare_copy(srv->tmp_buf, toSend);
-
- lseek(ifd, offset, SEEK_SET);
- if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
- close(ifd);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- close(ifd);
-
- if (-1 == (r = send(sock->fd, srv->tmp_buf->ptr, toSend, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#endif
- c->offset += r;
- cq->bytes_out += r;
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
- }
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/network_writev.c b/src/network_writev.c
deleted file mode 100644
index 63c5dd46..00000000
--- a/src/network_writev.c
+++ /dev/null
@@ -1,356 +0,0 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* we need O_DIRECT */
-#endif
-
-#include "network_backends.h"
-
-#ifdef USE_WRITEV
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "sys-files.h"
-
-#ifndef UIO_MAXIOV
-# if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
-/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
-# define UIO_MAXIOV 1024
-# elif defined(__sgi)
-/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
-# define UIO_MAXIOV 512
-# elif defined(__sun)
-/* Solaris (and SunOS?) defines IOV_MAX instead */
-# ifndef IOV_MAX
-# define UIO_MAXIOV 16
-# else
-# define UIO_MAXIOV IOV_MAX
-# endif
-# elif defined(IOV_MAX)
-# define UIO_MAXIOV IOV_MAX
-# else
-# error UIO_MAXIOV nor IOV_MAX are defined
-# endif
-#endif
-
-#if 0
-#define LOCAL_BUFFERING 1
-#endif
-
-NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
- char * offset;
- size_t toSend;
- ssize_t r;
-
- size_t num_chunks, i;
- struct iovec chunks[UIO_MAXIOV];
- chunk *tc; /* transfer chunks */
- size_t num_bytes = 0;
-
- UNUSED(con);
- /* we can't send more then SSIZE_MAX bytes in one chunk */
-
- /* build writev list
- *
- * 1. limit: num_chunks < UIO_MAXIOV
- * 2. limit: num_bytes < SSIZE_MAX
- */
- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
-
- for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
- if (tc->mem->used == 0) {
- chunks[i].iov_base = tc->mem->ptr;
- chunks[i].iov_len = 0;
- } else {
- offset = tc->mem->ptr + tc->offset;
- toSend = tc->mem->used - 1 - tc->offset;
-
- chunks[i].iov_base = offset;
-
- /* protect the return value of writev() */
- if (toSend > SSIZE_MAX ||
- num_bytes + toSend > SSIZE_MAX) {
- chunks[i].iov_len = SSIZE_MAX - num_bytes;
-
- num_chunks = i + 1;
- break;
- } else {
- chunks[i].iov_len = toSend;
- }
-
- num_bytes += toSend;
- }
- }
-
- if ((r = writev(sock->fd, chunks, num_chunks)) < 0) {
- switch (errno) {
- case EAGAIN:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case EINTR:
- return NETWORK_STATUS_INTERRUPTED;
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "writev failed:", strerror(errno), sock->fd);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- cq->bytes_out += r;
-
- /* check which chunks have been written */
-
- for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
- if (r >= (ssize_t)chunks[i].iov_len) {
- /* written */
- r -= chunks[i].iov_len;
- tc->offset += chunks[i].iov_len;
- } else {
- /* partially written */
-
- tc->offset += r;
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- /* all chunks have been pushed out */
- return NETWORK_STATUS_SUCCESS;
-}
-
-NETWORK_BACKEND_WRITE(writev) {
- chunk *c, *tc;
-
- for(c = cq->first; c; c = c->next) {
- int chunk_finished = 0;
- network_status_t ret;
-
- switch(c->type) {
- case MEM_CHUNK:
- ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
-
- /* check which chunks are finished now */
- for (tc = c; tc && chunk_is_done(tc); tc = tc->next) {
- /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
- if (chunk_finished) {
- c = c->next;
- } else {
- chunk_finished = 1;
- }
- }
-
- if (ret != NETWORK_STATUS_SUCCESS) {
- return ret;
- }
-
- break;
- case FILE_CHUNK: {
- ssize_t r;
- off_t abs_offset;
- off_t toSend;
- stat_cache_entry *sce = NULL;
-
-#define KByte * 1024
-#define MByte * 1024 KByte
-#define GByte * 1024 MByte
- const off_t we_want_to_mmap = 512 KByte;
- char *start = NULL;
-
- if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- strerror(errno), c->file.name);
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- abs_offset = c->file.start + c->offset;
-
- if (abs_offset > sce->st.st_size) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "file was shrinked:", c->file.name);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- /* mmap the buffer
- * - first mmap
- * - new mmap as the we are at the end of the last one */
- if (c->file.mmap.start == MAP_FAILED ||
- abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
-
- /* Optimizations for the future:
- *
- * adaptive mem-mapping
- * the problem:
- * we mmap() the whole file. If someone has alot large files and 32bit
- * machine the virtual address area will be unrun and we will have a failing
- * mmap() call.
- * solution:
- * only mmap 16M in one chunk and move the window as soon as we have finished
- * the first 8M
- *
- * read-ahead buffering
- * the problem:
- * sending out several large files in parallel trashes the read-ahead of the
- * kernel leading to long wait-for-seek times.
- * solutions: (increasing complexity)
- * 1. use madvise
- * 2. use a internal read-ahead buffer in the chunk-structure
- * 3. use non-blocking IO for file-transfers
- * */
-
- /* all mmap()ed areas are 512kb expect the last which might be smaller */
- off_t we_want_to_send;
- size_t to_mmap;
-
- /* this is a remap, move the mmap-offset */
- if (c->file.mmap.start != MAP_FAILED) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.offset += we_want_to_mmap;
- } else {
- /* in case the range-offset is after the first mmap()ed area we skip the area */
- c->file.mmap.offset = 0;
-
- while (c->file.mmap.offset + we_want_to_mmap < c->file.start) {
- c->file.mmap.offset += we_want_to_mmap;
- }
- }
-
- /* length is rel, c->offset too, assume there is no limit at the mmap-boundaries */
- we_want_to_send = c->file.length - c->offset;
- to_mmap = (c->file.start + c->file.length) - c->file.mmap.offset;
-
- /* we have more to send than we can mmap() at once */
- if (abs_offset + we_want_to_send > c->file.mmap.offset + we_want_to_mmap) {
- we_want_to_send = (c->file.mmap.offset + we_want_to_mmap) - abs_offset;
- to_mmap = we_want_to_mmap;
- }
-
- if (-1 == c->file.fd) { /* open the file if not already open */
- if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY | (srv->srvconf.use_noatime ? O_NOATIME : 0) ))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-#ifdef FD_CLOEXEC
- fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
-#endif
- }
-
- if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
- /* close it here, otherwise we'd have to set FD_CLOEXEC */
-
- log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
- strerror(errno), c->file.name, c->file.fd);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- c->file.mmap.length = to_mmap;
-#ifdef LOCAL_BUFFERING
- buffer_copy_string_len(c->mem, c->file.mmap.start, c->file.mmap.length);
-#else
-#ifdef HAVE_MADVISE
- /* don't advise files < 64Kb */
- if (c->file.mmap.length > (64 KByte)) {
- /* darwin 7 is returning EINVAL all the time and I don't know how to
- * detect this at runtime.i
- *
- * ignore the return value for now */
- madvise(c->file.mmap.start, c->file.mmap.length, MADV_WILLNEED);
- }
-#endif
-#endif
-
- /* chunk_reset() or chunk_free() will cleanup for us */
- }
-
- /* to_send = abs_mmap_end - abs_offset */
- toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
-
- if (toSend < 0) {
- log_error_write(srv, __FILE__, __LINE__, "soooo",
- "toSend is negative:",
- toSend,
- c->file.mmap.length,
- abs_offset,
- c->file.mmap.offset);
- assert(toSend < 0);
- }
-
-#ifdef LOCAL_BUFFERING
- start = c->mem->ptr;
-#else
- start = c->file.mmap.start;
-#endif
-
- if ((r = write(sock->fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) {
- switch (errno) {
- case EAGAIN:
- case EINTR:
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- case EPIPE:
- case ECONNRESET:
- return NETWORK_STATUS_CONNECTION_CLOSE;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssd",
- "write failed:", strerror(errno), sock->fd);
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
- }
-
- c->offset += r;
- cq->bytes_out += r;
-
- if (c->offset == c->file.length) {
- chunk_finished = 1;
-
- /* we don't need the mmaping anymore */
- if (c->file.mmap.start != MAP_FAILED) {
- munmap(c->file.mmap.start, c->file.mmap.length);
- c->file.mmap.start = MAP_FAILED;
- }
- }
-
- break;
- }
- default:
-
- log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
-
- return NETWORK_STATUS_FATAL_ERROR;
- }
-
- if (!chunk_finished) {
- /* not finished yet */
-
- return NETWORK_STATUS_WAIT_FOR_EVENT;
- }
- }
-
- return NETWORK_STATUS_SUCCESS;
-}
-
-#endif
diff --git a/src/plugin.c b/src/plugin.c
deleted file mode 100644
index 98ccae82..00000000
--- a/src/plugin.c
+++ /dev/null
@@ -1,592 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-
-#include <stdio.h>
-
-#include "plugin.h"
-#include "log.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "sys-files.h"
-
-#ifndef _WIN32
-#include <dlfcn.h>
-#endif
-/*
- *
- * if you change this enum to add a new callback, be sure
- * - that PLUGIN_FUNC_SIZEOF is the last entry
- * - that you add PLUGIN_TO_SLOT twice:
- * 1. as callback-dispatcher
- * 2. in plugins_call_init()
- *
- */
-
-typedef struct {
- PLUGIN_DATA;
-} plugin_data;
-
-typedef enum {
- PLUGIN_FUNC_UNSET,
- PLUGIN_FUNC_HANDLE_URI_CLEAN,
- PLUGIN_FUNC_HANDLE_URI_RAW,
- PLUGIN_FUNC_HANDLE_RESPONSE_DONE,
- PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
- PLUGIN_FUNC_HANDLE_TRIGGER,
- PLUGIN_FUNC_HANDLE_SIGHUP,
- PLUGIN_FUNC_HANDLE_START_BACKEND,
- PLUGIN_FUNC_HANDLE_SEND_REQUEST_CONTENT,
- PLUGIN_FUNC_HANDLE_RESPONSE_HEADER,
- PLUGIN_FUNC_HANDLE_READ_RESPONSE_CONTENT,
- PLUGIN_FUNC_HANDLE_FILTER_RESPONSE_CONTENT,
- PLUGIN_FUNC_HANDLE_JOBLIST,
- PLUGIN_FUNC_HANDLE_DOCROOT,
- PLUGIN_FUNC_HANDLE_PHYSICAL,
- PLUGIN_FUNC_CONNECTION_RESET,
- PLUGIN_FUNC_INIT,
- PLUGIN_FUNC_CLEANUP,
- PLUGIN_FUNC_SET_DEFAULTS,
-
- PLUGIN_FUNC_SIZEOF
-} plugin_t;
-
-static plugin *plugin_init(void) {
- plugin *p;
-
- p = calloc(1, sizeof(*p));
-
- p->required_plugins = array_init();
-
- return p;
-}
-
-static void plugin_free(plugin *p) {
- int use_dlclose = 1;
-
- if (p->name) buffer_free(p->name);
-
- array_free(p->required_plugins);
-
- /* if we are running under valgrind,
- * don't unload the plugins to keep the symbols intact */
- if (RUNNING_ON_VALGRIND) use_dlclose = 0;
-
-#ifndef LIGHTTPD_STATIC
- if (use_dlclose && p->lib) {
-#ifdef _WIN32
- FreeLibrary(p->lib);
-#else
- dlclose(p->lib);
-#endif
- }
-#endif
-
- free(p);
-}
-
-static int plugins_register(server *srv, plugin *p) {
- plugin **ps;
- if (0 == srv->plugins.size) {
- srv->plugins.size = 4;
- srv->plugins.ptr = malloc(srv->plugins.size * sizeof(*ps));
- srv->plugins.used = 0;
- } else if (srv->plugins.used == srv->plugins.size) {
- srv->plugins.size += 4;
- srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
- }
-
- ps = srv->plugins.ptr;
- ps[srv->plugins.used++] = p;
-
- return 0;
-}
-
-/**
- *
- *
- *
- */
-
-#ifdef LIGHTTPD_STATIC
-
-#define PLUGIN_STATIC(x) int x ## _plugin_init(plugin *p)
-
-PLUGIN_STATIC(mod_access);
-PLUGIN_STATIC(mod_accesslog);
-PLUGIN_STATIC(mod_alias);
-PLUGIN_STATIC(mod_auth);
-PLUGIN_STATIC(mod_cgi);
-PLUGIN_STATIC(mod_dirlisting);
-PLUGIN_STATIC(mod_evasive);
-PLUGIN_STATIC(mod_evhost);
-PLUGIN_STATIC(mod_expire);
-PLUGIN_STATIC(mod_deflate);
-PLUGIN_STATIC(mod_compress);
-PLUGIN_STATIC(mod_flv_streaming);
-PLUGIN_STATIC(mod_chunked);
-PLUGIN_STATIC(mod_indexfile);
-PLUGIN_STATIC(mod_mysql_vhost);
-PLUGIN_STATIC(mod_postgresql_vhost);
-PLUGIN_STATIC(mod_proxy_backend_ajp13);
-PLUGIN_STATIC(mod_proxy_backend_fastcgi);
-PLUGIN_STATIC(mod_proxy_backend_http);
-PLUGIN_STATIC(mod_proxy_backend_scgi);
-PLUGIN_STATIC(mod_proxy_core);
-PLUGIN_STATIC(mod_redirect);
-PLUGIN_STATIC(mod_rewrite);
-PLUGIN_STATIC(mod_secdownload);
-PLUGIN_STATIC(mod_setenv);
-PLUGIN_STATIC(mod_simple_vhost);
-PLUGIN_STATIC(mod_sql_vhost_core);
-PLUGIN_STATIC(mod_ssi);
-PLUGIN_STATIC(mod_staticfile);
-PLUGIN_STATIC(mod_status);
-PLUGIN_STATIC(mod_trigger_b4_dl);
-PLUGIN_STATIC(mod_uploadprogress);
-PLUGIN_STATIC(mod_userdir);
-PLUGIN_STATIC(mod_usertrack);
-PLUGIN_STATIC(mod_webdav);
-PLUGIN_STATIC(mod_magnet);
-
-#undef PLUGIN_STATIC
-
-#define PLUGIN_STATIC(x) { #x, x ## _plugin_init }
-
-struct {
- const char *name;
- int (*init)(plugin *pl);
-} const static_plugins[] = {
-PLUGIN_STATIC(mod_access),
-PLUGIN_STATIC(mod_accesslog),
-PLUGIN_STATIC(mod_alias),
-PLUGIN_STATIC(mod_auth),
-PLUGIN_STATIC(mod_cgi),
-PLUGIN_STATIC(mod_dirlisting),
-PLUGIN_STATIC(mod_evasive),
-PLUGIN_STATIC(mod_evhost),
-PLUGIN_STATIC(mod_expire),
-PLUGIN_STATIC(mod_deflate),
-PLUGIN_STATIC(mod_compress),
-PLUGIN_STATIC(mod_flv_streaming),
-PLUGIN_STATIC(mod_chunked),
-PLUGIN_STATIC(mod_indexfile),
-PLUGIN_STATIC(mod_mysql_vhost),
-PLUGIN_STATIC(mod_postgresql_vhost),
-PLUGIN_STATIC(mod_proxy_backend_ajp13),
-PLUGIN_STATIC(mod_proxy_backend_fastcgi),
-PLUGIN_STATIC(mod_proxy_backend_http),
-PLUGIN_STATIC(mod_proxy_backend_scgi),
-PLUGIN_STATIC(mod_proxy_core),
-PLUGIN_STATIC(mod_redirect),
-PLUGIN_STATIC(mod_rewrite),
-PLUGIN_STATIC(mod_secdownload),
-PLUGIN_STATIC(mod_setenv),
-PLUGIN_STATIC(mod_simple_vhost),
-PLUGIN_STATIC(mod_sql_vhost_core),
-PLUGIN_STATIC(mod_ssi),
-PLUGIN_STATIC(mod_staticfile),
-PLUGIN_STATIC(mod_status),
-PLUGIN_STATIC(mod_trigger_b4_dl),
-PLUGIN_STATIC(mod_uploadprogress),
-PLUGIN_STATIC(mod_userdir),
-PLUGIN_STATIC(mod_usertrack),
-PLUGIN_STATIC(mod_webdav),
-PLUGIN_STATIC(mod_magnet),
-
- { NULL, NULL }
-};
-
-#undef PLUGIN_STATIC
-
-#endif
-
-int plugins_load(server *srv) {
- plugin *p;
- int (*init)(plugin *pl);
-
- const char *error;
- size_t i, j, k;
-
- for (i = 0; i < srv->srvconf.modules->used; i++) {
- data_string *d = (data_string *)srv->srvconf.modules->data[i];
- char *modules = d->value->ptr;
-
- p = plugin_init();
-
-#ifdef LIGHTTPD_STATIC
- for (j = 0; static_plugins[j].name; j++) {
- if (0 == strcmp(BUF_STR(d->value), static_plugins[j].name)) {
- init = static_plugins[j].init;
-
- break;
- }
- }
-
- if (static_plugins[j].name == NULL) {
- ERROR("the plugin '%s' is not compiled in", SAFE_BUF_STR(d->value));
- return -1;
- }
-#else
- buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
-
- if (strlen(srv->srvconf.modules_dir->ptr) != 0) buffer_append_string(srv->tmp_buf, DIR_SEPERATOR_STR);
- buffer_append_string(srv->tmp_buf, modules);
-#if defined(_WIN32) || defined(__CYGWIN__)
- buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".dll"));
-#else
- buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(".so"));
-#endif
-
-#ifdef _WIN32
- if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL );
-
- log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
- lpMsgBuf, srv->tmp_buf);
-
- plugin_free(p);
-
- return -1;
-
- }
-#else
- if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
- srv->tmp_buf, dlerror());
-
- plugin_free(p);
-
- return -1;
- }
-
-#endif
- buffer_reset(srv->tmp_buf);
- buffer_copy_string(srv->tmp_buf, modules);
- buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("_plugin_init"));
-
-#ifdef _WIN32
- init = (int (*)(plugin *pl)) GetProcAddress(p->lib, srv->tmp_buf->ptr);
-
- if (init == NULL) {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL );
-
- log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
-
- plugin_free(p);
- return -1;
- }
-
-#else
-#if 1
- init = (int (*)(plugin *))(intptr_t)dlsym(p->lib, srv->tmp_buf->ptr);
-#else
- *(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr);
-#endif
- if ((error = dlerror()) != NULL) {
- ERROR("dlsym(%s) failed: %s", SAFE_BUF_STR(srv->tmp_buf), error);
-
- plugin_free(p);
- return -1;
- }
-
-#endif
-#endif
- if ((*init)(p)) {
- ERROR("plugin-init failed for %s", SAFE_BUF_STR(d->value));
-
- plugin_free(p);
- return -1;
- }
-
- /* check if the required plugin is loaded */
- for (k = 0; k < p->required_plugins->used; k++) {
- data_string *req = (data_string *)p->required_plugins->data[k];
-
- for (j = 0; j < i; j++) {
- data_string *mod = (data_string *)srv->srvconf.modules->data[j];
-
- if (buffer_is_equal(req->value, mod->value)) break;
- }
-
- if (j == i) {
- /* not found */
- log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
-
- plugin_free(p);
-
- return -1;
- }
- }
- plugins_register(srv, p);
- }
-
- return 0;
-}
-
-#define PLUGIN_TO_SLOT(x, y) \
- handler_t plugins_call_##y(server *srv, connection *con) {\
- plugin **slot;\
- size_t j;\
- if (!srv->plugin_slots) return HANDLER_GO_ON;\
- slot = ((plugin ***)(srv->plugin_slots))[x];\
- if (!slot) return HANDLER_GO_ON;\
- for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
- plugin *p = slot[j];\
- handler_t r;\
- switch(r = p->y(srv, con, p->data)) {\
- case HANDLER_GO_ON:\
- break;\
- case HANDLER_FINISHED:\
- case HANDLER_COMEBACK:\
- case HANDLER_WAIT_FOR_EVENT:\
- case HANDLER_WAIT_FOR_FD:\
- case HANDLER_ERROR:\
- if (con->conf.log_request_handling) TRACE("-- plugins_call_...: plugin '%s' returns %d", SAFE_BUF_STR(p->name), r); \
- return r;\
- default:\
- ERROR("-- plugins_call_...: plugin '%s' returns %d (unexpected)", SAFE_BUF_STR(p->name), r); \
- return HANDLER_ERROR;\
- }\
- }\
- return HANDLER_GO_ON;\
- }
-
-/**
- * plugins that use
- *
- * - server *srv
- * - connection *con
- * - void *p_d (plugin_data *)
- */
-
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_START_BACKEND, handle_start_backend)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SEND_REQUEST_CONTENT, handle_send_request_content)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_HEADER, handle_response_header)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_READ_RESPONSE_CONTENT, handle_read_response_content)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_FILTER_RESPONSE_CONTENT, handle_filter_response_content)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_DONE, handle_response_done)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset)
-
-#undef PLUGIN_TO_SLOT
-
-#define PLUGIN_TO_SLOT(x, y) \
- handler_t plugins_call_##y(server *srv) {\
- plugin **slot;\
- size_t j;\
- if (!srv->plugin_slots) return HANDLER_GO_ON;\
- slot = ((plugin ***)(srv->plugin_slots))[x];\
- if (!slot) return HANDLER_GO_ON;\
- for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
- plugin *p = slot[j];\
- handler_t r;\
- switch(r = p->y(srv, p->data)) {\
- case HANDLER_GO_ON:\
- break;\
- case HANDLER_FINISHED:\
- case HANDLER_COMEBACK:\
- case HANDLER_WAIT_FOR_EVENT:\
- case HANDLER_WAIT_FOR_FD:\
- case HANDLER_ERROR:\
- return r;\
- default:\
- log_error_write(srv, __FILE__, __LINE__, "sbsd", #x, p->name, "unknown state:", r);\
- return HANDLER_ERROR;\
- }\
- }\
- return HANDLER_GO_ON;\
- }
-
-/**
- * plugins that use
- *
- * - server *srv
- * - void *p_d (plugin_data *)
- */
-
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
-PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults)
-
-#undef PLUGIN_TO_SLOT
-
-#if 0
-/**
- *
- * special handler
- *
- */
-handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
- size_t i;
- plugin **ps;
-
- ps = srv->plugins.ptr;
-
- for (i = 0; i < srv->plugins.used; i++) {
- plugin *p = ps[i];
- if (p->handle_fdevent) {
- handler_t r;
- switch(r = p->handle_fdevent(srv, fdc, p->data)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_FINISHED:
- case HANDLER_COMEBACK:
- case HANDLER_WAIT_FOR_EVENT:
- case HANDLER_ERROR:
- return r;
- default:
- log_error_write(srv, __FILE__, __LINE__, "d", r);
- break;
- }
- }
- }
-
- return HANDLER_GO_ON;
-}
-#endif
-/**
- *
- * - call init function of all plugins to init the plugin-internals
- * - added each plugin that supports has callback to the corresponding slot
- *
- * - is only called once.
- */
-
-handler_t plugins_call_init(server *srv) {
- size_t i;
- plugin **ps;
-
- ps = srv->plugins.ptr;
-
- /* fill slots */
-
- srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
-
- for (i = 0; i < srv->plugins.used; i++) {
- size_t j;
- /* check which calls are supported */
-
- plugin *p = ps[i];
-
-#define PLUGIN_TO_SLOT(x, y) \
- if (p->y) { \
- plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
- if (!slot) { \
- slot = calloc(srv->plugins.used, sizeof(*slot));\
- ((plugin ***)(srv->plugin_slots))[x] = slot; \
- } \
- for (j = 0; j < srv->plugins.used; j++) { \
- if (slot[j]) continue;\
- slot[j] = p;\
- break;\
- }\
- }
-
-
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_START_BACKEND, handle_start_backend);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SEND_REQUEST_CONTENT, handle_send_request_content);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_HEADER, handle_response_header);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_READ_RESPONSE_CONTENT, handle_read_response_content);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_FILTER_RESPONSE_CONTENT, handle_filter_response_content)
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_RESPONSE_DONE, handle_response_done);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
-
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
- PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup);
-#undef PLUGIN_TO_SLOT
-
- if (p->init) {
- if (NULL == (p->data = p->init(srv))) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "plugin-init failed for module", p->name);
- return HANDLER_ERROR;
- }
-
- /* used for con->mode, DIRECT == 0, plugins above that */
- ((plugin_data *)(p->data))->id = i + 1;
-
- if (p->version != LIGHTTPD_VERSION_ID) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "plugin-version doesn't match lighttpd-version for", p->name);
- return HANDLER_ERROR;
- }
- } else {
- p->data = NULL;
- }
- }
-
- return HANDLER_GO_ON;
-}
-
-/**
- * get the config-storage of the named plugin
- */
-void *plugin_get_config(server *srv, const char *name) {
- size_t i;
-
- for (i = 0; i < srv->plugins.used; i++) {
- plugin *p = ((plugin **)srv->plugins.ptr)[i];
-
- if (buffer_is_equal_string(p->name, name, strlen(name))) {
- return p->data;
- }
- }
-
- return NULL;
-}
-
-void plugins_free(server *srv) {
- size_t i;
- plugins_call_cleanup(srv);
-
- for (i = 0; i < srv->plugins.used; i++) {
- plugin *p = ((plugin **)srv->plugins.ptr)[i];
-
- plugin_free(p);
- }
-
- for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
- plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
-
- if (slot) free(slot);
- }
-
- free(srv->plugin_slots);
- srv->plugin_slots = NULL;
-
- free(srv->plugins.ptr);
- srv->plugins.ptr = NULL;
- srv->plugins.used = 0;
-}
diff --git a/src/plugin.h b/src/plugin.h
deleted file mode 100644
index 112c4f7c..00000000
--- a/src/plugin.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-#include "settings.h"
-#include "base.h"
-#include "buffer.h"
-
-
-
-#define SERVER_FUNC(x) \
- static handler_t x(server *srv, void *p_d)
-
-#define CONNECTION_FUNC(x) \
- static handler_t x(server *srv, connection *con, void *p_d)
-
-#define INIT_FUNC(x) \
- static void * x(server *srv)
-/*
- * The PATCH_OPTION() macro is used in the patch_connection() functions
- * of the modules to update the config object for the current request.
- */
-#define PATCH_OPTION(x) \
- p->conf.x = s->x
-
-#define FREE_FUNC SERVER_FUNC
-#define TRIGGER_FUNC SERVER_FUNC
-#define SETDEFAULTS_FUNC SERVER_FUNC
-#define SIGHUP_FUNC SERVER_FUNC
-
-#define SUBREQUEST_FUNC CONNECTION_FUNC
-#define JOBLIST_FUNC CONNECTION_FUNC
-#define PHYSICALPATH_FUNC CONNECTION_FUNC
-#define REQUESTDONE_FUNC CONNECTION_FUNC
-#define URIHANDLER_FUNC CONNECTION_FUNC
-
-#define PLUGIN_DATA size_t id
-
-/**
- * we have 4 states on the connection:
- * - read-header
- * - read-content
- * - write-header
- * - write-content
- */
-
-typedef struct {
- size_t version;
-
- buffer *name; /* name of the plugin */
-
- void *(* init) (server *srv);
- handler_t (* set_defaults) (server *srv, void *p_d);
- handler_t (* cleanup) (server *srv, void *p_d);
- /* is called ... */
- handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
- handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
-
- handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set (mod_rewrite) */
- handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set (mod_access, mod_auth) */
- handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root (e.g. mod_simple_vhost) */
- handler_t (* handle_physical) (server *srv, connection *con, void *p_d); /* mapping url to physical path (e.g. mod_alias, mod_proxy_core) */
- handler_t (* handle_start_backend) (server *srv, connection *con, void *p_d); /* file exists locally (e.g. mod_staticfile) */
- handler_t (* handle_send_request_content)(server *srv, connection *con, void *p_d); /* a handler for the request content */
- handler_t (* handle_response_header) (server *srv, connection *con, void *p_d); /* a handler for the request content */
- handler_t (* handle_read_response_content)(server *srv, connection *con, void *p_d); /* read the content from the source and push it to the next queue */
- handler_t (* handle_filter_response_content)(server *srv, connection *con, void *p_d); /* apply filters to response content (compression/chunk encoding/ etc..) */
- handler_t (* handle_response_done) (server *srv, connection *con, void *p_d); /* after the response is sent (e.g. mod_accesslog) */
- handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* end of a request-response cycle (mod_acceslog, mod_proxy_core) */
- handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection [remove-me ?] */
- handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled [remove-me ?] */
-
- void *data;
-
- /* dlopen handle */
- void *lib;
-
- array *required_plugins;
-} plugin;
-
-LI_EXPORT int plugins_load(server *srv);
-LI_EXPORT void plugins_free(server *srv);
-
-LI_EXPORT handler_t plugins_call_handle_uri_raw(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_uri_clean(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_docroot(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_physical(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_start_backend(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_send_request_content(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_response_header(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_read_response_content(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_filter_response_content(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_response_done(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_connection_close(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_handle_joblist(server *srv, connection *con);
-LI_EXPORT handler_t plugins_call_connection_reset(server *srv, connection *con);
-
-LI_EXPORT handler_t plugins_call_handle_trigger(server *srv);
-LI_EXPORT handler_t plugins_call_handle_sighup(server *srv);
-
-LI_EXPORT handler_t plugins_call_init(server *srv);
-LI_EXPORT handler_t plugins_call_set_defaults(server *srv);
-LI_EXPORT handler_t plugins_call_cleanup(server *srv);
-
-LI_EXPORT int config_insert_values_global(server *srv, array *ca, const config_values_t *cv);
-LI_EXPORT int config_insert_values_internal(server *srv, array *ca, const config_values_t *cv);
-LI_EXPORT int config_setup_connection(server *srv, connection *con);
-LI_EXPORT int config_patch_connection(server *srv, connection *con, comp_key_t comp);
-LI_EXPORT int config_check_cond(server *srv, connection *con, data_config *dc);
-LI_EXPORT int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
-LI_EXPORT int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
-
-LI_EXPORT void* plugin_get_config(server *srv, const char *name);
-
-#endif
diff --git a/src/proc_open.c b/src/proc_open.c
deleted file mode 100644
index 7e010922..00000000
--- a/src/proc_open.c
+++ /dev/null
@@ -1,395 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include "proc_open.h"
-
-#ifdef _WIN32
-#include <io.h>
-#include <fcntl.h>
-#else
-#include <sys/wait.h>
-#include <unistd.h>
-#endif
-
-
-#ifdef _WIN32
-/* {{{ win32 stuff */
-# define SHELLENV "ComSpec"
-# define SECURITY_DC , SECURITY_ATTRIBUTES *security
-# define SECURITY_CC , security
-# define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
-static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
-{
- HANDLE copy, self = GetCurrentProcess();
-
- if (!DuplicateHandle(self, src, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS |
- (closeorig ? DUPLICATE_CLOSE_SOURCE : 0)))
- return NULL;
- return copy;
-}
-# define close_descriptor(fd) CloseHandle(fd)
-static void pipe_close_parent(pipe_t *p) {
- /* don't let the child inherit the parent side of the pipe */
- p->parent = dup_handle(p->parent, FALSE, TRUE);
-}
-static void pipe_close_child(pipe_t *p) {
- close_descriptor(p->child);
- p->fd = _open_osfhandle((long)p->parent,
- (p->fd == 0 ? O_RDONLY : O_WRONLY)|O_BINARY);
-}
-/* }}} */
-#else /* _WIN32 */
-/* {{{ unix way */
-# define SHELLENV "SHELL"
-# define SECURITY_DC
-# define SECURITY_CC
-# define close_descriptor(fd) close(fd)
-static void pipe_close_parent(pipe_t *p) {
- /* don't close stdin */
- close_descriptor(p->parent);
- if (dup2(p->child, p->fd) != p->fd) {
- perror("pipe_child dup2");
- } else {
- close_descriptor(p->child);
- p->child = p->fd;
- }
-}
-static void pipe_close_child(pipe_t *p) {
- close_descriptor(p->child);
- p->fd = p->parent;
-}
-/* }}} */
-#endif /* _WIN32 */
-
-/* {{{ pipe_close */
-static void pipe_close(pipe_t *p) {
- close_descriptor(p->parent);
- close_descriptor(p->child);
-#ifdef _WIN32
- close(p->fd);
-#endif
-}
-/* }}} */
-/* {{{ pipe_open */
-static int pipe_open(pipe_t *p, int fd SECURITY_DC) {
- descriptor_t newpipe[2];
-
- if (0 != pipe(newpipe)) {
- fprintf(stderr, "can't open pipe");
- return -1;
- }
- if (0 == fd) {
- p->parent = newpipe[1]; /* write */
- p->child = newpipe[0]; /* read */
- } else {
- p->parent = newpipe[0]; /* read */
- p->child = newpipe[1]; /* write */
- }
- p->fd = fd;
-
- return 0;
-}
-/* }}} */
-
-/* {{{ proc_open_pipes */
-static int proc_open_pipes(proc_handler_t *proc SECURITY_DC) {
- if (pipe_open(&(proc->in), 0 SECURITY_CC) != 0) {
- return -1;
- }
- if (pipe_open(&(proc->out), 1 SECURITY_CC) != 0) {
- return -1;
- }
- if (pipe_open(&(proc->err), 2 SECURITY_CC) != 0) {
- return -1;
- }
- return 0;
-}
-/* }}} */
-/* {{{ proc_close_pipes */
-static void proc_close_pipes(proc_handler_t *proc) {
- pipe_close(&proc->in);
- pipe_close(&proc->out);
- pipe_close(&proc->err);
-}
-/* }}} */
-/* {{{ proc_close_parents */
-static void proc_close_parents(proc_handler_t *proc) {
- pipe_close_parent(&proc->in);
- pipe_close_parent(&proc->out);
- pipe_close_parent(&proc->err);
-}
-/* }}} */
-/* {{{ proc_close_childs */
-static void proc_close_childs(proc_handler_t *proc) {
- pipe_close_child(&proc->in);
- pipe_close_child(&proc->out);
- pipe_close_child(&proc->err);
-}
-/* }}} */
-
-#ifdef _WIN32
-/* {{{ proc_close */
-int proc_close(proc_handler_t *proc) {
- proc_pid_t child = proc->child;
- DWORD wstatus;
-
- proc_close_pipes(proc);
- WaitForSingleObject(child, INFINITE);
- GetExitCodeProcess(child, &wstatus);
- CloseHandle(child);
-
- return wstatus;
-}
-/* }}} */
-/* {{{ proc_open */
-int proc_open(proc_handler_t *proc, const char *command) {
- PROCESS_INFORMATION pi;
- STARTUPINFO si;
- BOOL procok;
- SECURITY_ATTRIBUTES security;
- const char *shell = NULL;
- const char *windir = NULL;
- buffer *cmdline;
-
- if (NULL == (shell = getenv(SHELLENV)) &&
- NULL == (windir = getenv("SystemRoot")) &&
- NULL == (windir = getenv("windir"))) {
- fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
- return -1;
- }
-
- /* we use this to allow the child to inherit handles */
- memset(&security, 0, sizeof(security));
- security.nLength = sizeof(security);
- security.bInheritHandle = TRUE;
- security.lpSecurityDescriptor = NULL;
-
- if (proc_open_pipes(proc, &security) != 0) {
- return -1;
- }
- proc_close_parents(proc);
-
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = proc->in.child;
- si.hStdOutput = proc->out.child;
- si.hStdError = proc->err.child;
-
- memset(&pi, 0, sizeof(pi));
-
- cmdline = buffer_init();
- if (shell) {
- buffer_append_string(cmdline, shell);
- } else {
- buffer_append_string(cmdline, windir);
- buffer_append_string_len(cmdline, CONST_STR_LEN("\\system32\\cmd.exe"));
- }
- buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
- buffer_append_string(cmdline, command);
- procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
- NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
-
- if (FALSE == procok) {
- fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
- buffer_free(cmdline);
- return -1;
- }
- buffer_free(cmdline);
-
- proc->child = pi.hProcess;
- CloseHandle(pi.hThread);
-
- proc_close_childs(proc);
-
- return 0;
-}
-/* }}} */
-#else /* _WIN32 */
-/* {{{ proc_close */
-int proc_close(proc_handler_t *proc) {
- pid_t child = proc->child;
- int wstatus;
- pid_t wait_pid;
-
- proc_close_pipes(proc);
-
- do {
- wait_pid = waitpid(child, &wstatus, 0);
- } while (wait_pid == -1 && errno == EINTR);
-
- if (wait_pid == -1) {
- return -1;
- } else {
- if (WIFEXITED(wstatus))
- wstatus = WEXITSTATUS(wstatus);
- }
-
- return wstatus;
-}
-/* }}} */
-/* {{{ proc_open */
-int proc_open(proc_handler_t *proc, const char *command) {
- pid_t child;
- const char *shell;
-
- if (NULL == (shell = getenv(SHELLENV))) {
- shell = "/bin/sh";
- }
-
- if (proc_open_pipes(proc) != 0) {
- return -1;
- }
-
- /* the unix way */
-
- child = fork();
-
- if (child == 0) {
- /* this is the child process */
-
- /* close those descriptors that we just opened for the parent stuff,
- * dup new descriptors into required descriptors and close the original
- * cruft
- */
- proc_close_parents(proc);
-
- execl(shell, shell, "-c", command, (char *)NULL);
- _exit(127);
-
- } else if (child < 0) {
- fprintf(stderr, "failed to forking");
- proc_close(proc);
- return -1;
-
- } else {
- proc->child = child;
- proc_close_childs(proc);
- return 0;
- }
-}
-/* }}} */
-#endif /* _WIN32 */
-
-/* {{{ proc_read_fd_to_buffer */
-static void proc_read_fd_to_buffer(int fd, buffer *b) {
- int s; /* win32 has not ssize_t */
-
- for (;;) {
- buffer_prepare_append(b, 512);
- if ((s = read(fd, (void *)(b->ptr + b->used), 512 - 1)) <= 0) {
- break;
- }
- b->used += s;
- }
- b->ptr[b->used] = '\0';
-}
-/* }}} */
-/* {{{ proc_open_buffer */
-int proc_open_buffer(const char *command, buffer *in, buffer *out, buffer *err) {
- proc_handler_t proc;
-
- if (proc_open(&proc, command) != 0) {
- return -1;
- }
-
- if (in) {
- if (write(proc.in.fd, (void *)in->ptr, in->used) < 0) {
- perror("error writing pipe");
- return -1;
- }
- }
- pipe_close(&proc.in);
-
- if (out) {
- proc_read_fd_to_buffer(proc.out.fd, out);
- }
- pipe_close(&proc.out);
-
- if (err) {
- proc_read_fd_to_buffer(proc.err.fd, err);
- }
- pipe_close(&proc.err);
-
- proc_close(&proc);
-
- return 0;
-}
-/* }}} */
-
-/* {{{ test */
-#ifdef DEBUG_PROC_OPEN
-int main() {
- proc_handler_t proc;
- buffer *in = buffer_init(), *out = buffer_init(), *err = buffer_init();
- int wstatus;
-
-#define FREE() do { \
- buffer_free(in); \
- buffer_free(out); \
- buffer_free(err); \
-} while (0)
-
-#define RESET() do { \
- buffer_reset(in); \
- buffer_reset(out); \
- buffer_reset(err); \
- wstatus = proc_close(&proc); \
- if (0&&wstatus != 0) { \
- fprintf(stdout, "exitstatus %d\n", wstatus); \
- return __LINE__ - 200; \
- } \
-} while (0)
-
-#define ERROR_OUT() do { \
- fprintf(stdout, "failed opening proc\n"); \
- wstatus = proc_close(&proc); \
- fprintf(stdout, "exitstatus %d\n", wstatus); \
- FREE(); \
- return __LINE__ - 300; \
-} while (0)
-
-#ifdef _WIN32
-#define CMD_CAT "pause"
-#else
-#define CMD_CAT "cat"
-#endif
-
- do {
- fprintf(stdout, "test: echo 123 without read\n");
- if (proc_open(&proc, "echo 321") != 0) {
- ERROR_OUT();
- }
- close_descriptor(proc.in.parent);
- close_descriptor(proc.out.parent);
- close_descriptor(proc.err.parent);
- RESET();
-
- fprintf(stdout, "test: echo 321 with read\n"); fflush(stdout);
- if (proc_open_buffer("echo 321", NULL, out, err) != 0) {
- ERROR_OUT();
- }
- fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
- RESET();
-
- fprintf(stdout, "test: echo 123 | " CMD_CAT "\n"); fflush(stdout);
- buffer_copy_string_len(in, CONST_STR_LEN("123\n"));
- if (proc_open_buffer(CMD_CAT, in, out, err) != 0) {
- ERROR_OUT();
- }
- fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
- RESET();
- } while (0);
-
-#undef RESET
-#undef ERROR_OUT
-
- fprintf(stdout, "ok\n");
-
- FREE();
- return 0;
-}
-#endif /* DEBUG_PROC_OPEN */
-/* }}} */
-
diff --git a/src/proc_open.h b/src/proc_open.h
deleted file mode 100644
index 57a54b51..00000000
--- a/src/proc_open.h
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#include "buffer.h"
-
-#ifdef _WIN32
-#include <windows.h>
-typedef HANDLE descriptor_t;
-typedef HANDLE proc_pid_t;
-#else
-typedef int descriptor_t;
-typedef pid_t proc_pid_t;
-#endif
-
-typedef struct {
- descriptor_t parent, child;
- int fd;
-} pipe_t;
-
-typedef struct {
- pipe_t in, out, err;
- proc_pid_t child;
-} proc_handler_t;
-
-LI_EXPORT int proc_close(proc_handler_t *ht);
-LI_EXPORT int proc_open(proc_handler_t *ht, const char *command);
-LI_EXPORT int proc_open_buffer(const char *command, buffer *in, buffer *out, buffer *err);
diff --git a/src/request.c b/src/request.c
deleted file mode 100644
index 816b5368..00000000
--- a/src/request.c
+++ /dev/null
@@ -1,599 +0,0 @@
-#include <sys/stat.h>
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "request.h"
-#include "keyvalue.h"
-#include "log.h"
-#include "http_req.h"
-
-#include "sys-strings.h"
-
-static int request_check_hostname(buffer *host) {
- enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
- size_t i;
- int label_len = 0;
- size_t host_len;
- char *colon;
- int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
- int level = 0;
-
- /*
- * hostport = host [ ":" port ]
- * host = hostname | IPv4address | IPv6address
- * hostname = *( domainlabel "." ) toplabel [ "." ]
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- * IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
- * IPv6address = "[" ... "]"
- * port = *digit
- */
-
- /* no Host: */
- if (buffer_is_empty(host)) return 0;
- if (host->used < 1) return 0;
-
- host_len = host->used - 1;
-
- /* IPv6 adress */
- if (host->ptr[0] == '[') {
- char *c = host->ptr + 1;
- int colon_cnt = 0;
-
- /* check portnumber */
- for (; *c && *c != ']'; c++) {
- if (*c == ':') {
- if (++colon_cnt > 7) {
- return -1;
- }
- } else if (!light_isxdigit(*c)) {
- return -1;
- }
- }
-
- /* missing ] */
- if (!*c) {
- return -1;
- }
-
- /* check port */
- if (*(c+1) == ':') {
- for (c += 2; *c; c++) {
- if (!light_isdigit(*c)) {
- return -1;
- }
- }
- }
- return 0;
- }
-
- if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
- char *c = colon + 1;
-
- /* check portnumber */
- for (; *c; c++) {
- if (!light_isdigit(*c)) return -1;
- }
-
- /* remove the port from the host-len */
- host_len = colon - host->ptr;
- }
-
- /* Host is empty */
- if (host_len == 0) return -1;
-
- /* if the hostname ends in a "." strip it */
- if (host->ptr[host_len-1] == '.') {
- /* shift port info one left */
- if (NULL != colon) memmove(colon-1, colon, host->used - host_len);
- else host->ptr[host_len-1] = '\0';
- host_len -= 1;
- host->used -= 1;
- }
-
- if (host_len == 0) return -1;
-
- /* scan from the right and skip the \0 */
- for (i = host_len; i-- > 0; ) {
- const char c = host->ptr[i];
-
- switch (stage) {
- case TOPLABEL:
- if (c == '.') {
- /* only switch stage, if this is not the last character */
- if (i != host_len - 1) {
- if (label_len == 0) {
- return -1;
- }
-
- /* check the first character at right of the dot */
- if (is_ip == 0) {
- if (!light_isalnum(host->ptr[i+1])) {
- return -1;
- }
- } else if (!light_isdigit(host->ptr[i+1])) {
- is_ip = 0;
- } else if ('-' == host->ptr[i+1]) {
- return -1;
- } else {
- /* just digits */
- is_ip = 1;
- }
-
- stage = DOMAINLABEL;
-
- label_len = 0;
- level++;
- } else if (i == 0) {
- /* just a dot and nothing else is evil */
- return -1;
- }
- } else if (i == 0) {
- /* the first character of the hostname */
- if (!light_isalnum(c)) {
- return -1;
- }
- label_len++;
- } else {
- if (c != '-' && !light_isalnum(c)) {
- return -1;
- }
- if (is_ip == -1) {
- if (!light_isdigit(c)) is_ip = 0;
- }
- label_len++;
- }
-
- break;
- case DOMAINLABEL:
- if (is_ip == 1) {
- if (c == '.') {
- if (label_len == 0) {
- return -1;
- }
-
- label_len = 0;
- level++;
- } else if (!light_isdigit(c)) {
- return -1;
- } else {
- label_len++;
- }
- } else {
- if (c == '.') {
- if (label_len == 0) {
- return -1;
- }
-
- /* c is either - or alphanum here */
- if ('-' == host->ptr[i+1]) {
- return -1;
- }
-
- label_len = 0;
- level++;
- } else if (i == 0) {
- if (!light_isalnum(c)) {
- return -1;
- }
- label_len++;
- } else {
- if (c != '-' && !light_isalnum(c)) {
- return -1;
- }
- label_len++;
- }
- }
-
- break;
- }
- }
-
- /* a IP has to consist of 4 parts */
- if (is_ip == 1 && level != 3) {
- return -1;
- }
-
- if (label_len == 0) {
- return -1;
- }
-
- return 0;
-}
-
-#if 0
-#define DUMP_HEADER
-#endif
-
-static int http_request_split_value(array *vals, buffer *b) {
- char *s;
- size_t i;
- int state = 0;
- /*
- * parse
- *
- * val1, val2, val3, val4
- *
- * into a array (more or less a explode() incl. striping of whitespaces
- */
-
- if (b->used == 0) return 0;
-
- s = b->ptr;
-
- for (i =0; i < b->used - 1; ) {
- char *start = NULL, *end = NULL;
- data_string *ds;
-
- switch (state) {
- case 0: /* ws */
-
- /* skip ws */
- for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
-
-
- state = 1;
- break;
- case 1: /* value */
- start = s;
-
- for (; *s != ',' && i < b->used - 1; i++, s++);
- end = s - 1;
-
- for (; (*end == ' ' || *end == '\t') && end > start; end--);
-
- if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
- ds = data_string_init();
- }
-
- buffer_copy_string_len(ds->value, start, end-start+1);
- array_insert_unique(vals, (data_unset *)ds);
-
- if (*s == ',') {
- state = 0;
- i++;
- s++;
- } else {
- /* end of string */
-
- state = 2;
- }
- break;
- default:
- i++;
- break;
- }
- }
- return 0;
-}
-
-int http_request_parse(server *srv, connection *con, http_req *req) {
- size_t i;
- enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_CLOSE, HTTP_CONNECTION_KEEPALIVE } keep_alive_set = HTTP_CONNECTION_UNSET;
-
- if (req->protocol == HTTP_VERSION_UNSET) {
- con->http_status = 505; /* Version not Supported */
- return 0;
- }
-
- if (req->method == HTTP_METHOD_UNSET) {
- con->http_status = 405; /* Method not allowed */
- return 0;
- }
-
- if (buffer_is_empty(req->uri_raw)) {
- con->http_status = 400;
- return 0;
- }
-
- /* strip absolute URLs
- * */
-
- buffer_copy_string_buffer(con->request.orig_uri, req->uri_raw);
- if (req->uri_raw->ptr[0] == '/') {
- buffer_copy_string_buffer(con->request.uri, req->uri_raw);
- } else if (req->uri_raw->ptr[0] == '*') {
- if (req->method != HTTP_METHOD_OPTIONS) {
- con->http_status = 400;
- return 0;
- }
- buffer_copy_string_buffer(con->request.uri, req->uri_raw);
- } else {
- /* GET http://www.example.org/foobar */
- char *sl;
- int l;
-
- if (0 == strncmp(BUF_STR(req->uri_raw), "https://", 8)) {
- l = 8;
- } else if (0 == strncmp(BUF_STR(req->uri_raw), "http://", 7)) {
- l = 7;
- } else {
- con->http_status = 400;
- return 0;
- }
-
- if (NULL == (sl = strchr(BUF_STR(req->uri_raw) + l, '/'))) {
- con->http_status = 400;
- return 0;
- }
-
- buffer_copy_string(con->request.uri, sl);
- buffer_copy_string_len(con->request.http_host, BUF_STR(req->uri_raw) + l, sl - BUF_STR(req->uri_raw) - l);
-
- if (request_check_hostname(con->request.http_host)) {
- if (srv->srvconf.log_request_header_on_error) {
- TRACE("Host header is invalid (Status: 400), was %s", SAFE_BUF_STR(con->request.http_host));
- }
- con->http_status = 400;
- con->keep_alive = 0;
-
- buffer_reset(con->request.http_host);
-
- return 0;
- }
- }
-
- con->request.http_method = req->method;
- con->request.http_version = req->protocol;
-
- for (i = 0; i < req->headers->used; i++) {
- data_string *ds = (data_string *)req->headers->data[i];
- data_string *hdr;
- int cmp;
-
- /* this list is sorted */
- if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
- array *vals;
- size_t vi;
- /* Connection: Keep-Alive, ... */
-
- vals = srv->split_vals;
-
- array_reset(vals);
- http_request_split_value(vals, ds->value);
-
- for (vi = 0; vi < vals->used; vi++) {
- data_string *dsv = (data_string *)vals->data[vi];
-
- if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
- keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
-
- break;
- } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
- keep_alive_set = HTTP_CONNECTION_CLOSE;
-
- break;
- }
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
- char *err;
- off_t r;
-
- /* ignore the header, if it is a duplicate */
- if (con->request.content_length != -1) continue;
-
- r = str_to_off_t(ds->value->ptr, &err, 10);
-
- if (*err != '\0') {
- TRACE("content-length is not a number: %s (Status: 400)", err);
-
- con->http_status = 400;
-
- return 0;
- }
-
- /**
- * check if we had a over- or underrun in the string conversion
- */
- if (r == STR_OFF_T_MIN ||
- r == STR_OFF_T_MAX) {
- if (errno == ERANGE) {
- con->http_status = 413;
-
- return 0;
- }
- }
-
- /**
- * negative content-length is not supported
- * and is a bad request
- */
- if (r < 0) {
- con->http_status = 400;
-
- return 0;
- }
-
- /* don't handle more the SSIZE_MAX bytes in content-length */
- if (r > SSIZE_MAX) {
- con->http_status = 413;
-
- ERROR("request-size too long: %s (Status: 413)", SAFE_BUF_STR(ds->value));
-
- return 0;
- }
-
- con->request.content_length = r;
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
- /* HTTP 2616 8.2.3
- * Expect: 100-continue
- *
- * -> (10.1.1) 100 (read content, process request, send final status-code)
- * -> (10.4.18) 417 (close)
- *
- *
- */
-
- if (0 != buffer_caseless_compare(CONST_BUF_LEN(ds->value), CONST_STR_LEN("100-continue"))) {
- /* we only support 100-continue */
- con->http_status = 417;
- return 0;
- }
-
- if (con->request.http_version != HTTP_VERSION_1_1) {
- /* only HTTP/1.1 clients can send us this header */
- con->http_status = 417;
- return 0;
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
- if (request_check_hostname(ds->value)) {
- TRACE("Host header is invalid (Status: 400), was %s", SAFE_BUF_STR(ds->value));
- con->http_status = 400;
- con->keep_alive = 0;
-
- return 0;
- }
-
- if (!buffer_is_empty(con->request.http_host) && !buffer_is_equal(con->request.http_host, ds->value)) {
- TRACE("%s", "Host header is duplicate (Status: 400)");
- con->http_status = 400;
-
- return 0;
- }
-
- buffer_copy_string_buffer(con->request.http_host, ds->value);
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
- data_string *old;
-
- if (NULL != (old = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("If-Modified-Since")))) {
- if (0 != buffer_caseless_compare(CONST_BUF_LEN(old->value), CONST_BUF_LEN(ds->value))) {
- /* duplicate header and different timestamps */
- con->http_status = 400;
-
- TRACE("%s", "If-Modified-Since is duplicate (Status: 400)");
-
- return 0;
- }
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
- data_string *old;
- /* if dup, only the first one will survive */
- if (NULL != (old = (data_string *)array_get_element(con->request.headers, CONST_STR_LEN("If-None-Match")))) {
- continue;
- }
- } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
- if (NULL != array_get_element(con->request.headers, CONST_STR_LEN("Range"))) {
- /* duplicate Range header */
-
- TRACE("%s", "Range: header is duplicate (Status: 400)");
-
- con->http_status = 400;
- con->keep_alive = 0;
-
- return 0;
- }
- }
-
- if (NULL == (hdr = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
- hdr = data_string_init();
- }
-
- buffer_copy_string_buffer(hdr->key, ds->key);
- buffer_copy_string_buffer(hdr->value, ds->value);
-
- array_insert_unique(con->request.headers, (data_unset *)hdr);
- }
-
-
- con->header_len = i;
-
- /* do some post-processing */
-
- if (con->request.http_version == HTTP_VERSION_1_1) {
- if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
- /* no Connection-Header sent */
-
- /* HTTP/1.1 -> keep-alive default TRUE */
- con->keep_alive = 1;
- } else {
- con->keep_alive = 0;
- }
-
- /* RFC 2616, 14.23 */
- if (buffer_is_empty(con->request.http_host)) {
- con->http_status = 400;
- con->response.keep_alive = 0;
- con->keep_alive = 0;
-
- if (srv->srvconf.log_request_header_on_error) {
- log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
- log_error_write(srv, __FILE__, __LINE__, "Sb",
- "request-header:\n",
- con->request.request);
- }
- return 0;
- }
- } else {
- if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
- /* no Connection-Header sent */
-
- /* HTTP/1.0 -> keep-alive default FALSE */
- con->keep_alive = 1;
- } else {
- con->keep_alive = 0;
- }
- }
-
- switch(con->request.http_method) {
- case HTTP_METHOD_GET:
- case HTTP_METHOD_HEAD:
- /* content-length is forbidden for those */
- if (con->request.content_length != -1) {
- /* content-length is missing */
- if (srv->srvconf.log_request_header_on_error) {
- ERROR("GET/HEAD with content-length: %d", 400);
- }
-
- con->keep_alive = 0;
- con->http_status = 400;
- return 0;
- }
- break;
- case HTTP_METHOD_POST:
- /* content-length is required for them */
- if (con->request.content_length == -1) {
- /* content-length is missing */
- if (srv->srvconf.log_request_header_on_error) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "POST-request, but content-length missing -> 411");
- }
-
- con->keep_alive = 0;
- con->http_status = 411;
- return 0;
-
- }
- break;
- default:
- /* the may have a content-length */
- break;
- }
-
-
- /* check if we have read post data */
- if (con->request.content_length != -1) {
- /* divide by 1024 as srvconf.max_request_size is in kBytes */
- if (srv->srvconf.max_request_size != 0 &&
- ((size_t)(con->request.content_length >> 10)) > srv->srvconf.max_request_size) {
- /* the request body itself is larger then
- * our our max_request_size
- */
-
- con->http_status = 413;
- con->keep_alive = 0;
-
- log_error_write(srv, __FILE__, __LINE__, "sos",
- "request-size too long:", con->request.content_length, "-> 413");
- return 0;
- }
- }
-
- return 0;
-}
-
-
diff --git a/src/request.h b/src/request.h
deleted file mode 100644
index e5cc87c2..00000000
--- a/src/request.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _REQUEST_H_
-#define _REQUEST_H_
-
-#include "base.h"
-#include "http_req.h"
-
-LI_EXPORT int http_request_parse(server *srv, connection *con, http_req *req);
-
-#endif
diff --git a/src/response.c b/src/response.c
deleted file mode 100644
index 6dfc4e62..00000000
--- a/src/response.c
+++ /dev/null
@@ -1,794 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <limits.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include <stdio.h>
-
-#include "settings.h"
-
-#include "response.h"
-#include "keyvalue.h"
-#include "log.h"
-#include "stat_cache.h"
-#include "chunk.h"
-
-#include "connections.h"
-
-#include "plugin.h"
-
-#include "sys-socket.h"
-#include "sys-files.h"
-#include "sys-strings.h"
-
-int http_response_write_header(server *srv, connection *con, chunkqueue *raw) {
- buffer *b;
- size_t i;
- int have_date = 0;
- int have_server = 0;
- int allow_keep_alive = 0;
-
- b = chunkqueue_get_prepend_buffer(raw);
-
- if (con->request.http_version == HTTP_VERSION_1_1) {
- buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 "));
- } else {
- buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.0 "));
- }
- buffer_append_long(b, con->http_status);
- buffer_append_string_len(b, CONST_STR_LEN(" "));
- buffer_append_string(b, get_http_status_name(con->http_status));
-
- if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
- response_header_overwrite(srv, con, CONST_STR_LEN("Transfer-Encoding"), CONST_STR_LEN("chunked"));
- allow_keep_alive = 1;
- } else if ((con->http_status >= 100 && con->http_status < 200) ||
- con->http_status == 204 ||
- con->http_status == 304) {
- /* 1xx, 204 and 304 never have a content-body ->
- * never have a Content-Length and are always
- * able to do keep-alive
- */
- allow_keep_alive = 1;
- } else if (con->response.content_length >= 0) {
- buffer_copy_off_t(srv->tmp_buf, con->response.content_length);
- response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), srv->tmp_buf->ptr, srv->tmp_buf->used - 1);
-
- allow_keep_alive = 1;
- }
-
- /* keep-alive needs Content-Length or chunked encoding. */
- if (!allow_keep_alive) con->keep_alive = 0;
-
- /* disable keep-alive if requested */
- if (con->request_count > con->conf.max_keep_alive_requests || 0 == con->conf.max_keep_alive_idle) {
- con->keep_alive = 0;
- } else {
- con->keep_alive_idle = con->conf.max_keep_alive_idle;
- }
-
- if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
- if (con->keep_alive) {
- response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
- } else {
- response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
- }
- }
-
-
- /* add all headers */
- for (i = 0; i < con->response.headers->used; i++) {
- data_string *ds;
-
- ds = (data_string *)con->response.headers->data[i];
-
- if (ds->value->used && ds->key->used &&
- 0 != strncasecmp(ds->key->ptr, CONST_STR_LEN("X-LIGHTTPD-")) &&
- 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
- if (0 == strcasecmp(ds->key->ptr, "Date")) have_date = 1;
- if (0 == strcasecmp(ds->key->ptr, "Server")) have_server = 1;
-
- buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
- buffer_append_string_buffer(b, ds->key);
- buffer_append_string_len(b, CONST_STR_LEN(": "));
- buffer_append_string_buffer(b, ds->value);
-#if 0
- log_error_write(srv, __FILE__, __LINE__, "bb",
- ds->key, ds->value);
-#endif
- }
- }
-
- if (!have_date) {
- /* HTTP/1.1 requires a Date: header */
- buffer_append_string_len(b, CONST_STR_LEN("\r\nDate: "));
-
- /* cache the generated timestamp */
- if (srv->cur_ts != srv->last_generated_date_ts) {
- buffer_prepare_copy(srv->ts_date_str, 255);
-
- strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
- "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
-
- srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
-
- srv->last_generated_date_ts = srv->cur_ts;
- }
-
- buffer_append_string_buffer(b, srv->ts_date_str);
- }
-
- if (!have_server) {
- if (buffer_is_empty(con->conf.server_tag)) {
- buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: " PACKAGE_NAME "/" PACKAGE_VERSION));
- } else {
- buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: "));
- buffer_append_string_buffer(b, con->conf.server_tag);
- }
- }
-
- buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
-
-
- con->bytes_header = b->used - 1;
- raw->bytes_in += b->used - 1;
-
- if (con->conf.log_response_header) {
- log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
- }
-
- return 0;
-}
-
-#ifdef USE_OPENSSL
-static void https_add_ssl_entries(connection *con) {
- X509 *xs;
- X509_NAME *xn;
- X509_NAME_ENTRY *xe;
- if (
- SSL_get_verify_result(con->sock->ssl) != X509_V_OK
- || !(xs = SSL_get_peer_certificate(con->sock->ssl))
- ) {
- return;
- }
-
- xn = X509_get_subject_name(xs);
- for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
- int xobjnid;
- const char * xobjsn;
- data_string *envds;
-
- if (!(xe = X509_NAME_get_entry(xn, i))) {
- continue;
- }
- xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe));
- xobjsn = OBJ_nid2sn(xobjnid);
- if (!xobjsn) {
- continue;
- }
-
- if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
- envds = data_string_init();
- }
- buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_"));
- buffer_append_string(envds->key, xobjsn);
- buffer_copy_string_len(
- envds->value,
- (const char *)xe->value->data, xe->value->length
- );
- /* pick one of the exported values as "authed user", for example
- * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" or "SSL_CLIENT_S_DN_emailAddress"
- */
- if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) {
- buffer_copy_string_buffer(con->authed_user, envds->value);
- }
- array_insert_unique(con->environment, (data_unset *)envds);
- }
- if (con->conf.ssl_verifyclient_export_cert) {
- BIO *bio;
- if (NULL != (bio = BIO_new(BIO_s_mem()))) {
- data_string *envds;
- int n;
-
- PEM_write_bio_X509(bio, xs);
- n = BIO_pending(bio);
-
- if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
- envds = data_string_init();
- }
-
- buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT"));
- buffer_prepare_copy(envds->value, n+1);
- BIO_read(bio, envds->value->ptr, n);
- BIO_free(bio);
- envds->value->ptr[n] = '\0';
- envds->value->used = n+1;
- array_insert_unique(con->environment, (data_unset *)envds);
- }
- }
- X509_free(xs);
-}
-#endif
-
-
-handler_t handle_get_backend(server *srv, connection *con) {
- handler_t r;
-
- /* looks like someone has already made a decision */
- if (con->mode == DIRECT &&
- (con->http_status != 0 && con->http_status != 200)) {
- /* remove a packets in the queue */
-
- return HANDLER_FINISHED;
- }
-
- /* no decision yet, build conf->filename */
- if (con->mode == DIRECT && con->physical.path->used == 0) {
- char *qstr;
-
- /* we only come here when we have to parse the full request again
- *
- * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
- * problem here as mod_setenv might get called multiple times
- *
- * fastcgi-auth might lead to a COMEBACK too
- * fastcgi again dead server too
- *
- * mod_compress might add headers twice too
- *
- * */
-
- if (con->conf.log_condition_handling) {
- TRACE("run condition: %s", "");
- }
- config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
-
- /**
- * prepare strings
- *
- * - uri.path_raw
- * - uri.path (secure)
- * - uri.query
- *
- */
-
- /**
- * Name according to RFC 2396
- *
- * - scheme
- * - authority
- * - path
- * - query
- *
- * (scheme)://(authority)(path)?(query)#fragment
- *
- *
- */
-
- if (con->conf.is_ssl) {
- buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("https"));
- } else {
- buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("http"));
- }
- 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_REMOTE_IP); /* Client-IP */
- config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
- 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, '#'))) {
- con->request.uri->used = qstr - con->request.uri->ptr;
- con->request.uri->ptr[con->request.uri->used++] = '\0';
- }
-
- /** extract query string from request.uri */
- if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
- buffer_copy_string (con->uri.query, qstr + 1);
- buffer_copy_string_len(con->uri.path_raw, con->request.uri->ptr, qstr - con->request.uri->ptr);
- } else {
- buffer_reset (con->uri.query);
- buffer_copy_string_buffer(con->uri.path_raw, con->request.uri);
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "splitting Request-URI");
- TRACE("Request-URI : %s", SAFE_BUF_STR(con->request.uri));
- TRACE("URI-scheme : %s", SAFE_BUF_STR(con->uri.scheme));
- TRACE("URI-authority: %s", SAFE_BUF_STR(con->uri.authority));
- TRACE("URI-path : %s", SAFE_BUF_STR(con->uri.path_raw));
- TRACE("URI-query : %s", SAFE_BUF_STR(con->uri.query));
- }
-
- if (srv->sockets_disabled) {
- con->keep_alive = 0;
- }
-
-
- /**
- *
- * call plugins
- *
- * - based on the raw URL
- *
- */
-
- switch(r = plugins_call_handle_uri_raw(srv, con)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_FINISHED:
- case HANDLER_COMEBACK:
- case HANDLER_WAIT_FOR_EVENT:
- case HANDLER_ERROR:
- return r;
- default:
- ERROR("plugins_call_handle_uri_raw() returned unexpected: %d", r);
- break;
- }
-
- /* build filename
- *
- * - decode url-encodings (e.g. %20 -> ' ')
- * - remove path-modifiers (e.g. /../)
- */
-
-
-
- if (con->request.http_method == HTTP_METHOD_OPTIONS &&
- con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
- /* OPTIONS * ... */
- buffer_copy_string_buffer(con->uri.path, con->uri.path_raw);
- } else {
- buffer_copy_string_buffer(srv->tmp_buf, con->uri.path_raw);
- buffer_urldecode_path(srv->tmp_buf);
- buffer_path_simplify(con->uri.path, srv->tmp_buf);
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "sanitizing URI");
- TRACE("URI-path : %s", SAFE_BUF_STR(con->uri.path));
- }
-
-#ifdef USE_OPENSSL
- if (con->conf.is_ssl && con->conf.ssl_verifyclient) {
- https_add_ssl_entries(con);
- }
-#endif
-
- /**
- *
- * call plugins
- *
- * - based on the clean URL
- *
- */
-
- config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
- config_patch_connection(srv, con, COMP_HTTP_QUERY_STRING); /* HTTPqs */
-
- /* do we have to downgrade to 1.0 ? */
- if (!con->conf.allow_http11) {
- con->request.http_version = HTTP_VERSION_1_0;
- }
-
- switch(r = plugins_call_handle_uri_clean(srv, con)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_FINISHED:
- case HANDLER_COMEBACK:
- case HANDLER_WAIT_FOR_EVENT:
- case HANDLER_ERROR:
- return r;
- default:
- ERROR("plugins_call_handle_uri_clean() returned unexpected: %d", r);
- break;
- }
-
- if (con->request.http_method == HTTP_METHOD_OPTIONS &&
- con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
- /* option requests are handled directly without checking the path */
-
- response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
-
- con->http_status = 200;
- /* no more content to send */
- con->send->is_closed = 1;
-
- return HANDLER_FINISHED;
- }
-
- /***
- *
- * border
- *
- * logical filename (URI) becomes a physical filename here
- *
- *
- *
- */
-
-
-
-
- /* 1. stat()
- * ... ISREG() -> ok, go on
- * ... ISDIR() -> index-file -> redirect
- *
- * 2. pathinfo()
- * ... ISREG()
- *
- * 3. -> 404
- *
- */
-
- /*
- * SEARCH DOCUMENT ROOT
- */
-
- /* set a default */
-
- buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
- buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
-
- filename_unix2local(con->physical.rel_path);
-#if defined(_WIN32) || defined(__CYGWIN__)
- /* strip dots and spaces from the end
- *
- * windows/dos handle those filenames as the same file
- *
- * foo == foo. == foo..... == "foo... " == "foo.. ./"
- *
- * This will affect PATHINFO in some cases
- *
- * on native windows we could prepend the filename with \\?\ to circumvent
- * this behaviour. I have no idea how to push this through cygwin
- *
- * */
-
- if (con->physical.rel_path->used > 1) {
- buffer *b = con->physical.rel_path;
- size_t i;
-
- if (b->used > 2 &&
- b->ptr[b->used-2] == '/' &&
- (b->ptr[b->used-3] == ' ' ||
- b->ptr[b->used-3] == '.')) {
- b->ptr[b->used--] = '\0';
- }
-
- for (i = b->used - 2; b->used > 1; i--) {
- if (b->ptr[i] == ' ' ||
- b->ptr[i] == '.') {
- b->ptr[b->used--] = '\0';
- } else {
- break;
- }
- }
- }
-#endif
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "before doc_root");
- TRACE("Doc-Root : %s", SAFE_BUF_STR(con->physical.doc_root));
- TRACE("Rel-Path : %s", SAFE_BUF_STR(con->physical.rel_path));
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
- /* the docroot plugin should set the doc_root and might also set the physical.path
- * for us (all vhost-plugins are supposed to set the doc_root)
- * */
- switch(r = plugins_call_handle_docroot(srv, con)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_FINISHED:
- case HANDLER_COMEBACK:
- case HANDLER_WAIT_FOR_EVENT:
- case HANDLER_ERROR:
- return r;
- default:
- ERROR("plugins_call_handle_docroot() returned unexpected: %d", r);
- break;
- }
-
- /* The default Mac OS X and Windows filesystems can't distiguish between
- * upper- and lowercase, so convert to lowercase
- */
- if (con->conf.force_lowercase_filenames) {
- buffer_to_lower(con->physical.rel_path);
- }
-
- /* the docroot plugins might set the servername; if they don't we take http-host */
- if (buffer_is_empty(con->server_name)) {
- buffer_copy_string_buffer(con->server_name, con->uri.authority);
- }
-
- /**
- * create physical filename
- * -> physical.path = docroot + rel_path
- *
- */
-
- buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
- PATHNAME_APPEND_SLASH(con->physical.path);
- buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
- if (con->physical.rel_path->used &&
- con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
- buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
- } else {
- buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
- }
-
- /* win32: directories can't have a trailing slash */
- if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
- con->physical.path->ptr[con->physical.path->used - 2] = '\0';
- con->physical.path->used--;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "after doc_root");
- TRACE("Doc-Root : %s", SAFE_BUF_STR(con->physical.doc_root));
- TRACE("Rel-Path : %s", SAFE_BUF_STR(con->physical.rel_path));
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
- switch(r = plugins_call_handle_physical(srv, con)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_FINISHED:
- case HANDLER_COMEBACK:
- case HANDLER_WAIT_FOR_EVENT:
- case HANDLER_ERROR:
- return r;
- default:
- ERROR("plugins_call_handle_physical() returned unexpected: %d", r);
- break;
- }
-
- config_patch_connection(srv, con, COMP_PHYSICAL_PATH); /* physical-path */
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "logical -> physical");
- TRACE("Doc-Root : %s", SAFE_BUF_STR(con->physical.doc_root));
- TRACE("Rel-Path : %s", SAFE_BUF_STR(con->physical.rel_path));
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
- }
-
- /*
- * No one took the file away from the normal path of execution yet (like mod_access)
- *
- * we don't have a backend yet, try to resolve the physical path and go on
- *
- */
-
- if (con->mode == DIRECT) {
- char *slash = NULL;
- char *pathinfo = NULL;
- int found = 0;
- stat_cache_entry *sce = NULL;
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "handling physical path");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
- switch ((r = stat_cache_get_entry_async(srv, con, con->physical.path, &sce))) {
- case HANDLER_GO_ON:
- /* file exists */
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "file found");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
-#ifdef HAVE_LSTAT
- if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "access denied due symlink restriction");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
- buffer_reset(con->physical.path);
- return HANDLER_FINISHED;
- };
-#endif
-
- if (S_ISDIR(sce->st.st_mode)) {
- if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
- /* redirect to .../ */
-
- http_response_redirect_to_directory(srv, con);
-
- return HANDLER_FINISHED;
- }
-#ifdef HAVE_LSTAT
- } else if (!S_ISREG(sce->st.st_mode) && !sce->is_symlink) {
-#else
- } else if (!S_ISREG(sce->st.st_mode)) {
-#endif
- /* any special handling of non-reg files ?*/
-
-
- }
- break;
- case HANDLER_WAIT_FOR_EVENT:
- return HANDLER_WAIT_FOR_EVENT;
- case HANDLER_ERROR:
- switch (errno) {
- case EACCES:
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "access denied");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
- buffer_reset(con->physical.path);
- return HANDLER_FINISHED;
- case ENOENT:
- con->http_status = 404;
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "file not found");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
- buffer_reset(con->physical.path);
- return HANDLER_FINISHED;
- case ENOTDIR:
- /* PATH_INFO ! :) */
- break;
- case EMFILE:
- return HANDLER_WAIT_FOR_FD;
- default:
- /* we have no idea what happened, so tell the user. */
- con->http_status = 500;
-
- ERROR("checking file '%s' (%s) failed: %d (%s) -> sending status 500",
- SAFE_BUF_STR(con->uri.path),
- SAFE_BUF_STR(con->physical.path),
- errno, strerror(errno));
-
- buffer_reset(con->physical.path);
-
- return HANDLER_FINISHED;
- }
-
- /* not found, perhaps PATHINFO */
-
- buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
-
- do {
- 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 (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
- found = S_ISREG(sce->st.st_mode);
- break;
- }
-
- if (pathinfo != NULL) {
- *pathinfo = '\0';
- }
- slash = strrchr(srv->tmp_buf->ptr, '/');
-
- if (pathinfo != NULL) {
- /* restore '/' */
- *pathinfo = '/';
- }
-
- if (slash) pathinfo = slash;
- } while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > (con->physical.basedir->used - 2)));
-
- if (found == 0) {
- /* no, it really doesn't exists */
- con->http_status = 404;
-
- if (con->conf.log_file_not_found) {
- TRACE("file not found: %s -> %s",
- SAFE_BUF_STR(con->uri.path),
- SAFE_BUF_STR(con->physical.path));
- }
-
- buffer_reset(con->physical.path);
-
- 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);
-
- /*
- * shorten uri.path
- */
-
- con->uri.path->used -= strlen(pathinfo);
- con->uri.path->ptr[con->uri.path->used - 1] = '\0';
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "after pathinfo check");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- TRACE("URI : %s", SAFE_BUF_STR(con->uri.path));
- TRACE("Pathinfo : %s", SAFE_BUF_STR(con->request.pathinfo));
- }
- break;
- default:
- ERROR("stat_cache_get_entry_async() returned unexpected: %d", r);
- break;
- }
-
- config_patch_connection(srv, con, COMP_PHYSICAL_PATH_EXISTS); /* physical-path */
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "handling subrequest");
- TRACE("Path : %s", SAFE_BUF_STR(con->physical.path));
- }
-
- /* call the handlers */
- switch(r = plugins_call_handle_start_backend(srv, con)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_FINISHED:
- case HANDLER_COMEBACK:
- case HANDLER_WAIT_FOR_EVENT:
- case HANDLER_ERROR:
- return r;
-
- default:
- ERROR("plugins_call_handle_start_backend() returned unexpected: %d", r);
- return r;
- }
-
- if (con->conf.log_request_handling) {
- TRACE("-- %s", "subrequest finished");
- }
- }
-
- if (con->mode == DIRECT) {
- /* if we are still here, no one wanted the file; status 403 is ok I think */
- con->http_status = 403;
-
- if (con->conf.log_request_handling) {
- TRACE("%s", "aaaaaaah, sending 403");
- }
-
- return HANDLER_FINISHED;
- } else {
- return HANDLER_GO_ON;
- }
-}
-
-
-
diff --git a/src/response.h b/src/response.h
deleted file mode 100644
index 0a35debc..00000000
--- a/src/response.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _RESPONSE_H_
-#define _RESPONSE_H_
-
-#include <time.h>
-
-#include "settings.h"
-
-#include "server.h"
-
-LI_API int http_response_parse(server *srv, connection *con);
-LI_API int http_response_write_header(server *srv, connection *con, chunkqueue *cq);
-
-LI_API int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen);
-LI_API int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen);
-LI_API int response_header_append(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen);
-
-LI_API handler_t handle_get_backend(server *srv, connection *con);
-LI_API int http_response_redirect_to_directory(server *srv, connection *con);
-LI_API int http_response_handle_cachable(server *srv, connection *con, buffer * mtime);
-
-LI_API buffer * strftime_cache_get(server *srv, time_t last_mod);
-#endif
diff --git a/src/server.c b/src/server.c
deleted file mode 100644
index be0accc3..00000000
--- a/src/server.c
+++ /dev/null
@@ -1,1792 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#endif
-
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <time.h>
-#include <signal.h>
-#include <assert.h>
-#include <locale.h>
-
-#include <stdio.h>
-
-#include "settings.h"
-#include "server.h"
-#include "buffer.h"
-#include "network.h"
-#include "network_backends.h"
-#include "log.h"
-#include "keyvalue.h"
-#include "response.h"
-#include "request.h"
-#include "chunk.h"
-#include "fdevent.h"
-#include "connections.h"
-#include "stat_cache.h"
-#include "plugin.h"
-#include "joblist.h"
-#include "status_counter.h"
-
-/**
- * stack-size of the aio-threads
- *
- * the default is 8Mbyte which is a bit to much. Reducing it to 64k seems to be fine
- * If you experience random segfaults, increase it.
- */
-
-#define LI_THREAD_STACK_SIZE (64 * 1024)
-
-
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#else
-#ifdef _WIN32
-#include "xgetopt.h"
-#endif
-#endif
-
-#include "valgrind/valgrind.h"
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef HAVE_PWD_H
-#include <grp.h>
-#include <pwd.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
-
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
-#ifdef USE_OPENSSL
-#include <openssl/err.h>
-#endif
-
-#ifndef __sgi
-/* IRIX doesn't like the alarm based time() optimization */
-/* #define USE_ALARM */
-#endif
-
-#ifdef _WIN32
-#undef HAVE_SIGNAL
-#endif
-
-#include "sys-files.h"
-#include "sys-process.h"
-#include "sys-socket.h"
-
-#ifdef HAVE_GETUID
-# ifndef HAVE_ISSETUGID
-
-static int l_issetugid() {
- return (geteuid() != getuid() || getegid() != getgid());
-}
-
-# define issetugid l_issetugid
-# endif
-#endif
-
-static volatile sig_atomic_t srv_shutdown = 0;
-static volatile sig_atomic_t graceful_shutdown = 0;
-static volatile sig_atomic_t graceful_restart = 0;
-static volatile sig_atomic_t handle_sig_alarm = 1;
-static volatile sig_atomic_t handle_sig_hup = 0;
-static volatile siginfo_t last_sigterm_info;
-static volatile siginfo_t last_sighup_info;
-
-#if defined(HAVE_SIGACTION) && defined(SA_SIGINFO)
-static void sigaction_handler(int sig, siginfo_t *si, void *context) {
- static siginfo_t empty_siginfo;
- UNUSED(context);
-
- if (!si) si = &empty_siginfo;
-
- switch (sig) {
- case SIGTERM:
- srv_shutdown = 1;
- memcpy((siginfo_t*) &last_sigterm_info, si, sizeof(*si));
- break;
- case SIGINT:
- if (graceful_shutdown) {
- srv_shutdown = 1;
- } else {
- graceful_shutdown = 1;
- }
-
- memcpy((siginfo_t*) &last_sigterm_info, si, sizeof(*si));
-
- break;
- case SIGALRM:
- handle_sig_alarm = 1;
- break;
- case SIGHUP:
- handle_sig_hup = 1;
- memcpy((siginfo_t*) &last_sighup_info, si, sizeof(*si));
- break;
- case SIGCHLD:
- break;
- }
-}
-#elif defined(HAVE_SIGNAL) || defined(HAVE_SIGACTION)
-static void signal_handler(int sig) {
- switch (sig) {
- case SIGTERM: srv_shutdown = 1; break;
- case SIGINT:
- if (graceful_shutdown) srv_shutdown = 1;
- else graceful_shutdown = 1;
-
- break;
- case SIGALRM: handle_sig_alarm = 1; break;
- case SIGHUP: handle_sig_hup = 1; break;
- case SIGCHLD: break;
- }
-}
-#endif
-
-#ifdef HAVE_FORK
-static void daemonize(void) {
-#ifdef SIGTTOU
- signal(SIGTTOU, SIG_IGN);
-#endif
-#ifdef SIGTTIN
- signal(SIGTTIN, SIG_IGN);
-#endif
-#ifdef SIGTSTP
- signal(SIGTSTP, SIG_IGN);
-#endif
- if (0 != fork()) exit(0);
-
- if (-1 == setsid()) exit(0);
-
- signal(SIGHUP, SIG_IGN);
-
- if (0 != fork()) exit(0);
-
- if (0 != chdir("/")) exit(0);
-}
-#endif
-
-static server *server_init(void) {
- int i;
- FILE *frandom = NULL;
-
- server *srv = calloc(1, sizeof(*srv));
- assert(srv);
-
- srv->max_fds = 1024;
-#define CLEAN(x) \
- srv->x = buffer_init();
-
- CLEAN(response_header);
- CLEAN(parse_full_path);
- CLEAN(ts_debug_str);
- CLEAN(ts_date_str);
- CLEAN(response_range);
- CLEAN(tmp_buf);
- srv->empty_string = buffer_init_string("");
- CLEAN(cond_check_buf);
-
- CLEAN(srvconf.errorlog_file);
- CLEAN(srvconf.breakagelog_file);
- CLEAN(srvconf.groupname);
- CLEAN(srvconf.username);
- CLEAN(srvconf.changeroot);
- CLEAN(srvconf.bindhost);
- CLEAN(srvconf.event_handler);
- CLEAN(srvconf.pid_file);
-
- CLEAN(tmp_chunk_len);
-#undef CLEAN
-
-#define CLEAN(x) \
- srv->x = array_init();
-
- CLEAN(config_context);
- CLEAN(config_touched);
-#undef CLEAN
-
- for (i = 0; i < FILE_CACHE_MAX; i++) {
- srv->mtime_cache[i].mtime = (time_t)-1;
- srv->mtime_cache[i].str = buffer_init();
- }
-
- if ((NULL != (frandom = fopen("/dev/urandom", "rb")) || NULL != (frandom = fopen("/dev/random", "rb")))
- && 1 == fread(srv->entropy, sizeof(srv->entropy), 1, frandom)) {
- srand(*(unsigned int*)srv->entropy);
- srv->is_real_entropy = 1;
- } else {
- unsigned int j;
- srand(time(NULL) ^ getpid());
- srv->is_real_entropy = 0;
- for (j = 0; j < sizeof(srv->entropy); j++)
- srv->entropy[j] = rand();
- }
- if (frandom) fclose(frandom);
-
- srv->cur_ts = time(NULL);
- srv->startup_ts = srv->cur_ts;
-
- srv->conns = calloc(1, sizeof(*srv->conns));
- assert(srv->conns);
-
- srv->joblist = calloc(1, sizeof(*srv->joblist));
- assert(srv->joblist);
-
- srv->joblist_prev = calloc(1, sizeof(*srv->joblist));
- assert(srv->joblist_prev);
-
- srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
- assert(srv->fdwaitqueue);
-
- srv->srvconf.modules = array_init();
- srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
- srv->srvconf.network_backend = buffer_init();
- srv->srvconf.upload_tempdirs = array_init();
-
- srv->split_vals = array_init();
-
-#ifdef USE_LINUX_AIO_SENDFILE
- srv->linux_io_ctx = NULL;
- /**
- * we can't call io_setup before the fork() in daemonize()
- */
-#endif
-
- return srv;
-}
-
-static void server_free(server *srv) {
- size_t i;
-
- for (i = 0; i < FILE_CACHE_MAX; i++) {
- buffer_free(srv->mtime_cache[i].str);
- }
-
-
-#ifdef USE_LINUX_AIO_SENDFILE
- if (srv->linux_io_ctx) {
- io_destroy(srv->linux_io_ctx);
- }
-#endif
-
-#define CLEAN(x) \
- buffer_free(srv->x);
-
- CLEAN(response_header);
- CLEAN(parse_full_path);
- CLEAN(ts_debug_str);
- CLEAN(ts_date_str);
- CLEAN(response_range);
- CLEAN(tmp_buf);
- CLEAN(empty_string);
- CLEAN(cond_check_buf);
-
- CLEAN(srvconf.errorlog_file);
- CLEAN(srvconf.breakagelog_file);
- CLEAN(srvconf.groupname);
- CLEAN(srvconf.username);
- CLEAN(srvconf.changeroot);
- CLEAN(srvconf.bindhost);
- CLEAN(srvconf.event_handler);
- CLEAN(srvconf.pid_file);
- CLEAN(srvconf.modules_dir);
- CLEAN(srvconf.network_backend);
-
- CLEAN(tmp_chunk_len);
-#undef CLEAN
-
-#ifdef USE_GTHREAD
- fdevent_unregister(srv->ev, srv->wakeup_iosocket);
- iosocket_free(srv->wakeup_iosocket);
-#endif
-
-#if 0
- fdevent_unregister(srv->ev, srv->fd);
-#endif
- fdevent_free(srv->ev);
-
- free(srv->conns);
-
- if (srv->config_storage) {
- for (i = 0; i < srv->config_context->used; i++) {
- specific_config *s = srv->config_storage[i];
-
- if (!s) continue;
-
- buffer_free(s->document_root);
- buffer_free(s->server_name);
- buffer_free(s->server_tag);
- buffer_free(s->ssl_pemfile);
- buffer_free(s->ssl_ca_file);
- buffer_free(s->error_handler);
- buffer_free(s->errorfile_prefix);
- array_free(s->mimetypes);
- buffer_free(s->ssl_cipher_list);
- buffer_free(s->ssl_verifyclient_username);
-#ifdef USE_OPENSSL
- SSL_CTX_free(s->ssl_ctx);
-#endif
-
- free(s);
- }
- free(srv->config_storage);
- srv->config_storage = NULL;
- }
-
-#define CLEAN(x) \
- array_free(srv->x);
-
- CLEAN(config_context);
- CLEAN(config_touched);
- CLEAN(srvconf.upload_tempdirs);
-#undef CLEAN
-
- joblist_free(srv, srv->joblist);
- joblist_free(srv, srv->joblist_prev);
- fdwaitqueue_free(srv, srv->fdwaitqueue);
-
- if (srv->stat_cache) {
- stat_cache_free(srv->stat_cache);
- }
-
- array_free(srv->srvconf.modules);
- array_free(srv->split_vals);
-#ifdef USE_OPENSSL
- if (srv->ssl_is_init) {
- CRYPTO_cleanup_all_ex_data();
- ERR_free_strings();
- ERR_remove_state(0);
- EVP_cleanup();
- }
-#endif
- free(srv);
-}
-
-static void show_version (void) {
-#ifdef USE_OPENSSL
-# define TEXT_SSL " (ssl)"
-#else
-# define TEXT_SSL
-#endif
- char *b = PACKAGE_NAME "-" PACKAGE_VERSION TEXT_SSL \
-" - a light and fast webserver\n" \
-"Build-Date: " __DATE__ " " __TIME__ "\n";
-;
-#undef TEXT_SSL
- if (-1 == write(STDOUT_FILENO, b, strlen(b))) {
- /* what to do if this happens ? */
-
- exit(-1);
- }
-}
-
-static void show_features (void) {
- const fdevent_handler_info_t *handler;
- const network_backend_info_t *backend;
-
- const char *features =
-#ifdef HAVE_IPV6
- "\t+ IPv6 support\n"
-#else
- "\t- IPv6 support\n"
-#endif
-#if defined HAVE_ZLIB_H && defined HAVE_LIBZ
- "\t+ zlib support\n"
-#else
- "\t- zlib support\n"
-#endif
-#if defined HAVE_BZLIB_H && defined HAVE_LIBBZ2
- "\t+ bzip2 support\n"
-#else
- "\t- bzip2 support\n"
-#endif
-#ifdef HAVE_LIBCRYPT
- "\t+ crypt support\n"
-#else
- "\t- crypt support\n"
-#endif
-#ifdef USE_OPENSSL
- "\t+ SSL Support\n"
-#else
- "\t- SSL Support\n"
-#endif
-#ifdef HAVE_LIBPCRE
- "\t+ PCRE support\n"
-#else
- "\t- PCRE support\n"
-#endif
-#ifdef HAVE_MYSQL
- "\t+ MySQL support\n"
-#else
- "\t- MySQL support\n"
-#endif
-#if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
- "\t+ LDAP support\n"
-#else
- "\t- LDAP support\n"
-#endif
-#ifdef HAVE_MEMCACHE_H
- "\t+ memcached support\n"
-#else
- "\t- memcached support\n"
-#endif
-#ifdef HAVE_FAM_H
- "\t+ FAM support\n"
-#else
- "\t- FAM support\n"
-#endif
-#ifdef HAVE_LUA_H
- "\t+ LUA support\n"
-#else
- "\t- LUA support\n"
-#endif
-#ifdef HAVE_LIBXML_H
- "\t+ xml support\n"
-#else
- "\t- xml support\n"
-#endif
-#ifdef HAVE_SQLITE3_H
- "\t+ SQLite support\n"
-#else
- "\t- SQLite support\n"
-#endif
-#ifdef HAVE_GDBM_H
- "\t+ GDBM support\n"
-#else
- "\t- GDBM support\n"
-#endif
- ;
-
- show_version();
-
- printf("\nEvent Handlers:\n\n");
- for (handler = fdevent_get_handlers(); handler->name; handler++) {
- printf("\t%c %s", handler->init ? '+' : '-', handler->name);
- if (handler->description) {
- printf(": %s\n", handler->description);
- }
- else {
- printf("\n");
- }
- }
-
- printf("\nNetwork Backends:\n\n");
- for (backend = network_get_backends(); backend->name; backend++) {
- printf("\t%c %s", backend->write_handler ? '+' : '-', backend->name);
- if (backend->description) {
- printf(": %s\n", backend->description);
- }
- else {
- printf("\n");
- }
- }
-
-#ifdef USE_MMAP
- printf("\t+ (mmap) support\n");
-#else
- printf("\t- (mmap) support\n");
-#endif
- printf("\nFeatures:\n\n%s", features);
-}
-
-static void show_help (void) {
-#ifdef USE_OPENSSL
-# define TEXT_SSL " (ssl)"
-#else
-# define TEXT_SSL
-#endif
- char *b = PACKAGE_NAME "-" PACKAGE_VERSION TEXT_SSL " ("__DATE__ " " __TIME__ ")" \
-" - a light and fast webserver\n" \
-"usage:\n" \
-" -f <name> filename of the config-file\n" \
-" -m <name> module directory (default: "LIBRARY_DIR")\n" \
-" -p print the parsed config-file in internal form, and exit\n" \
-" -t test the config-file, and exit\n" \
-" -D don't go to background (default: go to background)\n" \
-" -I go to background on SIGINT (useful with -D)\n" \
-" has no effect when using kqueue or /dev/poll\n" \
-" -v show version\n" \
-" -V show compile-time features\n" \
-" -h show this help\n" \
-"\n"
-;
-#undef TEXT_SSL
-#undef TEXT_IPV6
- if (-1 == write(STDOUT_FILENO, b, strlen(b))) {
- exit(-1);
- }
-}
-
-/**
- * call this function whenever you get a EMFILE or ENFILE as return-value
- *
- * after each socket(), accept(), connect() or open() call
- *
- */
-int server_out_of_fds(server *srv, connection *con) {
- /* we get NULL of accept() ran out of FDs */
-
- if (con) {
- fdwaitqueue_append(srv, con);
- }
-
- return 0;
-}
-
-static int lighty_mainloop(server *srv) {
- fdevent_revents *revents = fdevent_revents_init();
- int poll_errno;
- size_t conns_user_at_sockets_disabled = 0;
-
- /* the getevents and the poll() have to run in parallel
- * as soon as one has data, it has to interrupt the otherone */
-
- /* main-loop */
- while (!srv_shutdown) {
- int n;
- size_t ndx;
- time_t min_ts;
-
- if (handle_sig_hup) {
- handler_t r;
-
- /* reset notification */
- handle_sig_hup = 0;
-
-#if 0
- pid_t pid;
-
- /* send the old process into a graceful-shutdown and start a
- * new process right away
- *
- * BUGS:
- * - if webserver is running on port < 1024 (e.g. 80, 433)
- * we don't have the permissions to bind to that port anymore
- *
- *
- * */
- if (0 == (pid = fork())) {
- execve(argv[0], argv, envp);
-
- exit(-1);
- } else if (pid == -1) {
-
- } else {
- /* parent */
-
- graceful_shutdown = 1; /* shutdown without killing running connections */
- graceful_restart = 1; /* don't delete pid file */
- }
-#else
- /* cycle logfiles */
-
- switch(r = plugins_call_handle_sighup(srv)) {
- case HANDLER_GO_ON:
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
- break;
- }
-
- if (-1 == log_error_cycle()) {
- log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
-
- return -1;
- } else {
- TRACE("logfiles cycled by UID=%d, PID=%d",
- last_sighup_info.si_uid,
- last_sighup_info.si_pid);
- }
-#endif
- }
-
- if (handle_sig_alarm) {
- /* a new second */
-
-#ifdef USE_ALARM
- /* reset notification */
- handle_sig_alarm = 0;
-#endif
-
- /* get current time */
- min_ts = time(NULL);
-
- if (min_ts != srv->cur_ts) {
- int cs = 0;
- connections *conns = srv->conns;
- handler_t r;
-
- switch(r = plugins_call_handle_trigger(srv)) {
- case HANDLER_GO_ON:
- break;
- case HANDLER_ERROR:
- log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "d", r);
- break;
- }
-
- /* trigger waitpid */
- srv->cur_ts = min_ts;
-
- /* cleanup stat-cache */
- stat_cache_trigger_cleanup(srv);
- /**
- * check all connections for timeouts
- *
- */
- for (ndx = 0; ndx < conns->used; ndx++) {
- int changed = 0;
- connection *con;
- int t_diff;
-
- con = conns->ptr[ndx];
-
- switch (con->state) {
- case CON_STATE_READ_REQUEST_HEADER:
- case CON_STATE_READ_REQUEST_CONTENT:
- if (con->recv->is_closed) {
- if (srv->cur_ts - con->read_idle_ts > con->conf.max_connection_idle) {
- /* time - out */
-#if 0
- TRACE("(connection process timeout) [%s]", SAFE_BUF_STR(con->dst_addr_buf));
-#endif
- connection_set_state(srv, con, CON_STATE_ERROR);
- changed = 1;
- }
- }
-
- if (con->request_count == 1) {
- if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
- /* time - out */
-#if 0
- TRACE("(initial read timeout) [%s]", SAFE_BUF_STR(con->dst_addr_buf));
-#endif
- connection_set_state(srv, con, CON_STATE_ERROR);
- changed = 1;
- }
- } else {
- if (srv->cur_ts - con->read_idle_ts > con->keep_alive_idle) {
- /* time - out */
-#if 0
- TRACE("(keep-alive read timeout) [%s]", SAFE_BUF_STR(con->dst_addr_buf));
-#endif
- connection_set_state(srv, con, CON_STATE_ERROR);
- changed = 1;
- }
- }
- break;
- case CON_STATE_WRITE_RESPONSE_HEADER:
- case CON_STATE_WRITE_RESPONSE_CONTENT:
-
-
- if (con->write_request_ts != 0 &&
- srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
- /* time - out */
- if (con->conf.log_timeouts) {
- log_error_write(srv, __FILE__, __LINE__, "sbsosds",
- "NOTE: a request for",
- con->request.uri,
- "timed out after writing",
- con->bytes_written,
- "bytes. We waited",
- (int)con->conf.max_write_idle,
- "seconds. If this a problem increase server.max-write-idle");
- }
- connection_set_state(srv, con, CON_STATE_ERROR);
- changed = 1;
- }
- break;
- default:
- /* the other ones are uninteresting */
- break;
- }
- /* we don't like div by zero */
- if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
-
- if (con->traffic_limit_reached &&
- (con->conf.kbytes_per_second == 0 ||
- ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
- /* enable connection again */
- con->traffic_limit_reached = 0;
-
- changed = 1;
- }
-
- if (changed) {
- connection_state_machine(srv, con);
- }
- con->bytes_written_cur_second = 0;
- *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
-
-#if 0
- if (cs == 0) {
- fprintf(stderr, "connection-state: ");
- cs = 1;
- }
-
- fprintf(stderr, "c[%d,%d]: %s ",
- con->fd,
- con->fcgi.fd,
- connection_get_state(con->state));
-#endif
- }
-
- if (cs == 1) fprintf(stderr, "\n");
- }
- }
-
- if (srv->sockets_disabled) {
- /* our server sockets are disabled, why ? */
-
- if ((srv->fdwaitqueue->used == 0) &&
- (srv->conns->used <= srv->max_conns * 9 / 10) &&
- (0 == graceful_shutdown)) {
- size_t i;
-
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
- fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN);
- }
-
- TRACE("[note] sockets enabled again%s", "");
-
- srv->sockets_disabled = 0;
- }
- } else {
- if ((srv->fdwaitqueue->used) || /* looks like some cons are waiting for FDs*/
- (srv->conns->used >= srv->max_conns) || /* out of connections */
- (graceful_shutdown)) { /* graceful_shutdown */
- size_t i;
-
- /* disable server-fds */
-
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
-
- fdevent_event_del(srv->ev, srv_socket->sock);
-
- if (graceful_shutdown) {
- /* we don't want this socket anymore,
- *
- * closing it right away will make it possible for
- * the next lighttpd to take over (graceful restart)
- * */
-
- fdevent_unregister(srv->ev, srv_socket->sock);
- closesocket(srv_socket->sock->fd);
- srv_socket->sock->fd = -1;
-
-#ifdef HAVE_FORK
- /* FreeBSD kqueue could possibly work with rfork(RFFDG)
- * while Solaris /dev/poll would require re-registering
- * all fd */
- if (srv->srvconf.daemonize_on_shutdown &&
- srv->event_handler != FDEVENT_HANDLER_FREEBSD_KQUEUE &&
- srv->event_handler != FDEVENT_HANDLER_SOLARIS_DEVPOLL) {
- daemonize();
- }
-#endif
-
- /* network_close() will cleanup after us */
- }
- }
-
- if (graceful_shutdown) {
- TRACE("[note] graceful shutdown started by UID=%d, PID=%d", last_sigterm_info.si_uid, last_sigterm_info.si_pid);
- } else if (srv->fdwaitqueue->used) {
- TRACE("[note] out of FDs, server-socket get disabled for a while, we have %zu connections open and they are waiting for %zu FDs",
- srv->conns->used, srv->fdwaitqueue->used);
- } else if (srv->conns->used >= srv->max_conns) {
- TRACE("[note] we reached our connection limit of %zu connections. Disabling server-sockets for a while", srv->max_conns);
- }
-
- srv->sockets_disabled = 1;
-
- /* we count the number of free fds indirectly.
- *
- * instead of checking the fds we only check the connection handles we free'd since
- * the server-sockets got disabled
- * */
- conns_user_at_sockets_disabled = srv->conns->used;
- }
- }
-
- if (graceful_shutdown && srv->conns->used == 0) {
- /* we are in graceful shutdown phase and all connections are closed
- * we are ready to terminate without harming anyone */
- srv_shutdown = 1;
- continue;
- }
-
- /* we still have some fds to share */
- if (!srv_shutdown && srv->fdwaitqueue->used) {
- /* ok, we are back to the problem of 'how many fds do we have available ?' */
- connection *con;
- int fd;
- int avail_fds = conns_user_at_sockets_disabled - srv->conns->used;
-
- if (-1 == (fd = open("/dev/null", O_RDONLY))) {
- switch (errno) {
- case EMFILE:
- avail_fds = 0;
-
- break;
- default:
- break;
- }
- } else {
- close(fd);
-
- /* we have at least one FD as we just checked */
- if (!avail_fds) avail_fds++;
- }
-
-
- TRACE("conns used: %zu, fd-waitqueue has %zu entries, fds to share: %d", srv->conns->used, srv->fdwaitqueue->used, avail_fds);
-
- while (avail_fds-- && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue))) {
- connection_state_machine(srv, con);
- }
- }
- n = fdevent_poll(srv->ev, 1000);
- poll_errno = errno;
-#ifdef USE_GTHREAD
- g_atomic_int_set(&srv->did_wakeup, 0);
-#endif
-
- if (n > 0) {
- /* n is the number of events */
- size_t i;
- fdevent_get_revents(srv->ev, n, revents);
-
- /* handle client connections first
- *
- * this is a bit of a hack, but we have to make sure than we handle
- * close-events before the connection is reused for a keep-alive
- * request
- *
- * this is mostly an issue for mod_proxy_core, but you never know
- *
- */
-
- for (i = 0; i < revents->used; i++) {
- fdevent_revent *revent = revents->ptr[i];
- handler_t r;
-
- /* skip server-fds */
- if (revent->handler == network_server_handle_fdevent) continue;
-
- switch (r = (*(revent->handler))(srv, revent->context, revent->revents)) {
- case HANDLER_WAIT_FOR_FD:
- server_out_of_fds(srv, NULL);
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- case HANDLER_WAIT_FOR_EVENT:
- break;
- case HANDLER_ERROR:
- /* should never happen */
- SEGFAULT("got HANDLER_ERROR from a plugin: %s", "dieing");
- break;
- default:
- ERROR("got handler_t(%d) from a plugin: ignored", r);
- break;
- }
- }
-
- for (i = 0; i < revents->used; i++) {
- fdevent_revent *revent = revents->ptr[i];
- handler_t r;
-
- /* server fds only */
- if (revent->handler != network_server_handle_fdevent) continue;
-
- switch (r = (*(revent->handler))(srv, revent->context, revent->revents)) {
- case HANDLER_WAIT_FOR_FD:
- server_out_of_fds(srv, NULL);
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- case HANDLER_WAIT_FOR_EVENT:
- break;
- case HANDLER_ERROR:
- /* should never happen */
- SEGFAULT("got HANDLER_ERROR from a plugin: %s", "dieing");
- break;
- default:
- ERROR("got handler_t(%d) from a plugin: ignored", r);
- break;
- }
- }
-
- } else if (n < 0 && poll_errno != EINTR) {
- ERROR("fdevent_poll failed: %s", strerror(poll_errno));
- }
-
- /*
- * Note: Two joblist's are needed so a connection can be added back into the joblist
- * without getting stuck inside the for loop.
- */
-#ifdef USE_GTHREAD
- {
- connection *con;
- while (NULL != (con = g_async_queue_try_pop(srv->joblist_queue))) {
- joblist_append(srv, con);
- }
- }
-#endif
- if(srv->joblist->used > 0) {
- connections *joblist = srv->joblist;
- /* switch joblist queues. */
- srv->joblist = srv->joblist_prev;
- srv->joblist_prev = joblist;
- }
- for (ndx = 0; ndx < srv->joblist_prev->used; ndx++) {
- connection *con = srv->joblist_prev->ptr[ndx];
- handler_t r;
-
- con->in_joblist = 0;
- connection_state_machine(srv, con);
-
- switch(r = plugins_call_handle_joblist(srv, con)) {
- case HANDLER_FINISHED:
- case HANDLER_GO_ON:
- break;
- default:
- ERROR("got handler_t(%d) from a plugin: ignored", r);
- break;
- }
- }
-
- srv->joblist_prev->used = 0;
- }
-
- fdevent_revents_free(revents);
-
- return 0;
-}
-
-#ifdef USE_GTHREAD
-static handler_t wakeup_handle_fdevent(void *s, void *context, int revent) {
- server *srv = (server *)s;
- connection *con = context;
- char buf[16];
- UNUSED(con);
- UNUSED(revent);
-
- (void) read(srv->wakeup_iosocket->fd, buf, sizeof(buf));
- return HANDLER_GO_ON;
-}
-#endif
-
-int main (int argc, char **argv, char **envp) {
- server *srv = NULL;
- int print_config = 0;
- int test_config = 0;
- int i_am_root;
- int o;
- int num_childs = 0;
- int pid_fd = -1, fd;
- size_t i;
-#ifdef USE_GTHREAD
- GThread **stat_cache_threads;
- GThread **aio_write_threads = NULL;
-#ifdef USE_LINUX_AIO_SENDFILE
- GThread *linux_aio_read_thread_id = NULL;
-#endif
- GError *gerr = NULL;
-#endif
-
-#ifdef HAVE_SIGACTION
- struct sigaction act;
-#endif
-#ifdef HAVE_GETRLIMIT
- struct rlimit rlim;
-#endif
-
-#ifdef USE_ALARM
- struct itimerval interval;
-
- interval.it_interval.tv_sec = 1;
- interval.it_interval.tv_usec = 0;
- interval.it_value.tv_sec = 1;
- interval.it_value.tv_usec = 0;
-#endif
-
- UNUSED(envp);
-
- log_init();
- status_counter_init();
-
- /* for nice %b handling in strfime() */
- setlocale(LC_TIME, "C");
-
- if (NULL == (srv = server_init())) {
- fprintf(stderr, "did this really happen?\n");
- return -1;
- }
-
- /* init structs done */
-
- srv->srvconf.port = 0;
-#ifdef HAVE_GETUID
- i_am_root = (getuid() == 0);
-#else
- i_am_root = 0;
-#endif
- srv->srvconf.dont_daemonize = 0;
- srv->srvconf.daemonize_on_shutdown = 0;
- srv->srvconf.max_stat_threads = 4;
- srv->srvconf.max_read_threads = 8;
-
- while(-1 != (o = getopt(argc, argv, "f:m:hvVDIpt"))) {
- switch(o) {
- case 'f':
- if (config_read(srv, optarg)) {
- server_free(srv);
- return -1;
- }
- break;
- case 'm':
- buffer_copy_string(srv->srvconf.modules_dir, optarg);
- break;
- case 'p': print_config = 1; break;
- case 't': test_config = 1; break;
- case 'D': srv->srvconf.dont_daemonize = 1; break;
- case 'I': srv->srvconf.daemonize_on_shutdown = 1; break;
- case 'v': show_version(); return 0;
- case 'V': show_features(); return 0;
- case 'h': show_help(); return 0;
- default:
- show_help();
- server_free(srv);
- return -1;
- }
- }
-
- if (!srv->config_storage) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "No configuration available. Try using -f option.");
-
- server_free(srv);
- return -1;
- }
-
- if (print_config) {
- data_unset *dc = srv->config_context->data[0];
- if (dc) {
- dc->print(dc, 0);
- fprintf(stdout, "\n");
- } else {
- /* shouldn't happend */
- fprintf(stdout, "global config not found\n");
- }
- }
-
- if (test_config) {
- printf("Syntax OK\n");
- }
-
- if (test_config || print_config) {
- server_free(srv);
- return 0;
- }
-
- /* close stdin and stdout, as they are not needed */
- /* move stdin to /dev/null */
- if (-1 != (fd = open("/dev/null", O_RDONLY))) {
- close(STDIN_FILENO);
- dup2(fd, STDIN_FILENO);
- close(fd);
- }
-
- /* move stdout to /dev/null */
- if (-1 != (fd = open("/dev/null", O_WRONLY))) {
- close(STDOUT_FILENO);
- dup2(fd, STDOUT_FILENO);
- close(fd);
- }
-
- if (0 != config_set_defaults(srv)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "setting default values failed");
- server_free(srv);
- return -1;
- }
-
- /* UID handling */
-#ifdef HAVE_GETUID
- if (!i_am_root && issetugid()) {
- /* we are setuid-root */
-
- log_error_write(srv, __FILE__, __LINE__, "s",
- "Are you nuts ? Don't apply a SUID bit to this binary");
-
- server_free(srv);
- return -1;
- }
-#endif
-
- /* check document-root */
- if (srv->config_storage[0]->document_root->used <= 1) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "document-root is not set\n");
-
- server_free(srv);
-
- return -1;
- }
-
- if (plugins_load(srv)) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "loading plugins finally failed");
-
- plugins_free(srv);
- server_free(srv);
-
- return -1;
- }
-
-#ifndef _WIN32
- /* open pid file BEFORE chroot */
- if (srv->srvconf.pid_file->used) {
- if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
- struct stat st;
- if (errno != EEXIST) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
- return -1;
- }
-
- if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
- }
-
- if (!S_ISREG(st.st_mode)) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
- return -1;
- }
-
- if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
- return -1;
- }
- }
- }
-#endif
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- /* select limits itself
- *
- * as it is a hard limit and will lead to a segfault we add some safety
- * */
- fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
- srv->max_fds = FD_SETSIZE - 4;
- } else {
- srv->max_fds = 4096;
- }
-
- if (i_am_root) {
- struct group *grp = NULL;
- struct passwd *pwd = NULL;
- int use_rlimit = 1;
-
- /* valgrind only supports 1024 fds */
- if (RUNNING_ON_VALGRIND) use_rlimit = 0;
-
-#ifdef HAVE_GETRLIMIT
- if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
- log_error_write(srv, __FILE__, __LINE__,
- "ss", "couldn't get 'max filedescriptors'",
- strerror(errno));
- return -1;
- }
-
- if (use_rlimit && srv->srvconf.max_fds) {
- /* set rlimits */
-
- rlim.rlim_cur = srv->srvconf.max_fds;
- rlim.rlim_max = srv->srvconf.max_fds;
-
- if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
- log_error_write(srv, __FILE__, __LINE__,
- "ss", "couldn't set 'max filedescriptors'",
- strerror(errno));
- return -1;
- }
- }
-
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
- } else {
- srv->max_fds = rlim.rlim_cur;
- }
-
- /* set core file rlimit, if enable_cores is set */
- if (use_rlimit && srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
- rlim.rlim_cur = rlim.rlim_max;
- setrlimit(RLIMIT_CORE, &rlim);
- }
-#endif
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- /* don't raise the limit above FD_SET_SIZE */
- if (srv->max_fds > ((int)FD_SETSIZE) - 200) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "can't raise max filedescriptors above", FD_SETSIZE - 200,
- "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
- return -1;
- }
- }
-
-
-#ifdef HAVE_PWD_H
- /* set user and group */
- if (srv->srvconf.username->used) {
- if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "can't find username", srv->srvconf.username);
- return -1;
- }
-
- if (pwd->pw_uid == 0) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "I will not set uid to 0\n");
- return -1;
- }
- }
-
- if (srv->srvconf.groupname->used) {
- if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "can't find groupname", srv->srvconf.groupname);
- return -1;
- }
- if (grp->gr_gid == 0) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "I will not set gid to 0\n");
- return -1;
- }
- }
-#endif
- /* we need root-perms for port < 1024 */
- if (0 != network_init(srv)) {
- plugins_free(srv);
- server_free(srv);
-
- return -1;
- }
-
-#ifdef HAVE_PWD_H
- /**
- * initgroups() has to be called before chroot()
- */
- 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();
-
- if (-1 == chroot(srv->srvconf.changeroot->ptr)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "chroot failed: ", strerror(errno));
- return -1;
- }
- if (-1 == chdir("/")) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "chdir failed: ", strerror(errno));
- return -1;
- }
- }
-#endif
-#ifdef HAVE_PWD_H
- /* drop root privs */
- if (srv->srvconf.username->used) setuid(pwd->pw_uid);
-#endif
-#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
- /**
- * IRIX 6.5.x has prctl() but no PR_SET_DUMPABLE
- */
- if (srv->srvconf.enable_cores) {
- prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
- }
-#endif
- } else {
-
-#ifdef HAVE_GETRLIMIT
- if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
- log_error_write(srv, __FILE__, __LINE__,
- "ss", "couldn't get 'max filedescriptors'",
- strerror(errno));
- return -1;
- }
-
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- srv->max_fds = rlim.rlim_cur < ((int)FD_SETSIZE) - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
- } else {
- srv->max_fds = rlim.rlim_cur;
- }
-
- /* set core file rlimit, if enable_cores is set */
- if (srv->srvconf.enable_cores && getrlimit(RLIMIT_CORE, &rlim) == 0) {
- rlim.rlim_cur = rlim.rlim_max;
- setrlimit(RLIMIT_CORE, &rlim);
- }
-
-#endif
- if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
- /* don't raise the limit above FD_SET_SIZE */
- if (srv->max_fds > ((int)FD_SETSIZE) - 4) {
- log_error_write(srv, __FILE__, __LINE__, "sd",
- "can't raise max filedescriptors above", FD_SETSIZE - 4,
- "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
- return -1;
- }
- }
-
- if (0 != network_init(srv)) {
- plugins_free(srv);
- server_free(srv);
-
- return -1;
- }
- }
-
- /* set max-conns */
- if (srv->srvconf.max_conns > srv->max_fds/2) {
- /* we can't have more connections than max-fds/2 */
- log_error_write(srv, __FILE__, __LINE__, "sdd", "can't have more connections than fds/2: ", srv->srvconf.max_conns, srv->max_fds);
- srv->max_conns = srv->max_fds/2;
- } else if (srv->srvconf.max_conns) {
- /* otherwise respect the wishes of the user */
- srv->max_conns = srv->srvconf.max_conns;
- } else {
- /* or use the default: we really don't want to hit max-fds */
- srv->max_conns = srv->max_fds/3;
- }
-
- if (HANDLER_GO_ON != plugins_call_init(srv)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
-
- plugins_free(srv);
- network_close(srv);
- server_free(srv);
-
- return -1;
- }
-
-#ifdef HAVE_FORK
- /* network is up, let's deamonize ourself */
- if (srv->srvconf.dont_daemonize == 0) daemonize();
-#endif
-
-#ifdef HAVE_PWD_H
- srv->gid = getgid();
- srv->uid = getuid();
-#endif
-
- /* write pid file */
- if (pid_fd != -1) {
- buffer_copy_long(srv->tmp_buf, getpid());
- buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN("\n"));
- if (-1 == write(pid_fd, srv->tmp_buf->ptr, srv->tmp_buf->used - 1)) {
- ERROR("writing to PID to '%s' failed: %s, ignored", "...", strerror(errno));
- }
- close(pid_fd);
- pid_fd = -1;
- }
-
- if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
-
- plugins_free(srv);
- network_close(srv);
- server_free(srv);
-
- return -1;
- }
-
- /* dump unused config-keys */
- for (i = 0; i < srv->config_context->used; i++) {
- array *config = ((data_config *)srv->config_context->data[i])->value;
- size_t j;
-
- for (j = 0; config && j < config->used; j++) {
- data_unset *du = config->data[j];
-
- /* all var.* is known as user defined variable */
- if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
- continue;
- }
-
- if (NULL == array_get_element(srv->config_touched, CONST_BUF_LEN(du->key))) {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "WARNING: unknown config-key:",
- du->key,
- "(ignored)");
- }
- }
- }
-
- if (srv->config_unsupported) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "Configuration contains unsupported keys. Going down.");
- }
-
- if (srv->config_deprecated) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "Configuration contains deprecated keys. Going down.");
- }
-
- if (srv->config_unsupported || srv->config_deprecated) {
- plugins_free(srv);
- network_close(srv);
- server_free(srv);
-
- return -1;
- }
-
- if (-1 == log_error_open(srv->srvconf.errorlog_file, srv->srvconf.breakagelog_file, srv->srvconf.errorlog_use_syslog, srv->srvconf.dont_daemonize)) {
- 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
- memset(&act, 0, sizeof(act));
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
-# if defined(SA_SIGINFO)
- act.sa_sigaction = sigaction_handler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
-# else
- act.sa_handler = signal_handler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
-# endif
- sigaction(SIGINT, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGALRM, &act, NULL);
- sigaction(SIGCHLD, &act, NULL);
-
-#elif defined(HAVE_SIGNAL)
- /* ignore the SIGPIPE from sendfile() */
- signal(SIGPIPE, SIG_IGN);
- signal(SIGALRM, signal_handler);
- signal(SIGTERM, signal_handler);
- signal(SIGHUP, signal_handler);
- signal(SIGCHLD, signal_handler);
- signal(SIGINT, signal_handler);
-#endif
-
-#ifdef USE_ALARM
- signal(SIGALRM, signal_handler);
-
- /* setup periodic timer (1 second) */
- if (setitimer(ITIMER_REAL, &interval, NULL)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
- return -1;
- }
-
- getitimer(ITIMER_REAL, &interval);
-#endif
-
-#ifdef HAVE_FORK
- /* start watcher and workers */
- num_childs = srv->srvconf.max_worker;
- if (num_childs > 0) {
- int child = 0;
- while (!child && !srv_shutdown) {
- if (num_childs > 0) {
- switch (fork()) {
- case -1:
- return -1;
- case 0:
- child = 1;
- break;
- default:
- num_childs--;
- break;
- }
- } else {
- int status;
-
- if (-1 != wait(&status)) {
- /* a child terminated, restart it */
- num_childs++;
- } else {
- /* we got interrupted */
-
- switch (errno) {
- case EINTR:
- /**
- * we got asked to rotate the logs
- *
- * as we are just the parent and have no main-loop we have to fix it ourself
- */
- if (handle_sig_hup) {
- handle_sig_hup = 0;
-
- log_error_cycle();
- }
- break;
- default:
- TRACE("(angel) wait() failed with: %s (errno=%d)", strerror(errno), errno);
- break;
- }
- }
- }
- }
-
- if (srv_shutdown) {
- /* kill all childs */
- kill(0, SIGTERM);
- }
-
- /* if we are the parent, leave here */
- if (!child) return 0;
- }
-#endif
-
- if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
- log_error_write(srv, __FILE__, __LINE__,
- "s", "fdevent_init failed");
- return -1;
- }
- /*
- * kqueue() is called here, select resets its internals,
- * all server sockets get their handlers
- *
- * */
- if (0 != network_register_fdevents(srv)) {
- plugins_free(srv);
- network_close(srv);
- server_free(srv);
-
- return -1;
- }
-
-#ifdef USE_GTHREAD
- if (pipe(srv->wakeup_pipe) == -1) {
- log_error_write(srv, __FILE__, __LINE__, "s", "pipe() failed");
- return -1;
- }
- srv->wakeup_iosocket = iosocket_init();
- srv->wakeup_iosocket->type = IOSOCKET_TYPE_PIPE;
- srv->wakeup_iosocket->fd = srv->wakeup_pipe[0];
- srv->did_wakeup = 0;
- fdevent_fcntl_set(srv->ev, srv->wakeup_iosocket);
- /* block on write */
-#ifdef FD_CLOEXEC
- /* close fd on exec (cgi) */
- fcntl(srv->wakeup_pipe[1], F_SETFD, FD_CLOEXEC);
-#endif
- fdevent_register(srv->ev, srv->wakeup_iosocket, wakeup_handle_fdevent, NULL);
- fdevent_event_add(srv->ev, srv->wakeup_iosocket, FDEVENT_IN);
-#endif
-
- /* might fail if user is using fam (not gamin) and famd isn't running */
- if (NULL == (srv->stat_cache = stat_cache_init())) {
- log_error_write(srv, __FILE__, __LINE__, "s",
- "stat-cache could not be setup, dieing.");
- return -1;
- }
-
-#ifdef USE_GTHREAD
- g_thread_init(NULL);
-
- srv->stat_queue = g_async_queue_new();
- srv->joblist_queue = g_async_queue_new();
- srv->aio_write_queue = g_async_queue_new();
-#ifdef HAVE_SYS_INOTIFY_H
- if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_INOTIFY) {
- srv->stat_cache->sock->fd = inotify_init();
-
- fdevent_register(srv->ev, srv->stat_cache->sock, stat_cache_handle_fdevent, NULL);
- fdevent_event_add(srv->ev, srv->stat_cache->sock, FDEVENT_IN);
- }
-#endif
- stat_cache_threads = calloc(srv->srvconf.max_stat_threads, sizeof(*stat_cache_threads));
-
- for (i = 0; i < srv->srvconf.max_stat_threads; i++) {
- stat_cache_threads[i] = g_thread_create(stat_cache_thread, srv, 1, &gerr);
- if (gerr) {
- ERROR("g_thread_create failed: %s", gerr->message);
-
- return -1;
- }
- }
-
-#ifndef _WIN32
- switch (srv->network_backend) {
- case NETWORK_BACKEND_GTHREAD_AIO:
- aio_write_threads = calloc(srv->srvconf.max_read_threads, sizeof(*aio_write_threads));
- for (i = 0; i < srv->srvconf.max_read_threads; i++) {
- aio_write_threads[i] = g_thread_create_full(network_gthread_aio_read_thread, srv, LI_THREAD_STACK_SIZE, 1, TRUE, G_THREAD_PRIORITY_NORMAL, &gerr);
- if (gerr) {
- ERROR("g_thread_create failed: %s", gerr->message);
-
- return -1;
- }
- }
- break;
-#ifdef USE_GTHREAD_SENDFILE
- case NETWORK_BACKEND_GTHREAD_SENDFILE:
- aio_write_threads = calloc(srv->srvconf.max_read_threads, sizeof(*aio_write_threads));
- for (i = 0; i < srv->srvconf.max_read_threads; i++) {
- aio_write_threads[i] = g_thread_create_full(network_gthread_sendfile_read_thread, srv, LI_THREAD_STACK_SIZE, 1, TRUE, G_THREAD_PRIORITY_NORMAL, &gerr);
- if (gerr) {
- ERROR("g_thread_create failed: %s", gerr->message);
-
- return -1;
- }
- }
- break;
-#endif
-#ifdef USE_GTHREAD_FREEBSD_SENDFILE
- case NETWORK_BACKEND_GTHREAD_FREEBSD_SENDFILE:
- aio_write_threads = calloc(srv->srvconf.max_read_threads, sizeof(*aio_write_threads));
- for (i = 0; i < srv->srvconf.max_read_threads; i++) {
- aio_write_threads[i] = g_thread_create_full(network_gthread_freebsd_sendfile_read_thread, srv, LI_THREAD_STACK_SIZE, 1, TRUE, G_THREAD_PRIORITY_NORMAL, &gerr);
- if (gerr) {
- ERROR("g_thread_create failed: %s", gerr->message);
-
- return -1;
- }
- }
- break;
-#endif
-#ifdef USE_POSIX_AIO
- case NETWORK_BACKEND_POSIX_AIO:
- srv->posix_aio_iocbs = calloc(srv->srvconf.max_read_threads, sizeof(*srv->posix_aio_iocbs));
- break;
-#endif
-#ifdef USE_LINUX_AIO_SENDFILE
- case NETWORK_BACKEND_LINUX_AIO_SENDFILE:
- TRACE("WARNING: You selected the experimental network.backend '%s'", "linux-aio-sendfile");
- srv->linux_io_iocbs = calloc(srv->srvconf.max_read_threads, sizeof(*srv->linux_io_iocbs));
- if (0 != (i = io_setup(srv->srvconf.max_read_threads, &(srv->linux_io_ctx)))) {
- ERROR("io-setup() failed somehow %s", strerror(-i));
-
- return -1;
- }
- linux_aio_read_thread_id = g_thread_create(linux_aio_read_thread, srv, 1, &gerr);
- if (gerr) {
- ERROR("g_thread_create failed: %s", gerr->message);
-
- return -1;
- }
- break;
-#endif
- default:
- break;
- }
-#endif /* ifndef _WIN32 */
-
-#endif /* USE_GTHREAD */
-
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
- if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->sock)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
- return -1;
- }
- }
-
- lighty_mainloop(srv);
-
- if (0 == graceful_restart &&
- srv->srvconf.pid_file->used &&
- srv->srvconf.changeroot->used == 0) {
- if (0 != unlink(srv->srvconf.pid_file->ptr)) {
- if (errno != EACCES && errno != EPERM) {
- log_error_write(srv, __FILE__, __LINE__, "sbds",
- "unlink failed for:",
- srv->srvconf.pid_file,
- errno,
- strerror(errno));
- }
- }
- }
-
- /* kill the threads */
-
- srv->is_shutdown = 1;
-#ifdef USE_GTHREAD
-#ifdef USE_LINUX_AIO_SENDFILE
- if (srv->network_backend == NETWORK_BACKEND_LINUX_AIO_SENDFILE) {
- g_thread_join(linux_aio_read_thread_id);
- free(srv->linux_io_iocbs);
- }
-#endif
-#ifdef USE_POSIX_AIO
- if (srv->network_backend == NETWORK_BACKEND_POSIX_AIO) {
- free(srv->posix_aio_iocbs);
- }
-#endif
- if (aio_write_threads != NULL) {
- for (i = 0; i < srv->srvconf.max_read_threads; i++) {
- g_thread_join(aio_write_threads[i]);
- }
- free(aio_write_threads);
- }
-
- for (i = 0; i < srv->srvconf.max_stat_threads; i++) {
- g_async_queue_push(srv->stat_queue, (void *) 1);
- }
-
- for (i = 0; i < srv->srvconf.max_stat_threads; i++) {
- g_thread_join(stat_cache_threads[i]);
- }
-
- /* the ref-count should be 0 now */
- g_async_queue_unref(srv->stat_queue);
- g_async_queue_unref(srv->joblist_queue);
- g_async_queue_unref(srv->aio_write_queue);
-#endif
- /* clean-up */
- network_close(srv);
- connections_free(srv);
- plugins_free(srv);
- server_free(srv);
-
- TRACE("server stopped by UID=%d, PID=%d", last_sigterm_info.si_uid, last_sigterm_info.si_pid);
-
- log_free();
- status_counter_free();
-
-#ifdef USE_GTHREAD
- free(stat_cache_threads);
-#endif
-
- chunkpool_free();
-
- return 0;
-}
diff --git a/src/server.h b/src/server.h
deleted file mode 100644
index c6fddf97..00000000
--- a/src/server.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _SERVER_H_
-#define _SERVER_H_
-
-#include "base.h"
-
-typedef enum { CONFIG_UNSET, CONFIG_DOCUMENT_ROOT } config_var_t;
-
-LI_EXPORT int config_read(server *srv, const char *fn);
-LI_EXPORT int config_set_defaults(server *srv);
-LI_EXPORT buffer * config_get_value_buffer(server *srv, connection *con, config_var_t field);
-
-#ifdef USE_GTHREAD
-gpointer stat_cache_thread(gpointer );
-gpointer network_gthread_aio_read_thread(gpointer );
-gpointer network_gthread_sendfile_read_thread(gpointer );
-gpointer network_gthread_freebsd_sendfile_read_thread(gpointer );
-gpointer linux_aio_read_thread(gpointer );
-#endif
-
-#endif
diff --git a/src/settings.h b/src/settings.h
deleted file mode 100644
index 4724e83d..00000000
--- a/src/settings.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef _LIGHTTPD_SETTINGS_H_
-#define _LIGHTTPD_SETTINGS_H_
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define BV(x) (1 << x)
-
-#define INET_NTOP_CACHE_MAX 4
-#define FILE_CACHE_MAX 16
-
-/**
- * max size of a buffer which will just be reset
- * to ->used = 0 instead of really freeing the buffer
- *
- * 64kB (no real reason, just a guess)
- */
-#define BUFFER_MAX_REUSE_SIZE (4 * 1024)
-
-/**
- * max size of the HTTP request header
- *
- * 32k should be enough for everything (just a guess)
- *
- */
-#define MAX_HTTP_REQUEST_HEADER (32 * 1024)
-
-#ifdef HAVE_GLIB_H
-#include <glib.h>
-#endif
-
-/**
- * if glib supports threads we will use it for async file-io
- */
-#ifdef G_THREADS_ENABLED
-# ifndef USE_GTHREAD
-# define USE_GTHREAD
-# endif
-#endif
-
-
-/* on linux 2.4.x you get either sendfile or LFS */
-#if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILE && (!defined _LARGEFILE_SOURCE || defined HAVE_SENDFILE64) && defined HAVE_WRITEV && defined(__linux__) && !defined HAVE_SENDFILE_BROKEN
-# define USE_LINUX_SENDFILE
-# include <sys/sendfile.h>
-# include <sys/uio.h>
-#endif
-
-/* all the Async IO backends need GTHREAD support */
-#if defined(USE_GTHREAD)
-# if defined(USE_LINUX_SENDFILE)
-# if defined(HAVE_LIBAIO_H)
- /** disabled for now as not all FSs are async-io capable */
-# define USE_LINUX_AIO_SENDFILE
-# endif
-# define USE_GTHREAD_SENDFILE
-# endif
-# if defined(HAVE_AIO_H) && (!defined(__FreeBSD__))
-/* FreeBSD has no SIGEV_THREAD for us */
-# define USE_POSIX_AIO
-# include <sys/types.h> /* macosx wants it */
-# include <aio.h>
-# endif
-# ifdef HAVE_MMAP
-# define USE_GTHREAD_AIO
-# endif
-#endif
-
-#if defined HAVE_SYS_UIO_H && defined HAVE_SENDFILE && defined HAVE_WRITEV && (defined(__FreeBSD__) || defined(__DragonFly__))
-# define USE_FREEBSD_SENDFILE
-# include <sys/uio.h>
-#endif
-
-#if defined(USE_FREEBSD_SENDFILE) && defined(USE_GTHREAD)
-# define USE_GTHREAD_FREEBSD_SENDFILE
-#endif
-
-
-#if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILEV && defined HAVE_WRITEV && defined(__sun)
-# define USE_SOLARIS_SENDFILEV
-# include <sys/sendfile.h>
-# include <sys/uio.h>
-#endif
-
-#if defined HAVE_SYS_UIO_H && defined HAVE_WRITEV
-# define USE_WRITEV
-# include <sys/uio.h>
-#endif
-
-#if defined HAVE_SYS_MMAN_H && defined HAVE_MMAP
-# define USE_MMAP
-# include <sys/mman.h>
-/* NetBSD 1.3.x needs it */
-# ifndef MAP_FAILED
-# define MAP_FAILED -1
-# endif
-
-#if defined(MAP_ANON)
-#define HAVE_MEM_MMAP_ANON
-#else
-/* let's try /dev/zero */
-#define HAVE_MEM_MMAP_ZERO
-#endif
-
-#endif
-
-#if defined HAVE_SYS_UIO_H && defined HAVE_WRITEV && defined HAVE_SEND_FILE && defined(__aix)
-# define USE_AIX_SENDFILE
-#endif
-
-
-/**
-* unix can use read/write or recv/send on sockets
-* win32 only recv/send
-*/
-#ifdef _WIN32
-
-# define WIN32_LEAN_AND_MEAN
-# define NOGDI
-# define USE_WIN32_SEND
-/* wait for async-io support
-# define USE_WIN32_TRANSMITFILE
-*/
-#else
-# define USE_WRITE
-#endif
-
-
-typedef enum { HANDLER_UNSET,
- HANDLER_GO_ON,
- HANDLER_FINISHED,
- HANDLER_COMEBACK,
- HANDLER_WAIT_FOR_EVENT,
- HANDLER_ERROR,
- HANDLER_WAIT_FOR_FD
-} handler_t;
-
-/* Shared library support */
-#ifdef _WIN32
- #define LI_IMPORT __declspec(dllimport)
- #define LI_EXPORT __declspec(dllexport)
- #define LI_DLLLOCAL
- #define LI_DLLPUBLIC
-#else
- #define LI_IMPORT
- #ifdef GCC_HASCLASSVISIBILITY
- #define LI_EXPORT __attribute__ ((visibility("default")))
- #define LI_DLLLOCAL __attribute__ ((visibility("hidden")))
- #define LI_DLLPUBLIC __attribute__ ((visibility("default")))
- #else
- #define LI_EXPORT
- #define LI_DLLLOCAL
- #define LI_DLLPUBLIC
- #endif
-#endif
-
-#ifdef LI_DECLARE_EXPORTS
-#define LI_API LI_EXPORT
-#else
-#define LI_API LI_IMPORT
-#endif
-
-/* Throwable classes must always be visible on GCC in all binaries */
-#ifdef _WIN32
- #define LI_EXCEPTIONAPI(api) api
-#elif defined(GCC_HASCLASSVISIBILITY)
- #define LI_EXCEPTIONAPI(api) LI_EXPORT
-#else
- #define LI_EXCEPTIONAPI(api)
-#endif
-
-#ifdef UNUSED_PARAM
-#elif defined(__GNUC__)
-# define UNUSED_PARAM(x) UNUSED_ ## x __attribute__((unused))
-#elif defined(__LCLINT__)
-# define UNUSED_PARAM(x) /*@unused@*/ x
-#else
-# define UNUSED_PARAM(x) x
-#endif
-
-
-#endif
diff --git a/src/splaytree.c b/src/splaytree.c
deleted file mode 100644
index 5d6a2b40..00000000
--- a/src/splaytree.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- An implementation of top-down splaying with sizes
- D. Sleator <sleator@cs.cmu.edu>, January 1994.
-
- This extends top-down-splay.c to maintain a size field in each node.
- This is the number of nodes in the subtree rooted there. This makes
- it possible to efficiently compute the rank of a key. (The rank is
- the number of nodes to the left of the given key.) It it also
- possible to quickly find the node of a given rank. Both of these
- operations are illustrated in the code below. The remainder of this
- introduction is taken from top-down-splay.c.
-
- "Splay trees", or "self-adjusting search trees" are a simple and
- efficient data structure for storing an ordered set. The data
- structure consists of a binary tree, with no additional fields. It
- allows searching, insertion, deletion, deletemin, deletemax,
- splitting, joining, and many other operations, all with amortized
- logarithmic performance. Since the trees adapt to the sequence of
- requests, their performance on real access patterns is typically even
- better. Splay trees are described in a number of texts and papers
- [1,2,3,4].
-
- The code here is adapted from simple top-down splay, at the bottom of
- page 669 of [2]. It can be obtained via anonymous ftp from
- spade.pc.cs.cmu.edu in directory /usr/sleator/public.
-
- The chief modification here is that the splay operation works even if the
- item being splayed is not in the tree, and even if the tree root of the
- tree is NULL. So the line:
-
- t = splay(i, t);
-
- causes it to search for item with key i in the tree rooted at t. If it's
- there, it is splayed to the root. If it isn't there, then the node put
- at the root is the last one before NULL that would have been reached in a
- normal binary search for i. (It's a neighbor of i in the tree.) This
- allows many other operations to be easily implemented, as shown below.
-
- [1] "Data Structures and Their Algorithms", Lewis and Denenberg,
- Harper Collins, 1991, pp 243-251.
- [2] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
- JACM Volume 32, No 3, July 1985, pp 652-686.
- [3] "Data Structure and Algorithm Analysis", Mark Weiss,
- Benjamin Cummins, 1992, pp 119-130.
- [4] "Data Structures, Algorithms, and Performance", Derick Wood,
- Addison-Wesley, 1993, pp 367-375
-*/
-
-#include <stdlib.h>
-#include <assert.h>
-#include "splaytree.h"
-
-#define compare(i,j) ((i)-(j))
-/* This is the comparison. */
-/* Returns <0 if i<j, =0 if i=j, and >0 if i>j */
-
-#define node_size splaytree_size
-
-/* Splay using the key i (which may or may not be in the tree.)
- * The starting root is t, and the tree used is defined by rat
- * size fields are maintained */
-splay_tree * splaytree_splay (splay_tree *t, int i) {
- splay_tree N, *l, *r, *y;
- int comp, root_size, l_size, r_size;
-
- if (t == NULL) return t;
- N.left = N.right = NULL;
- l = r = &N;
- root_size = node_size(t);
- l_size = r_size = 0;
-
- for (;;) {
- comp = compare(i, t->key);
- if (comp < 0) {
- if (t->left == NULL) break;
- if (compare(i, t->left->key) < 0) {
- y = t->left; /* rotate right */
- t->left = y->right;
- y->right = t;
- t->size = node_size(t->left) + node_size(t->right) + 1;
- t = y;
- if (t->left == NULL) break;
- }
- r->left = t; /* link right */
- r = t;
- t = t->left;
- r_size += 1+node_size(r->right);
- } else if (comp > 0) {
- if (t->right == NULL) break;
- if (compare(i, t->right->key) > 0) {
- y = t->right; /* rotate left */
- t->right = y->left;
- y->left = t;
- t->size = node_size(t->left) + node_size(t->right) + 1;
- t = y;
- if (t->right == NULL) break;
- }
- l->right = t; /* link left */
- l = t;
- t = t->right;
- l_size += 1+node_size(l->left);
- } else {
- break;
- }
- }
- l_size += node_size(t->left); /* Now l_size and r_size are the sizes of */
- r_size += node_size(t->right); /* the left and right trees we just built.*/
- t->size = l_size + r_size + 1;
-
- l->right = r->left = NULL;
-
- /* The following two loops correct the size fields of the right path */
- /* from the left child of the root and the right path from the left */
- /* child of the root. */
- for (y = N.right; y != NULL; y = y->right) {
- y->size = l_size;
- l_size -= 1+node_size(y->left);
- }
- for (y = N.left; y != NULL; y = y->left) {
- y->size = r_size;
- r_size -= 1+node_size(y->right);
- }
-
- l->right = t->left; /* assemble */
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
-
- return t;
-}
-
-splay_tree * splaytree_insert(splay_tree * t, int i, void *data) {
-/* Insert key i into the tree t, if it is not already there. */
-/* Return a pointer to the resulting tree. */
- splay_tree * new;
-
- if (t != NULL) {
- t = splaytree_splay(t, i);
- if (compare(i, t->key)==0) {
- return t; /* it's already there */
- }
- }
- new = (splay_tree *) malloc (sizeof (splay_tree));
- assert(new);
- if (t == NULL) {
- new->left = new->right = NULL;
- } else if (compare(i, t->key) < 0) {
- new->left = t->left;
- new->right = t;
- t->left = NULL;
- t->size = 1+node_size(t->right);
- } else {
- new->right = t->right;
- new->left = t;
- t->right = NULL;
- t->size = 1+node_size(t->left);
- }
- new->key = i;
- new->data = data;
- new->size = 1 + node_size(new->left) + node_size(new->right);
- return new;
-}
-
-splay_tree * splaytree_delete(splay_tree *t, int i) {
-/* Deletes i from the tree if it's there. */
-/* Return a pointer to the resulting tree. */
- splay_tree * x;
- int tsize;
-
- if (t==NULL) return NULL;
- tsize = t->size;
- t = splaytree_splay(t, i);
- if (compare(i, t->key) == 0) { /* found it */
- if (t->left == NULL) {
- x = t->right;
- } else {
- x = splaytree_splay(t->left, i);
- x->right = t->right;
- }
- free(t);
- if (x != NULL) {
- x->size = tsize-1;
- }
- return x;
- } else {
- return t; /* It wasn't there */
- }
-}
-
-splay_tree *find_rank(int r, splay_tree *t) {
-/* Returns a pointer to the node in the tree with the given rank. */
-/* Returns NULL if there is no such node. */
-/* Does not change the tree. To guarantee logarithmic behavior, */
-/* the node found here should be splayed to the root. */
- int lsize;
- if ((r < 0) || (r >= node_size(t))) return NULL;
- for (;;) {
- lsize = node_size(t->left);
- if (r < lsize) {
- t = t->left;
- } else if (r > lsize) {
- r = r - lsize -1;
- t = t->right;
- } else {
- return t;
- }
- }
-}
-
-
diff --git a/src/splaytree.h b/src/splaytree.h
deleted file mode 100644
index e9c1c68e..00000000
--- a/src/splaytree.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _SPLAY_TREE_H_
-#define _SPLAY_TREE_H_
-
-typedef struct tree_node {
- struct tree_node * left, * right;
- int key;
- int size; /* maintained to be the number of nodes rooted here */
-
- void *data;
-} splay_tree;
-
-
-LI_EXPORT splay_tree * splaytree_splay (splay_tree *t, int key);
-LI_EXPORT splay_tree * splaytree_insert(splay_tree *t, int key, void *data);
-LI_EXPORT splay_tree * splaytree_delete(splay_tree *t, int key);
-LI_EXPORT splay_tree * splaytree_size(splay_tree *t);
-
-#define splaytree_size(x) (((x)==NULL) ? 0 : ((x)->size))
-/* This macro returns the size of a node. Unlike "x->size", */
-/* it works even if x=NULL. The test could be avoided by using */
-/* a special version of NULL which was a real node with size 0. */
-
-
-#endif
diff --git a/src/stat_cache.c b/src/stat_cache.c
deleted file mode 100644
index 55587ec2..00000000
--- a/src/stat_cache.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * make sure _GNU_SOURCE is defined
- */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "log.h"
-#include "stat_cache.h"
-#include "fdevent.h"
-#include "etag.h"
-#include "server.h"
-#include "joblist.h"
-
-#ifdef HAVE_ATTR_ATTRIBUTES_H
-#include <attr/attributes.h>
-#endif
-
-#include "sys-mmap.h"
-#include "sys-files.h"
-#include "sys-strings.h"
-
-#undef HAVE_FAM_H
-#undef HAVE_SYS_INOTIFY_H
-
-#if 0
-/* enables debug code for testing if all nodes in the stat-cache as accessable */
-#define DEBUG_STAT_CACHE
-#endif
-
-/*
- * stat-cache
- *
- * we cache the stat() calls in our own storage
- * the directories are cached in FAM
- *
- * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
- *
- * if the stat()-cache is queried we check if the version id for the directory is the
- * same and return immediatly.
- *
- *
- * What we need:
- *
- * - for each stat-cache entry we need a fast indirect lookup on the directory name
- * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
- *
- * stat <<-> directory <-> FAMRequest
- *
- * if file is deleted, directory is dirty, file is rechecked ...
- * if directory is deleted, directory mapping is removed
- *
- * */
-
-/* the directory name is too long to always compare on it
- * - we need a hash
- * - the hash-key is used as sorting criteria for a tree
- * - a splay-tree is used as we can use the caching effect of it
- */
-
-/* we want to cleanup the stat-cache every few seconds, let's say 10
- *
- * - remove entries which are outdated since 30s
- * - remove entries which are fresh but havn't been used since 60s
- * - if we don't have a stat-cache entry for a directory, release it from the monitor
- */
-#ifdef USE_GTHREAD
-typedef struct {
- buffer *name;
-
- void *con;
-} stat_job;
-
-static stat_job *stat_job_init() {
- stat_job *sj = calloc(1, sizeof(*sj));
-
- sj->name = buffer_init();
-
- return sj;
-}
-
-static void stat_job_free(stat_job *sj) {
- if (!sj) return;
-
- buffer_free(sj->name);
-
- free(sj);
-}
-
-gpointer stat_cache_thread(gpointer _srv) {
- server *srv = (server *)_srv;
- stat_job *sj = NULL;
-
- /* take the stat-job-queue */
- GAsyncQueue * inq;
-
- g_async_queue_ref(srv->stat_queue);
-
- inq = srv->stat_queue;
-
- /* */
- while (!srv->is_shutdown) {
- /* let's see what we have to stat */
- struct stat st;
-
- if ((sj = g_async_queue_pop(inq))) {
- if(sj == (stat_job *) 1)
- continue; /* just notifying us that srv->is_shutdown changed */
-
- /* don't care about the return code for now */
- stat(sj->name->ptr, &st);
-
- joblist_async_append(srv, sj->con);
- stat_job_free(sj);
- }
- }
-
- g_async_queue_unref(srv->stat_queue);
-
- return NULL;
-}
-#endif
-
-#ifdef HAVE_GLIB_H
-static guint sc_key_hash(gconstpointer v) {
- buffer *b = (buffer *)v;
-
- return g_str_hash(b->ptr);
-}
-
-static gboolean sc_key_equal(gconstpointer v1, gconstpointer v2) {
- buffer *b1 = (buffer *)v1;
- buffer *b2 = (buffer *)v2;
-
- return buffer_is_equal(b1, b2);
-}
-#endif
-
-stat_cache *stat_cache_init(void) {
- stat_cache *fc = NULL;
-
- fc = calloc(1, sizeof(*fc));
-
- fc->dir_name = buffer_init();
- fc->hash_key = buffer_init();
-
-#if defined(HAVE_SYS_INOTIFY_H)
- fc->sock = iosocket_init();
-#endif
-#ifdef HAVE_GLIB_H
- fc->files = g_hash_table_new(sc_key_hash, sc_key_equal);
-#endif
-
- return fc;
-}
-
-static stat_cache_entry * stat_cache_entry_init(void) {
- stat_cache_entry *sce = NULL;
-
- sce = calloc(1, sizeof(*sce));
-
- sce->name = buffer_init();
- sce->etag = buffer_init();
- sce->content_type = buffer_init();
-
- return sce;
-}
-
-static void stat_cache_entry_free(void *data) {
- stat_cache_entry *sce = data;
- if (!sce) return;
-
- buffer_free(sce->etag);
- buffer_free(sce->name);
- buffer_free(sce->content_type);
-
- free(sce);
-}
-
-#ifdef HAVE_GLIB_H
-static gboolean stat_cache_free_hrfunc(gpointer _key, gpointer _value, gpointer _user_data) {
- stat_cache_entry *sce = _value;
- buffer *b = _key;
- UNUSED(_user_data);
-
- buffer_free(b);
- stat_cache_entry_free(sce);
-
- return TRUE;
-}
-#endif
-
-void stat_cache_free(stat_cache *sc) {
-#ifdef HAVE_GLIB_H
- g_hash_table_foreach_remove(sc->files, stat_cache_free_hrfunc, NULL);
- g_hash_table_destroy(sc->files);
-#endif
-
- buffer_free(sc->dir_name);
- buffer_free(sc->hash_key);
-
-#if defined(HAVE_SYS_INOTIFY_H)
- if (sc->sock) iosocket_free(sc->sock);
-#endif
-
- free(sc);
-}
-
-#ifdef HAVE_XATTR
-static int stat_cache_attr_get(buffer *buf, char *name) {
- int attrlen;
- int ret;
-
- attrlen = 1024;
- buffer_prepare_copy(buf, attrlen);
- attrlen--;
- if(0 == (ret = attr_get(name, "Content-Type", buf->ptr, &attrlen, 0))) {
- buf->used = attrlen + 1;
- buf->ptr[attrlen] = '\0';
- }
- return ret;
-}
-#endif
-
-handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent) {
- server *srv = _srv;
-
- switch (srv->srvconf.stat_cache_engine) {
-#ifdef HAVE_SYS_INOTIFY_H
- case STAT_CACHE_ENGINE_INOTIFY:
- return stat_cache_handle_fdevent_inotify(_srv, _fce, revent);
-#else
- UNUSED(_fce);
- UNUSED(revent);
-#endif
- default:
- return HANDLER_GO_ON;
- }
-}
-#ifdef HAVE_LSTAT
-static int stat_cache_lstat(server *srv, buffer *dname, struct stat *lst) {
- if (lstat(dname->ptr, lst) == 0) {
- return S_ISLNK(lst->st_mode) ? 0 : 1;
- } else {
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "lstat failed for:",
- dname, strerror(errno));
- }
- return -1;
-}
-#endif
-
-static int stat_cache_entry_is_current(server *srv, stat_cache_entry *sce) {
- struct stat st;
- UNUSED(srv);
- UNUSED(sce);
-
- if (-1 == stat(sce->name->ptr, &st)) {
- return 0;
- }
- /* still existing */
-
- if (st.st_dev != sce->st.st_dev || st.st_ino != sce->st.st_ino) {
- return 0; /* different file */
- }
-
- /* same file, still existing: update other stats: */
- sce->st = st;
- /* need to check other properties before this: sce->stat_ts = srv->cur_ts; */
- return 1;
-}
-
-static void stat_cache_remove_entry(stat_cache *sc, buffer *hash_key, stat_cache_entry *sce) {
-#ifdef HAVE_GLIB_H
- gpointer orig_key;
- if (!g_hash_table_lookup_extended(sc->files, hash_key, &orig_key, NULL))
- return;
- g_hash_table_remove(sc->files, hash_key);
- stat_cache_entry_free(sce);
- buffer_free((buffer*) orig_key);
-#else
- stat_cache_entry_free(sce);
-#endif
-}
-
-/***
- *
- *
- *
- * returns:
- * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
- * - HANDLER_ERROR on stat() failed -> see errno for problem
- *
- *
- * glib: if glib is not available, we don't cache
- */
-
-static handler_t stat_cache_get_entry_internal(server *srv, connection *con, buffer *name, stat_cache_entry **ret_sce, int async) {
- stat_cache_entry *sce = NULL;
- stat_cache *sc;
- struct stat st;
- size_t k;
- int fd;
- struct stat lst;
-
- *ret_sce = NULL;
-
- /*
- * check if the directory for this file has changed
- */
-
- sc = srv->stat_cache;
-
- buffer_copy_string_buffer(sc->hash_key, name);
- buffer_append_long(sc->hash_key, con->conf.follow_symlink);
-
-#ifdef HAVE_GLIB_H
- if ((sce = (stat_cache_entry *)g_hash_table_lookup(sc->files, sc->hash_key))) {
- /* know this entry already */
-
- if (sce->state == STAT_CACHE_ENTRY_STAT_FINISHED &&
- stat_cache_entry_is_current(srv, sce)) {
- /* verify that this entry is still fresh */
-
- *ret_sce = sce;
-
- return HANDLER_GO_ON;
- }
- }
-
- if (!sce) {
- sce = stat_cache_entry_init();
-
- buffer_copy_string_buffer(sce->name, name);
-
- g_hash_table_insert(sc->files, buffer_init_string(BUF_STR(sc->hash_key)), sce);
- }
-#else
- /**
- * we don't have glib, but we still have to store the sce somewhere to not loose it
- */
- sce = stat_cache_entry_init();
-
- buffer_copy_string_buffer(sce->name, name);
-#endif
-
- /*
- * *lol*
- * - open() + fstat() on a named-pipe results in a (intended) hang.
- * - stat() if regular file + open() to see if we can read from it is better
- *
- * */
-
- /* pass a job to the stat-queue */
-#ifdef USE_GTHREAD
- if (async &&
- srv->srvconf.max_stat_threads > 0 &&
- sce->state == STAT_CACHE_ENTRY_UNSET) {
- stat_job *sj = stat_job_init();
-
- buffer_copy_string_buffer(sj->name, name);
- sj->con = con;
-
- g_async_queue_push(srv->stat_queue, sj);
-
- sce->state = STAT_CACHE_ENTRY_ASYNC_STAT;
-
- /* the response for this will be in the stat-cache,
- * a second call will just fetch the data from the stat-cache */
-
- return HANDLER_WAIT_FOR_EVENT;
- }
-#endif
- /*
- * O_NONBLOCK skips named pipes and locked files
- *
- * O_NOATIME leads to EPERM on SYMLINKS
- * */
-#ifndef O_NONBLOCK
-#define O_NONBLOCK 0
-#endif
- if (-1 == (fd = open(name->ptr, O_NONBLOCK | O_RDONLY | (srv->srvconf.use_noatime ? O_NOATIME : 0)))) {
- if (srv->srvconf.use_noatime && errno == EPERM) {
- if (-1 == (fd = open(name->ptr, O_NONBLOCK | O_RDONLY))) {
- stat_cache_remove_entry(sc, sc->hash_key, sce);
- return HANDLER_ERROR;
- }
- } else {
- stat_cache_remove_entry(sc, sc->hash_key, sce);
- return HANDLER_ERROR;
- }
- }
-
- if (-1 == fstat(fd, &st)) {
- close(fd);
- stat_cache_remove_entry(sc, sc->hash_key, sce);
- return HANDLER_ERROR;
- }
-
- close(fd);
-
- sce->st = st;
- sce->stat_ts = srv->cur_ts;
- sce->state = STAT_CACHE_ENTRY_STAT_FINISHED;
-
- /* catch the obvious symlinks
- *
- * this is not a secure check as we still have a race-condition between
- * the stat() and the open. We can only solve this by
- * 1. open() the file
- * 2. fstat() the fd
- *
- * and keeping the file open for the rest of the time. But this can
- * only be done at network level.
- *
- * per default it is not a symlink
- * */
-
-#ifdef HAVE_LSTAT
- sce->is_symlink = 0;
-
- /* we want to only check for symlinks if we should block symlinks.
- */
- if (!con->conf.follow_symlink) {
- if (stat_cache_lstat(srv, name, &lst) == 0) {
-#ifdef DEBUG_STAT_CACHE
- TRACE("found symlink in %s", SAFE_BUF_STR(name));
-#endif
- sce->is_symlink = 1;
- }
-
- /*
- * we assume "/" can not be symlink, so
- * skip the symlink stuff if our path is /
- **/
- else if ((name->used > 2)) {
- buffer *dname;
- char *s_cur;
-
- dname = buffer_init();
- buffer_copy_string_buffer(dname, name);
-
- while ((s_cur = strrchr(dname->ptr,'/'))) {
- *s_cur = '\0';
- dname->used = s_cur - dname->ptr + 1;
- if (dname->ptr == s_cur) {
-#ifdef DEBUG_STAT_CACHE
- log_error_write(srv, __FILE__, __LINE__, "s", "reached /");
-#endif
- break;
- }
-#ifdef DEBUG_STAT_CACHE
- log_error_write(srv, __FILE__, __LINE__, "sbs",
- "checking if", dname, "is a symlink");
-#endif
- if (stat_cache_lstat(srv, dname, &lst) == 0) {
- sce->is_symlink = 1;
-#ifdef DEBUG_STAT_CACHE
- log_error_write(srv, __FILE__, __LINE__, "sb",
- "found symlink", dname);
-#endif
- break;
- }
- }
- buffer_free(dname);
- }
- }
-#endif
-
- if (S_ISREG(st.st_mode)) {
- /* determine mimetype */
- buffer_reset(sce->content_type);
-#ifdef HAVE_XATTR
- if (con->conf.use_xattr) {
- stat_cache_attr_get(sce->content_type, name->ptr);
- }
-#endif
- /* xattr did not set a content-type. ask the config */
- if (buffer_is_empty(sce->content_type)) {
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
- buffer *type = ds->key;
-
- if (type->used == 0) continue;
-
- /* check if the right side is the same */
- if (type->used > name->used) continue;
-
- if (0 == strncasecmp(name->ptr + name->used - type->used, type->ptr, type->used - 1)) {
- buffer_copy_string_buffer(sce->content_type, ds->value);
- break;
- }
- }
- }
- etag_create(sce->etag, &(sce->st), con->etag_flags);
- } else if (S_ISDIR(st.st_mode)) {
- etag_create(sce->etag, &(sce->st), con->etag_flags);
- }
-
- *ret_sce = sce;
-
- return HANDLER_GO_ON;
-}
-
-
-handler_t stat_cache_get_entry_async(server *srv, connection *con, buffer *name, stat_cache_entry **ret_sce) {
- return stat_cache_get_entry_internal(srv, con, name, ret_sce, 1);
-}
-
-handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **ret_sce) {
- return stat_cache_get_entry_internal(srv, con, name, ret_sce, 0);
-}
-
-/**
- * remove stat() from cache which havn't been stat()ed for
- * more than 10 seconds
- *
- *
- * walk though the stat-cache, collect the ids which are too old
- * and remove them in a second loop
- */
-
-#ifdef HAVE_GLIB_H
-static gboolean stat_cache_remove_old_entry(gpointer _key, gpointer _value, gpointer user_data) {
- server *srv = user_data;
- buffer *key = _key;
- stat_cache_entry *sce = _value;
-
- if (sce->state == STAT_CACHE_ENTRY_STAT_FINISHED &&
- srv->cur_ts - sce->stat_ts > 10) {
- buffer_free(key);
- stat_cache_entry_free(sce);
-
- return TRUE;
- }
-
- return FALSE;
-}
-#endif
-
-int stat_cache_trigger_cleanup(server *srv) {
- stat_cache *sc;
-
- sc = srv->stat_cache;
-
-#ifdef HAVE_GLIB_H
- if (!sc->files) return 0;
-
- g_hash_table_foreach_remove(sc->files, stat_cache_remove_old_entry, srv);
-#endif
-
- return 0;
-}
diff --git a/src/stat_cache.h b/src/stat_cache.h
deleted file mode 100644
index 3790edcf..00000000
--- a/src/stat_cache.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _FILE_CACHE_H_
-#define _FILE_CACHE_H_
-
-#include "base.h"
-
-LI_EXPORT stat_cache * stat_cache_init(void);
-LI_EXPORT void stat_cache_free(stat_cache *fc);
-
-LI_EXPORT handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **fce);
-LI_EXPORT handler_t stat_cache_get_entry_async(server *srv, connection *con, buffer *name, stat_cache_entry **fce);
-LI_EXPORT handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent);
-
-LI_EXPORT int stat_cache_trigger_cleanup(server *srv);
-#endif
diff --git a/src/status_counter.c b/src/status_counter.c
deleted file mode 100644
index 6a3233f4..00000000
--- a/src/status_counter.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <stdlib.h>
-
-#include "status_counter.h"
-/**
- * The status array can carry all the status information you want
- * the key to the array is <module-prefix>.<name>
- * and the values are counters
- *
- * example:
- * fastcgi.backends = 10
- * fastcgi.active-backends = 6
- * fastcgi.backend.<key>.load = 24
- * fastcgi.backend.<key>....
- *
- * fastcgi.backend.<key>.disconnects = ...
- */
-
-static array *counters = NULL;
-
-void status_counter_init(void) {
- counters = array_init();
-}
-void status_counter_free(void) {
- array_free(counters);
-}
-
-array *status_counter_get_array(void) {
- return counters;
-}
-
-data_integer *status_counter_get_counter(const char *s, size_t len) {
- data_integer *di;
- array *status = status_counter_get_array();
-
- if (NULL == (di = (data_integer *)array_get_element(status, s, len))) {
- /* not found, create it */
-
- if (NULL == (di = (data_integer *)array_get_unused_element(status, TYPE_INTEGER))) {
- di = data_integer_init();
- }
- buffer_copy_string_len(di->key, s, len);
- di->value = 0;
-
- array_insert_unique(status, (data_unset *)di);
- }
- return di;
-}
-
-/* dummies of the statistic framework functions
- * they will be moved to a statistics.c later */
-int status_counter_inc(const char *s, size_t len) {
- data_integer *di = status_counter_get_counter(s, len);
-
- di->value++;
-
- return 0;
-}
-
-int status_counter_dec(const char *s, size_t len) {
- data_integer *di = status_counter_get_counter(s, len);
-
- if (di->value > 0) di->value--;
-
- return 0;
-}
-
-int status_counter_set(const char *s, size_t len, int val) {
- data_integer *di = status_counter_get_counter(s, len);
-
- di->value = val;
-
- return 0;
-}
-
-
diff --git a/src/status_counter.h b/src/status_counter.h
deleted file mode 100644
index 34d39a76..00000000
--- a/src/status_counter.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _STATUS_COUNTER_H_
-#define _STATUS_COUNTER_H_
-
-#include <sys/types.h>
-
-#include "array.h"
-
-LI_EXPORT void status_counter_init(void);
-LI_EXPORT void status_counter_free(void);
-LI_EXPORT array * status_counter_get_array(void);
-LI_EXPORT data_integer * status_counter_get_counter(const char *s, size_t len);
-LI_EXPORT int status_counter_inc(const char *s, size_t len);
-LI_EXPORT int status_counter_dec(const char *s, size_t len);
-LI_EXPORT int status_counter_set(const char *s, size_t len, int val);
-
-#define COUNTER_INC(di) if (di) di->value++;
-#define COUNTER_DEC(di) if (di && di->value > 0) di->value--;
-#define COUNTER_SET(di, val) if (di) di->value = val;
-
-#endif
diff --git a/src/stream.c b/src/stream.c
deleted file mode 100644
index e4b52875..00000000
--- a/src/stream.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <fcntl.h>
-
-#include "stream.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "sys-mmap.h"
-#include "sys-files.h"
-
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-int stream_open(stream *f, buffer *fn) {
- struct stat st;
-#ifdef HAVE_MMAP
- int fd;
-#elif defined _WIN32
- HANDLE *fh, *mh;
- void *p;
-#endif
-
- f->start = NULL;
-
- if (-1 == stat(fn->ptr, &st)) {
- return -1;
- }
-
- f->size = st.st_size;
-
-#ifdef HAVE_MMAP
- if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
- return -1;
- }
-
- f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
-
- close(fd);
-
- if (MAP_FAILED == f->start) {
- return -1;
- }
-
-#elif defined _WIN32
- fh = CreateFile(fn->ptr,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_READONLY,
- NULL);
-
- if (fh == INVALID_HANDLE_VALUE) return -1;
-
- mh = CreateFileMapping( fh,
- NULL,
- PAGE_READONLY,
- (sizeof(off_t) > 4) ? f->size >> 32 : 0,
- f->size & 0xffffffff,
- NULL);
-
- if (!mh) {
-/*
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL );
-*/
- return -1;
- }
-
- p = MapViewOfFile(mh,
- FILE_MAP_READ,
- 0,
- 0,
- 0);
- CloseHandle(mh);
- CloseHandle(fh);
-
- f->start = p;
-#else
-# error no mmap found
-#endif
-
- return 0;
-}
-
-int stream_close(stream *f) {
-#ifdef HAVE_MMAP
- if (f->start) munmap(f->start, f->size);
-#elif defined(__WIN32)
- if (f->start) UnmapViewOfFile(f->start);
-#endif
-
- f->start = NULL;
-
- return 0;
-}
diff --git a/src/stream.h b/src/stream.h
deleted file mode 100644
index 0a974c05..00000000
--- a/src/stream.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _STREAM_H_
-#define _STREAM_H_
-
-#include "buffer.h"
-
-typedef struct {
- char *start;
- off_t size;
-} stream;
-
-LI_EXPORT int stream_open(stream *f, buffer *fn);
-LI_EXPORT int stream_close(stream *f);
-
-#endif
diff --git a/src/sys-files.c b/src/sys-files.c
deleted file mode 100644
index 2a9079a3..00000000
--- a/src/sys-files.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "sys-files.h"
-
-#ifdef _WIN32
-#include "buffer.h"
-DIR *opendir(const char *dn) {
- DIR *d = malloc(sizeof(*d));
-
- if (INVALID_HANDLE_VALUE == (d->h = FindFirstFile(dn, &(d->finddata)))) {
- free(d);
- return NULL;
- }
-
- return d;
-}
-
-struct dirent *readdir(DIR *d) {
- if (!d->dent.d_name) {
- /* opendir has set a finddata already, push it out */
-
- d->dent.d_name = d->finddata.cFileName;
- return &(d->dent);
- }
- if (FindNextFile(d->h, &(d->finddata))) {
- d->dent.d_name = d->finddata.cFileName;
- return &(d->dent);
- } else {
- return NULL;
- }
-}
-
-void closedir(DIR *d) {
- FindClose(d);
-
- free(d);
-}
-
-buffer *pathname_unix2local(buffer *fn) {
- size_t i;
-
- for (i = 0; i < fn->used; i++) {
- if (fn->ptr[i] == '/') {
- fn->ptr[i] = '\\';
- }
- }
-
- return fn;
-}
-
-buffer *filename_unix2local(buffer *fn) {
- size_t i;
-
- for (i = 0; i < fn->used; i++) {
- if (fn->ptr[i] == '/') {
- fn->ptr[i] = '\\';
- }
- }
-#if 0
- buffer_prepare_append(fn, 4);
- memmove(fn->ptr + 4, fn->ptr, fn->used);
- memcpy(fn->ptr, "\\\\?\\", 4);
- fn->used += 4;
-#endif
- return fn;
-}
-#endif
-
diff --git a/src/sys-files.h b/src/sys-files.h
deleted file mode 100644
index b964f990..00000000
--- a/src/sys-files.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef _SYS_FILES_H_
-#define _SYS_FILES_H_
-
-#define DIR_SEPERATOR_UNIX '/'
-#define DIR_SEPERATOR_UNIX_STR "/"
-#define DIR_SEPERATOR_WIN '\\'
-#define DIR_SEPERATOR_WIN_STR "\\"
-
-#include "settings.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#include <io.h> /* open */
-#include <direct.h> /* chdir */
-
-#include "buffer.h"
-
-#define DIR_SEPERATOR DIR_SEPERATOR_WIN
-#define DIR_SEPERATOR_STR DIR_SEPERATOR_WIN_STR
-
-#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
-
-#undef S_ISDIR
-#undef S_ISCHR
-#undef S_ISBLK
-#undef S_ISREG
-#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
-#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR)
-#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK)
-#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
-/* we don't support symlinks */
-#define S_ISLNK(mode) 0
-
-#define lstat stat
-#define mkstemp(x) open(mktemp(x), O_RDWR)
-#define mkdir(x, y) mkdir(x)
-
-/* retrieve the most recent network, or general libc error */
-#define light_sock_errno() (WSAGetLastError())
-
-struct dirent {
- const char *d_name;
-};
-
-typedef struct {
- HANDLE h;
- WIN32_FIND_DATA finddata;
- struct dirent dent;
-} DIR;
-
-LI_EXPORT DIR * opendir(const char *dn);
-LI_EXPORT struct dirent * readdir(DIR *d);
-LI_EXPORT void closedir(DIR *d);
-
-LI_EXPORT buffer * filename_unix2local(buffer *b);
-LI_EXPORT buffer * pathname_unix2local(buffer *b);
-
-#else
-#include <unistd.h>
-#include <dirent.h>
-
-#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
-#define DIR_SEPERATOR_STR DIR_SEPERATOR_UNIX_STR
-
-#define light_sock_errno() (errno)
-
-#define filename_unix2local(x) /* (x) */
-#define pathname_unix2local(x) /* (x) */
-#endif
-
-#define PATHNAME_APPEND_SLASH(x) \
- if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
- char sl[2] = { DIR_SEPERATOR, 0 }; \
- BUFFER_APPEND_STRING_CONST(x, sl); \
- }
-
-#ifndef O_LARGEFILE
-# define O_LARGEFILE 0
-#endif
-
-#ifndef O_NOATIME
-# define O_NOATIME 0
-#endif
-
-#endif
-
-
diff --git a/src/sys-mmap.h b/src/sys-mmap.h
deleted file mode 100644
index 560987b3..00000000
--- a/src/sys-mmap.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef WIN32_MMAP_H
-#define WIN32_MMAP_H
-
-#include "settings.h"
-
-#ifdef _WIN32
-
-#define MAP_FAILED -1
-#define PROT_SHARED 0
-#define MAP_SHARED 0
-#define PROT_READ 0
-
-#define mmap(a, b, c, d, e, f) (-1)
-#define munmap(a, b) (-1)
-
-#include <windows.h>
-
-#else
-#include <sys/mman.h>
-
-#ifndef MAP_FAILED
-#define MAP_FAILED -1
-#endif
-#endif
-
-#endif
diff --git a/src/sys-process.h b/src/sys-process.h
deleted file mode 100644
index 53df76e7..00000000
--- a/src/sys-process.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _SYS_PROCESS_H_
-#define _SYS_PROCESS_H_
-
-#ifdef _WIN32
-#include <process.h>
-#define pid_t int
-/* win32 has no fork() */
-#define kill(x, y) do { } while (0)
-#define getpid() 0
-
-#else
-#include <sys/wait.h>
-#include <unistd.h>
-#endif
-
-#endif
-
diff --git a/src/sys-socket.c b/src/sys-socket.c
deleted file mode 100644
index 97664115..00000000
--- a/src/sys-socket.c
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "base.h"
-#include "sys-socket.h"
-
-#ifndef HAVE_INET_ATON
-/* win32 has inet_addr instead if inet_aton */
-# ifdef HAVE_INET_ADDR
-int inet_aton(const char *cp, struct in_addr *inp) {
- struct in_addr a;
-
- a.s_addr = inet_addr(cp);
-
- if (INADDR_NONE == a.s_addr) {
- return 0;
- }
-
- inp->s_addr = a.s_addr;
-
- return 1;
-}
-# else
-# error no inet_aton emulation found
-# endif
-
-#endif
-
-#ifdef _WIN32
-
-#include <winsock2.h>
-
-/* windows doesn't have inet_ntop */
-
-/*
-I have to look into this more. WSAAddressToString takes a sockaddr structure, which includes
-the port number, so I must first test this stuff more carefully. For now, no IPV6 on windows.
-You will notice that HAVE_IPV6 is never true for win32.
-*/
-
-const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
-{
- /* WSAAddressToString takes a full sockaddr, while inet_ntop only takes the address */
- struct sockaddr_in sock4;
- struct sockaddr_in6 sock6;
- DWORD addrLen = cnt;
- int err = 0;
-
- /* src is either an in_addr or an in6_addr. */
- const struct in_addr *src4 = (const struct in_addr*) src;
- const struct in6_addr *src6 = (const struct in6_addr*) src;
-
- int ipv6 = af == AF_INET6;
-
- // DebugBreak();
-
- if ( ipv6 )
- {
- sock6.sin6_family = AF_INET6;
- sock6.sin6_port = 0;
- sock6.sin6_addr = *src6;
- }
- else
- {
- sock4.sin_family = AF_INET;
- sock4.sin_port = 0;
- sock4.sin_addr = *src4;
- }
-
- err = WSAAddressToStringA(
- ipv6 ? (LPSOCKADDR) &sock6 : (LPSOCKADDR) &sock4,
- ipv6 ? sizeof(sock6) : sizeof(sock4),
- NULL,
- dst, &addrLen );
- return err == 0 ? dst : NULL;
-}
-
-
-#endif
diff --git a/src/sys-socket.h b/src/sys-socket.h
deleted file mode 100644
index cf93efd2..00000000
--- a/src/sys-socket.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef SYS_SOCKET_H
-#define SYS_SOCKET_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef _WIN32
-#ifndef FD_SETSIZE
-/* By default this is 64 */
-#define FD_SETSIZE 4096
-#endif
-#include <winsock2.h>
-#include <ws2tcpip.h>
-//#include <wspiapi.h>
-//#define HAVE_IPV6 -- not until we've resolved the inet_ntop issue.
-
-#define ECONNRESET WSAECONNRESET
-#define EINPROGRESS WSAEINPROGRESS
-#define EALREADY WSAEALREADY
-#define ENOTCONN WSAENOTCONN
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define ECONNABORTED WSAECONNABORTED
-#define ECONNREFUSED WSAECONNREFUSED
-#define EHOSTUNREACH WSAEHOSTUNREACH
-#define ioctl ioctlsocket
-#define hstrerror(x) ""
-#define STDIN_FILENO 0
-#define STDOUT_FILENO 1
-#define STDERR_FILENO 2
-#ifndef __MINGW32__
-#define ssize_t int
-#endif
-
-#define sockread( fd, buf, bytes ) recv( fd, buf, bytes, 0 )
-
-LI_EXPORT const char * inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
-int inet_aton(const char *cp, struct in_addr *inp);
-#define HAVE_INET_ADDR
-#undef HAVE_INET_ATON
-
-#else
-#include <sys/types.h> /* required by netinet/tcp.h on FreeBSD */
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/un.h>
-#include <arpa/inet.h>
-
-#ifndef SUN_LEN
-#define SUN_LEN(su) \
- (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
-#endif
-
-#define sockread( fd, buf, bytes ) read( fd, buf, bytes )
-#define closesocket(x) close(x)
-
-#include <netdb.h>
-#endif /* !_WIN32 */
-
-typedef union {
-#ifdef HAVE_IPV6
- struct sockaddr_in6 ipv6;
-#endif
- struct sockaddr_in ipv4;
-#ifdef HAVE_SYS_UN_H
- struct sockaddr_un un;
-#endif
- struct sockaddr plain;
-} sock_addr;
-
-#endif
diff --git a/src/sys-strings.h b/src/sys-strings.h
deleted file mode 100644
index 1103a8c1..00000000
--- a/src/sys-strings.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef _SYS_STRINGS_H_
-#define _SYS_STRINGS_H_
-
-#ifdef _WIN32
-#define strcasecmp stricmp
-#define strncasecmp strnicmp
-#include <stdlib.h>
-#define str_to_off_t(p, e, b) _strtoi64(p, e, b)
-#define STR_OFF_T_MAX LLONG_MAX
-#define STR_OFF_T_MIN LLONG_MIN
-#define strtoull _strtoui64
-#ifdef __MINGW32__
-/* missing prototype */
-unsigned __int64 _strtoui64(
- const char *nptr,
- char **endptr,
- int base
- );
-__int64 _strtoi64(
- const char *nptr,
- char **endptr,
- int base
- );
-#endif
-#else /** we are a unix */
-
-/**
- * we use strtoll() for parsing the ranges into a off_t
- *
- * if off_t is 32bit, we can use strtol() instead
- */
- #if SIZEOF_OFF_T == SIZEOF_LONG
- #define str_to_off_t(p, e, b) strtol(p, e, b)
- #define STR_OFF_T_MAX LONG_MAX
- #define STR_OFF_T_MIN LONG_MIN
- #elif defined(HAVE_STRTOLL)
- #define str_to_off_t(p, e, b) strtoll(p, e, b)
- #define STR_OFF_T_MAX LLONG_MAX
- #define STR_OFF_T_MIN LLONG_MIN
- #else
- #error off_t is more than 4 bytes but we can not parse it with strtol() (run autogen.sh again if you build from svn)
- #endif
-#endif
-
-#endif
-
diff --git a/src/timing.c b/src/timing.c
deleted file mode 100644
index 94c9441b..00000000
--- a/src/timing.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "base.h"
-#include "timing.h"
-
-void timing_log(server *srv, connection *con, int field) {
-#ifdef HAVE_GLIB_H
- if (srv->srvconf.log_timing) {
- g_get_current_time(&(con->timestamps[field]));
- }
-#endif
-}
-
diff --git a/src/timing.h b/src/timing.h
deleted file mode 100644
index 7fbb2ae5..00000000
--- a/src/timing.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _TIMING_H_
-#define _TIMING_H_
-
-#include "base.h"
-
-#define TIME_DIFF(t2, t1) \
- ((con->timestamps[t2].tv_sec - con->timestamps[t1].tv_sec) * 1000 + \
- (con->timestamps[t2].tv_usec - con->timestamps[t1].tv_usec) / 1000)
-
-LI_API void timing_log(server *srv, connection *con, int field);
-
-#endif
diff --git a/src/valgrind/Makefile.am b/src/valgrind/Makefile.am
deleted file mode 100644
index f3071778..00000000
--- a/src/valgrind/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = valgrind.h
diff --git a/src/valgrind/valgrind.h b/src/valgrind/valgrind.h
deleted file mode 100644
index a7120859..00000000
--- a/src/valgrind/valgrind.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/* -*- c -*-
- ----------------------------------------------------------------
-
- Notice that the following BSD-style license applies to this one
- file (valgrind.h) only. The entire rest of Valgrind is licensed
- under the terms of the GNU General Public License, version 2. See
- the COPYING file in the source distribution for details.
-
- ----------------------------------------------------------------
-
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Julian Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- ----------------------------------------------------------------
-
- Notice that the above BSD-style license applies to this one file
- (valgrind.h) only. The entire rest of Valgrind is licensed under
- the terms of the GNU General Public License, version 2. See the
- COPYING file in the source distribution for details.
-
- ----------------------------------------------------------------
-*/
-
-
-/* This file is for inclusion into client (your!) code.
-
- You can use these macros to manipulate and query Valgrind's
- execution inside your own programs.
-
- The resulting executables will still run without Valgrind, just a
- little bit more slowly than they otherwise would, but otherwise
- unchanged. When not running on valgrind, each client request
- consumes very few (eg. < 10) instructions, so the resulting performance
- loss is negligible unless you plan to execute client requests
- millions of times per second. Nevertheless, if that is still a
- problem, you can compile with the NVALGRIND symbol defined (gcc
- -DNVALGRIND) so that client requests are not even compiled in. */
-
-#ifndef __VALGRIND_H
-#define __VALGRIND_H
-
-#include <stdarg.h>
-
-/* Nb: this file might be included in a file compiled with -ansi. So
- we can't use C++ style "//" comments nor the "asm" keyword (instead
- use "__asm__"). */
-
-/* If we're not compiling for our target architecture, don't generate
- any inline asms. Note that in this file we're using the compiler's
- CPP symbols for identifying architectures, which are different to
- the ones we use within the rest of Valgrind. */
-#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__)
-# ifndef NVALGRIND
-# define NVALGRIND 1
-# endif /* NVALGRIND */
-#endif
-
-/* ------------------------------------------------------------------ */
-/* The architecture-specific part */
-/* ------------------------------------------------------------------ */
-
-#ifdef NVALGRIND
-
-/* Define NVALGRIND to completely remove the Valgrind magic sequence
- from the compiled code (analogous to NDEBUG's effects on assert()) */
-#define VALGRIND_MAGIC_SEQUENCE( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4) \
- { \
- (_zzq_rlval) = (_zzq_default); \
- }
-
-#else /* NVALGRIND */
-
-/* The following defines the magic code sequences which the JITter spots and
- handles magically. Don't look too closely at them; they will rot
- your brain. We must ensure that the default value gets put in the return
- slot, so that everything works when this is executed not under Valgrind.
- Args are passed in a memory block, and so there's no intrinsic limit to
- the number that could be passed, but it's currently four.
-
- The macro args are:
- _zzq_rlval result lvalue
- _zzq_default default value (result returned when running on real CPU)
- _zzq_request request code
- _zzq_arg1..4 request params
-
- Nb: we put the assembly code sequences for all architectures in this one
- file. This is because this file must be stand-alone, and we don't want
- to have multiple files.
-*/
-
-#ifdef __x86_64__
-#define VALGRIND_MAGIC_SEQUENCE( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4) \
- \
- { volatile unsigned long long _zzq_args[5]; \
- _zzq_args[0] = (volatile unsigned long long)(_zzq_request); \
- _zzq_args[1] = (volatile unsigned long long)(_zzq_arg1); \
- _zzq_args[2] = (volatile unsigned long long)(_zzq_arg2); \
- _zzq_args[3] = (volatile unsigned long long)(_zzq_arg3); \
- _zzq_args[4] = (volatile unsigned long long)(_zzq_arg4); \
- __asm__ volatile("roll $29, %%eax ; roll $3, %%eax\n\t" \
- "rorl $27, %%eax ; rorl $5, %%eax\n\t" \
- "roll $13, %%eax ; roll $19, %%eax" \
- : "=d" (_zzq_rlval) \
- : "a" (&_zzq_args[0]), "0" (_zzq_default) \
- : "cc", "memory" \
- ); \
- }
-#endif /* __x86_64__ */
-
-#ifdef __i386__
-#define VALGRIND_MAGIC_SEQUENCE( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4) \
- \
- { unsigned int _zzq_args[5]; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- __asm__ volatile("roll $29, %%eax ; roll $3, %%eax\n\t" \
- "rorl $27, %%eax ; rorl $5, %%eax\n\t" \
- "roll $13, %%eax ; roll $19, %%eax" \
- : "=d" (_zzq_rlval) \
- : "a" (&_zzq_args[0]), "0" (_zzq_default) \
- : "cc", "memory" \
- ); \
- }
-#endif /* __i386__ */
-
-#ifdef __powerpc__
-#define VALGRIND_MAGIC_SEQUENCE( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4) \
- \
- { volatile unsigned int _zzq_args[5]; \
- register unsigned int _zzq_tmp __asm__("r3"); \
- register volatile unsigned int *_zzq_ptr __asm__("r4"); \
- _zzq_args[0] = (volatile unsigned int)(_zzq_request); \
- _zzq_args[1] = (volatile unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (volatile unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (volatile unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (volatile unsigned int)(_zzq_arg4); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("tw 0,3,27\n\t" \
- "rlwinm 0,0,29,0,0\n\t" \
- "rlwinm 0,0,3,0,0\n\t" \
- "rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,19,0,0\n\t" \
- "nop\n\t" \
- : "=r" (_zzq_tmp) \
- : "0" (_zzq_default), "r" (_zzq_ptr) \
- : "memory"); \
- _zzq_rlval = (__typeof__(_zzq_rlval)) _zzq_tmp; \
- }
-#endif /* __powerpc__ */
-
-/* Insert assembly code for other architectures here... */
-
-#endif /* NVALGRIND */
-
-
-/* ------------------------------------------------------------------ */
-/* The architecture-independent part */
-/* ------------------------------------------------------------------ */
-
-/* Some request codes. There are many more of these, but most are not
- exposed to end-user view. These are the public ones, all of the
- form 0x1000 + small_number.
-
- Core ones are in the range 0x00000000--0x0000ffff. The non-public ones
- start at 0x2000.
-*/
-
-/* These macros are used by tools -- they must be public, but don't embed them
- * into other programs. */
-#define VG_USERREQ_TOOL_BASE(a,b) \
- ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
-#define VG_IS_TOOL_USERREQ(a, b, v) \
- (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
-
-typedef
- enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
- VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
-
- /* These allow any function to be called from the
- simulated CPU but run on the real CPU.
- Nb: the first arg passed to the function is always the ThreadId of
- the running thread! So CLIENT_CALL0 actually requires a 1 arg
- function, etc. */
- VG_USERREQ__CLIENT_CALL0 = 0x1101,
- VG_USERREQ__CLIENT_CALL1 = 0x1102,
- VG_USERREQ__CLIENT_CALL2 = 0x1103,
- VG_USERREQ__CLIENT_CALL3 = 0x1104,
-
- /* Can be useful in regression testing suites -- eg. can send
- Valgrind's output to /dev/null and still count errors. */
- VG_USERREQ__COUNT_ERRORS = 0x1201,
-
- /* These are useful and can be interpreted by any tool that tracks
- malloc() et al, by using vg_replace_malloc.c. */
- VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
- VG_USERREQ__FREELIKE_BLOCK = 0x1302,
- /* Memory pool support. */
- VG_USERREQ__CREATE_MEMPOOL = 0x1303,
- VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
- VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
- VG_USERREQ__MEMPOOL_FREE = 0x1306,
-
- /* Allow printfs to valgrind log. */
- VG_USERREQ__PRINTF = 0x1401,
- VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
-
- /* Stack support. */
- VG_USERREQ__STACK_REGISTER = 0x1501,
- VG_USERREQ__STACK_DEREGISTER = 0x1502,
- VG_USERREQ__STACK_CHANGE = 0x1503,
- } Vg_ClientRequest;
-
-#ifndef __GNUC__
-#define __extension__
-#endif
-
-/* Returns the number of Valgrinds this code is running under. That is,
- 0 if running natively, 1 if running under Valgrind, 2 if running under
- Valgrind which is running under another Valgrind, etc. */
-#define RUNNING_ON_VALGRIND __extension__ \
- ({unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0 /* returned if not */, \
- VG_USERREQ__RUNNING_ON_VALGRIND, \
- 0, 0, 0, 0); \
- _qzz_res; \
- })
-
-
-/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
- _qzz_len - 1]. Useful if you are debugging a JITter or some such,
- since it provides a way to make sure valgrind will retranslate the
- invalidated area. Returns no value. */
-#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__DISCARD_TRANSLATIONS, \
- _qzz_addr, _qzz_len, 0, 0); \
- }
-
-#ifdef NVALGRIND
-
-#define VALGRIND_PRINTF(...)
-#define VALGRIND_PRINTF_BACKTRACE(...)
-
-#else /* NVALGRIND */
-
-int VALGRIND_PRINTF(const char *format, ...)
- __attribute__((format(__printf__, 1, 2)));
-__attribute__((weak))
-int
-VALGRIND_PRINTF(const char *format, ...)
-{
- unsigned long _qzz_res;
- va_list vargs;
- va_start(vargs, format);
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, VG_USERREQ__PRINTF,
- (unsigned long)format, (unsigned long)vargs, 0, 0);
- va_end(vargs);
- return (int)_qzz_res;
-}
-
-int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
- __attribute__((format(__printf__, 1, 2)));
-__attribute__((weak))
-int
-VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
-{
- unsigned long _qzz_res;
- va_list vargs;
- va_start(vargs, format);
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
- (unsigned long)format, (unsigned long)vargs, 0, 0);
- va_end(vargs);
- return (int)_qzz_res;
-}
-
-#endif /* NVALGRIND */
-
-/* These requests allow control to move from the simulated CPU to the
- real CPU, calling an arbitary function */
-#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
- ({unsigned long _qyy_res; \
- VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL0, \
- _qyy_fn, \
- 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
- ({unsigned long _qyy_res; \
- VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL1, \
- _qyy_fn, \
- _qyy_arg1, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
- ({unsigned long _qyy_res; \
- VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL2, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
- ({unsigned long _qyy_res; \
- VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL3, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, _qyy_arg3); \
- _qyy_res; \
- })
-
-
-/* Counts the number of errors that have been recorded by a tool. Nb:
- the tool must record the errors with VG_(maybe_record_error)() or
- VG_(unique_error)() for them to be counted. */
-#define VALGRIND_COUNT_ERRORS \
- ({unsigned int _qyy_res; \
- VALGRIND_MAGIC_SEQUENCE(_qyy_res, 0 /* default return */, \
- VG_USERREQ__COUNT_ERRORS, \
- 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-/* Mark a block of memory as having been allocated by a malloc()-like
- function. `addr' is the start of the usable block (ie. after any
- redzone) `rzB' is redzone size if the allocator can apply redzones;
- use '0' if not. Adding redzones makes it more likely Valgrind will spot
- block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
- for calloc(). Put it immediately after the point where a block is
- allocated.
-
- If you're allocating memory via superblocks, and then handing out small
- chunks of each superblock, if you don't have redzones on your small
- blocks, it's worth marking the superblock with VALGRIND_MAKE_NOACCESS
- when it's created, so that block overruns are detected. But if you can
- put redzones on, it's probably better to not do this, so that messages
- for small overruns are described in terms of the small block rather than
- the superblock (but if you have a big overrun that skips over a redzone,
- you could miss an error this way). See memcheck/tests/custom_alloc.c
- for an example.
-
- Nb: block must be freed via a free()-like function specified
- with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
-#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__MALLOCLIKE_BLOCK, \
- addr, sizeB, rzB, is_zeroed); \
- }
-
-/* Mark a block of memory as having been freed by a free()-like function.
- `rzB' is redzone size; it must match that given to
- VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
- checker. Put it immediately after the point where the block is freed. */
-#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__FREELIKE_BLOCK, \
- addr, rzB, 0, 0); \
- }
-
-/* Create a memory pool. */
-#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__CREATE_MEMPOOL, \
- pool, rzB, is_zeroed, 0); \
- }
-
-/* Destroy a memory pool. */
-#define VALGRIND_DESTROY_MEMPOOL(pool) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__DESTROY_MEMPOOL, \
- pool, 0, 0, 0); \
- }
-
-/* Associate a piece of memory with a memory pool. */
-#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_ALLOC, \
- pool, addr, size, 0); \
- }
-
-/* Disassociate a piece of memory from a memory pool. */
-#define VALGRIND_MEMPOOL_FREE(pool, addr) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_FREE, \
- pool, addr, 0, 0); \
- }
-
-/* Mark a piece of memory as being a stack. Returns a stack id. */
-#define VALGRIND_STACK_REGISTER(start, end) \
- ({unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__STACK_REGISTER, \
- start, end, 0, 0); \
- _qzz_res; \
- })
-
-/* Unmark the piece of memory associated with a stack id as being a
- stack. */
-#define VALGRIND_STACK_DEREGISTER(id) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__STACK_DEREGISTER, \
- id, 0, 0, 0); \
- }
-
-/* Change the start and end address of the stack id. */
-#define VALGRIND_STACK_CHANGE(id, start, end) \
- {unsigned int _qzz_res; \
- VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, \
- VG_USERREQ__STACK_CHANGE, \
- id, start, end, 0); \
- }
-
-#endif /* __VALGRIND_H */
diff --git a/src/xgetopt.c b/src/xgetopt.c
deleted file mode 100644
index 73694ada..00000000
--- a/src/xgetopt.c
+++ /dev/null
@@ -1,222 +0,0 @@
-// XGetopt.cpp Version 1.2
-//
-// Author: Hans Dietrich
-// hdietrich2@hotmail.com
-//
-// Description:
-// XGetopt.cpp implements getopt(), a function to parse command lines.
-//
-// History
-// Version 1.2 - 2003 May 17
-// - Added Unicode support
-//
-// Version 1.1 - 2002 March 10
-// - Added example to XGetopt.cpp module header
-//
-// This software is released into the public domain.
-// You are free to use it in any way you like.
-//
-// This software is provided "as is" with no expressed
-// or implied warranty. I accept no liability for any
-// damage or loss of business that this software may cause.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////////////////////////////
-// if you are using precompiled headers then include this line:
-//#include "stdafx.h"
-///////////////////////////////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////////////////////////////
-// if you are not using precompiled headers then include these lines:
-#include <windows.h>
-#include <stdio.h>
-#include <tchar.h>
-///////////////////////////////////////////////////////////////////////////////
-
-
-#include "XGetopt.h"
-
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// X G e t o p t . c p p
-//
-//
-// NAME
-// getopt -- parse command line options
-//
-// SYNOPSIS
-// int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
-//
-// extern TCHAR *optarg;
-// extern int optind;
-//
-// DESCRIPTION
-// The getopt() function parses the command line arguments. Its
-// arguments argc and argv are the argument count and array as
-// passed into the application on program invocation. In the case
-// of Visual C++ programs, argc and argv are available via the
-// variables __argc and __argv (double underscores), respectively.
-// getopt returns the next option letter in argv that matches a
-// letter in optstring. (Note: Unicode programs should use
-// __targv instead of __argv. Also, all character and string
-// literals should be enclosed in _T( ) ).
-//
-// optstring is a string of recognized option letters; if a letter
-// is followed by a colon, the option is expected to have an argument
-// that may or may not be separated from it by white space. optarg
-// is set to point to the start of the option argument on return from
-// getopt.
-//
-// Option letters may be combined, e.g., "-ab" is equivalent to
-// "-a -b". Option letters are case sensitive.
-//
-// getopt places in the external variable optind the argv index
-// of the next argument to be processed. optind is initialized
-// to 0 before the first call to getopt.
-//
-// When all options have been processed (i.e., up to the first
-// non-option argument), getopt returns EOF, optarg will point
-// to the argument, and optind will be set to the argv index of
-// the argument. If there are no non-option arguments, optarg
-// will be set to NULL.
-//
-// The special option "--" may be used to delimit the end of the
-// options; EOF will be returned, and "--" (and everything after it)
-// will be skipped.
-//
-// RETURN VALUE
-// For option letters contained in the string optstring, getopt
-// will return the option letter. getopt returns a question mark (?)
-// when it encounters an option letter not included in optstring.
-// EOF is returned when processing is finished.
-//
-// BUGS
-// 1) Long options are not supported.
-// 2) The GNU double-colon extension is not supported.
-// 3) The environment variable POSIXLY_CORRECT is not supported.
-// 4) The + syntax is not supported.
-// 5) The automatic permutation of arguments is not supported.
-// 6) This implementation of getopt() returns EOF if an error is
-// encountered, instead of -1 as the latest standard requires.
-//
-// EXAMPLE
-// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[])
-// {
-// int c;
-//
-// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF)
-// {
-// switch (c)
-// {
-// case _T('a'):
-// TRACE(_T("option a\n"));
-// //
-// // set some flag here
-// //
-// break;
-//
-// case _T('B'):
-// TRACE( _T("option B\n"));
-// //
-// // set some other flag here
-// //
-// break;
-//
-// case _T('n'):
-// TRACE(_T("option n: value=%d\n"), atoi(optarg));
-// //
-// // do something with value here
-// //
-// break;
-//
-// case _T('?'):
-// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]);
-// return FALSE;
-// break;
-//
-// default:
-// TRACE(_T("WARNING: no handler for option %c\n"), c);
-// return FALSE;
-// break;
-// }
-// }
-// //
-// // check for non-option args here
-// //
-// return TRUE;
-// }
-//
-///////////////////////////////////////////////////////////////////////////////
-
-TCHAR *optarg; // global argument pointer
-int optind = 0; // global argv index
-
-int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
-{
- static TCHAR *next = NULL;
- TCHAR c;
- TCHAR *cp = NULL;
-
- if (optind == 0)
- next = NULL;
-
- optarg = NULL;
-
- if (next == NULL || *next == _T('\0'))
- {
- if (optind == 0)
- optind++;
-
- if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0'))
- {
- optarg = NULL;
- if (optind < argc)
- optarg = argv[optind];
- return EOF;
- }
-
- if (_tcscmp(argv[optind], _T("--")) == 0)
- {
- optind++;
- optarg = NULL;
- if (optind < argc)
- optarg = argv[optind];
- return EOF;
- }
-
- next = argv[optind];
- next++; // skip past -
- optind++;
- }
-
- c = *next++;
- cp = _tcschr(optstring, c);
-
- if (cp == NULL || c == _T(':'))
- return _T('?');
-
- cp++;
- if (*cp == _T(':'))
- {
- if (*next != _T('\0'))
- {
- optarg = next;
- next = NULL;
- }
- else if (optind < argc)
- {
- optarg = argv[optind];
- optind++;
- }
- else
- {
- return _T('?');
- }
- }
-
- return c;
-}
diff --git a/tests/.cvsignore b/tests/.cvsignore
deleted file mode 100644
index 15fa299a..00000000
--- a/tests/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-Makefile.in
-Makefile
-.deps
-.libs
-fcgi-auth
-fcgi-responder
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
deleted file mode 100644
index 30ac6983..00000000
--- a/tests/CMakeLists.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-SET(T_FILES
- prepare.sh
- cachable.t
- core-condition.t
- core-keepalive.t
- core-request.t
- core-response.t
- core.t
- core-var-include.t
- fastcgi.t
- lowercase.t
- mod-access.t
- mod-auth.t
- mod-cgi.t
- mod-redirect.t
- mod-rewrite.t
- mod-secdownload.t
- mod-setenv.t
- mod-ssi.t
- mod-userdir.t
- request.t
- symlink.t
-)
-
-FOREACH(it ${T_FILES})
- ADD_TEST(${it} "${lighttpd_SOURCE_DIR}/tests/wrapper.sh"
- "${lighttpd_SOURCE_DIR}/tests"
- "${lighttpd_BINARY_DIR}"
- "${lighttpd_SOURCE_DIR}/tests/${it}")
-ENDFOREACH(it)
diff --git a/tests/LightyTest.pm b/tests/LightyTest.pm
deleted file mode 100755
index 3aa0fdc1..00000000
--- a/tests/LightyTest.pm
+++ /dev/null
@@ -1,373 +0,0 @@
-#! /usr/bin/perl -w
-
-package LightyTest;
-use strict;
-use IO::Socket;
-use Test::More;
-use Socket;
-use Cwd 'abs_path';
-use POSIX qw(:sys_wait_h dup2);
-use Errno qw(EADDRINUSE);
-
-sub mtime {
- my $file = shift;
- my @stat = stat $file;
- return @stat ? $stat[9] : 0;
-}
-sub new {
- my $class = shift;
- my $self = {};
- my $lpath;
-
- $self->{CONFIGFILE} = 'lighttpd.conf';
-
- $lpath = (defined $ENV{'top_builddir'} ? $ENV{'top_builddir'} : '..');
- $self->{BASEDIR} = abs_path($lpath);
-
- $lpath = (defined $ENV{'top_builddir'} ? $ENV{'top_builddir'}."/tests/" : '.');
- $self->{TESTDIR} = abs_path($lpath);
-
- $lpath = (defined $ENV{'srcdir'} ? $ENV{'srcdir'} : '.');
- $self->{SRCDIR} = abs_path($lpath);
-
-
- if (mtime($self->{BASEDIR}.'/src/lighttpd') > mtime($self->{BASEDIR}.'/build/lighttpd')) {
- $self->{BINDIR} = $self->{BASEDIR}.'/src';
- if (mtime($self->{BASEDIR}.'/src/.libs')) {
- $self->{MODULES_PATH} = $self->{BASEDIR}.'/src/.libs';
- } else {
- $self->{MODULES_PATH} = $self->{BASEDIR}.'/src';
- }
- } else {
- $self->{BINDIR} = $self->{BASEDIR}.'/build';
- $self->{MODULES_PATH} = $self->{BASEDIR}.'/build';
- }
- $self->{LIGHTTPD_PATH} = $self->{BINDIR}.'/lighttpd';
- $self->{PORT} = 2048;
-
- my ($name, $aliases, $addrtype, $net) = gethostbyaddr(inet_aton("127.0.0.1"), AF_INET);
-
- $self->{HOSTNAME} = $name;
-
- bless($self, $class);
-
- return $self;
-}
-
-sub listening_on {
- my $self = shift;
- my $port = shift;
-
- my $remote =
- IO::Socket::INET->new(Proto => "tcp",
- PeerAddr => "127.0.0.1",
- PeerPort => $port) or return 0;
-
- close $remote;
-
- return 1;
-}
-
-sub stop_proc {
- my $self = shift;
-
- my $pid = $self->{LIGHTTPD_PID};
- if (defined $pid && $pid != -1) {
- kill('TERM', $pid) or return -1;
- return -1 if ($pid != waitpid($pid, 0));
- } else {
- diag("Process not started, nothing to stop");
- return -1;
- }
-
- return 0;
-}
-
-sub wait_for_port_with_proc {
- my $self = shift;
- my $port = shift;
- my $child = shift;
-
- while (0 == $self->listening_on($port)) {
- select(undef, undef, undef, 0.1);
-
- # the process is gone, we failed
- if (0 != waitpid($child, WNOHANG)) {
- return -1;
- }
- }
-
- return 0;
-}
-
-sub start_proc {
- my $self = shift;
- # kill old proc if necessary
- #$self->stop_proc;
-
- # pre-process configfile if necessary
- #
-
- $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
- $ENV{'PORT'} = $self->{PORT};
-
- my $cmdline = $self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH};
- if (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'strace') {
- $cmdline = "strace -tt -s 512 -o strace ".$cmdline;
- } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'truss') {
- $cmdline = "truss -a -l -w all -v all -o strace ".$cmdline;
- } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'gdb') {
- $cmdline = "gdb --batch -ex 'run' -ex 'bt full' --args ".$cmdline." > gdb.out";
- } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'valgrind') {
- $cmdline = "valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --log-file=valgrind ".$cmdline;
- }
- # diag("starting lighttpd at :".$self->{PORT}.", cmdline: ".$cmdline );
- my $child = fork();
- if (not defined $child) {
- diag("Fork failed");
- return -1;
- }
- if ($child == 0) {
- exec $cmdline or die($?);
- }
-
- if (0 != $self->wait_for_port_with_proc($self->{PORT}, $child)) {
- diag(sprintf('The process %i is not up', $child));
- return -1;
- }
-
- $self->{LIGHTTPD_PID} = $child;
-
- 0;
-}
-
-sub handle_http {
- my $self = shift;
- my $t = shift;
- my $EOL = "\015\012";
- my $BLANK = $EOL x 2;
- my $host = "127.0.0.1";
-
- my @request = $t->{REQUEST};
- my @response = $t->{RESPONSE};
- my $is_debug = $ENV{"TRACE_HTTP"};
-
- my $remote =
- IO::Socket::INET->new(Proto => "tcp",
- PeerAddr => $host,
- PeerPort => $self->{PORT});
-
- if (not defined $remote) {
- diag("connect failed: $!");
- return -1;
- }
-
- $remote->autoflush(1);
-
- diag("sending request header to ".$host.":".$self->{PORT}) if $is_debug;
- foreach(@request) {
- # pipeline requests
- s/\r//g;
- s/\n/$EOL/g;
-
- print $remote $_.$BLANK;
- diag("<< ".$_) if $is_debug;
- }
- shutdown($remote, 1); # I've stopped writing data
- diag("... done") if $is_debug;
-
- my $lines = "";
-
- diag("receiving response") if $is_debug;
- # read everything
- while(<$remote>) {
- $lines .= $_;
- diag(">> ".$_) if $is_debug;
- }
- diag("... done") if $is_debug;
-
- close $remote;
-
- my $full_response = $lines;
-
- my $href;
- foreach $href ( @{ $t->{RESPONSE} }) {
- # first line is always response header
- my %resp_hdr;
- my $resp_body;
- my $resp_line;
- my $conditions = $_;
-
- for (my $ln = 0; defined $lines; $ln++) {
- (my $line, $lines) = split($EOL, $lines, 2);
-
- # header finished
- last if (not defined($line)) or (length($line) == 0);
-
- if ($ln == 0) {
- # response header
- $resp_line = $line;
- } else {
- # response vars
-
- if ($line =~ /^([^:]+):\s*(.+)$/) {
- (my $h = $1) =~ tr/[A-Z]/[a-z]/;
-
- if (defined $resp_hdr{$h}) {
-# diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
-# $h, $resp_hdr{$h}, $2));
- $resp_hdr{$h} .= ', '.$2;
- } else {
- $resp_hdr{$h} = $2;
- }
- } else {
- diag(sprintf("unexpected line '%s'\n", $line));
- return -1;
- }
- }
- }
-
- if (not defined($resp_line)) {
- diag(sprintf("empty response\n"));
- return -1;
- }
-
- $t->{etag} = $resp_hdr{'etag'};
- $t->{date} = $resp_hdr{'date'};
-
- # check length
- if (defined $resp_hdr{"content-length"}) {
- $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
- if (length($lines) < $resp_hdr{"content-length"}) {
- $lines = "";
- } else {
- $lines = substr($lines, $resp_hdr{"content-length"});
- }
- undef $lines if (length($lines) == 0);
- } else {
- $resp_body = $lines;
- undef $lines;
- }
-
- # check conditions
- if ($resp_line =~ /^(HTTP\/1\.[01]) ([0-9]{3}) .+$/) {
- if ($href->{'HTTP-Protocol'} ne $1) {
- diag(sprintf("proto failed: expected '%s', got '%s'\n", $href->{'HTTP-Protocol'}, $1));
- return -1;
- }
- if ($href->{'HTTP-Status'} ne $2) {
- diag(sprintf("status failed: expected '%s', got '%s'\n", $href->{'HTTP-Status'}, $2));
- return -1;
- }
- } else {
- diag(sprintf("unexpected resp_line '%s'\n", $resp_line));
- return -1;
- }
-
- if (defined $href->{'HTTP-Content'}) {
- $resp_body = "" unless defined $resp_body;
- if ($href->{'HTTP-Content'} ne $resp_body) {
- diag(sprintf("body failed: expected '%s', got '%s'\n", $href->{'HTTP-Content'}, $resp_body));
- return -1;
- }
- }
-
- if (defined $href->{'-HTTP-Content'}) {
- if (defined $resp_body && $resp_body ne '') {
- diag(sprintf("body failed: expected empty body, got '%s'\n", $resp_body));
- return -1;
- }
- }
-
- foreach (keys %{ $href }) {
- next if $_ eq 'HTTP-Protocol';
- next if $_ eq 'HTTP-Status';
- next if $_ eq 'HTTP-Content';
- next if $_ eq '-HTTP-Content';
-
- (my $k = $_) =~ tr/[A-Z]/[a-z]/;
-
- my $verify_value = 1;
- my $key_inverted = 0;
-
- if (substr($k, 0, 1) eq '+') {
- $k = substr($k, 1);
- $verify_value = 0;
- } elsif (substr($k, 0, 1) eq '-') {
- ## the key should NOT exist
- $k = substr($k, 1);
- $key_inverted = 1;
- $verify_value = 0; ## skip the value check
- }
-
- if ($key_inverted) {
- if (defined $resp_hdr{$k}) {
- diag(sprintf("header '%s' MUST not be set\n", $k));
- return -1;
- }
- } else {
- if (not defined $resp_hdr{$k}) {
- diag(sprintf("required header '%s' is missing\n", $k));
- return -1;
- }
- }
-
- if ($verify_value) {
- if ($href->{$_} =~ /^\/(.+)\/$/) {
- if ($resp_hdr{$k} !~ /$1/) {
- diag(sprintf("response-header failed: expected '%s', got '%s', regex: %s\n",
- $href->{$_}, $resp_hdr{$k}, $1));
- return -1;
- }
- } elsif ($href->{$_} ne $resp_hdr{$k}) {
- diag(sprintf("response-header failed: expected '%s', got '%s'\n",
- $href->{$_}, $resp_hdr{$k}));
- return -1;
- }
- }
- }
- }
-
- # we should have sucked up everything
- if (defined $lines) {
- diag(sprintf("unexpected lines '%s'\n", $lines));
- return -1;
- }
-
- return 0;
-}
-
-sub spawnfcgi {
- my ($self, $binary, $port) = @_;
- my $child = fork();
- if (not defined $child) {
- diag("Couldn't fork\n");
- return -1;
- }
- if ($child == 0) {
- my $iaddr = inet_aton('localhost') || die "no host: localhost";
- my $proto = getprotobyname('tcp');
- socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
- setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die "setsockopt: $!";
- bind(SOCK, sockaddr_in($port, $iaddr)) || die "bind: $!";
- listen(SOCK, 1024) || die "listen: $!";
- dup2(fileno(SOCK), 0) || die "dup2: $!";
- exec $binary or die($?);
- } else {
- if (0 != $self->wait_for_port_with_proc($port, $child)) {
- diag(sprintf('The process %i is not up (port %i, %s)', $child, $port, $binary));
- return -1;
- }
- return $child;
- }
-}
-
-sub endspawnfcgi {
- my ($self, $pid) = @_;
- return -1 if (-1 == $pid);
- kill(2, $pid);
- waitpid($pid, 0);
- return 0;
-}
-
-1;
diff --git a/tests/Makefile.am b/tests/Makefile.am
deleted file mode 100644
index 06824313..00000000
--- a/tests/Makefile.am
+++ /dev/null
@@ -1,70 +0,0 @@
-# lighttpd.conf and conformance.pl expect this directory
-testdir=$(srcdir)/tmp/lighttpd/
-
-if CHECK_WITH_FASTCGI
-check_PROGRAMS=fcgi-auth fcgi-responder
-
-fcgi_auth_SOURCES=fcgi-auth.c
-fcgi_auth_LDADD=-lfcgi
-
-fcgi_responder_SOURCES=fcgi-responder.c
-fcgi_responder_LDADD=-lfcgi
-endif
-
-TESTS=\
- prepare.sh \
- run-tests.pl \
- cleanup.sh
-
-CONFS=fastcgi-10.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-compress.conf \
- fastcgi.t \
- mod-redirect.t \
- mod-userdir.t \
- mod-rewrite.t \
- request.t \
- mod-ssi.t \
- LightyTest.pm \
- mod-setenv.t \
- lowercase.t \
- lowercase.conf \
- proxy.conf \
- cachable.t \
- default.conf \
- proxy-backend-1.conf \
- proxy-backend-2.conf
-
-
-TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
-
-EXTRA_DIST=wrapper.sh lighttpd.conf \
- lighttpd.user \
- lighttpd.htpasswd \
- $(CONFS) \
- $(TESTS)
-
-SUBDIRS=docroot
-
-leak-check:
- for i in $(TESTS); do \
- $(srcdir)/$$i; \
- echo $$?; \
- done
-
-clean-local:
- rm -f *.out
diff --git a/tests/bug-06.conf b/tests/bug-06.conf
deleted file mode 100644
index 93a298eb..00000000
--- a/tests/bug-06.conf
+++ /dev/null
@@ -1,152 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-# server.license = "00000001000000013feccb804014587f000000010000000105911c976a3d462c8eaa2d7ca850432c"
-
-## 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 = "Apache 1.3.29"
-
-
-##
-## Format: <errorfile-prefix><status>.html
-## -> ..../status-404.html for 'File not found'
-#server.errorfile-prefix = "/home/weigon/projects/lighttpd/doc/status-"
-
-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_cgi",
- "mod_proxy_core",
- "mod_proxy_backend_fastcgi",
- "mod_compress",
- "mod_accesslog" )
-
-server.indexfiles = ( "index.html",
- "index.htm", "default.htm", "index.php" )
-
-#,-- only root can use these options
-#|
-#|# chroot() to directory (default: no chroot() )
-#| server.chroot /
-#|# change uid to <uid> (default: don't care)
-#| server.userid wwwrun
-#|# change uid to <uid> (default: don't care)
-#| server.groupid wwwrun
-#|
-#`--
-
-
-######################## 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")
-
-$PHYSICAL["existing-path"] =~ "\.php$" {
- proxy-core.debug = 0
- proxy-core.protocol = "fastcgi"
- proxy-core.backends = ( "127.0.0.1:1026" )
-}
-
-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.url = "ldap://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/" )
-
-expire.url = ( "/buggy/" => "access 2 hours", "/asdhas/" => "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"
-
-simple-vhost.document-root = "pages"
-simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
-simple-vhost.default-host = "www.example.org"
-
-$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"
-}
-
diff --git a/tests/bug-12.conf b/tests/bug-12.conf
deleted file mode 100644
index 1be96902..00000000
--- a/tests/bug-12.conf
+++ /dev/null
@@ -1,154 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-# server.license = "00000001000000013feccb804014587f000000010000000105911c976a3d462c8eaa2d7ca850432c"
-
-## 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 = "Apache 1.3.29"
-
-
-##
-## Format: <errorfile-prefix><status>.html
-## -> ..../status-404.html for 'File not found'
-#server.errorfile-prefix = "/home/weigon/projects/lighttpd/doc/status-"
-
-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_cgi",
- "mod_proxy_core",
- "mod_proxy_backend_fastcgi",
- "mod_compress",
- "mod_accesslog" )
-
-server.indexfiles = ( "index.html",
- "index.htm", "default.htm", "index.php" )
-
-server.error-handler-404 = "/indexfile/return-404.php"
-
-#,-- only root can use these options
-#|
-#|# chroot() to directory (default: no chroot() )
-#| server.chroot /
-#|# change uid to <uid> (default: don't care)
-#| server.userid wwwrun
-#|# change uid to <uid> (default: don't care)
-#| server.groupid wwwrun
-#|
-#`--
-
-
-######################## 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")
-
-$PHYSICAL["existing-path"] =~ "\.php$" {
- proxy-core.debug = 0
- proxy-core.protocol = "fastcgi"
- proxy-core.backends = ( "127.0.0.1:1026" )
-}
-
-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.url = "ldap://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/" )
-
-expire.url = ( "/buggy/" => "access 2 hours", "/asdhas/" => "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"
-
-simple-vhost.document-root = "pages"
-simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
-simple-vhost.default-host = "www.example.org"
-
-$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"
-}
-
diff --git a/tests/cachable.t b/tests/cachable.t
deleted file mode 100755
index 5d94532d..00000000
--- a/tests/cachable.t
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/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 => 12;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-$tf->{CONFIGFILE} = 'lighttpd.conf';
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-## check if If-Modified-Since, If-None-Match works
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Last-Modified' => ''} ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
-
-my $now = $t->{date};
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: $now
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: $now; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+ETag' => ''} ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
-
-my $etag = $t->{etag};
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-If-Modified-Since: $now; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: Foo
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-If-Modified-Since: $now foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/cleanup.sh b/tests/cleanup.sh
deleted file mode 100755
index 5ee34a62..00000000
--- a/tests/cleanup.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-if test x$srcdir = x; then
- srcdir=.
-fi
-
-tmpdir=$top_builddir/tests/tmp/
-
-# remove test-framework
-rm -rf $tmpdir
-
-printf "%-40s" "cleaning up"
-
-exit 0
diff --git a/tests/condition.conf b/tests/condition.conf
deleted file mode 100644
index 92c05add..00000000
--- a/tests/condition.conf
+++ /dev/null
@@ -1,59 +0,0 @@
-
-debug.log-request-handling = "enable"
-debug.log-condition-handling = "enable"
-
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-## 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 = "Apache 1.3.29"
-
-
-server.modules = (
- "mod_redirect",
- "mod_accesslog" )
-
-######################## MODULE CONFIG ############################
-
-
-accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
-
-mimetype.assign = ( ".html" => "text/html" )
-
-url.redirect = ("^" => "/default")
-
-$HTTP["host"] == "www.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "www.example.org"
- url.redirect = ("^" => "/match_1")
-}
-else $HTTP["host"] == "test1.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "test1.example.org"
- url.redirect = ("^" => "/match_2")
-}
-# comments
-else $HTTP["host"] == "test2.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "test2.example.org"
- url.redirect = ("^" => "/match_3")
-}
-
- # comments
-
-else $HTTP["host"] == "test3.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "test3.example.org"
- url.redirect = ("^" => "/match_4")
-
- # comments
- $HTTP["url"] == "/index.html" {
- url.redirect = ("^" => "/match_5")
- }
-}
diff --git a/tests/core-condition.t b/tests/core-condition.t
deleted file mode 100755
index 53919a15..00000000
--- a/tests/core-condition.t
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/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 => 17;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-$tf->{CONFIGFILE} = 'condition.conf';
-ok($tf->start_proc == 0, "Starting lighttpd") 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' => 301, 'Location' => "/match_1" } ];
-ok($tf->handle_http($t) == 0, 'config deny');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Host: test1.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => "/match_2" } ];
-ok($tf->handle_http($t) == 0, '2nd child of chaining');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Host: test2.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => "/match_3" } ];
-ok($tf->handle_http($t) == 0, '3rd child of chaining');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Host: test3.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => "/match_5" } ];
-ok($tf->handle_http($t) == 0, 'nesting');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
-$tf->{CONFIGFILE} = 'lighttpd.conf';
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /nofile.png HTTP/1.0
-Host: referer.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'condition: Referer - no referer');
-
-$t->{REQUEST} = ( <<EOF
-GET /nofile.png HTTP/1.0
-Host: referer.example.org
-Referer: http://referer.example.org/
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'condition: Referer - referer matches regex');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'condition: Referer - no referer');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-Host: www.example.org
-Referer: http://referer.example.org/
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'condition: Referer - referer matches regex');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-Host: www.example.org
-Referer: http://evil-referer.example.org/
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'condition: Referer - referer doesn\'t match');
-
-$t->{REQUEST} = ( <<EOF
-GET /nofile HTTP/1.1
-Host: bug255.example.org
-
-GET /nofile HTTP/1.1
-Host: bug255.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 403 }, { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'remote ip cache (#255)');
-
-$t->{REQUEST} = ( <<EOF
-GET /empty-ref.noref HTTP/1.0
-Cookie: empty-ref
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'condition: $HTTP["referer"] == "" and Referer is no set');
-
-$t->{REQUEST} = ( <<EOF
-GET /empty-ref.noref HTTP/1.0
-Cookie: empty-ref
-Referer:
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'condition: $HTTP["referer"] == "" and Referer is empty');
-
-$t->{REQUEST} = ( <<EOF
-GET /empty-ref.noref HTTP/1.0
-Cookie: empty-ref
-Referer: foobar
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'condition: $HTTP["referer"] == "" and Referer: foobar');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/core-keepalive.t b/tests/core-keepalive.t
deleted file mode 100755
index b4f51f90..00000000
--- a/tests/core-keepalive.t
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/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;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Connection: keep-alive
-Host: 123.example.org
-
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-
-ok($tf->handle_http($t) == 0, 'Explicit HTTP/1.0 Keep-Alive');
-
-undef $t->{RESPONSE};
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Connection: keep-alive
-Host: 123.example.org
-
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-
-ok($tf->handle_http($t) == 0, 'Explicit HTTP/1.0 Keep-Alive');
-
-undef $t->{RESPONSE};
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Connection: keep-alive
-Host: 123.example.org
-
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Implicit HTTP/1.0 Keep-Alive');
-
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.1
-Connection: keep-alive
-Host: 123.example.org
-
-GET /12345.txt HTTP/1.1
-Host: 123.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Explicit HTTP/1.1 Keep-Alive');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.1
-Host: 123.example.org
-
-GET /12345.txt HTTP/1.1
-Host: 123.example.org
-Connection: close
-EOF
- );
-
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
-
-ok($tf->handle_http($t) == 0, 'Implicit HTTP/1.1 Keep-Alive');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
diff --git a/tests/core-request.t b/tests/core-request.t
deleted file mode 100755
index dab208e1..00000000
--- a/tests/core-request.t
+++ /dev/null
@@ -1,278 +0,0 @@
-#!/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 => 33;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-## Low-Level Request-Header Parsing - URI
-
-$t->{REQUEST} = ( <<EOF
-GET /index%2ehtml HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'URL-encoding');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html%00 HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'URL-encoding, %00');
-
-
-
-## Low-Level Request-Header Parsing - Host
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'hostname');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: 127.0.0.1
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'IPv4 address');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: [::1]
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'IPv6 address');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: www.example.org:80
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'hostname + port');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: 127.0.0.1:80
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'IPv4 address + port');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: [::1]:80
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'IPv6 address + port');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: ../123.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'directory traversal');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: .jsdh.sfdg.sdfg.
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'leading and trailing dot');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: jsdh.sfdg.sdfg.
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'trailing dot is ok');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: .jsdh.sfdg.sdfg
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'leading dot');
-
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: jsdh..sfdg.sdfg
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'two dots');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: jsdh.sfdg.sdfg:asd
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'broken port-number');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: jsdh.sfdg.sdfg:-1
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'negative port-number');
-
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: :80
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'port given but host missing');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: .jsdh.sfdg.:sdfg.
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'port and host are broken');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: a.b-c.d123
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'allowed characters in host-name');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: -a.c
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'leading dash');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: .
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'dot only');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: a192.168.2.10:1234
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'broken IPv4 address - non-digit');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: 192.168.2:1234
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'broken IPv4 address - too short');
-
-
-
-## Low-Level Request-Header Parsing - Content-Length
-
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Content-Length: -2
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'negative Content-Length');
-
-$t->{REQUEST} = ( <<EOF
-POST /12345.txt HTTP/1.0
-Host: 123.example.org
-Content-Length: 2147483648
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 413 } ];
-ok($tf->handle_http($t) == 0, 'Content-Length > max-request-size');
-
-$t->{REQUEST} = ( <<EOF
-POST /12345.txt HTTP/1.0
-Host: 123.example.org
-Content-Length:
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 411 } ];
-ok($tf->handle_http($t) == 0, 'Content-Length is empty');
-
-print "\nLow-Level Request-Header Parsing - HTTP/1.1\n";
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.1
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Host missing');
-
-print "\nContent-Type\n";
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
-ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.JPG HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
-ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg (upper case)');
-
-$t->{REQUEST} = ( <<EOF
-GET /a HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'application/octet-stream' } ];
-ok($tf->handle_http($t) == 0, 'Content-Type - unknown');
-
-$t->{REQUEST} = ( <<EOF
-GET HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'empty request-URI');
-
-$t->{REQUEST} = ( <<EOF
-GET /Foo.txt HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'uppercase filenames');
-
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/core-response.t b/tests/core-response.t
deleted file mode 100755
index 98157875..00000000
--- a/tests/core-response.t
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/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 => 12;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-## Low-Level Response-Header Parsing - HTTP/1.1
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.1
-Host: www.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, '+Date' => '' } ];
-ok($tf->handle_http($t) == 0, 'Date header');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.1
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400, 'Connection' => 'close' } ];
-ok($tf->handle_http($t) == 0, 'Host missing');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+ETag' => '' } ];
-ok($tf->handle_http($t) == 0, 'ETag is set');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'ETag' => '/^".+"$/' } ];
-ok($tf->handle_http($t) == 0, 'ETag has quotes');
-
-
-
-## Low-Level Response-Header Parsing - Content-Length
-
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.html HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => '6' } ];
-ok($tf->handle_http($t) == 0, 'Content-Length for text/html');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => '6' } ];
-ok($tf->handle_http($t) == 0, 'Content-Length for text/plain');
-
-
-## Low-Level Response-Header Parsing - Location
-
-$t->{REQUEST} = ( <<EOF
-GET /dummydir HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/dummydir/' } ];
-ok($tf->handle_http($t) == 0, 'internal redirect in directory');
-
-$t->{REQUEST} = ( <<EOF
-GET /dummydir?foo HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/dummydir/?foo' } ];
-ok($tf->handle_http($t) == 0, 'internal redirect in directory + querystring');
-
-## simple-vhost
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: no-simple.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => '6' } ];
-ok($tf->handle_http($t) == 0, 'disabling simple-vhost via conditionals');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: simple.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'simple-vhost via conditionals');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/core-var-include.t b/tests/core-var-include.t
deleted file mode 100755
index c57f75d9..00000000
--- a/tests/core-var-include.t
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/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 => 17;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-$ENV{"env_test"} = "good_env";
-
-$tf->{CONFIGFILE} = 'var-include.conf';
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( "GET /index.html HTTP/1.0\r\nHost: www.example.org\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => "/redirect" } ];
-ok($tf->handle_http($t) == 0, 'basic test');
-
-my $myvar = "good";
-my $server_name = "test.example.org";
-my $mystr = "string";
-$mystr .= "_append";
-my $tests = {
- "include" => "/good_include",
- "concat" => "/good_" . "concat",
- "servername1" => "/good_" . $server_name,
- "servername2" => $server_name . "/good_",
- "servername3" => "/good_" . $server_name . "/",
- "var.myvar" => "/good_var_myvar" . $myvar,
- "myvar" => "/good_myvar" . $myvar,
- "env" => "/" . $ENV{"env_test"},
-
- "number1" => "/good_number" . "1",
- "number2" => "1" . "/good_number",
- "array_append" => "/good_array_append",
- "string_append" => "/good_" . $mystr,
- "number_append" => "/good_" . "2",
-
- "include_shell" => "/good_include_shell_" . "456"
-};
-
-foreach my $test (keys %{ $tests }) {
- my $expect = $tests->{$test};
- $t->{REQUEST} = ( <<EOF
-GET /$test HTTP/1.0
-Host: $server_name
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => $expect } ];
- ok($tf->handle_http($t) == 0, $test);
-}
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
diff --git a/tests/core.t b/tests/core.t
deleted file mode 100755
index 476c79bf..00000000
--- a/tests/core.t
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/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 => 21;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Valid HTTP/1.0 Request') or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'missing Protocol');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/01.01
-Host: foo
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'zeros in protocol version');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/.01
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 505 } ];
-ok($tf->handle_http($t) == 0, 'missing major version');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/01.
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 505 } ];
-ok($tf->handle_http($t) == 0, 'missing minor version');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/a.b
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 505 } ];
-ok($tf->handle_http($t) == 0, 'strings as version');
-
-$t->{REQUEST} = ( <<EOF
-BC /
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'missing protocol + unknown method');
-
-$t->{REQUEST} = ( <<EOF
-ABC
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'missing protocol + unknown method + missing URI');
-
-$t->{REQUEST} = ( <<EOF
-ABC / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 501 } ];
-ok($tf->handle_http($t) == 0, 'unknown method');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.3
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 505 } ];
-ok($tf->handle_http($t) == 0, 'unknown protocol');
-
-$t->{REQUEST} = ( <<EOF
-GET http://www.example.org/ HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'absolute URI');
-
-print "\nLow-Level Request-Header Parsing\n";
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-ABC : foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'whitespace after key');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-ABC a: foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'whitespace with-in key');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-ABC:foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'no whitespace');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-ABC:foo
- bc
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'line-folding');
-
-print "\nLow-Level Request-Header Parsing - URI\n";
-$t->{REQUEST} = ( <<EOF
-GET /index%2ehtml HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'URL-encoding');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html%00 HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'URL-encoding, %00');
-
-$t->{REQUEST} = ( <<EOF
-OPTIONS * HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'OPTIONS');
-
-$t->{REQUEST} = ( <<EOF
-OPTIONS / HTTP/1.1
-Host: www.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'OPTIONS');
-
-
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/default.conf b/tests/default.conf
deleted file mode 100644
index 1eefc6cb..00000000
--- a/tests/default.conf
+++ /dev/null
@@ -1,113 +0,0 @@
-server.name = "www.example.org"
-
-## bind to port (default: 80)
-server.port = env.PORT
-
-
-server.dir-listing = "enable"
-
-#server.event-handler = "linux-sysepoll"
-#server.event-handler = "linux-rtsig"
-
-server.modules = (
- "mod_rewrite",
- "mod_setenv",
- "mod_access",
- "mod_auth",
- "mod_status",
- "mod_expire",
- "mod_simple_vhost",
- "mod_redirect",
- "mod_secdownload",
- "mod_ssi",
-# "mod_proxy",
- "mod_proxy_core",
- "mod_proxy_backend_fastcgi",
- "mod_cgi",
- "mod_compress",
- "mod_userdir",
- "mod_accesslog",
- )
-
-server.indexfiles = ( "index.php", "index.html",
- "index.htm", "default.htm" )
-
-ssi.extension = ( ".shtml" )
-
-######################## MODULE CONFIG ############################
-
-
-accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
-server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.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" => "tracenv", "SETENV" => "setenv")
-
-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.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
-auth.backend.plain.groupfile = "lighttpd.group"
-
-auth.backend.ldap.url = "ldap://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" => "valid-user"
- ),
- "/auth.php" =>
- (
- "method" => "basic",
- "realm" => "download archiv",
- "require" => "user=jan"
- ),
- "/server-config" =>
- (
- "method" => "basic",
- "realm" => "download archiv",
- "require" => "valid-user"
- )
- )
-
-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" )
-
-#### status module
-status.status-url = "/server-status"
-status.config-url = "/server-config"
-
diff --git a/tests/docroot/123/12345.html b/tests/docroot/123/12345.html
deleted file mode 100644
index e56e15bb..00000000
--- a/tests/docroot/123/12345.html
+++ /dev/null
@@ -1 +0,0 @@
-12345
diff --git a/tests/docroot/123/12345.txt b/tests/docroot/123/12345.txt
deleted file mode 100644
index e56e15bb..00000000
--- a/tests/docroot/123/12345.txt
+++ /dev/null
@@ -1 +0,0 @@
-12345
diff --git a/tests/docroot/123/Makefile.am b/tests/docroot/123/Makefile.am
deleted file mode 100644
index 64712d7a..00000000
--- a/tests/docroot/123/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST=12345.html 12345.txt dummyfile.bla phpinfo.php
diff --git a/tests/docroot/123/dummyfile.bla b/tests/docroot/123/dummyfile.bla
deleted file mode 100644
index e56e15bb..00000000
--- a/tests/docroot/123/dummyfile.bla
+++ /dev/null
@@ -1 +0,0 @@
-12345
diff --git a/tests/docroot/123/phpinfo.php b/tests/docroot/123/phpinfo.php
deleted file mode 100644
index 147cebcd..00000000
--- a/tests/docroot/123/phpinfo.php
+++ /dev/null
@@ -1 +0,0 @@
-<?php phpinfo(); ?>
diff --git a/tests/docroot/Makefile.am b/tests/docroot/Makefile.am
deleted file mode 100644
index d14aa288..00000000
--- a/tests/docroot/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-SUBDIRS=123 www
diff --git a/tests/docroot/www/Makefile.am b/tests/docroot/www/Makefile.am
deleted file mode 100644
index dbf04723..00000000
--- a/tests/docroot/www/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-EXTRA_DIST=cgi.php cgi.pl index.html index.txt phpinfo.php \
- redirect.php cgi-pathinfo.pl get-env.php get-server-env.php \
- nph-status.pl prefix.fcgi get-header.pl ssi.shtml get-post-len.pl \
- exec-date.shtml get-post-md5.php
-SUBDIRS=go indexfile expire
diff --git a/tests/docroot/www/cgi-pathinfo.pl b/tests/docroot/www/cgi-pathinfo.pl
deleted file mode 100644
index af8d4dfb..00000000
--- a/tests/docroot/www/cgi-pathinfo.pl
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /usr/bin/perl
-
-print "Content-Type: text/html\r\n\r\n";
-
-print $ENV{"PATH_INFO"};
-
-0;
diff --git a/tests/docroot/www/cgi.php b/tests/docroot/www/cgi.php
deleted file mode 100644
index d92e52f9..00000000
--- a/tests/docroot/www/cgi.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-#ob_start(/*"ob_gzhandler"*/);
-print "12345<br />\n";
-#phpinfo();
-#header("Content-Length: ".ob_get_length());
-#ob_end_flush();
-
-?>
diff --git a/tests/docroot/www/cgi.pl b/tests/docroot/www/cgi.pl
deleted file mode 100644
index 9695adf6..00000000
--- a/tests/docroot/www/cgi.pl
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /usr/bin/perl
-
-print "Content-Type: text/html\r\n\r\n";
-
-print $ENV{"SCRIPT_NAME"};
-
-0;
diff --git a/tests/docroot/www/exec-date.shtml b/tests/docroot/www/exec-date.shtml
deleted file mode 100644
index 2c8535bc..00000000
--- a/tests/docroot/www/exec-date.shtml
+++ /dev/null
@@ -1 +0,0 @@
-<!--#exec cmd="expr 1 + 1"-->
diff --git a/tests/docroot/www/expire/Makefile.am b/tests/docroot/www/expire/Makefile.am
deleted file mode 100644
index 7812b143..00000000
--- a/tests/docroot/www/expire/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST=access.txt modification.txt
diff --git a/tests/docroot/www/expire/access.txt b/tests/docroot/www/expire/access.txt
deleted file mode 100644
index e69de29b..00000000
--- a/tests/docroot/www/expire/access.txt
+++ /dev/null
diff --git a/tests/docroot/www/expire/modification.txt b/tests/docroot/www/expire/modification.txt
deleted file mode 100644
index e69de29b..00000000
--- a/tests/docroot/www/expire/modification.txt
+++ /dev/null
diff --git a/tests/docroot/www/get-env.php b/tests/docroot/www/get-env.php
deleted file mode 100644
index bdaa9a4a..00000000
--- a/tests/docroot/www/get-env.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
- $env = $_GET["env"];
- print isset($_ENV[$env]) ? $_ENV[$env] : '';
-?>
diff --git a/tests/docroot/www/get-header.pl b/tests/docroot/www/get-header.pl
deleted file mode 100644
index 905f3e79..00000000
--- a/tests/docroot/www/get-header.pl
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/perl
-
-my $s = $ENV{$ENV{"QUERY_STRING"}};
-
-printf("Content-Length: %d\r\n", length($s));
-print "Content-Type: text/plain\r\n\r\n";
-
-print $s;
diff --git a/tests/docroot/www/get-post-len.pl b/tests/docroot/www/get-post-len.pl
deleted file mode 100644
index bac8bbf8..00000000
--- a/tests/docroot/www/get-post-len.pl
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/perl
-
-
-print "Content-Type: text/plain\r\n\r\n";
-
-if ($ENV{"REQUEST_METHOD"} eq "POST") {
- my $l = 0;
- while(<>) {
- $l += length($_);
- }
- print $l;
-} else {
- print "0";
-}
-
diff --git a/tests/docroot/www/get-post-md5.php b/tests/docroot/www/get-post-md5.php
deleted file mode 100644
index 0c250c41..00000000
--- a/tests/docroot/www/get-post-md5.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
- print md5($_POST[$_GET["var"]]);
-?>
diff --git a/tests/docroot/www/get-server-env.php b/tests/docroot/www/get-server-env.php
deleted file mode 100644
index 17b49945..00000000
--- a/tests/docroot/www/get-server-env.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
- print $_SERVER[$_GET["env"]];
-?>
diff --git a/tests/docroot/www/go/Makefile.am b/tests/docroot/www/go/Makefile.am
deleted file mode 100644
index fe20c503..00000000
--- a/tests/docroot/www/go/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST=cgi.php
diff --git a/tests/docroot/www/go/cgi.php b/tests/docroot/www/go/cgi.php
deleted file mode 100644
index d92e52f9..00000000
--- a/tests/docroot/www/go/cgi.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-#ob_start(/*"ob_gzhandler"*/);
-print "12345<br />\n";
-#phpinfo();
-#header("Content-Length: ".ob_get_length());
-#ob_end_flush();
-
-?>
diff --git a/tests/docroot/www/index.html b/tests/docroot/www/index.html
deleted file mode 100644
index 3c149671..00000000
--- a/tests/docroot/www/index.html
+++ /dev/null
@@ -1,113 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
-<TITLE>Webserver testpage</TITLE>
-<META content="iso-8859-1" http-equiv="charset">
-<META name="author" content="Christian Hofmann, SuSE Linux AG">
-</HEAD>
-<BODY BGCOLOR="#ffffff" LINK="#669900" ALINK="#669900" VLINK="#fb8000" text=black marginwidth="0" marginheight="0" leftmargin="0" topmargin="0">
-<TABLE border="0" width="760" cellpadding="0" cellspacing="0">
- <TR>
- <TD rowspan="4" bgcolor="#669900" width="50">&nbsp;</TD>
- <td valign=top height="70" width="29" bgcolor="#669900">&nbsp;</td>
- <td valign="middle" height="70" width="152" align="center" bgcolor="#669900">&nbsp;</td>
- <td valign=middle height="70" width="529" bgcolor="#669900">
- <div align="center">
- <font face="Courier New,Courier,mono" size="5" color="white"><B>+++ testinfo - webserver +++</b></font>
- </div>
- </td>
- </tr>
- <TR>
- <td width="29" height="100" valign="middle" bgcolor="#669900">&nbsp;</td>
- <td width="152" height="100" align="center" valign="bottom"><IMG src="gif/penguin.gif" width=90 height=76 hspace=0 vspace=0 border=0 alt=" "></td>
- <td width="529" height="100" valign="middle">
- <div align="center">
- <font face="Courier New,Courier,mono" size="3"><I>This is only a test page for the webserver!</I></font><br>
- <font face="Courier New,Courier,mono" size="-1">SuSE is not responsible for the contents of this domain!</font>
- </div>
- </td>
- </tr>
- <tr>
- <td valign=top align=left colspan="4">
- <table border="0" cellpadding="0" cellspacing="0" width="710" vspace="0" hspace="0">
- <TR>
- <TD bgcolor="#669900" width="29" height="20">&nbsp;</TD>
- <TD width="152" height="20">&nbsp;</TD>
- <TD width="558" height="20" colspan="2">&nbsp;</TD>
- </tr>
- <TR>
- <TD height="50" align=left width="181" colspan="2"><IMG src="gif/sysinfo_en.png" width="181" height="50" border="0" alt="system information"></TD>
- <TD width="529" colspan="2" rowspan="2" valign=top>
- <FONT face="helvetica, arial, sans-serif">
- <B>Operating system:</B> [ SuSE Linux 8.0 (i386)
- ]<BR>
- <B>Host:</B> [ grisu.home.kneschke.de, Kernel: 2.4.18-4GB (i686)
- ]
- </FONT>
- </TD>
- </TR>
- <TR>
- <TD bgcolor="#669900" width="29" height="40">&nbsp;</TD>
- <TD width="181" height="40">&nbsp;</TD>
- </TR>
-
- <TR>
- <TD height="50" align=left width="181" colspan="2"><IMG src="gif/version_en.png" width="181" height="50" border="0" alt="webserver and modules"></TD>
- <TD width="529" colspan="2" rowspan="2" valign=top>
- <FONT face="helvetica,arial,sans-serif">
- <B>Webserver version:</B><br>
- [ lighttpd/0.1.0 (Unix) ]<br><br>
-
- <B>Installed modules:</B><br>
- <I>[ PHP module is not installed ]</I><br>
- <I>[ Apache perl module (mod_perl) is not installed ]</I><br>
- <I>[ Apache DAV module (mod_dav) is not installed ]</I><br>
- <I>[ Apache Python module (mod_python) is not installed ]</I><br>
-
- </FONT>
- </TD>
- </TR>
- <TR>
- <TD bgcolor="#669900" width="29" height="100">&nbsp;</TD>
- <TD width="181" height="100">&nbsp;</TD>
- </TR>
- <TR>
- <TD colspan="2" height="50" align=left width="181"><IMG src="gif/docu_en.png" width="181" height="50" border="0" alt="documentation"></TD>
- <TD width="529" colspan="2" rowspan="2" valign=top>
- <FONT face="helvetica,arial,sans-serif">
-<I>[ This host is not configured as server for the SuSE help system ]</I><br><br>
-<I>[ Apache manual is not installed ]</I><br>
-
- <BR>
- <A HREF="http://www.suse.de/">[ The SuSE website ]</A><BR>
-
-
-
- </FONT>
- </TD>
-
- </TR>
- <TR>
- <TD bgcolor="#669900" width="29" height="90">&nbsp;</TD>
- <TD width="181" height="90">&nbsp;</TD>
- </Table>
- </td>
- </tr>
- <tr>
- <td width=29 bgcolor="#669900">&nbsp;</td>
- <td valign=bottom align=right width="681" colspan="3"><A HREF="http://www.suse.de/en/"><IMG src="gif/powered_by_suse.gif" alt="powered by SuSE" width=100 height=40 hspace=5 vspace=5 border=0></A></td>
- </tr>
-
-</TABLE>
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/docroot/www/index.txt b/tests/docroot/www/index.txt
deleted file mode 100644
index 3c149671..00000000
--- a/tests/docroot/www/index.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
-<TITLE>Webserver testpage</TITLE>
-<META content="iso-8859-1" http-equiv="charset">
-<META name="author" content="Christian Hofmann, SuSE Linux AG">
-</HEAD>
-<BODY BGCOLOR="#ffffff" LINK="#669900" ALINK="#669900" VLINK="#fb8000" text=black marginwidth="0" marginheight="0" leftmargin="0" topmargin="0">
-<TABLE border="0" width="760" cellpadding="0" cellspacing="0">
- <TR>
- <TD rowspan="4" bgcolor="#669900" width="50">&nbsp;</TD>
- <td valign=top height="70" width="29" bgcolor="#669900">&nbsp;</td>
- <td valign="middle" height="70" width="152" align="center" bgcolor="#669900">&nbsp;</td>
- <td valign=middle height="70" width="529" bgcolor="#669900">
- <div align="center">
- <font face="Courier New,Courier,mono" size="5" color="white"><B>+++ testinfo - webserver +++</b></font>
- </div>
- </td>
- </tr>
- <TR>
- <td width="29" height="100" valign="middle" bgcolor="#669900">&nbsp;</td>
- <td width="152" height="100" align="center" valign="bottom"><IMG src="gif/penguin.gif" width=90 height=76 hspace=0 vspace=0 border=0 alt=" "></td>
- <td width="529" height="100" valign="middle">
- <div align="center">
- <font face="Courier New,Courier,mono" size="3"><I>This is only a test page for the webserver!</I></font><br>
- <font face="Courier New,Courier,mono" size="-1">SuSE is not responsible for the contents of this domain!</font>
- </div>
- </td>
- </tr>
- <tr>
- <td valign=top align=left colspan="4">
- <table border="0" cellpadding="0" cellspacing="0" width="710" vspace="0" hspace="0">
- <TR>
- <TD bgcolor="#669900" width="29" height="20">&nbsp;</TD>
- <TD width="152" height="20">&nbsp;</TD>
- <TD width="558" height="20" colspan="2">&nbsp;</TD>
- </tr>
- <TR>
- <TD height="50" align=left width="181" colspan="2"><IMG src="gif/sysinfo_en.png" width="181" height="50" border="0" alt="system information"></TD>
- <TD width="529" colspan="2" rowspan="2" valign=top>
- <FONT face="helvetica, arial, sans-serif">
- <B>Operating system:</B> [ SuSE Linux 8.0 (i386)
- ]<BR>
- <B>Host:</B> [ grisu.home.kneschke.de, Kernel: 2.4.18-4GB (i686)
- ]
- </FONT>
- </TD>
- </TR>
- <TR>
- <TD bgcolor="#669900" width="29" height="40">&nbsp;</TD>
- <TD width="181" height="40">&nbsp;</TD>
- </TR>
-
- <TR>
- <TD height="50" align=left width="181" colspan="2"><IMG src="gif/version_en.png" width="181" height="50" border="0" alt="webserver and modules"></TD>
- <TD width="529" colspan="2" rowspan="2" valign=top>
- <FONT face="helvetica,arial,sans-serif">
- <B>Webserver version:</B><br>
- [ lighttpd/0.1.0 (Unix) ]<br><br>
-
- <B>Installed modules:</B><br>
- <I>[ PHP module is not installed ]</I><br>
- <I>[ Apache perl module (mod_perl) is not installed ]</I><br>
- <I>[ Apache DAV module (mod_dav) is not installed ]</I><br>
- <I>[ Apache Python module (mod_python) is not installed ]</I><br>
-
- </FONT>
- </TD>
- </TR>
- <TR>
- <TD bgcolor="#669900" width="29" height="100">&nbsp;</TD>
- <TD width="181" height="100">&nbsp;</TD>
- </TR>
- <TR>
- <TD colspan="2" height="50" align=left width="181"><IMG src="gif/docu_en.png" width="181" height="50" border="0" alt="documentation"></TD>
- <TD width="529" colspan="2" rowspan="2" valign=top>
- <FONT face="helvetica,arial,sans-serif">
-<I>[ This host is not configured as server for the SuSE help system ]</I><br><br>
-<I>[ Apache manual is not installed ]</I><br>
-
- <BR>
- <A HREF="http://www.suse.de/">[ The SuSE website ]</A><BR>
-
-
-
- </FONT>
- </TD>
-
- </TR>
- <TR>
- <TD bgcolor="#669900" width="29" height="90">&nbsp;</TD>
- <TD width="181" height="90">&nbsp;</TD>
- </Table>
- </td>
- </tr>
- <tr>
- <td width=29 bgcolor="#669900">&nbsp;</td>
- <td valign=bottom align=right width="681" colspan="3"><A HREF="http://www.suse.de/en/"><IMG src="gif/powered_by_suse.gif" alt="powered by SuSE" width=100 height=40 hspace=5 vspace=5 border=0></A></td>
- </tr>
-
-</TABLE>
-</BODY>
-</HTML>
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/docroot/www/indexfile/Makefile.am b/tests/docroot/www/indexfile/Makefile.am
deleted file mode 100644
index 04727308..00000000
--- a/tests/docroot/www/indexfile/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_DIST=index.php return-404.php rewrite.php
diff --git a/tests/docroot/www/indexfile/index.php b/tests/docroot/www/indexfile/index.php
deleted file mode 100644
index e0c7d9ec..00000000
--- a/tests/docroot/www/indexfile/index.php
+++ /dev/null
@@ -1 +0,0 @@
-<?php print $_SERVER["PHP_SELF"]; ?>
diff --git a/tests/docroot/www/indexfile/return-404.php b/tests/docroot/www/indexfile/return-404.php
deleted file mode 100644
index dd680cc5..00000000
--- a/tests/docroot/www/indexfile/return-404.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
- header("Status: 404");
-
- print $_SERVER["PHP_SELF"];
-?>
diff --git a/tests/docroot/www/indexfile/rewrite.php b/tests/docroot/www/indexfile/rewrite.php
deleted file mode 100644
index fb412907..00000000
--- a/tests/docroot/www/indexfile/rewrite.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
- print $_SERVER["QUERY_STRING"];
-?>
diff --git a/tests/docroot/www/nph-status.pl b/tests/docroot/www/nph-status.pl
deleted file mode 100644
index dd033f87..00000000
--- a/tests/docroot/www/nph-status.pl
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/perl
-
-my $status = 200;
-
-if (defined $ENV{"QUERY_STRING"}) {
- $status = $ENV{"QUERY_STRING"};
-}
-
-if ($status == 0 && $status ne "0") {
- # not a number, just send as content
- print $status;
-} else {
- print "HTTP/1.0 ".$status." FooBar\r\n\r\n";
-}
diff --git a/tests/docroot/www/phpinfo.php b/tests/docroot/www/phpinfo.php
deleted file mode 100644
index 147cebcd..00000000
--- a/tests/docroot/www/phpinfo.php
+++ /dev/null
@@ -1 +0,0 @@
-<?php phpinfo(); ?>
diff --git a/tests/docroot/www/prefix.fcgi b/tests/docroot/www/prefix.fcgi
deleted file mode 100644
index e3883520..00000000
--- a/tests/docroot/www/prefix.fcgi
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-echo $_SERVER[$_GET["var"]];
-?>
diff --git a/tests/docroot/www/redirect.php b/tests/docroot/www/redirect.php
deleted file mode 100644
index 0489d22d..00000000
--- a/tests/docroot/www/redirect.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
- header('Location: http://www.example.org:2048/');
-?>
diff --git a/tests/docroot/www/ssi.shtml b/tests/docroot/www/ssi.shtml
deleted file mode 100644
index 473c5c65..00000000
--- a/tests/docroot/www/ssi.shtml
+++ /dev/null
@@ -1 +0,0 @@
-<!--#echo var="SCRIPT_NAME" -->
diff --git a/tests/fastcgi-10.conf b/tests/fastcgi-10.conf
deleted file mode 100644
index 1ed841b1..00000000
--- a/tests/fastcgi-10.conf
+++ /dev/null
@@ -1,129 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-## 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 = "Apache 1.3.29"
-
-##
-## Format: <errorfile-prefix><status>.html
-## -> ..../status-404.html for 'File not found'
-#server.errorfile-prefix = "/home/weigon/projects/lighttpd/doc/status-"
-
-server.dir-listing = "enable"
-
-#server.event-handler = "linux-sysepoll"
-#server.event-handler = "linux-rtsig"
-
-#server.modules.path = ""
-server.modules = (
- "mod_rewrite",
- "mod_access",
- "mod_auth",
-# "mod_httptls",
- "mod_status",
- "mod_expire",
-# "mod_simple_vhost",
- "mod_redirect",
-# "mod_evhost",
-# "mod_localizer",
-# "mod_cgi",
- "mod_proxy_core",
- "mod_proxy_backend_fastcgi",
- "mod_compress",
- "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")
-
-$PHYSICAL["existing-path"] =~ "\.php$" {
- proxy-core.debug = 0
- proxy-core.protocol = "fastcgi"
- proxy-core.backends = ( "127.0.0.1:1026" )
-}
-
-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.url = "ldap://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/" )
-
-expire.url = ( "/buggy/" => "access 2 hours", "/asdhas/" => "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"
-}
-
diff --git a/tests/fastcgi.t b/tests/fastcgi.t
deleted file mode 100755
index 37b82f71..00000000
--- a/tests/fastcgi.t
+++ /dev/null
@@ -1,233 +0,0 @@
-#!/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 Test::More tests => 32;
-use LightyTest;
-
-my $tf = LightyTest->new();
-
-my $t;
-my $php_child = -1;
-
-my $phpbin = (defined $ENV{'PHP'} ? $ENV{'PHP'} : '/usr/bin/php-cgi');
-
-SKIP: {
- skip "PHP already running on port 1026", 1 if $tf->listening_on(1026);
- skip "no php binary found", 1 unless -x $phpbin;
- ok(-1 != ($php_child = $tf->spawnfcgi($phpbin, 1026)), "Spawning php");
-}
-
-SKIP: {
- skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
-
- ok($tf->start_proc == 0, "Starting lighttpd") or goto cleanup;
-
- $t->{REQUEST} = ( <<EOF
-POST /get-post-md5.php?var=content HTTP/1.0
-Host: zzz.example.org
-Content-Type: application/x-www-form-urlencoded
-Content-Length: 11
-
-content=abc
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '900150983cd24fb0d6963f7d28e17f72' } ];
- ok($tf->handle_http($t) == 0, 'Post data');
-
- $t->{REQUEST} = ( <<EOF
-GET /phpinfo.php HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'valid request');
-
- $t->{REQUEST} = ( <<EOF
-GET /phpinfofoobar.php HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'file not found');
-
- $t->{REQUEST} = ( <<EOF
-GET /go/ HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'index-file handling');
-
- $t->{REQUEST} = ( <<EOF
-GET /redirect.php HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 302, 'Location' => 'http://www.example.org:2048/' } ];
- ok($tf->handle_http($t) == 0, 'Status + Location via FastCGI');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php?env=PHP_SELF HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, '$_SERVER["PHP_SELF"]');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php/foo?env=SCRIPT_NAME HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/get-server-env.php' } ];
- ok($tf->handle_http($t) == 0, '$_SERVER["SCRIPT_NAME"]');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php/foo?env=PATH_INFO HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/foo' } ];
- ok($tf->handle_http($t) == 0, '$_SERVER["PATH_INFO"]');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php?env=SERVER_NAME HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
- ok($tf->handle_http($t) == 0, 'SERVER_NAME');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php?env=SERVER_NAME HTTP/1.0
-Host: foo.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
- ok($tf->handle_http($t) == 0, 'SERVER_NAME');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php?env=SERVER_NAME HTTP/1.0
-Host: vvv.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
- ok($tf->handle_http($t) == 0, 'SERVER_NAME');
-
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php?env=SERVER_NAME HTTP/1.0
-Host: zzz.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'zzz.example.org' } ];
- ok($tf->handle_http($t) == 0, 'SERVER_NAME');
-
- $t->{REQUEST} = ( <<EOF
-GET /cgi.php/abc HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'PATHINFO');
-
- $t->{REQUEST} = ( <<EOF
-GET /cgi.php%20%20%20 HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'No source retrieval');
-
- $t->{REQUEST} = ( <<EOF
-GET /www/abc/def HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'PATHINFO on a directory');
-
- $t->{REQUEST} = ( <<EOF
-GET /indexfile/ HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/indexfile/index.php' } ];
- ok($tf->handle_http($t) == 0, 'PHP_SELF + Indexfile, Bug #3');
-
- $t->{REQUEST} = ( <<EOF
-GET /prefix.fcgi?var=SCRIPT_NAME HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/prefix.fcgi' } ];
- ok($tf->handle_http($t) == 0, 'PATH_INFO, check-local off');
-
- $t->{REQUEST} = ( <<EOF
-GET /prefix.fcgi/foo/bar?var=SCRIPT_NAME HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/prefix.fcgi' } ];
- ok($tf->handle_http($t) == 0, 'PATH_INFO, check-local off');
-
- $t->{REQUEST} = ( <<EOF
-GET /prefix.fcgi/foo/bar?var=PATH_INFO HTTP/1.0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/foo/bar' } ];
- ok($tf->handle_http($t) == 0, 'PATH_INFO, check-local off');
-
-
- ok($tf->stop_proc == 0, "Stopping lighttpd");
-
-
- $tf->{CONFIGFILE} = 'fastcgi-10.conf';
- ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or goto cleanup;
- $t->{REQUEST} = ( <<EOF
-GET /get-server-env.php?env=SERVER_NAME HTTP/1.0
-Host: zzz.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'zzz.example.org' } ];
- ok($tf->handle_http($t) == 0, 'FastCGI + Host');
-
- ok($tf->stop_proc == 0, "Stopping lighttpd");
-
- $tf->{CONFIGFILE} = 'bug-06.conf';
- ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or goto cleanup;
- $t->{REQUEST} = ( <<EOF
-GET /indexfile/ HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/indexfile/index.php' } ];
- ok($tf->handle_http($t) == 0, 'Bug #6');
-
- ok($tf->stop_proc == 0, "Stopping lighttpd");
-
- $tf->{CONFIGFILE} = 'bug-12.conf';
- ok($tf->start_proc == 0, "Starting lighttpd with bug-12.conf") or goto cleanup;
- $t->{REQUEST} = ( <<EOF
-POST /indexfile/abc HTTP/1.0
-Host: www.example.org
-Content-Length: 0
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'HTTP-Content' => '/indexfile/return-404.php' } ];
- ok($tf->handle_http($t) == 0, 'Bug #12');
-
- ok($tf->stop_proc == 0, "Stopping lighttpd");
-}
-
-SKIP: {
- skip "PHP not started, cannot stop it", 1 unless $php_child != -1;
- ok(0 == $tf->endspawnfcgi($php_child), "Stopping php");
-}
-
-exit 0;
-
-cleanup: ;
-
-$tf->endspawnfcgi($php_child) if $php_child != -1;
-
-die();
diff --git a/tests/fcgi-auth.c b/tests/fcgi-auth.c
deleted file mode 100644
index 92cd3731..00000000
--- a/tests/fcgi-auth.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "config.h"
-#ifdef HAVE_FASTCGI_FASTCGI_H
-#include <fastcgi/fcgi_stdio.h>
-#else
-#include <fcgi_stdio.h>
-#endif
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-int main () {
- char* p;
-
- while (FCGI_Accept() >= 0) {
- /* wait for fastcgi authorizer request */
-
- printf("Content-type: text/html\r\n");
-
- if (((p = getenv("QUERY_STRING")) == NULL) ||
- strcmp(p, "ok") != 0) {
- printf("Status: 403 Forbidden\r\n\r\n");
- } else {
- printf("\r\n");
- /* default Status is 200 - allow access */
- }
-
- printf("foobar\r\n");
- }
-
- return 0;
-}
diff --git a/tests/fcgi-responder.c b/tests/fcgi-responder.c
deleted file mode 100644
index 41707d33..00000000
--- a/tests/fcgi-responder.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "config.h"
-#ifdef HAVE_FASTCGI_FASTCGI_H
-#include <fastcgi/fcgi_stdio.h>
-#else
-#include <fcgi_stdio.h>
-#endif
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-int main () {
- int num_requests = 2;
-
- while (num_requests > 0 && FCGI_Accept() >= 0) {
- char* p = NULL;
- char* doc_root = NULL;
- char fname[4096];
- char* pfname = (char *)fname;
-
- doc_root = getenv("DOCUMENT_ROOT");
- p = getenv("QUERY_STRING");
-
- if (NULL != p && NULL != doc_root) {
- snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
- if (0 == strcmp(p, "lf")) {
- printf("Status: 200 OK\n\n");
- } else if (0 == strcmp(p, "crlf")) {
- printf("Status: 200 OK\r\n\r\n");
- } else if (0 == strcmp(p, "slow-lf")) {
- printf("Status: 200 OK\n");
- fflush(stdout);
- printf("\n");
- } else if (0 == strcmp(p,"slow-crlf")) {
- printf("Status: 200 OK\r\n");
- fflush(stdout);
- printf("\r\n");
- } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
- printf("Status: 200 OK\r\n");
- printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
- printf("\r\n");
- } else if (0 == strcmp(p,"xsendfile")) {
- printf("Status: 200 OK\r\n");
- printf("X-Sendfile: %s\r\n", pfname);
- printf("\r\n");
- } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
- printf("Status: 200 OK\r\n");
- printf("X-SeNdFiLe: %s\r\n", pfname);
- printf("\r\n");
- } else if (0 == strcmp(p, "die-at-end")) {
- printf("Status: 200 OK\r\n\r\n");
- num_requests--;
- } else {
- printf("Status: 200 OK\r\n\r\n");
- }
- } else {
- printf("Status: 500 Internal Foo\r\n\r\n");
- }
-
- printf("test123");
- }
-
- return 0;
-}
diff --git a/tests/lighttpd.conf b/tests/lighttpd.conf
deleted file mode 100644
index 1444f1dd..00000000
--- a/tests/lighttpd.conf
+++ /dev/null
@@ -1,127 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-server.tag = "Apache 1.3.29"
-
-debug.log-request-handling = "enable"
-debug.log-response-header = "enable"
-## 64 Mbyte ... nice limit
-server.max-request-size = 65000
-
-include "default.conf"
-
-setenv.add-request-header = ( "FOO" => "foo")
-setenv.add-response-header = ( "BAR" => "foo")
-
-$HTTP["host"] == "cache.example.org" {
- compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
-}
-
-$HTTP["url"] =~ "\.pdf$" {
- server.range-requests = "disable"
-}
-
-$PHYSICAL["existing-path"] =~ "\.php$" {
- proxy-core.debug = 0
- proxy-core.protocol = "fastcgi"
- proxy-core.backends = ( "127.0.0.1:1026" )
-}
-
-$HTTP["url"] =~ "^/prefix.fcgi" {
- proxy-core.debug = 0
- proxy-core.protocol = "fastcgi"
- proxy-core.backends = ( "127.0.0.1:1026" )
- proxy-core.rewrite-request = (
- "_pathinfo" => ( "^/prefix.fcgi(/.*)" => "$1" ),
- "_scriptname" => ( "^(/prefix.fcgi)" => "$1" )
- )
-}
-
-#fastcgi.debug = 0
-#fastcgi.server = ( ".php" => ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
-# "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
-# )
-
-$HTTP["host"] == "auth-htpasswd.example.org" {
- auth.backend = "htpasswd"
-}
-
-$HTTP["host"] == "vvv.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- secdownload.secret = "verysecret"
- secdownload.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- secdownload.uri-prefix = "/sec/"
- secdownload.timeout = 120
-}
-
-$HTTP["host"] == "zzz.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "zzz.example.org"
-}
-
-$HTTP["host"] == "symlink.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "symlink.example.org"
- server.follow-symlink = "enable"
-}
-
-$HTTP["host"] == "nosymlink.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "symlink.example.org"
- server.follow-symlink = "disable"
-}
-
-$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"
-}
-
-$HTTP["host"] =~ "(vvv).example.org" {
- url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
-}
-
-$HTTP["host"] =~ "(zzz).example.org" {
- url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" )
-}
-
-$HTTP["host"] =~ "(remoteip)\.example\.org" {
- $HTTP["remoteip"] =~ "(127\.0\.0\.1)" {
- url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" )
- }
-}
-
-$HTTP["remoteip"] =~ "(127\.0\.0\.1)" {
- $HTTP["host"] =~ "(remoteip2)\.example\.org" {
- url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" )
- }
-}
-
-$HTTP["host"] =~ "bug255\.example\.org$" {
- $HTTP["remoteip"] == "127.0.0.1" {
- url.access-deny = ( "" )
- }
-}
-
-$HTTP["referer"] !~ "^($|http://referer\.example\.org)" {
- url.access-deny = ( ".jpg" )
-}
-
-# deny access for all image stealers
-$HTTP["host"] == "referer.example.org" {
- $HTTP["referer"] !~ "^($|http://referer\.example\.org)" {
- url.access-deny = ( ".png" )
- }
-}
-
-$HTTP["cookie"] =~ "empty-ref" {
- $HTTP["referer"] == "" {
- url.access-deny = ( "" )
- }
-}
-
-
diff --git a/tests/lighttpd.htpasswd b/tests/lighttpd.htpasswd
deleted file mode 100644
index 1faf25a4..00000000
--- a/tests/lighttpd.htpasswd
+++ /dev/null
@@ -1,2 +0,0 @@
-des:12tMnfw882VDQ
-md5:$1$md5$kIa7Juuiv8zja0ILQPR36/
diff --git a/tests/lighttpd.user b/tests/lighttpd.user
deleted file mode 100644
index 020aedc6..00000000
--- a/tests/lighttpd.user
+++ /dev/null
@@ -1 +0,0 @@
-jan:jan
diff --git a/tests/lowercase.conf b/tests/lowercase.conf
deleted file mode 100644
index b95fe122..00000000
--- a/tests/lowercase.conf
+++ /dev/null
@@ -1,70 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-## bind to localhost (default: all interfaces)
-server.bind = "localhost"
-server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
-
-server.force-lowercase-filenames = "enable"
-
-server.dir-listing = "enable"
-
-server.modules = (
- "mod_rewrite",
- "mod_setenv",
- "mod_secdownload",
- "mod_access",
- "mod_auth",
- "mod_status",
- "mod_expire",
- "mod_redirect",
-# "mod_cgi"
- )
-
-server.indexfiles = ( "index.php", "index.html",
- "index.htm", "default.htm" )
-
-
-######################## MODULE CONFIG ############################
-
-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" )
-
-auth.backend = "plain"
-auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
-
-auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
-
-$HTTP["host"] == "lowercase-auth" {
- auth.require = ( "/image.jpg" =>
- (
- "method" => "digest",
- "realm" => "download archiv",
- "require" => "valid-user"
- )
- )
-}
-
-$HTTP["host"] == "lowercase-deny" {
- url.access-deny = ( ".jpg")
-}
-
-$HTTP["host"] == "lowercase-exclude" {
- static-file.exclude-extensions = ( ".jpg" )
-}
diff --git a/tests/lowercase.t b/tests/lowercase.t
deleted file mode 100755
index 54d64c1e..00000000
--- a/tests/lowercase.t
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/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;
-
-$tf->{CONFIGFILE} = 'lowercase.conf';
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-## check if lower-casing works
-
-$t->{REQUEST} = ( <<EOF
-GET /image.JPG HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'uppercase access');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'lowercase access');
-
-## check that mod-auth works
-
-$t->{REQUEST} = ( <<EOF
-GET /image.JPG HTTP/1.0
-Host: lowercase-auth
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'uppercase access');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-Host: lowercase-auth
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'lowercase access');
-
-
-## check that mod-staticfile exclude works
-$t->{REQUEST} = ( <<EOF
-GET /image.JPG HTTP/1.0
-Host: lowercase-exclude
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-Host: lowercase-exclude
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'lowercase access');
-
-
-## check that mod-access exclude works
-$t->{REQUEST} = ( <<EOF
-GET /image.JPG HTTP/1.0
-Host: lowercase-deny
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg HTTP/1.0
-Host: lowercase-deny
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'lowercase access');
-
-
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/mod-access.t b/tests/mod-access.t
deleted file mode 100755
index 7c872b2a..00000000
--- a/tests/mod-access.t
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/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 => 3;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html~ HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'forbid access to ...~');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/mod-auth.t b/tests/mod-auth.t
deleted file mode 100755
index 6e5d5893..00000000
--- a/tests/mod-auth.t
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/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 => 14;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Missing Auth-token');
-
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-Authorization: Basic \x80mFuOmphb
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid base64 Auth-token');
-
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-Authorization: Basic amFuOmphb
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Basic-Auth: Wrong Auth-token');
-
-$t->{REQUEST} = ( <<EOF
-GET /server-config HTTP/1.0
-Authorization: Basic amFuOmphbg==
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - plain');
-
-$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)');
-
-SKIP: {
- skip "no md5 for crypt under cygwin", 1 if $^O eq 'cygwin';
-$t->{REQUEST} = ( <<EOF
-GET /server-config HTTP/1.0
-Host: auth-htpasswd.example.org
-Authorization: Basic bWQ1Om1kNQ==
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (md5)');
-}
-
-$t->{REQUEST} = ( <<EOF
-GET /server-config HTTP/1.0
-Authorization: Basic bWQ1Om1kNA==
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token');
-
-## this should not crash
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-User-Agent: Wget/1.9.1
-Authorization: Digest username="jan", realm="jan", nonce="9a5428ccc05b086a08d918e73b01fc6f",
- uri="/server-status", response="ea5f7d9a30b8b762f9610ccb87dea74f"
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Digest-Auth: missing qop, no crash');
-
-## this should not crash
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-User-Agent: Wget/1.9.1
-Authorization: Digest username="jan", realm="jan",
- nonce="b1d12348b4620437c43dd61c50ae4639",
- uri="/MJ-BONG.xm.mpc", qop=auth, noncecount=00000001",
- cnonce="036FCA5B86F7E7C4965C7F9B8FE714B7",
- response="29B32C2953C763C6D033C8A49983B87E"
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Digest-Auth: missing nc (noncecount instead), no crash');
-
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-Authorization: Basic =
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid Base64');
-
-
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-User-Agent: Wget/1.9.1
-Authorization: Digest username="jan", realm="jan",
- nonce="b1d12348b4620437c43dd61c50ae4639", algorithm="md5-sess",
- uri="/MJ-BONG.xm.mpc", qop=auth, noncecount=00000001",
- cnonce="036FCA5B86F7E7C4965C7F9B8FE714B7",
- nc="asd",
- response="29B32C2953C763C6D033C8A49983B87E"
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Digest-Auth: md5-sess + missing cnonce');
-
-$t->{REQUEST} = ( <<EOF
-GET /server-status HTTP/1.0
-User-Agent: Wget/1.9.1
-Authorization: Digest username="jan", realm="jan",
- nonce="b1d12348b4620437c43dd61c50ae4639", algorithm="md5-sess",
- uri="/MJ-BONG.xm.mpc", qop=auth, noncecount=00000001",
- cnonce="036FCA5B86F7E7C4965C7F9B8FE714B7",
- nc="asd",
- response="29B32C2953C763C6D033C8A49983B87E"
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
-ok($tf->handle_http($t) == 0, 'Digest-Auth: trailing WS');
-
-
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/mod-cgi.t b/tests/mod-cgi.t
deleted file mode 100755
index 7992299c..00000000
--- a/tests/mod-cgi.t
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/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 => 19;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-# mod-cgi
-#
-$t->{REQUEST} = ( <<EOF
-GET /cgi.pl HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'perl via cgi');
-
-$t->{REQUEST} = ( <<EOF
-GET /cgi.pl/foo HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/cgi.pl' } ];
-ok($tf->handle_http($t) == 0, 'perl via cgi + pathinfo');
-
-$t->{REQUEST} = ( <<EOF
-GET /cgi-pathinfo.pl/foo HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/foo' } ];
-ok($tf->handle_http($t) == 0, 'perl via cgi + pathinfo');
-
-$t->{REQUEST} = ( <<EOF
-GET /nph-status.pl?30 HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 502 } ];
-ok($tf->handle_http($t) == 0, 'NPH + perl, invalid status-code (#14)');
-
-$t->{REQUEST} = ( <<EOF
-GET /nph-status.pl?304 HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'NPH + perl, setting status-code (#1125)');
-
-$t->{REQUEST} = ( <<EOF
-GET /nph-status.pl?200 HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'NPH + perl, setting status-code');
-
-TODO: {
- local $TODO = "NPH current isn't working";
-$t->{REQUEST} = ( <<EOF
-GET /nph-status.pl?textcontent HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'textcontent' } ];
-ok($tf->handle_http($t) == 0, 'NPH + perl, sending content without headers');
-}
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?GATEWAY_INTERFACE HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'CGI/1.1' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: GATEWAY_INTERFACE');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?QUERY_STRING HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'QUERY_STRING' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: QUERY_STRING');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?GATEWAY_INTERFACE HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'CGI/1.1' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: GATEWAY_INTERFACE');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_HOST HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_XX_YY123 HTTP/1.0
-xx-yy123: foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: quoting headers with numbers');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_HOST HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_HOST HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_HOST HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'text/plain' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_HOST HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Content-Length' => '' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?CONTENT_LENGTH HTTP/1.0
-Host: www.example.org
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '' } ];
-ok($tf->handle_http($t) == 0, 'cgi-env: CONTENT_LENGTH');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/mod-compress.conf b/tests/mod-compress.conf
deleted file mode 100644
index 02da9049..00000000
--- a/tests/mod-compress.conf
+++ /dev/null
@@ -1,32 +0,0 @@
-debug.log-request-handling = "enable"
-debug.log-response-header = "disable"
-debug.log-request-header = "disable"
-
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-## 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.modules = (
- "mod_compress"
-)
-
-######################## MODULE CONFIG ############################
-
-mimetype.assign = (
- ".html" => "text/html",
- ".txt" => "text/plain",
-)
-
-$HTTP["host"] == "cache.example.org" {
- compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
-}
-compress.filetype = ("text/plain", "text/html")
-
-compress.allowed-encodings = ( "gzip", "deflate" )
diff --git a/tests/mod-compress.t b/tests/mod-compress.t
deleted file mode 100755
index 82927cea..00000000
--- a/tests/mod-compress.t
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/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 => 11;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-$tf->{CONFIGFILE} = 'mod-compress.conf';
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Accept-Encoding: deflate
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '' } ];
-ok($tf->handle_http($t) == 0, 'Vary is set');
-
-SKIP: {
- skip "disabled for now", 4;
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Accept-Encoding: deflate
-Host: no-cache.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1288', '+Content-Encoding' => '' } ];
-ok($tf->handle_http($t) == 0, 'deflate - Content-Length and Content-Encoding is set');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Accept-Encoding: deflate
-Host: cache.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1288', '+Content-Encoding' => '' } ];
-ok($tf->handle_http($t) == 0, 'deflate - Content-Length and Content-Encoding is set');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Accept-Encoding: gzip
-Host: no-cache.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1306', '+Content-Encoding' => '' } ];
-ok($tf->handle_http($t) == 0, 'gzip - Content-Length and Content-Encoding is set');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Accept-Encoding: gzip
-Host: cache.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1306', '+Content-Encoding' => '' } ];
-ok($tf->handle_http($t) == 0, 'gzip - Content-Length and Content-Encoding is set');
-}
-
-
-$t->{REQUEST} = ( <<EOF
-GET /index.txt HTTP/1.0
-Accept-Encoding: gzip, deflate
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', '+Content-Encoding' => '' } ];
-ok($tf->handle_http($t) == 0, 'gzip, deflate - Content-Length and Content-Encoding is set');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.txt HTTP/1.0
-Accept-Encoding: gzip, deflate
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', '+Content-Encoding' => '', 'Content-Type' => "text/plain" } ];
-ok($tf->handle_http($t) == 0, 'Content-Type is from the original file');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.txt HTTP/1.0
-Accept-encoding:
-X-Accept-encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0
-User-Agent: MYOB/6.66 (AN/ON)
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Type' => "text/plain" } ];
-ok($tf->handle_http($t) == 0, 'Empty Accept-Encoding');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.txt HTTP/1.0
-Accept-Encoding: bzip2, gzip, deflate
-Host: cache.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Encoding' => 'gzip', 'Content-Type' => "text/plain" } ];
-ok($tf->handle_http($t) == 0, 'bzip2 requested but disabled');
-
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
diff --git a/tests/mod-proxy.t.deprecated b/tests/mod-proxy.t.deprecated
deleted file mode 100644
index dc161726..00000000
--- a/tests/mod-proxy.t.deprecated
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/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 => 21;
-use LightyTest;
-
-my $tf_proxy = LightyTest->new();
-my $tf_backend1 = LightyTest->new();
-my $tf_backend2 = LightyTest->new();
-
-my $t;
-
-## we need two procs
-## 1. the real webserver
-## 2. the proxy server
-
-SKIP: {
- skip "disabled for now", 21;
-$tf_proxy->{PORT} = 2048;
-$tf_proxy->{CONFIGFILE} = 'proxy.conf';
-$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
-
-$tf_backend1->{PORT} = 2050;
-$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
-$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
-
-$tf_backend2->{PORT} = 2051;
-$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
-$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
-
-
-ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
-
-ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
-
-sleep(1);
-
-$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' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-rr/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-rr/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-fair/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
-
-## backend 2 starting
-ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-rr/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-rr/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-hash/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-hash/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-hash/bar HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-hash/bar HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
-
-## backend 1 stopping, failover
-ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-hash/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-hash/bar HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-rr/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
-
-$t->{REQUEST} = ( <<EOF
-GET /balance-fair/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
-ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
-
-
-ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
-
-ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
-}
diff --git a/tests/mod-redirect.t b/tests/mod-redirect.t
deleted file mode 100755
index bd962987..00000000
--- a/tests/mod-redirect.t
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/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 = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /redirect/ HTTP/1.0
-Host: vvv.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/' } ];
-ok($tf->handle_http($t) == 0, 'external redirect');
-
-$t->{REQUEST} = ( <<EOF
-GET /redirect/ HTTP/1.0
-Host: zzz.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/zzz' } ];
-ok($tf->handle_http($t) == 0, 'external redirect with cond regsub');
-
-$t->{REQUEST} = ( <<EOF
-GET /redirect/ HTTP/1.0
-Host: remoteip.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/127.0.0.1' } ];
-ok($tf->handle_http($t) == 0, 'external redirect with cond regsub on remoteip');
-
-$t->{REQUEST} = ( <<EOF
-GET /redirect/ HTTP/1.0
-Host: remoteip2.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/remoteip2' } ];
-ok($tf->handle_http($t) == 0, 'external redirect with cond regsub on remoteip2');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
diff --git a/tests/mod-rewrite.t b/tests/mod-rewrite.t
deleted file mode 100755
index 5cb3323e..00000000
--- a/tests/mod-rewrite.t
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/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;
-
-my $tf = LightyTest->new();
-my $t;
-my $php_child = -1;
-
-my $phpbin = (defined $ENV{'PHP'} ? $ENV{'PHP'} : '/usr/bin/php-cgi');
-
-SKIP: {
- skip "PHP already running on port 1026", 1 if $tf->listening_on(1026);
- skip "no php binary found", 1 unless -x $phpbin;
- ok(-1 != ($php_child = $tf->spawnfcgi($phpbin, 1026)), "Spawning php");
-}
-
-SKIP: {
- skip "no PHP running on port 1026", 5 unless $tf->listening_on(1026);
-
- ok($tf->start_proc == 0, "Starting lighttpd") or goto cleanup;
-
- $t->{REQUEST} = ( <<EOF
-GET /rewrite/foo HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '' } ];
- ok($tf->handle_http($t) == 0, 'valid request');
-
- $t->{REQUEST} = ( <<EOF
-GET /rewrite/foo?a=b HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'a=b' } ];
- ok($tf->handle_http($t) == 0, 'valid request');
-
- $t->{REQUEST} = ( <<EOF
-GET /rewrite/bar?a=b HTTP/1.0
-Host: www.example.org
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'bar&a=b' } ];
- ok($tf->handle_http($t) == 0, 'valid request');
-
- ok($tf->stop_proc == 0, "Stopping lighttpd");
-}
-
-SKIP: {
- skip "PHP not started, cannot stop it", 1 unless $php_child != -1;
- ok(0 == $tf->endspawnfcgi($php_child), "Stopping php");
-}
-
-
-exit 0;
-
-cleanup: ;
-
-$tf->endspawnfcgi($php_child) if $php_child != -1;
-
-die();
diff --git a/tests/mod-secdownload.t b/tests/mod-secdownload.t
deleted file mode 100755
index 3b5baef0..00000000
--- a/tests/mod-secdownload.t
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/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 - 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
deleted file mode 100755
index 90d764f8..00000000
--- a/tests/mod-setenv.t
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/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 = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?TRAC_ENV HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'tracenv' } ];
-ok($tf->handle_http($t) == 0, 'query first setenv');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?SETENV HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'setenv' } ];
-ok($tf->handle_http($t) == 0, 'query second setenv');
-
-$t->{REQUEST} = ( <<EOF
-GET /get-header.pl?HTTP_FOO HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo' } ];
-ok($tf->handle_http($t) == 0, 'query add-request-header');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'BAR' => 'foo' } ];
-ok($tf->handle_http($t) == 0, 'query add-response-header');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
diff --git a/tests/mod-ssi.t b/tests/mod-ssi.t
deleted file mode 100755
index 6254e472..00000000
--- a/tests/mod-ssi.t
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/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 => 4;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-# mod-cgi
-#
-$t->{REQUEST} = ( <<EOF
-GET /ssi.shtml HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => "/ssi.shtml\n" } ];
-ok($tf->handle_http($t) == 0, 'ssi - echo ');
-
-
-## bug #280
-$t->{REQUEST} = ( <<EOF
-GET /exec-date.shtml HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => "2\n\n" } ];
-ok($tf->handle_http($t) == 0, 'ssi - echo ');
-
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/mod-userdir.t b/tests/mod-userdir.t
deleted file mode 100755
index 10eb99ab..00000000
--- a/tests/mod-userdir.t
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/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 => 5;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-# get current user
-
-$t->{REQUEST} = ( <<EOF
-GET /~foobar/ HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'valid user');
-
-$t->{REQUEST} = ( <<EOF
-GET /~jan HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://'.$tf->{HOSTNAME}.':'.$tf->{PORT}.'/~jan/' } ];
-ok($tf->handle_http($t) == 0, 'valid user + redirect');
-
-$t->{REQUEST} = ( <<EOF
-GET /~jan HTTP/1.0
-Host: www.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://www.example.org/~jan/' } ];
-ok($tf->handle_http($t) == 0, 'valid user + redirect');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/prepare.sh b/tests/prepare.sh
deleted file mode 100755
index 71816d11..00000000
--- a/tests/prepare.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-
-if test x$srcdir = x; then
- srcdir=.
-fi
-
-if test x$top_builddir = x; then
- top_builddir=..
-fi
-
-tmpdir=$top_builddir/tests/tmp/lighttpd
-
-# create test-framework
-rm -rf $tmpdir
-mkdir -p $tmpdir/servers/www.example.org/pages/
-mkdir -p $tmpdir/servers/www.example.org/pages/dummydir/
-mkdir -p $tmpdir/servers/www.example.org/pages/go/
-mkdir -p $tmpdir/servers/www.example.org/pages/expire/
-mkdir -p $tmpdir/servers/www.example.org/pages/indexfile/
-mkdir -p $tmpdir/servers/123.example.org/pages/
-mkdir -p $tmpdir/logs/
-mkdir -p $tmpdir/cache/
-mkdir -p $tmpdir/cache/compress/
-
-# copy everything into the right places
-cp $srcdir/docroot/www/*.html \
- $srcdir/docroot/www/*.php \
- $srcdir/docroot/www/*.pl \
- $srcdir/docroot/www/*.fcgi \
- $srcdir/docroot/www/*.shtml \
- $srcdir/docroot/www/*.txt $tmpdir/servers/www.example.org/pages/
-cp $srcdir/docroot/www/go/*.php $tmpdir/servers/www.example.org/pages/go/
-cp $srcdir/docroot/www/expire/*.txt $tmpdir/servers/www.example.org/pages/expire/
-cp $srcdir/docroot/www/indexfile/*.php $tmpdir/servers/www.example.org/pages/indexfile/
-cp $srcdir/docroot/123/*.txt \
- $srcdir/docroot/123/*.html \
- $srcdir/docroot/123/*.php \
- $srcdir/docroot/123/*.bla $tmpdir/servers/123.example.org/pages/
-cp $srcdir/lighttpd.user $tmpdir/
-cp $srcdir/lighttpd.htpasswd $tmpdir/
-cp $srcdir/var-include-sub.conf $tmpdir/../
-touch $tmpdir/servers/www.example.org/pages/image.jpg \
- $tmpdir/servers/www.example.org/pages/image.JPG \
- $tmpdir/servers/www.example.org/pages/Foo.txt \
- $tmpdir/servers/www.example.org/pages/a
-echo "12345" > $tmpdir/servers/www.example.org/pages/range.pdf
-
-printf "%-40s" "preparing infrastructure"
-
-exit 0
diff --git a/tests/proxy-backend-1.conf b/tests/proxy-backend-1.conf
deleted file mode 100644
index 82ee19d4..00000000
--- a/tests/proxy-backend-1.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-1.pid"
-
-include "default.conf"
-
-
-server.tag = "proxy-backend-1"
diff --git a/tests/proxy-backend-2.conf b/tests/proxy-backend-2.conf
deleted file mode 100644
index 2580457d..00000000
--- a/tests/proxy-backend-2.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-2.pid"
-
-include "default.conf"
-
-
-server.tag = "proxy-backend-2"
diff --git a/tests/proxy.conf b/tests/proxy.conf
deleted file mode 100644
index 7285bdd2..00000000
--- a/tests/proxy.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
-server.tag = "proxy"
-
-include "default.conf"
-
-## 127.0.0.1 and 127.0.0.2 are the same host
-proxy.server = (
- "" => (( "host" => "127.0.0.1",
- "port" => 2050 ),
- ( "host" => "127.0.0.2",
- "port" => 2051 )
- ))
-
-$HTTP["url"] =~ "^/balance-rr/" {
- proxy.balance = "round-robin"
-}
-
-$HTTP["url"] =~ "^/balance-hash/" {
- proxy.balance = "hash"
-}
-
-$HTTP["url"] =~ "^/balance-fair/" {
- proxy.balance = "fair"
-}
-
diff --git a/tests/request.t b/tests/request.t
deleted file mode 100755
index 8a53ac52..00000000
--- a/tests/request.t
+++ /dev/null
@@ -1,418 +0,0 @@
-#!/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 => 43;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-## Basic Request-Handling
-
-$t->{REQUEST} = ( <<EOF
-GET /foobar HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'file not found');
-
-$t->{REQUEST} = ( <<EOF
-GET /foobar?foobar HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'file not found + querystring');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain' } ];
-ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype text/plain');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.html HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/html' } ];
-ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype text/html');
-
-$t->{REQUEST} = ( <<EOF
-GET /dummyfile.bla HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'application/octet-stream' } ];
-ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype application/octet-stream');
-
-$t->{REQUEST} = ( <<EOF
-POST / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 411 } ];
-ok($tf->handle_http($t) == 0, 'POST request, no Content-Length');
-
-
-$t->{REQUEST} = ( <<EOF
-POST / HTTP/1.0
-Content-type: application/x-www-form-urlencoded
-Content-length: 0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'POST request, empty request-body');
-
-$t->{REQUEST} = ( <<EOF
-HEAD / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-HTTP-Content' => ''} ];
-ok($tf->handle_http($t) == 0, 'HEAD request, no content');
-
-$t->{REQUEST} = ( <<EOF
-HEAD /12345.html HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-HTTP-Content' => '', 'Content-Type' => 'text/html', 'Content-Length' => '6'} ];
-ok($tf->handle_http($t) == 0, 'HEAD request, mimetype text/html, content-length');
-
-$t->{REQUEST} = ( <<EOF
-HEAD http://123.example.org/12345.html HTTP/1.1
-Connection: close
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, '-HTTP-Content' => '', 'Content-Type' => 'text/html', 'Content-Length' => '6'} ];
-ok($tf->handle_http($t) == 0, 'Hostname in first line, HTTP/1.1');
-
-$t->{REQUEST} = ( <<EOF
-HEAD https://123.example.org/12345.html HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-HTTP-Content' => '', 'Content-Type' => 'text/html', 'Content-Length' => '6'} ];
-ok($tf->handle_http($t) == 0, 'Hostname in first line as https url');
-
-$t->{REQUEST} = ( <<EOF
-HEAD /foobar?foobar HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, '-HTTP-Content' => '' } ];
-ok($tf->handle_http($t) == 0, 'HEAD request, file-not-found, query-string');
-
-TODO: {
- local $TODO = "The test is broken, the feature works";
-$t->{REQUEST} = ( <<EOF
-POST / HTTP/1.1
-Connection: close
-Content-Length: 4
-Host: www.example.org
-Expect: 100-continue
-
-1234
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 100} ];
-ok($tf->handle_http($t) == 0, 'Continue, Expect');
-}
-## ranges
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=0-3
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 206, 'HTTP-Content' => '1234' } ];
-ok($tf->handle_http($t) == 0, 'GET, Range 0-3');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=-3
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 206, 'HTTP-Content' => '45'."\n" } ];
-ok($tf->handle_http($t) == 0, 'GET, Range -3');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=3-
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 206, 'HTTP-Content' => '45'."\n" } ];
-ok($tf->handle_http($t) == 0, 'GET, Range 3-');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=0-1,3-4
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 206, 'HTTP-Content' => <<EOF
-\r
---fkj49sn38dcn3\r
-Content-Range: bytes 0-1/6\r
-Content-Type: text/plain\r
-\r
-12\r
---fkj49sn38dcn3\r
-Content-Range: bytes 3-4/6\r
-Content-Type: text/plain\r
-\r
-45\r
---fkj49sn38dcn3--\r
-EOF
- } ];
-ok($tf->handle_http($t) == 0, 'GET, Range 0-1,3-4');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=0--
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'GET, Range 0--');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=-2-3
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'GET, Range -2-3');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=-0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 416, 'HTTP-Content' => <<EOF
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>416 - Requested Range Not Satisfiable</title>
- </head>
- <body>
- <h1>416 - Requested Range Not Satisfiable</h1>
- </body>
-</html>
-EOF
- } ];
-ok($tf->handle_http($t) == 0, 'GET, Range -0');
-
-$t->{REQUEST} = ( <<EOF
-GET /12345.txt HTTP/1.0
-Host: 123.example.org
-Range: bytes=25-
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 416, 'HTTP-Content' => <<EOF
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>416 - Requested Range Not Satisfiable</title>
- </head>
- <body>
- <h1>416 - Requested Range Not Satisfiable</h1>
- </body>
-</html>
-EOF
- } ];
-
-ok($tf->handle_http($t) == 0, 'GET, Range start out of range');
-
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Hsgfsdjf: asdfhdf
-hdhd: shdfhfdasd
-hfhr: jfghsdfg
-jfuuehdmn: sfdgjfdg
-jvcbzufdg: sgfdfg
-hrnvcnd: jfjdfg
-jfusfdngmd: gfjgfdusdfg
-nfj: jgfdjdfg
-jfue: jfdfdg
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'larger headers');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Host: www.example.org
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Duplicate Host headers, Bug #25');
-
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Content-Length: 5
-Content-Length: 4
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Duplicate Content-Length headers');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: 5
-If-None-Match: 4
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Duplicate If-None-Match headers');
-
-TODO: {
- local $TODO = "Duplicate checks are broken for now, ignore them";
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Content-Type: 5
-Content-Type: 4
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Duplicate Content-Type headers');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Range: bytes=5-6
-Range: bytes=5-9
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Duplicate Range headers');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: 5
-If-Modified-Since: 4
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'Duplicate If-Modified-Since headers');
-}
-$t->{REQUEST} = ( <<EOF
-GET /range.pdf HTTP/1.0
-Range: bytes=0-
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'GET, Range with range-requests-disabled');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-Content-Length: 4
-
-1234
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'GET with Content-Length');
-
-$t->{REQUEST} = ( <<EOF
-OPTIONS / HTTP/1.0
-Content-Length: 4
-
-1234
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'OPTIONS with Content-Length');
-
-$t->{REQUEST} = ( <<EOF
-OPTIONS rtsp://221.192.134.146:80 RTSP/1.1
-Host: 221.192.134.146:80
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 505 } ];
-ok($tf->handle_http($t) == 0, 'OPTIONS for RTSP');
-
-$t->{REQUEST} = ( <<EOF
-HEAD / HTTP/1.0
-Content-Length: 4
-
-1234
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'HEAD with Content-Length');
-
-TODO: {
- local $TODO = "to be fixed later";
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 2036 00:00:02 GMT
-If-Modified-Since: Sun, 01 Jan 2036 00:00:02 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304} ];
-ok($tf->handle_http($t) == 0, 'Duplicate If-Mod-Since, with equal timestamps');
-}
-
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: \0\r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
-ok($tf->handle_http($t) == 0, 'invalid chars in Header values (bug #1286)');
-
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: \r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'empty If-Modified-Since');
-
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: foobar\r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'broken If-Modified-Since');
-
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: this string is too long to be a valid timestamp\r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'broken If-Modified-Since');
-
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-If-Modified-Since2: Sun, 01 Jan 2036 00:00:03 GMT
-If-Modified-Since: Sun, 01 Jan 2036 00:00:02 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Similar Headers (bug #1287)');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 2036 00:00:02 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, 'Content-Type' => 'text/html' } ];
-ok($tf->handle_http($t) == 0, 'If-Modified-Since');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 2036 00:00:02 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, '-Content-Length' => '' } ];
-ok($tf->handle_http($t) == 0, 'Status 304 has no Content-Length (#1002)');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/run-tests.pl b/tests/run-tests.pl
deleted file mode 100755
index 3650d557..00000000
--- a/tests/run-tests.pl
+++ /dev/null
@@ -1,20 +0,0 @@
-#! /usr/bin/env perl
-
-use strict;
-
-use Test::Harness qw(&runtests $verbose);
-$verbose = (defined $ENV{'VERBOSE'} ? $ENV{'VERBOSE'} : 0);
-my $tests = (defined $ENV{'RUNTESTS'} ? $ENV{'RUNTESTS'} : '');
-
-my $srcdir = (defined $ENV{'srcdir'} ? $ENV{'srcdir'} : '.');
-
-opendir DIR, $srcdir;
-my (@fs, $f);
-while ($f = readdir(DIR)) {
- if ($f =~ /^(.*)\.t$/) {
- next if ($tests ne '' and $tests !~ /(^|\s+)$1(\s+|$)/);
- push @fs, $srcdir.'/'.$f;
- }
-}
-closedir DIR;
-runtests @fs;
diff --git a/tests/symlink.t b/tests/symlink.t
deleted file mode 100755
index 187d9015..00000000
--- a/tests/symlink.t
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/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");
-};
diff --git a/tests/var-include-sub.conf b/tests/var-include-sub.conf
deleted file mode 100644
index 3e0c3b9c..00000000
--- a/tests/var-include-sub.conf
+++ /dev/null
@@ -1,34 +0,0 @@
-# file to be included
-$HTTP["host"] =~ "^" + server.name + "$" {
- url.redirect = (
- "^/include$" => "/good_include",
- "^/concat$" => "/good_" + "concat",
- "^/servername1$" => "/good_" + server.name,
- "^/servername2$" => server.name + "/good_",
- "^/servername3$" => "/good_" + server.name + "/",
- "^/var.myvar$" => "/good_var_myvar" + var.myvar,
- "^/myvar$" => "/good_myvar" + myvar,
- "^/number1$" => "/good_number" + one,
- "^/number2$" => one + "/good_number",
- "^/env$" => "/" + env.env_test,
- )
- num = 1
- num2 = 2
- num2 += 1
- # without var prefix
- mystr = "string"
- mystr += "_append"
- # from parent
- one += 1
- url.redirect += (
- "^/array_append$" => "/good_array_append",
- "^/string_append$" => "/good_" + mystr,
- "^/number_append$" => "/good_" + one,
- )
-
- cmd = "echo cmd_ok=456"
- include_shell cmd
- url.redirect += (
- "^/include_shell$" => "/good_include_shell_" + cmd_ok,
- )
-}
diff --git a/tests/var-include.conf b/tests/var-include.conf
deleted file mode 100644
index 397c91d3..00000000
--- a/tests/var-include.conf
+++ /dev/null
@@ -1,41 +0,0 @@
-
-debug.log-request-handling = "enable"
-debug.log-condition-handling = "enable"
-
-server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
-server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
-
-## bind to port (default: 80)
-server.port = 2048
-
-## 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 = "Apache 1.3.29"
-
-
-server.modules = ( "mod_redirect",
- "mod_accesslog" )
-
-######################## MODULE CONFIG ############################
-
-
-accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
-
-mimetype.assign = ( ".html" => "text/html" )
-
-url.redirect = ("^" => "/default")
-
-$HTTP["host"] == "www.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "www.example.org"
- url.redirect = ("^" => "/redirect")
-}
-$HTTP["host"] == "test.example.org" {
- server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
- server.name = "test.example.org"
- var.myvar = "good"
- var.one = 1
- include "var-include-sub.conf"
-}
diff --git a/tests/wrapper.sh b/tests/wrapper.sh
deleted file mode 100755
index 07cc784f..00000000
--- a/tests/wrapper.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-## get some parameters from the makefile
-
-srcdir=$1
-top_builddir=$2
-export SHELL srcdir top_builddir
-
-$3