diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2010-03-25 16:08:33 +0000 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2010-03-25 16:08:33 +0000 |
commit | 11527683bf98eabcbff2507aa894bd71a96167e8 (patch) | |
tree | 3bde02d77c306dc9ae4985ac597b8f67b8e18056 /contrib/package/uhttpd | |
parent | e47ac7cabc225eae353fd7c347f123a76897ef4d (diff) |
contrib/package: remove px5g, uhttpd - moved to OpenWrt core packages
Diffstat (limited to 'contrib/package/uhttpd')
-rw-r--r-- | contrib/package/uhttpd/Makefile | 92 | ||||
-rw-r--r-- | contrib/package/uhttpd/files/uhttpd.config | 53 | ||||
-rwxr-xr-x | contrib/package/uhttpd/files/uhttpd.init | 115 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/Makefile | 52 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-cgi.c | 561 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-cgi.h | 31 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-file.c | 395 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-file.h | 38 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-lua.c | 541 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-lua.h | 43 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-mimetypes.h | 80 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-tls.c | 82 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-tls.h | 35 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-utils.c | 749 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd-utils.h | 98 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd.c | 899 | ||||
-rw-r--r-- | contrib/package/uhttpd/src/uhttpd.h | 133 |
17 files changed, 0 insertions, 3997 deletions
diff --git a/contrib/package/uhttpd/Makefile b/contrib/package/uhttpd/Makefile deleted file mode 100644 index d5c07a359..000000000 --- a/contrib/package/uhttpd/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -# -# Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=uhttpd -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/uhttpd/default - SECTION:=net - CATEGORY:=Network - TITLE:=uHTTPd - tiny, single threaded HTTP server -endef - -define Package/uhttpd - $(Package/uhttpd/default) - MENU:=1 -endef - -define Package/uhttpd/description - uHTTPd is a tiny single threaded HTTP server with TLS, CGI and Lua - support. It is intended as a drop-in replacement for the Busybox - HTTP daemon. -endef - - -define Package/uhttpd-mod-tls - $(Package/uhttpd/default) - TITLE+= (TLS plugin) - DEPENDS:=uhttpd +libcyassl -endef - -define Package/uhttpd-mod-tls/description - The TLS plugin adds HTTPS support to uHTTPd. -endef - - -define Package/uhttpd-mod-lua - $(Package/uhttpd/default) - TITLE+= (Lua plugin) - DEPENDS:=uhttpd +liblua -endef - -define Package/uhttpd-mod-lua/description - The Lua plugin adds a CGI-like Lua runtime interface to uHTTPd. -endef - - -# hack to use CyASSL headers -TARGET_CFLAGS += -I$(firstword $(wildcard $(BUILD_DIR)/cyassl-*/include)) -MAKE_VARS += FPIC="$(FPIC)" - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/uhttpd/conffiles -/etc/config/uhttpd -endef - -define Package/uhttpd/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/uhttpd.init $(1)/etc/init.d/uhttpd - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_CONF) ./files/uhttpd.config $(1)/etc/config/uhttpd - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd $(1)/usr/sbin/uhttpd -endef - -define Package/uhttpd-mod-tls/install - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_tls.so $(1)/usr/lib/ -endef - -define Package/uhttpd-mod-lua/install - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_lua.so $(1)/usr/lib/ -endef - - -$(eval $(call BuildPackage,uhttpd)) -$(eval $(call BuildPackage,uhttpd-mod-tls)) -$(eval $(call BuildPackage,uhttpd-mod-lua)) diff --git a/contrib/package/uhttpd/files/uhttpd.config b/contrib/package/uhttpd/files/uhttpd.config deleted file mode 100644 index 0bca4f516..000000000 --- a/contrib/package/uhttpd/files/uhttpd.config +++ /dev/null @@ -1,53 +0,0 @@ -# Server configuration -config uhttpd main - - # Server document root - option home /www - - # Certificate and private key for HTTPS. - # If no listen_https addresses are given, - # the key options are ignored. - option cert /etc/uhttpd.crt - option key /etc/uhttpd.key - - # CGI url prefix, will be searched in docroot. - # Default is /cgi-bin - option cgi_prefix /cgi-bin - - # Lua url prefix and handler script. - # Lua support is disabled if no prefix given. -# option lua_prefix /luci -# option lua_handler /usr/lib/lua/luci/sgi/uhttpd.lua - - # HTTP listen addresses, multiple allowed - list listen_http 0.0.0.0:80 -# list listen_http [::]:80 - - # HTTPS listen addresses, multiple allowed - list listen_https 0.0.0.0:443 -# list listen_https [::]:443 - - # Basic auth realm, defaults to local hostname -# option realm OpenWrt - - # Configuration file in busybox httpd format -# option config /etc/httpd.conf - - -# Certificate defaults for px5g key generator -config cert px5g - - # Validity time - option days 730 - - # RSA key size - option bits 1024 - - # Location - option country DE - option state Berlin - option location Berlin - - # Common name - option commonname OpenWrt - diff --git a/contrib/package/uhttpd/files/uhttpd.init b/contrib/package/uhttpd/files/uhttpd.init deleted file mode 100755 index a25bf789c..000000000 --- a/contrib/package/uhttpd/files/uhttpd.init +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2010 Jo-Philipp Wich - -START=50 -UHTTPD_BIN="/usr/sbin/uhttpd" -PX5G_BIN="/usr/sbin/px5g" - - -append_listen_http() { - append UHTTPD_ARGS "-p $1" -} - -append_listen_https() { - append UHTTPD_ARGS "-s $1" -} - -append_arg() { - local cfg="$1" - local var="$2" - local opt="$3" - local def="$4" - local val - - config_get val "$cfg" "$var" - [ -n "$val" -o -n "$def" ] && append UHTTPD_ARGS "$opt ${val:-$def}" -} - -generate_keys() { - local cfg="$1" - local key="$2" - local crt="$3" - local days bits country state location commonname - - config_get days "$cfg" days - config_get bits "$cfg" bits - config_get country "$cfg" country - config_get state "$cfg" state - config_get location "$cfg" location - config_get commonname "$cfg" commonname - - [ -x "$PX5G_BIN" ] && { - $PX5G_BIN selfsigned -der \ - -days ${days:-730} -newkey rsa:${bits:-1024} -keyout "$UHTTPD_KEY" -out "$UHTTPD_CERT" \ - -subj /C=${country:-DE}/ST=${state:-Saxony}/L=${location:-Leipzig}/CN=${commonname:-OpenWrt} - } || { - echo "WARNING: the specified certificate and key" \ - "files do not exist and the px5g generator" \ - "is not available, skipping SSL setup." - } -} - -start_instance() -{ - UHTTPD_ARGS="" - UHTTPD_CERT="" - UHTTPD_KEY="" - - local cfg="$1" - local realm="$(uci get system.@system[0].hostname 2>/dev/null)" - local ssl - - append_arg "$cfg" home "-h" - append_arg "$cfg" realm "-r" "${realm:-OpenWrt}" - append_arg "$cfg" config "-c" - append_arg "$cfg" cgi_prefix "-x" - append_arg "$cfg" lua_prefix "-l" - append_arg "$cfg" lua_handler "-L" - - config_list_foreach "$cfg" listen_http \ - append_listen_http - - config_get ssl "$cfg" listen_https - config_get UHTTPD_KEY "$cfg" key /etc/uhttpd.key - config_get UHTTPD_CERT "$cfg" cert /etc/uhttpd.crt - - [ -n "$ssl" ] && { - [ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] || { - config_foreach generate_keys cert - } - - [ -f "$UHTTPD_CERT" -a -f "$UHTTPD_KEY" ] && { - append_arg "$cfg" cert "-C" - append_arg "$cfg" key "-K" - - config_list_foreach "$cfg" listen_https \ - append_listen_https - } - } - - start-stop-daemon -S -x $UHTTPD_BIN \ - -p /var/run/uhttpd_${cfg}.pid \ - -m -b -- -f $UHTTPD_ARGS -} - -stop_instance() -{ - local cfg="$1" - - [ -f /var/run/uhttpd_${cfg}.pid ] && { - start-stop-daemon -K -q -n ${UHTTPD_BIN##*/} \ - -p /var/run/uhttpd_${cfg}.pid -s TERM - - rm -f /var/run/uhttpd_${cfg}.pid - } -} - -start() { - config_load uhttpd - config_foreach start_instance uhttpd -} - -stop() { - config_load uhttpd - config_foreach stop_instance uhttpd -} diff --git a/contrib/package/uhttpd/src/Makefile b/contrib/package/uhttpd/src/Makefile deleted file mode 100644 index 06d61bdef..000000000 --- a/contrib/package/uhttpd/src/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -CGI_SUPPORT ?= 1 -LUA_SUPPORT ?= 1 -TLS_SUPPORT ?= 1 - -CFLAGS ?= -I./lua-5.1.4/src -I./cyassl-1.4.0/include -O0 -ggdb3 -LDFLAGS ?= -L./lua-5.1.4/src -L./cyassl-1.4.0/src/.libs - -CFLAGS += -Wall --std=gnu99 - -OBJ = uhttpd.o uhttpd-file.o uhttpd-utils.o -LIB = -Wl,--export-dynamic -lcrypt -ldl - -TLSLIB = -LUALIB = - - -world: compile - -ifeq ($(CGI_SUPPORT),1) - OBJ += uhttpd-cgi.o - CFLAGS += -DHAVE_CGI -endif - -ifeq ($(LUA_SUPPORT),1) - CFLAGS += -DHAVE_LUA - LUALIB = uhttpd_lua.so - - $(LUALIB): uhttpd-lua.c - $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \ - -shared -lm -llua -ldl \ - -o $(LUALIB) uhttpd-lua.c -endif - -ifeq ($(TLS_SUPPORT),1) - CFLAGS += -DHAVE_TLS - TLSLIB = uhttpd_tls.so - - $(TLSLIB): uhttpd-tls.c - $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \ - -shared -lcyassl \ - -o $(TLSLIB) uhttpd-tls.c -endif - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - -compile: $(OBJ) $(TLSLIB) $(LUALIB) - $(CC) -o uhttpd $(LDFLAGS) $(LIB) $(OBJ) - -clean: - rm -f *.o *.so uhttpd - diff --git a/contrib/package/uhttpd/src/uhttpd-cgi.c b/contrib/package/uhttpd/src/uhttpd-cgi.c deleted file mode 100644 index 5565197ca..000000000 --- a/contrib/package/uhttpd/src/uhttpd-cgi.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - CGI handler - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "uhttpd.h" -#include "uhttpd-utils.h" -#include "uhttpd-cgi.h" - -static struct http_response * uh_cgi_header_parse(char *buf, int len, int *off) -{ - char *bufptr = NULL; - char *hdrname = NULL; - int hdrcount = 0; - int pos = 0; - - static struct http_response res; - - - if( ((bufptr = strfind(buf, len, "\r\n\r\n", 4)) != NULL) || - ((bufptr = strfind(buf, len, "\n\n", 2)) != NULL) - ) { - *off = (int)(bufptr - buf) + ((bufptr[0] == '\r') ? 4 : 2); - - memset(&res, 0, sizeof(res)); - - res.statuscode = 200; - res.statusmsg = "OK"; - - bufptr = &buf[0]; - - for( pos = 0; pos < len; pos++ ) - { - if( !hdrname && (buf[pos] == ':') ) - { - buf[pos++] = 0; - - if( (pos < len) && (buf[pos] == ' ') ) - pos++; - - if( pos < len ) - { - hdrname = bufptr; - bufptr = &buf[pos]; - } - } - - else if( (buf[pos] == '\r') || (buf[pos] == '\n') ) - { - buf[pos++] = 0; - - if( ! hdrname ) - break; - - if( (pos < len) && (buf[pos] == '\n') ) - pos++; - - if( pos < len ) - { - if( (hdrcount + 1) < array_size(res.headers) ) - { - if( ! strcasecmp(hdrname, "Status") ) - { - res.statuscode = atoi(bufptr); - - if( res.statuscode < 100 ) - res.statuscode = 200; - - if( ((bufptr = strchr(bufptr, ' ')) != NULL) && (&bufptr[1] != 0) ) - res.statusmsg = &bufptr[1]; - } - else - { - res.headers[hdrcount++] = hdrname; - res.headers[hdrcount++] = bufptr; - } - - bufptr = &buf[pos]; - hdrname = NULL; - } - else - { - return NULL; - } - } - } - } - - return &res; - } - - return NULL; -} - -static char * uh_cgi_header_lookup(struct http_response *res, const char *hdrname) -{ - int i; - - foreach_header(i, res->headers) - { - if( ! strcasecmp(res->headers[i], hdrname) ) - return res->headers[i+1]; - } - - return NULL; -} - -static int uh_cgi_error_500(struct client *cl, struct http_request *req, const char *message) -{ - if( uh_http_sendf(cl, NULL, - "HTTP/%.1f 500 Internal Server Error\r\n" - "Content-Type: text/plain\r\n%s\r\n", - req->version, - (req->version > 1.0) - ? "Transfer-Encoding: chunked\r\n" : "" - ) >= 0 - ) { - return uh_http_send(cl, req, message, -1); - } - - return -1; -} - - -void uh_cgi_request(struct client *cl, struct http_request *req, struct path_info *pi) -{ - int i, hdroff, bufoff; - int hdrlen = 0; - int buflen = 0; - int fd_max = 0; - int content_length = 0; - int header_sent = 0; - - int rfd[2] = { 0, 0 }; - int wfd[2] = { 0, 0 }; - - char buf[UH_LIMIT_MSGHEAD]; - char hdr[UH_LIMIT_MSGHEAD]; - - pid_t child; - - fd_set reader; - fd_set writer; - - struct sigaction sa; - struct timeval timeout; - struct http_response *res; - - - /* spawn pipes for me->child, child->me */ - if( (pipe(rfd) < 0) || (pipe(wfd) < 0) ) - { - uh_http_sendhf(cl, 500, "Internal Server Error", - "Failed to create pipe: %s", strerror(errno)); - - if( rfd[0] > 0 ) close(rfd[0]); - if( rfd[1] > 0 ) close(rfd[1]); - if( wfd[0] > 0 ) close(wfd[0]); - if( wfd[1] > 0 ) close(wfd[1]); - - return; - } - - /* fork off child process */ - switch( (child = fork()) ) - { - /* oops */ - case -1: - uh_http_sendhf(cl, 500, "Internal Server Error", - "Failed to fork child: %s", strerror(errno)); - return; - - /* exec child */ - case 0: - /* restore SIGTERM */ - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigemptyset(&sa.sa_mask); - sigaction(SIGTERM, &sa, NULL); - - /* close loose pipe ends */ - close(rfd[0]); - close(wfd[1]); - - /* patch stdout and stdin to pipes */ - dup2(rfd[1], 1); - dup2(wfd[0], 0); - - /* check for regular, world-executable file */ - if( (pi->stat.st_mode & S_IFREG) && - (pi->stat.st_mode & S_IXOTH) - ) { - /* build environment */ - clearenv(); - - /* common information */ - setenv("GATEWAY_INTERFACE", "CGI/1.1", 1); - setenv("SERVER_SOFTWARE", "uHTTPd", 1); - setenv("PATH", "/sbin:/usr/sbin:/bin:/usr/bin", 1); - -#ifdef HAVE_TLS - /* https? */ - if( cl->tls ) - setenv("HTTPS", "on", 1); -#endif - - /* addresses */ - setenv("SERVER_NAME", sa_straddr(&cl->servaddr), 1); - setenv("SERVER_ADDR", sa_straddr(&cl->servaddr), 1); - setenv("SERVER_PORT", sa_strport(&cl->servaddr), 1); - setenv("REMOTE_HOST", sa_straddr(&cl->peeraddr), 1); - setenv("REMOTE_ADDR", sa_straddr(&cl->peeraddr), 1); - setenv("REMOTE_PORT", sa_strport(&cl->peeraddr), 1); - - /* path information */ - setenv("SCRIPT_NAME", pi->name, 1); - setenv("SCRIPT_FILENAME", pi->phys, 1); - setenv("DOCUMENT_ROOT", pi->root, 1); - setenv("QUERY_STRING", pi->query ? pi->query : "", 1); - - if( pi->info ) - setenv("PATH_INFO", pi->info, 1); - - - /* http version */ - if( req->version > 1.0 ) - setenv("SERVER_PROTOCOL", "HTTP/1.1", 1); - else - setenv("SERVER_PROTOCOL", "HTTP/1.0", 1); - - /* request method */ - switch( req->method ) - { - case UH_HTTP_MSG_GET: - setenv("REQUEST_METHOD", "GET", 1); - break; - - case UH_HTTP_MSG_HEAD: - setenv("REQUEST_METHOD", "HEAD", 1); - break; - - case UH_HTTP_MSG_POST: - setenv("REQUEST_METHOD", "POST", 1); - break; - } - - /* request url */ - setenv("REQUEST_URI", req->url, 1); - - /* remote user */ - if( req->realm ) - setenv("REMOTE_USER", req->realm->user, 1); - - /* request message headers */ - foreach_header(i, req->headers) - { - if( ! strcasecmp(req->headers[i], "Accept") ) - setenv("HTTP_ACCEPT", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Accept-Charset") ) - setenv("HTTP_ACCEPT_CHARSET", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Accept-Encoding") ) - setenv("HTTP_ACCEPT_ENCODING", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Accept-Language") ) - setenv("HTTP_ACCEPT_LANGUAGE", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Authorization") ) - setenv("HTTP_AUTHORIZATION", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Connection") ) - setenv("HTTP_CONNECTION", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Cookie") ) - setenv("HTTP_COOKIE", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Host") ) - setenv("HTTP_HOST", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Referer") ) - setenv("HTTP_REFERER", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "User-Agent") ) - setenv("HTTP_USER_AGENT", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Content-Type") ) - setenv("CONTENT_TYPE", req->headers[i+1], 1); - - else if( ! strcasecmp(req->headers[i], "Content-Length") ) - setenv("CONTENT_LENGTH", req->headers[i+1], 1); - } - - - /* execute child code ... */ - if( chdir(pi->root) ) - perror("chdir()"); - - execl(pi->phys, pi->phys, NULL); - - /* in case it fails ... */ - printf( - "Status: 500 Internal Server Error\r\n\r\n" - "Unable to launch the requested CGI program:\n" - " %s: %s\n", - pi->phys, strerror(errno) - ); - } - - /* 403 */ - else - { - printf( - "Status: 403 Forbidden\r\n\r\n" - "Access to this resource is forbidden\n" - ); - } - - close(wfd[0]); - close(rfd[1]); - exit(0); - - break; - - /* parent; handle I/O relaying */ - default: - /* close unneeded pipe ends */ - close(rfd[1]); - close(wfd[0]); - - /* max watch fd */ - fd_max = max(rfd[0], wfd[1]) + 1; - - /* find content length */ - if( req->method == UH_HTTP_MSG_POST ) - { - foreach_header(i, req->headers) - { - if( ! strcasecmp(req->headers[i], "Content-Length") ) - { - content_length = atoi(req->headers[i+1]); - break; - } - } - } - - - memset(hdr, 0, sizeof(hdr)); - -#define ensure(x) \ - do { if( x < 0 ) goto out; } while(0) - - /* I/O loop, watch our pipe ends and dispatch child reads/writes from/to socket */ - while( 1 ) - { - FD_ZERO(&reader); - FD_ZERO(&writer); - - FD_SET(rfd[0], &reader); - FD_SET(wfd[1], &writer); - - timeout.tv_sec = 15; - timeout.tv_usec = 0; - - /* wait until we can read or write or both */ - if( select(fd_max, &reader, (content_length > -1) ? &writer : NULL, NULL, &timeout) > 0 ) - { - /* ready to write to cgi program */ - if( FD_ISSET(wfd[1], &writer) ) - { - /* there is unread post data waiting */ - if( content_length > 0 ) - { - /* read it from socket ... */ - if( (buflen = uh_tcp_recv(cl, buf, min(content_length, sizeof(buf)))) > 0 ) - { - /* ... and write it to child's stdin */ - if( write(wfd[1], buf, buflen) < 0 ) - perror("write()"); - - content_length -= buflen; - } - - /* unexpected eof! */ - else - { - if( write(wfd[1], "", 0) < 0 ) - perror("write()"); - - content_length = 0; - } - } - - /* there is no more post data, close pipe to child's stdin */ - else if( content_length > -1 ) - { - close(wfd[1]); - content_length = -1; - } - } - - /* ready to read from cgi program */ - if( FD_ISSET(rfd[0], &reader) ) - { - /* read data from child ... */ - if( (buflen = read(rfd[0], buf, sizeof(buf))) > 0 ) - { - /* we have not pushed out headers yet, parse input */ - if( ! header_sent ) - { - /* head buffer not full and no end yet */ - if( hdrlen < sizeof(hdr) ) - { - bufoff = min(buflen, sizeof(hdr) - hdrlen); - memcpy(&hdr[hdrlen], buf, bufoff); - hdrlen += bufoff; - } - else - { - bufoff = 0; - } - - - /* try to parse header ... */ - if( (res = uh_cgi_header_parse(hdr, hdrlen, &hdroff)) != NULL ) - { - /* write status */ - ensure(uh_http_sendf(cl, NULL, - "HTTP/%.1f %03d %s\r\n" - "Connection: close\r\n", - req->version, res->statuscode, - res->statusmsg)); - - /* add Content-Type if no Location or Content-Type */ - if( !uh_cgi_header_lookup(res, "Location") && - !uh_cgi_header_lookup(res, "Content-Type") - ) { - ensure(uh_http_send(cl, NULL, - "Content-Type: text/plain\r\n", -1)); - } - - /* if request was HTTP 1.1 we'll respond chunked */ - if( (req->version > 1.0) && - !uh_cgi_header_lookup(res, "Transfer-Encoding") - ) { - ensure(uh_http_send(cl, NULL, - "Transfer-Encoding: chunked\r\n", -1)); - } - - /* write headers from CGI program */ - foreach_header(i, res->headers) - { - ensure(uh_http_sendf(cl, NULL, "%s: %s\r\n", - res->headers[i], res->headers[i+1])); - } - - /* terminate header */ - ensure(uh_http_send(cl, NULL, "\r\n", -1)); - - /* push out remaining head buffer */ - if( hdroff < hdrlen ) - ensure(uh_http_send(cl, req, &hdr[hdroff], hdrlen - hdroff)); - } - - /* ... failed and head buffer exceeded */ - else if( hdrlen >= sizeof(hdr) ) - { - ensure(uh_cgi_error_500(cl, req, - "The CGI program generated an invalid response:\n\n")); - - ensure(uh_http_send(cl, req, hdr, hdrlen)); - } - - /* ... failed but free buffer space, try again */ - else - { - continue; - } - - /* push out remaining read buffer */ - if( bufoff < buflen ) - ensure(uh_http_send(cl, req, &buf[bufoff], buflen - bufoff)); - - header_sent = 1; - continue; - } - - - /* headers complete, pass through buffer to socket */ - ensure(uh_http_send(cl, req, buf, buflen)); - } - - /* looks like eof from child */ - else - { - /* cgi script did not output useful stuff at all */ - if( ! header_sent ) - { - /* I would do this ... - * - * uh_cgi_error_500(cl, req, - * "The CGI program generated an " - * "invalid response:\n\n"); - * - * ... but in order to stay as compatible as possible, - * treat whatever we got as text/plain response and - * build the required headers here. - */ - - ensure(uh_http_sendf(cl, NULL, - "HTTP/%.1f 200 OK\r\n" - "Content-Type: text/plain\r\n" - "%s\r\n", - req->version, (req->version > 1.0) - ? "Transfer-Encoding: chunked\r\n" : "" - )); - - ensure(uh_http_send(cl, req, hdr, hdrlen)); - } - - /* send final chunk if we're in chunked transfer mode */ - ensure(uh_http_send(cl, req, "", 0)); - break; - } - } - } - - /* no activity for 15 seconds... looks dead */ - else - { - ensure(uh_http_sendhf(cl, 504, "Gateway Timeout", - "The CGI script took too long to produce a response")); - - break; - } - } - - out: - close(rfd[0]); - close(wfd[1]); - - if( !kill(child, 0) ) - kill(child, SIGTERM); - - break; - } -} - diff --git a/contrib/package/uhttpd/src/uhttpd-cgi.h b/contrib/package/uhttpd/src/uhttpd-cgi.h deleted file mode 100644 index c90557d8f..000000000 --- a/contrib/package/uhttpd/src/uhttpd-cgi.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - CGI header - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_CGI_ - -#include <errno.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <linux/limits.h> - -void uh_cgi_request( - struct client *cl, struct http_request *req, struct path_info *pi -); - -#endif diff --git a/contrib/package/uhttpd/src/uhttpd-file.c b/contrib/package/uhttpd/src/uhttpd-file.c deleted file mode 100644 index 2a06f8520..000000000 --- a/contrib/package/uhttpd/src/uhttpd-file.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Static file handler - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _XOPEN_SOURCE 500 /* strptime() */ -#define _BSD_SOURCE /* scandir(), timegm() */ - -#include "uhttpd.h" -#include "uhttpd-utils.h" -#include "uhttpd-file.h" - -#include "uhttpd-mimetypes.h" - - -static const char * uh_file_mime_lookup(const char *path) -{ - struct mimetype *m = &uh_mime_types[0]; - char *p, *pd, *ps; - - ps = strrchr(path, '/'); - pd = strrchr(path, '.'); - - /* use either slash or dot as separator, whatever comes last */ - p = (ps && pd && (ps > pd)) ? ps : pd; - - if( (p != NULL) && (*(++p) != 0) ) - { - while( m->extn ) - { - if( ! strcasecmp(p, m->extn) ) - return m->mime; - - m++; - } - } - - return "application/octet-stream"; -} - -static const char * uh_file_mktag(struct stat *s) -{ - static char tag[128]; - - snprintf(tag, sizeof(tag), "\"%x-%x-%x\"", - (unsigned int) s->st_ino, - (unsigned int) s->st_size, - (unsigned int) s->st_mtime - ); - - return tag; -} - -static time_t uh_file_date2unix(const char *date) -{ - struct tm t; - - memset(&t, 0, sizeof(t)); - - if( strptime(date, "%a, %d %b %Y %H:%M:%S %Z", &t) != NULL ) - return timegm(&t); - - return 0; -} - -static char * uh_file_unix2date(time_t ts) -{ - static char str[128]; - struct tm *t = gmtime(&ts); - - strftime(str, sizeof(str), "%a, %d %b %Y %H:%M:%S GMT", t); - - return str; -} - -static char * uh_file_header_lookup(struct http_request *req, const char *name) -{ - int i; - - foreach_header(i, req->headers) - { - if( ! strcasecmp(req->headers[i], name) ) - return req->headers[i+1]; - } - - return NULL; -} - -static void uh_file_response_ok_hdrs(struct client *cl, struct http_request *req, struct stat *s) -{ - uh_http_sendf(cl, NULL, "Connection: close\r\n"); - - if( s ) - { - uh_http_sendf(cl, NULL, "ETag: %s\r\n", uh_file_mktag(s)); - uh_http_sendf(cl, NULL, "Last-Modified: %s\r\n", uh_file_unix2date(s->st_mtime)); - } - - uh_http_sendf(cl, NULL, "Date: %s\r\n", uh_file_unix2date(time(NULL))); -} - -static void uh_file_response_200(struct client *cl, struct http_request *req, struct stat *s) -{ - uh_http_sendf(cl, NULL, "HTTP/%.1f 200 OK\r\n", req->version); - uh_file_response_ok_hdrs(cl, req, s); -} - -static void uh_file_response_304(struct client *cl, struct http_request *req, struct stat *s) -{ - uh_http_sendf(cl, NULL, "HTTP/%.1f 304 Not Modified\r\n", req->version); - uh_file_response_ok_hdrs(cl, req, s); -} - -static void uh_file_response_412(struct client *cl, struct http_request *req) -{ - uh_http_sendf(cl, NULL, - "HTTP/%.1f 412 Precondition Failed\r\n" - "Connection: close\r\n", req->version); -} - -static int uh_file_if_match(struct client *cl, struct http_request *req, struct stat *s) -{ - const char *tag = uh_file_mktag(s); - char *hdr = uh_file_header_lookup(req, "If-Match"); - char *p; - int i; - - if( hdr ) - { - p = &hdr[0]; - - for( i = 0; i < strlen(hdr); i++ ) - { - if( (hdr[i] == ' ') || (hdr[i] == ',') ) - { - hdr[i++] = 0; - p = &hdr[i]; - } - else if( !strcmp(p, "*") || !strcmp(p, tag) ) - { - return 1; - } - } - - uh_file_response_412(cl, req); - return 0; - } - - return 1; -} - -static int uh_file_if_modified_since(struct client *cl, struct http_request *req, struct stat *s) -{ - char *hdr = uh_file_header_lookup(req, "If-Modified-Since"); - - if( hdr ) - { - if( uh_file_date2unix(hdr) < s->st_mtime ) - { - return 1; - } - else - { - uh_file_response_304(cl, req, s); - return 0; - } - } - - return 1; -} - -static int uh_file_if_none_match(struct client *cl, struct http_request *req, struct stat *s) -{ - const char *tag = uh_file_mktag(s); - char *hdr = uh_file_header_lookup(req, "If-None-Match"); - char *p; - int i; - - if( hdr ) - { - p = &hdr[0]; - - for( i = 0; i < strlen(hdr); i++ ) - { - if( (hdr[i] == ' ') || (hdr[i] == ',') ) - { - hdr[i++] = 0; - p = &hdr[i]; - } - else if( !strcmp(p, "*") || !strcmp(p, tag) ) - { - if( (req->method == UH_HTTP_MSG_GET) || - (req->method == UH_HTTP_MSG_HEAD) ) - uh_file_response_304(cl, req, s); - else - uh_file_response_412(cl, req); - - return 0; - } - } - } - - return 1; -} - -static int uh_file_if_range(struct client *cl, struct http_request *req, struct stat *s) -{ - char *hdr = uh_file_header_lookup(req, "If-Range"); - - if( hdr ) - { - uh_file_response_412(cl, req); - return 0; - } - - return 1; -} - -static int uh_file_if_unmodified_since(struct client *cl, struct http_request *req, struct stat *s) -{ - char *hdr = uh_file_header_lookup(req, "If-Unmodified-Since"); - - if( hdr ) - { - if( uh_file_date2unix(hdr) <= s->st_mtime ) - { - uh_file_response_412(cl, req); - return 0; - } - } - - return 1; -} - - -static int uh_file_scandir_filter_dir(const struct dirent *e) -{ - return strcmp(e->d_name, ".") ? 1 : 0; -} - -static void uh_file_dirlist(struct client *cl, struct http_request *req, struct path_info *pi) -{ - int i, count; - char filename[PATH_MAX]; - char *pathptr; - struct dirent **files = NULL; - struct stat s; - - uh_http_sendf(cl, req, - "<html><head><title>Index of %s</title></head>" - "<body><h1>Index of %s</h1><hr /><ol>", - pi->name, pi->name - ); - - if( (count = scandir(pi->phys, &files, uh_file_scandir_filter_dir, alphasort)) > 0 ) - { - memset(filename, 0, sizeof(filename)); - memcpy(filename, pi->phys, sizeof(filename)); - pathptr = &filename[strlen(filename)]; - - /* list subdirs */ - for( i = 0; i < count; i++ ) - { - strncat(filename, files[i]->d_name, - sizeof(filename) - strlen(files[i]->d_name)); - - if( !stat(filename, &s) && (s.st_mode & S_IFDIR) ) - uh_http_sendf(cl, req, - "<li><strong><a href='%s%s'>%s</a>/</strong><br />" - "<small>modified: %s<br />directory - %.02f kbyte" - "<br /><br /></small></li>", - pi->name, files[i]->d_name, files[i]->d_name, - uh_file_unix2date(s.st_mtime), s.st_size / 1024.0 - ); - - *pathptr = 0; - } - - /* list files */ - for( i = 0; i < count; i++ ) - { - strncat(filename, files[i]->d_name, - sizeof(filename) - strlen(files[i]->d_name)); - - if( !stat(filename, &s) && !(s.st_mode & S_IFDIR) ) - uh_http_sendf(cl, req, - "<li><strong><a href='%s%s'>%s</a></strong><br />" - "<small>modified: %s<br />%s - %.02f kbyte<br />" - "<br /></small></li>", - pi->name, files[i]->d_name, files[i]->d_name, - uh_file_unix2date(s.st_mtime), - uh_file_mime_lookup(filename), s.st_size / 1024.0 - ); - - *pathptr = 0; - free(files[i]); - } - } - - free(files); - - uh_http_sendf(cl, req, "</ol><hr /></body></html>"); - uh_http_sendf(cl, req, ""); -} - - -void uh_file_request(struct client *cl, struct http_request *req, struct path_info *pi) -{ - int fd, rlen; - char buf[UH_LIMIT_MSGHEAD]; - - /* we have a file */ - if( (pi->stat.st_mode & S_IFREG) && ((fd = open(pi->phys, O_RDONLY)) > 0) ) - { - /* test preconditions */ - if( - uh_file_if_modified_since(cl, req, &pi->stat) && - uh_file_if_match(cl, req, &pi->stat) && - uh_file_if_range(cl, req, &pi->stat) && - uh_file_if_unmodified_since(cl, req, &pi->stat) && - uh_file_if_none_match(cl, req, &pi->stat) - ) { - /* write status */ - uh_file_response_200(cl, req, &pi->stat); - - uh_http_sendf(cl, NULL, "Content-Type: %s\r\n", uh_file_mime_lookup(pi->name)); - uh_http_sendf(cl, NULL, "Content-Length: %i\r\n", pi->stat.st_size); - - /* if request was HTTP 1.1 we'll respond chunked */ - if( (req->version > 1.0) && (req->method != UH_HTTP_MSG_HEAD) ) - uh_http_send(cl, NULL, "Transfer-Encoding: chunked\r\n", -1); - - /* close header */ - uh_http_send(cl, NULL, "\r\n", -1); - - /* send body */ - if( req->method != UH_HTTP_MSG_HEAD ) - { - /* pump file data */ - while( (rlen = read(fd, buf, sizeof(buf))) > 0 ) - { - if( uh_http_send(cl, req, buf, rlen) < 0 ) - break; - } - - /* send trailer in chunked mode */ - uh_http_send(cl, req, "", 0); - } - } - - /* one of the preconditions failed, terminate opened header and exit */ - else - { - uh_http_send(cl, NULL, "\r\n", -1); - } - - close(fd); - } - - /* directory */ - else if( pi->stat.st_mode & S_IFDIR ) - { - /* write status */ - uh_file_response_200(cl, req, NULL); - - if( req->version > 1.0 ) - uh_http_send(cl, NULL, "Transfer-Encoding: chunked\r\n", -1); - - uh_http_send(cl, NULL, "Content-Type: text/html\r\n\r\n", -1); - - /* content */ - uh_file_dirlist(cl, req, pi); - } - - /* 403 */ - else - { - uh_http_sendhf(cl, 403, "Forbidden", - "Access to this resource is forbidden"); - } -} - diff --git a/contrib/package/uhttpd/src/uhttpd-file.h b/contrib/package/uhttpd/src/uhttpd-file.h deleted file mode 100644 index 3d4681516..000000000 --- a/contrib/package/uhttpd/src/uhttpd-file.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Static file header - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_FILE_ - -#include <fcntl.h> -#include <time.h> -#include <strings.h> -#include <dirent.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <linux/limits.h> - -struct mimetype { - const char *extn; - const char *mime; -}; - -void uh_file_request( - struct client *cl, struct http_request *req, struct path_info *pi -); - -#endif diff --git a/contrib/package/uhttpd/src/uhttpd-lua.c b/contrib/package/uhttpd/src/uhttpd-lua.c deleted file mode 100644 index ab09841cd..000000000 --- a/contrib/package/uhttpd/src/uhttpd-lua.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Lua handler - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "uhttpd.h" -#include "uhttpd-utils.h" -#include "uhttpd-lua.h" - - -static int uh_lua_recv(lua_State *L) -{ - size_t length; - char buffer[UH_LIMIT_MSGHEAD]; - ssize_t rlen = 0; - fd_set reader; - struct timeval timeout; - - length = luaL_checknumber(L, 1); - - if( (length > 0) && (length <= sizeof(buffer)) ) - { - FD_ZERO(&reader); - FD_SET(fileno(stdin), &reader); - - /* fail after 0.1s */ - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - - /* check whether fd is readable */ - if( select(fileno(stdin) + 1, &reader, NULL, NULL, &timeout) > 0 ) - { - /* receive data */ - rlen = read(fileno(stdin), buffer, length); - lua_pushnumber(L, rlen); - - if( rlen > 0 ) - { - lua_pushlstring(L, buffer, rlen); - return 2; - } - - return 1; - } - - /* no, timeout and actually no data */ - lua_pushnumber(L, -2); - return 1; - } - - /* parameter error */ - lua_pushnumber(L, -3); - return 1; -} - -static int uh_lua_send_common(lua_State *L, int chunked) -{ - size_t length; - const char *buffer; - char chunk[16]; - ssize_t slen = 0; - - buffer = luaL_checklstring(L, 1, &length); - - if( chunked ) - { - if( length > 0 ) - { - snprintf(chunk, sizeof(chunk), "%X\r\n", length); - slen = write(fileno(stdout), chunk, strlen(chunk)); - slen += write(fileno(stdout), buffer, length); - slen += write(fileno(stdout), "\r\n", 2); - } - else - { - slen = write(fileno(stdout), "0\r\n\r\n", 5); - } - } - else - { - slen = write(fileno(stdout), buffer, length); - } - - lua_pushnumber(L, slen); - return 1; -} - -static int uh_lua_send(lua_State *L) -{ - return uh_lua_send_common(L, 0); -} - -static int uh_lua_sendc(lua_State *L) -{ - return uh_lua_send_common(L, 1); -} - -static int uh_lua_urldecode(lua_State *L) -{ - size_t inlen, outlen; - const char *inbuf; - char outbuf[UH_LIMIT_MSGHEAD]; - - inbuf = luaL_checklstring(L, 1, &inlen); - outlen = uh_urldecode(outbuf, sizeof(outbuf), inbuf, inlen); - - lua_pushlstring(L, outbuf, outlen); - return 1; -} - - -lua_State * uh_lua_init(const char *handler) -{ - lua_State *L = lua_open(); - const char *err_str = NULL; - - /* Load standard libaries */ - luaL_openlibs(L); - - /* build uhttpd api table */ - lua_newtable(L); - - /* register global send and receive functions */ - lua_pushcfunction(L, uh_lua_recv); - lua_setfield(L, -2, "recv"); - - lua_pushcfunction(L, uh_lua_send); - lua_setfield(L, -2, "send"); - - lua_pushcfunction(L, uh_lua_sendc); - lua_setfield(L, -2, "sendc"); - - lua_pushcfunction(L, uh_lua_urldecode); - lua_setfield(L, -2, "urldecode"); - - /* _G.uhttpd = { ... } */ - lua_setfield(L, LUA_GLOBALSINDEX, "uhttpd"); - - - /* load Lua handler */ - switch( luaL_loadfile(L, handler) ) - { - case LUA_ERRSYNTAX: - fprintf(stderr, - "Lua handler contains syntax errors, unable to continue\n"); - exit(1); - - case LUA_ERRMEM: - fprintf(stderr, - "Lua handler ran out of memory, unable to continue\n"); - exit(1); - - case LUA_ERRFILE: - fprintf(stderr, - "Lua cannot open the handler script, unable to continue\n"); - exit(1); - - default: - /* compile Lua handler */ - switch( lua_pcall(L, 0, 0, 0) ) - { - case LUA_ERRRUN: - err_str = luaL_checkstring(L, -1); - fprintf(stderr, - "Lua handler had runtime error, unable to continue\n" - "Error: %s\n", err_str - ); - exit(1); - - case LUA_ERRMEM: - err_str = luaL_checkstring(L, -1); - fprintf(stderr, - "Lua handler ran out of memory, unable to continue\n" - "Error: %s\n", err_str - ); - exit(1); - - default: - /* test handler function */ - lua_getglobal(L, UH_LUA_CALLBACK); - - if( ! lua_isfunction(L, -1) ) - { - fprintf(stderr, - "Lua handler provides no " UH_LUA_CALLBACK "(), unable to continue\n"); - exit(1); - } - - lua_pop(L, 1); - break; - } - - break; - } - - return L; -} - -void uh_lua_request(struct client *cl, struct http_request *req, lua_State *L) -{ - int i, data_sent; - int content_length = 0; - int buflen = 0; - int fd_max = 0; - char *query_string; - const char *prefix = cl->server->conf->lua_prefix; - const char *err_str = NULL; - - int rfd[2] = { 0, 0 }; - int wfd[2] = { 0, 0 }; - - char buf[UH_LIMIT_MSGHEAD]; - - pid_t child; - - fd_set reader; - fd_set writer; - - struct sigaction sa; - struct timeval timeout; - - - /* spawn pipes for me->child, child->me */ - if( (pipe(rfd) < 0) || (pipe(wfd) < 0) ) - { - uh_http_sendhf(cl, 500, "Internal Server Error", - "Failed to create pipe: %s", strerror(errno)); - - if( rfd[0] > 0 ) close(rfd[0]); - if( rfd[1] > 0 ) close(rfd[1]); - if( wfd[0] > 0 ) close(wfd[0]); - if( wfd[1] > 0 ) close(wfd[1]); - - return; - } - - - switch( (child = fork()) ) - { - case -1: - uh_http_sendhf(cl, 500, "Internal Server Error", - "Failed to fork child: %s", strerror(errno)); - break; - - case 0: - /* restore SIGTERM */ - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigemptyset(&sa.sa_mask); - sigaction(SIGTERM, &sa, NULL); - - /* close loose pipe ends */ - close(rfd[0]); - close(wfd[1]); - - /* patch stdout and stdin to pipes */ - dup2(rfd[1], 1); - dup2(wfd[0], 0); - - /* put handler callback on stack */ - lua_getglobal(L, UH_LUA_CALLBACK); - - /* build env table */ - lua_newtable(L); - - /* request method */ - switch(req->method) - { - case UH_HTTP_MSG_GET: - lua_pushstring(L, "GET"); - break; - - case UH_HTTP_MSG_HEAD: - lua_pushstring(L, "HEAD"); - break; - - case UH_HTTP_MSG_POST: - lua_pushstring(L, "POST"); - break; - } - - lua_setfield(L, -2, "REQUEST_METHOD"); - - /* request url */ - lua_pushstring(L, req->url); - lua_setfield(L, -2, "REQUEST_URI"); - - /* script name */ - lua_pushstring(L, cl->server->conf->lua_prefix); - lua_setfield(L, -2, "SCRIPT_NAME"); - - /* query string, path info */ - if( (query_string = strchr(req->url, '?')) != NULL ) - { - lua_pushstring(L, query_string + 1); - lua_setfield(L, -2, "QUERY_STRING"); - - if( (int)(query_string - req->url) > strlen(prefix) ) - { - lua_pushlstring(L, - &req->url[strlen(prefix)], - (int)(query_string - req->url) - strlen(prefix) - ); - - lua_setfield(L, -2, "PATH_INFO"); - } - } - else if( strlen(req->url) > strlen(prefix) ) - { - lua_pushstring(L, &req->url[strlen(prefix)]); - lua_setfield(L, -2, "PATH_INFO"); - } - - /* http protcol version */ - lua_pushnumber(L, floor(req->version * 10) / 10); - lua_setfield(L, -2, "HTTP_VERSION"); - - if( req->version > 1.0 ) - lua_pushstring(L, "HTTP/1.1"); - else - lua_pushstring(L, "HTTP/1.0"); - - lua_setfield(L, -2, "SERVER_PROTOCOL"); - - - /* address information */ - lua_pushstring(L, sa_straddr(&cl->peeraddr)); - lua_setfield(L, -2, "REMOTE_ADDR"); - - lua_pushinteger(L, sa_port(&cl->peeraddr)); - lua_setfield(L, -2, "REMOTE_PORT"); - - lua_pushstring(L, sa_straddr(&cl->servaddr)); - lua_setfield(L, -2, "SERVER_ADDR"); - - lua_pushinteger(L, sa_port(&cl->servaddr)); - lua_setfield(L, -2, "SERVER_PORT"); - - /* essential env vars */ - foreach_header(i, req->headers) - { - if( !strcasecmp(req->headers[i], "Content-Length") ) - { - lua_pushnumber(L, atoi(req->headers[i+1])); - lua_setfield(L, -2, "CONTENT_LENGTH"); - } - else if( !strcasecmp(req->headers[i], "Content-Type") ) - { - lua_pushstring(L, req->headers[i+1]); - lua_setfield(L, -2, "CONTENT_TYPE"); - } - } - - /* misc. headers */ - lua_newtable(L); - - foreach_header(i, req->headers) - { - if( strcasecmp(req->headers[i], "Content-Length") && - strcasecmp(req->headers[i], "Content-Type") - ) { - lua_pushstring(L, req->headers[i+1]); - lua_setfield(L, -2, req->headers[i]); - } - } - - lua_setfield(L, -2, "headers"); - - - /* call */ - switch( lua_pcall(L, 1, 0, 0) ) - { - case LUA_ERRMEM: - case LUA_ERRRUN: - err_str = luaL_checkstring(L, -1); - - if( ! err_str ) - err_str = "Unknown error"; - - printf( - "HTTP/%.1f 500 Internal Server Error\r\n" - "Connection: close\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: %i\r\n\r\n" - "Lua raised a runtime error:\n %s\n", - req->version, 31 + strlen(err_str), err_str - ); - - break; - - default: - break; - } - - close(wfd[0]); - close(rfd[1]); - exit(0); - - break; - - /* parent; handle I/O relaying */ - default: - /* close unneeded pipe ends */ - close(rfd[1]); - close(wfd[0]); - - /* max watch fd */ - fd_max = max(rfd[0], wfd[1]) + 1; - - /* find content length */ - if( req->method == UH_HTTP_MSG_POST ) - { - foreach_header(i, req->headers) - { - if( ! strcasecmp(req->headers[i], "Content-Length") ) - { - content_length = atoi(req->headers[i+1]); - break; - } - } - } - - -#define ensure(x) \ - do { if( x < 0 ) goto out; } while(0) - - data_sent = 0; - - /* I/O loop, watch our pipe ends and dispatch child reads/writes from/to socket */ - while( 1 ) - { - FD_ZERO(&reader); - FD_ZERO(&writer); - - FD_SET(rfd[0], &reader); - FD_SET(wfd[1], &writer); - - timeout.tv_sec = 15; - timeout.tv_usec = 0; - - /* wait until we can read or write or both */ - if( select(fd_max, &reader, (content_length > -1) ? &writer : NULL, NULL, &timeout) > 0 ) - { - /* ready to write to Lua child */ - if( FD_ISSET(wfd[1], &writer) ) - { - /* there is unread post data waiting */ - if( content_length > 0 ) - { - /* read it from socket ... */ - if( (buflen = uh_tcp_recv(cl, buf, min(content_length, sizeof(buf)))) > 0 ) - { - /* ... and write it to child's stdin */ - if( write(wfd[1], buf, buflen) < 0 ) - perror("write()"); - - content_length -= buflen; - } - - /* unexpected eof! */ - else - { - if( write(wfd[1], "", 0) < 0 ) - perror("write()"); - - content_length = 0; - } - } - - /* there is no more post data, close pipe to child's stdin */ - else if( content_length > -1 ) - { - close(wfd[1]); - content_length = -1; - } - } - - /* ready to read from Lua child */ - if( FD_ISSET(rfd[0], &reader) ) - { - /* read data from child ... */ - if( (buflen = read(rfd[0], buf, sizeof(buf))) > 0 ) - { - /* pass through buffer to socket */ - ensure(uh_tcp_send(cl, buf, buflen)); - data_sent = 1; - } - - /* looks like eof from child */ - else - { - /* error? */ - if( ! data_sent ) - uh_http_sendhf(cl, 500, "Internal Server Error", - "The Lua child did not produce any response"); - - break; - } - } - } - - /* no activity for 15 seconds... looks dead */ - else - { - ensure(uh_http_sendhf(cl, 504, "Gateway Timeout", - "The Lua handler took too long to produce a response")); - - break; - } - } - - out: - close(rfd[0]); - close(wfd[1]); - - if( !kill(child, 0) ) - kill(child, SIGTERM); - - break; - } -} - -void uh_lua_close(lua_State *L) -{ - lua_close(L); -} - - diff --git a/contrib/package/uhttpd/src/uhttpd-lua.h b/contrib/package/uhttpd/src/uhttpd-lua.h deleted file mode 100644 index 730466500..000000000 --- a/contrib/package/uhttpd/src/uhttpd-lua.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Lua header - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_LUA_ - -#include <math.h> /* floor() */ -#include <errno.h> - -#include <lua.h> -#include <lauxlib.h> -#include <lualib.h> - -#define UH_LUA_CALLBACK "handle_request" - -#define UH_LUA_ERR_TIMEOUT -1 -#define UH_LUA_ERR_TOOBIG -2 -#define UH_LUA_ERR_PARAM -3 - - -lua_State * uh_lua_init(); - -void uh_lua_request( - struct client *cl, struct http_request *req, lua_State *L -); - -void uh_lua_close(lua_State *L); - -#endif diff --git a/contrib/package/uhttpd/src/uhttpd-mimetypes.h b/contrib/package/uhttpd/src/uhttpd-mimetypes.h deleted file mode 100644 index 1c93f3113..000000000 --- a/contrib/package/uhttpd/src/uhttpd-mimetypes.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - MIME type definitions - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_MIMETYPES_ - -static struct mimetype uh_mime_types[] = { - - { "txt", "text/plain" }, - { "log", "text/plain" }, - { "js", "text/javascript" }, - { "css", "text/css" }, - { "htm", "text/html" }, - { "html", "text/html" }, - { "diff", "text/x-patch" }, - { "patch", "text/x-patch" }, - { "c", "text/x-csrc" }, - { "h", "text/x-chdr" }, - { "o", "text/x-object" }, - { "ko", "text/x-object" }, - - { "bmp", "image/bmp" }, - { "gif", "image/gif" }, - { "png", "image/png" }, - { "jpg", "image/jpeg" }, - { "jpeg", "image/jpeg" }, - { "svg", "image/svg+xml" }, - - { "zip", "application/zip" }, - { "pdf", "application/pdf" }, - { "xml", "application/xml" }, - { "xsl", "application/xml" }, - { "doc", "application/msword" }, - { "ppt", "application/vnd.ms-powerpoint" }, - { "xls", "application/vnd.ms-excel" }, - { "odt", "application/vnd.oasis.opendocument.text" }, - { "odp", "application/vnd.oasis.opendocument.presentation" }, - { "pl", "application/x-perl" }, - { "sh", "application/x-shellscript" }, - { "php", "application/x-php" }, - { "deb", "application/x-deb" }, - { "iso", "application/x-cd-image" }, - { "tgz", "application/x-compressed-tar" }, - { "gz", "application/x-gzip" }, - { "bz2", "application/x-bzip" }, - { "tar", "application/x-tar" }, - { "rar", "application/x-rar-compressed" }, - - { "mp3", "audio/mpeg" }, - { "ogg", "audio/x-vorbis+ogg" }, - { "wav", "audio/x-wav" }, - - { "mpg", "video/mpeg" }, - { "mpeg", "video/mpeg" }, - { "avi", "video/x-msvideo" }, - - { "README", "text/plain" }, - { "log", "text/plain" }, - { "cfg", "text/plain" }, - { "conf", "text/plain" }, - - { NULL, NULL } -}; - -#endif - diff --git a/contrib/package/uhttpd/src/uhttpd-tls.c b/contrib/package/uhttpd/src/uhttpd-tls.c deleted file mode 100644 index cb5061638..000000000 --- a/contrib/package/uhttpd/src/uhttpd-tls.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - TLS helper - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "uhttpd.h" -#include "uhttpd-tls.h" -#include "uhttpd-utils.h" - - -SSL_CTX * uh_tls_ctx_init() -{ - SSL_CTX *c = NULL; - SSL_load_error_strings(); - SSL_library_init(); - - if( (c = SSL_CTX_new(TLSv1_server_method())) != NULL ) - SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); - - return c; -} - -int uh_tls_ctx_cert(SSL_CTX *c, const char *file) -{ - return SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_ASN1); -} - -int uh_tls_ctx_key(SSL_CTX *c, const char *file) -{ - return SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_ASN1); -} - -void uh_tls_ctx_free(struct listener *l) -{ - SSL_CTX_free(l->tls); -} - - -void uh_tls_client_accept(struct client *c) -{ - if( c->server && c->server->tls ) - { - c->tls = SSL_new(c->server->tls); - SSL_set_fd(c->tls, c->socket); - } -} - -int uh_tls_client_recv(struct client *c, void *buf, int len) -{ - return SSL_read(c->tls, buf, len); -} - -int uh_tls_client_send(struct client *c, void *buf, int len) -{ - return SSL_write(c->tls, buf, len); -} - -void uh_tls_client_close(struct client *c) -{ - if( c->tls ) - { - SSL_shutdown(c->tls); - SSL_free(c->tls); - - c->tls = NULL; - } -} - - diff --git a/contrib/package/uhttpd/src/uhttpd-tls.h b/contrib/package/uhttpd/src/uhttpd-tls.h deleted file mode 100644 index 4a98b78c6..000000000 --- a/contrib/package/uhttpd/src/uhttpd-tls.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - TLS header - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_TLS_ - -#include <openssl/ssl.h> - - -SSL_CTX * uh_tls_ctx_init(); -int uh_tls_ctx_cert(SSL_CTX *c, const char *file); -int uh_tls_ctx_key(SSL_CTX *c, const char *file); -void uh_tls_ctx_free(struct listener *l); - -void uh_tls_client_accept(struct client *c); -int uh_tls_client_recv(struct client *c, void *buf, int len); -int uh_tls_client_send(struct client *c, void *buf, int len); -void uh_tls_client_close(struct client *c); - -#endif - diff --git a/contrib/package/uhttpd/src/uhttpd-utils.c b/contrib/package/uhttpd/src/uhttpd-utils.c deleted file mode 100644 index c1e08b069..000000000 --- a/contrib/package/uhttpd/src/uhttpd-utils.c +++ /dev/null @@ -1,749 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Utility functions - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _XOPEN_SOURCE 500 /* crypt() */ -#define _BSD_SOURCE /* strcasecmp(), strncasecmp() */ - -#include "uhttpd.h" -#include "uhttpd-utils.h" - -#ifdef HAVE_TLS -#include "uhttpd-tls.h" -#endif - - -static char *uh_index_files[] = { - "index.html", - "index.htm", - "default.html", - "default.htm" -}; - - -const char * sa_straddr(void *sa) -{ - static char str[INET6_ADDRSTRLEN]; - struct sockaddr_in *v4 = (struct sockaddr_in *)sa; - struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)sa; - - if( v4->sin_family == AF_INET ) - return inet_ntop(AF_INET, &(v4->sin_addr), str, sizeof(str)); - else - return inet_ntop(AF_INET6, &(v6->sin6_addr), str, sizeof(str)); -} - -const char * sa_strport(void *sa) -{ - static char str[6]; - snprintf(str, sizeof(str), "%i", sa_port(sa)); - return str; -} - -int sa_port(void *sa) -{ - return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); -} - -/* Simple strstr() like function that takes len arguments for both haystack and needle. */ -char *strfind(char *haystack, int hslen, const char *needle, int ndlen) -{ - int match = 0; - int i, j; - - for( i = 0; i < hslen; i++ ) - { - if( haystack[i] == needle[0] ) - { - match = ((ndlen == 1) || ((i + ndlen) <= hslen)); - - for( j = 1; (j < ndlen) && ((i + j) < hslen); j++ ) - { - if( haystack[i+j] != needle[j] ) - { - match = 0; - break; - } - } - - if( match ) - return &haystack[i]; - } - } - - return NULL; -} - - -int uh_tcp_send(struct client *cl, const char *buf, int len) -{ - fd_set writer; - struct timeval timeout; - - FD_ZERO(&writer); - FD_SET(cl->socket, &writer); - - timeout.tv_sec = 0; - timeout.tv_usec = 500000; - - if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 ) - { -#ifdef HAVE_TLS - if( cl->tls ) - return cl->server->conf->tls_send(cl, (void *)buf, len); - else -#endif - return send(cl->socket, buf, len, 0); - } - - return -1; -} - -int uh_tcp_peek(struct client *cl, char *buf, int len) -{ - int sz = uh_tcp_recv(cl, buf, len); - - /* store received data in peek buffer */ - if( sz > 0 ) - { - cl->peeklen = sz; - memcpy(cl->peekbuf, buf, sz); - } - - return sz; -} - -int uh_tcp_recv(struct client *cl, char *buf, int len) -{ - int sz = 0; - int rsz = 0; - - /* first serve data from peek buffer */ - if( cl->peeklen > 0 ) - { - sz = min(cl->peeklen, len); - len -= sz; cl->peeklen -= sz; - - memcpy(buf, cl->peekbuf, sz); - memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen); - } - - /* caller wants more */ - if( len > 0 ) - { -#ifdef HAVE_TLS - if( cl->tls ) - rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len); - else -#endif - rsz = recv(cl->socket, (void *)&buf[sz], len, 0); - - if( (sz == 0) || (rsz > 0) ) - sz += rsz; - } - - return sz; -} - -#define ensure(x) \ - do { if( x < 0 ) return -1; } while(0) - -int uh_http_sendhf(struct client *cl, int code, const char *summary, const char *fmt, ...) -{ - va_list ap; - - char buffer[UH_LIMIT_MSGHEAD]; - int len; - - len = snprintf(buffer, sizeof(buffer), - "HTTP/1.1 %03i %s\r\n" - "Connection: close\r\n" - "Content-Type: text/plain\r\n" - "Transfer-Encoding: chunked\r\n\r\n", - code, summary - ); - - ensure(uh_tcp_send(cl, buffer, len)); - - va_start(ap, fmt); - len = vsnprintf(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - ensure(uh_http_sendc(cl, buffer, len)); - ensure(uh_http_sendc(cl, NULL, 0)); - - return 0; -} - - -int uh_http_sendc(struct client *cl, const char *data, int len) -{ - char chunk[8]; - int clen; - - if( len == -1 ) - len = strlen(data); - - if( len > 0 ) - { - clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len); - ensure(uh_tcp_send(cl, chunk, clen)); - ensure(uh_tcp_send(cl, data, len)); - ensure(uh_tcp_send(cl, "\r\n", 2)); - } - else - { - ensure(uh_tcp_send(cl, "0\r\n\r\n", 5)); - } - - return 0; -} - -int uh_http_sendf( - struct client *cl, struct http_request *req, const char *fmt, ... -) { - va_list ap; - char buffer[UH_LIMIT_MSGHEAD]; - int len; - - va_start(ap, fmt); - len = vsnprintf(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - if( (req != NULL) && (req->version > 1.0) ) - ensure(uh_http_sendc(cl, buffer, len)); - else if( len > 0 ) - ensure(uh_tcp_send(cl, buffer, len)); - - return 0; -} - -int uh_http_send( - struct client *cl, struct http_request *req, const char *buf, int len -) { - if( len < 0 ) - len = strlen(buf); - - if( (req != NULL) && (req->version > 1.0) ) - ensure(uh_http_sendc(cl, buf, len)); - else if( len > 0 ) - ensure(uh_tcp_send(cl, buf, len)); - - return 0; -} - - -int uh_urldecode(char *buf, int blen, const char *src, int slen) -{ - int i; - int len = 0; - -#define hex(x) \ - (((x) <= '9') ? ((x) - '0') : \ - (((x) <= 'F') ? ((x) - 'A' + 10) : \ - ((x) - 'a' + 10))) - - for( i = 0; (i <= slen) && (i <= blen); i++ ) - { - if( src[i] == '%' ) - { - if( ((i+2) <= slen) && isxdigit(src[i+1]) && isxdigit(src[i+2]) ) - { - buf[len++] = (char)(16 * hex(src[i+1]) + hex(src[i+2])); - i += 2; - } - else - { - buf[len++] = '%'; - } - } - else - { - buf[len++] = src[i]; - } - } - - return len; -} - -int uh_urlencode(char *buf, int blen, const char *src, int slen) -{ - int i; - int len = 0; - const char hex[] = "0123456789abcdef"; - - for( i = 0; (i <= slen) && (i <= blen); i++ ) - { - if( isalnum(src[i]) || (src[i] == '-') || (src[i] == '_') || - (src[i] == '.') || (src[i] == '~') ) - { - buf[len++] = src[i]; - } - else if( (len+3) <= blen ) - { - buf[len++] = '%'; - buf[len++] = hex[(src[i] >> 4) & 15]; - buf[len++] = hex[(src[i] & 15) & 15]; - } - else - { - break; - } - } - - return len; -} - -int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen) -{ - int i = 0; - int len = 0; - - unsigned int cin = 0; - unsigned int cout = 0; - - - for( i = 0; (i <= slen) && (src[i] != 0); i++ ) - { - cin = src[i]; - - if( (cin >= '0') && (cin <= '9') ) - cin = cin - '0' + 52; - else if( (cin >= 'A') && (cin <= 'Z') ) - cin = cin - 'A'; - else if( (cin >= 'a') && (cin <= 'z') ) - cin = cin - 'a' + 26; - else if( cin == '+' ) - cin = 62; - else if( cin == '/' ) - cin = 63; - else if( cin == '=' ) - cin = 0; - else - continue; - - cout = (cout << 6) | cin; - - if( (i % 4) == 3 ) - { - if( (len + 3) < blen ) - { - buf[len++] = (char)(cout >> 16); - buf[len++] = (char)(cout >> 8); - buf[len++] = (char)(cout); - } - else - { - break; - } - } - } - - buf[len++] = 0; - return len; -} - - -struct path_info * uh_path_lookup(struct client *cl, const char *url) -{ - static char path_phys[PATH_MAX]; - static char path_info[PATH_MAX]; - static struct path_info p; - - char buffer[UH_LIMIT_MSGHEAD]; - char *docroot = cl->server->conf->docroot; - char *pathptr = NULL; - - int i = 0; - struct stat s; - - - memset(path_phys, 0, sizeof(path_phys)); - memset(path_info, 0, sizeof(path_info)); - memset(buffer, 0, sizeof(buffer)); - memset(&p, 0, sizeof(p)); - - /* copy docroot */ - memcpy(buffer, docroot, - min(strlen(docroot), sizeof(buffer) - 1)); - - /* separate query string from url */ - if( (pathptr = strchr(url, '?')) != NULL ) - { - p.query = pathptr[1] ? pathptr + 1 : NULL; - - /* urldecode component w/o query */ - if( pathptr > url ) - uh_urldecode( - &buffer[strlen(docroot)], - sizeof(buffer) - strlen(docroot) - 1, - url, (int)(pathptr - url) - 1 - ); - } - - /* no query string, decode all of url */ - else - { - uh_urldecode( - &buffer[strlen(docroot)], - sizeof(buffer) - strlen(docroot) - 1, - url, strlen(url) - ); - } - - /* create canon path */ - for( i = strlen(buffer); i >= 0; i-- ) - { - if( (buffer[i] == 0) || (buffer[i] == '/') ) - { - memset(path_info, 0, sizeof(path_info)); - memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1)); - - if( realpath(path_info, path_phys) ) - { - memset(path_info, 0, sizeof(path_info)); - memcpy(path_info, &buffer[i], - min(strlen(buffer) - i, sizeof(path_info) - 1)); - - break; - } - } - } - - /* check whether found path is within docroot */ - if( strncmp(path_phys, docroot, strlen(docroot)) || - ((path_phys[strlen(docroot)] != 0) && - (path_phys[strlen(docroot)] != '/')) - ) { - return NULL; - } - - /* test current path */ - if( ! stat(path_phys, &p.stat) ) - { - /* is a regular file */ - if( p.stat.st_mode & S_IFREG ) - { - p.root = docroot; - p.phys = path_phys; - p.name = &path_phys[strlen(docroot)]; - p.info = path_info[0] ? path_info : NULL; - } - - /* is a directory */ - else if( (p.stat.st_mode & S_IFDIR) && !strlen(path_info) ) - { - /* ensure trailing slash */ - if( path_phys[strlen(path_phys)-1] != '/' ) - path_phys[strlen(path_phys)] = '/'; - - /* try to locate index file */ - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, path_phys, sizeof(buffer)); - pathptr = &buffer[strlen(buffer)]; - - for( i = 0; i < array_size(uh_index_files); i++ ) - { - strncat(buffer, uh_index_files[i], sizeof(buffer)); - - if( !stat(buffer, &s) && (s.st_mode & S_IFREG) ) - { - memcpy(path_phys, buffer, sizeof(path_phys)); - memcpy(&p.stat, &s, sizeof(p.stat)); - break; - } - - *pathptr = 0; - } - - p.root = docroot; - p.phys = path_phys; - p.name = &path_phys[strlen(docroot)]; - } - } - - return p.phys ? &p : NULL; -} - - -static char uh_realms[UH_LIMIT_AUTHREALMS * sizeof(struct auth_realm)] = { 0 }; -static int uh_realm_count = 0; - -struct auth_realm * uh_auth_add(char *path, char *user, char *pass) -{ - struct auth_realm *new = NULL; - struct passwd *pwd; - struct spwd *spwd; - - if( uh_realm_count < UH_LIMIT_AUTHREALMS ) - { - new = (struct auth_realm *) - &uh_realms[uh_realm_count * sizeof(struct auth_realm)]; - - memset(new, 0, sizeof(struct auth_realm)); - - memcpy(new->path, path, - min(strlen(path), sizeof(new->path) - 1)); - - memcpy(new->user, user, - min(strlen(user), sizeof(new->user) - 1)); - - /* given password refers to a passwd entry */ - if( (strlen(pass) > 3) && !strncmp(pass, "$p$", 3) ) - { - /* try to resolve shadow entry */ - if( ((spwd = getspnam(&pass[3])) != NULL) && spwd->sp_pwdp ) - { - memcpy(new->pass, spwd->sp_pwdp, - min(strlen(spwd->sp_pwdp), sizeof(new->pass) - 1)); - } - - /* try to resolve passwd entry */ - else if( ((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd && - (pwd->pw_passwd[0] != '!') && (pwd->pw_passwd[0] != 0) - ) { - memcpy(new->pass, pwd->pw_passwd, - min(strlen(pwd->pw_passwd), sizeof(new->pass) - 1)); - } - } - - /* ordinary pwd */ - else - { - memcpy(new->pass, pass, - min(strlen(pass), sizeof(new->pass) - 1)); - } - - uh_realm_count++; - } - - return new; -} - -int uh_auth_check( - struct client *cl, struct http_request *req, struct path_info *pi -) { - int i, plen, rlen, protected; - char buffer[UH_LIMIT_MSGHEAD]; - char *user = NULL; - char *pass = NULL; - - struct auth_realm *realm = NULL; - - plen = strlen(pi->name); - protected = 0; - - /* check whether at least one realm covers the requested url */ - for( i = 0; i < uh_realm_count; i++ ) - { - realm = (struct auth_realm *) - &uh_realms[i * sizeof(struct auth_realm)]; - - rlen = strlen(realm->path); - - if( (plen >= rlen) && !strncasecmp(pi->name, realm->path, rlen) ) - { - req->realm = realm; - protected = 1; - break; - } - } - - /* requested resource is covered by a realm */ - if( protected ) - { - /* try to get client auth info */ - foreach_header(i, req->headers) - { - if( !strcasecmp(req->headers[i], "Authorization") && - (strlen(req->headers[i+1]) > 6) && - !strncasecmp(req->headers[i+1], "Basic ", 6) - ) { - memset(buffer, 0, sizeof(buffer)); - uh_b64decode(buffer, sizeof(buffer) - 1, - (unsigned char *) &req->headers[i+1][6], - strlen(req->headers[i+1]) - 6); - - if( (pass = strchr(buffer, ':')) != NULL ) - { - user = buffer; - *pass++ = 0; - } - - break; - } - } - - /* have client auth */ - if( user && pass ) - { - /* find matching realm */ - for( i = 0, realm = NULL; i < uh_realm_count; i++ ) - { - realm = (struct auth_realm *) - &uh_realms[i * sizeof(struct auth_realm)]; - - rlen = strlen(realm->path); - - if( (plen >= rlen) && - !strncasecmp(pi->name, realm->path, rlen) && - !strcmp(user, realm->user) - ) { - req->realm = realm; - break; - } - - realm = NULL; - } - - /* found a realm matching the username */ - if( realm ) - { - /* is a crypt passwd */ - if( realm->pass[0] == '$' ) - pass = crypt(pass, realm->pass); - - /* check user pass */ - if( !strcmp(pass, realm->pass) ) - return 1; - } - } - - /* 401 */ - uh_http_sendf(cl, NULL, - "HTTP/%.1f 401 Authorization Required\r\n" - "WWW-Authenticate: Basic realm=\"%s\"\r\n" - "Content-Type: text/plain\r\n" - "Content-Length: 23\r\n\r\n" - "Authorization Required\n", - req->version, cl->server->conf->realm - ); - - return 0; - } - - return 1; -} - - -static char uh_listeners[UH_LIMIT_LISTENERS * sizeof(struct listener)] = { 0 }; -static char uh_clients[UH_LIMIT_CLIENTS * sizeof(struct client)] = { 0 }; - -static int uh_listener_count = 0; -static int uh_client_count = 0; - - -struct listener * uh_listener_add(int sock, struct config *conf) -{ - struct listener *new = NULL; - socklen_t sl; - - if( uh_listener_count < UH_LIMIT_LISTENERS ) - { - new = (struct listener *) - &uh_listeners[uh_listener_count * sizeof(struct listener)]; - - new->socket = sock; - new->conf = conf; - - /* get local endpoint addr */ - sl = sizeof(struct sockaddr_in6); - memset(&(new->addr), 0, sl); - getsockname(sock, (struct sockaddr *) &(new->addr), &sl); - - uh_listener_count++; - } - - return new; -} - -struct listener * uh_listener_lookup(int sock) -{ - struct listener *cur = NULL; - int i; - - for( i = 0; i < uh_listener_count; i++ ) - { - cur = (struct listener *) &uh_listeners[i * sizeof(struct listener)]; - - if( cur->socket == sock ) - return cur; - } - - return NULL; -} - - -struct client * uh_client_add(int sock, struct listener *serv) -{ - struct client *new = NULL; - socklen_t sl; - - if( uh_client_count < UH_LIMIT_CLIENTS ) - { - new = (struct client *) - &uh_clients[uh_client_count * sizeof(struct client)]; - - new->socket = sock; - new->server = serv; - - /* get remote endpoint addr */ - sl = sizeof(struct sockaddr_in6); - memset(&(new->peeraddr), 0, sl); - getpeername(sock, (struct sockaddr *) &(new->peeraddr), &sl); - - /* get local endpoint addr */ - sl = sizeof(struct sockaddr_in6); - memset(&(new->servaddr), 0, sl); - getsockname(sock, (struct sockaddr *) &(new->servaddr), &sl); - - uh_client_count++; - } - - return new; -} - -struct client * uh_client_lookup(int sock) -{ - struct client *cur = NULL; - int i; - - for( i = 0; i < uh_client_count; i++ ) - { - cur = (struct client *) &uh_clients[i * sizeof(struct client)]; - - if( cur->socket == sock ) - return cur; - } - - return NULL; -} - -void uh_client_remove(int sock) -{ - struct client *del = uh_client_lookup(sock); - - if( del ) - { - memmove(del, del + 1, - sizeof(uh_clients) - (int)((char *)del - uh_clients) - sizeof(struct client)); - - uh_client_count--; - } -} - - diff --git a/contrib/package/uhttpd/src/uhttpd-utils.h b/contrib/package/uhttpd/src/uhttpd-utils.h deleted file mode 100644 index c7a6c90be..000000000 --- a/contrib/package/uhttpd/src/uhttpd-utils.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Utility header - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_UTILS_ - -#include <stdarg.h> -#include <fcntl.h> -#include <pwd.h> -#include <shadow.h> -#include <sys/stat.h> - -#define min(x, y) (((x) < (y)) ? (x) : (y)) -#define max(x, y) (((x) > (y)) ? (x) : (y)) - -#define array_size(x) \ - (sizeof(x) / sizeof(x[0])) - -#define foreach_header(i, h) \ - for( i = 0; (i + 1) < (sizeof(h) / sizeof(h[0])) && h[i]; i += 2 ) - -struct path_info { - char *root; - char *phys; - char *name; - char *info; - char *query; - struct stat stat; -}; - - -const char * sa_straddr(void *sa); -const char * sa_strport(void *sa); -int sa_port(void *sa); - -char *strfind(char *haystack, int hslen, const char *needle, int ndlen); - -int uh_tcp_send(struct client *cl, const char *buf, int len); -int uh_tcp_peek(struct client *cl, char *buf, int len); -int uh_tcp_recv(struct client *cl, char *buf, int len); - -int uh_http_sendhf( - struct client *cl, int code, const char *summary, - const char *fmt, ... -); - -#define uh_http_response(cl, code, message) \ - uh_http_sendhf(cl, code, message, message) - -int uh_http_sendc(struct client *cl, const char *data, int len); - -int uh_http_sendf( - struct client *cl, struct http_request *req, - const char *fmt, ... -); - -int uh_http_send( - struct client *cl, struct http_request *req, - const char *buf, int len -); - - -int uh_urldecode(char *buf, int blen, const char *src, int slen); -int uh_urlencode(char *buf, int blen, const char *src, int slen); -int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen); - - -struct auth_realm * uh_auth_add(char *path, char *user, char *pass); - -int uh_auth_check( - struct client *cl, struct http_request *req, struct path_info *pi -); - - -struct path_info * uh_path_lookup(struct client *cl, const char *url); - -struct listener * uh_listener_add(int sock, struct config *conf); -struct listener * uh_listener_lookup(int sock); - -struct client * uh_client_add(int sock, struct listener *serv); -struct client * uh_client_lookup(int sock); -void uh_client_remove(int sock); - -#endif diff --git a/contrib/package/uhttpd/src/uhttpd.c b/contrib/package/uhttpd/src/uhttpd.c deleted file mode 100644 index a7db794a5..000000000 --- a/contrib/package/uhttpd/src/uhttpd.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Main component - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _XOPEN_SOURCE 500 /* crypt() */ - -#include "uhttpd.h" -#include "uhttpd-utils.h" -#include "uhttpd-file.h" - -#ifdef HAVE_CGI -#include "uhttpd-cgi.h" -#endif - -#ifdef HAVE_LUA -#include "uhttpd-lua.h" -#endif - -#ifdef HAVE_TLS -#include "uhttpd-tls.h" -#endif - - -static int run = 1; - -static void uh_sigterm(int sig) -{ - run = 0; -} - -static void uh_config_parse(const char *path) -{ - FILE *c; - char line[512]; - char *user = NULL; - char *pass = NULL; - char *eol = NULL; - - if( (c = fopen(path ? path : "/etc/httpd.conf", "r")) != NULL ) - { - memset(line, 0, sizeof(line)); - - while( fgets(line, sizeof(line) - 1, c) ) - { - if( (line[0] == '/') && (strchr(line, ':') != NULL) ) - { - if( !(user = strchr(line, ':')) || (*user++ = 0) || - !(pass = strchr(user, ':')) || (*pass++ = 0) || - !(eol = strchr(pass, '\n')) || (*eol++ = 0) ) - continue; - - if( !uh_auth_add(line, user, pass) ) - { - fprintf(stderr, - "Can not manage more than %i basic auth realms, " - "will skip the rest\n", UH_LIMIT_AUTHREALMS - ); - - break; - } - } - } - - fclose(c); - } -} - -static int uh_socket_bind( - fd_set *serv_fds, int *max_fd, const char *host, const char *port, - struct addrinfo *hints, int do_tls, struct config *conf -) { - int sock = -1; - int yes = 1; - int status; - int bound = 0; - - struct listener *l = NULL; - struct addrinfo *addrs = NULL, *p = NULL; - - if( (status = getaddrinfo(host, port, hints, &addrs)) != 0 ) - { - fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status)); - } - - /* try to bind a new socket to each found address */ - for( p = addrs; p; p = p->ai_next ) - { - /* get the socket */ - if( (sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1 ) - { - perror("socket()"); - goto error; - } - - /* "address already in use" */ - if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1 ) - { - perror("setsockopt()"); - goto error; - } - - /* required to get parallel v4 + v6 working */ - if( p->ai_family == AF_INET6 ) - { - if( setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) == -1 ) - { - perror("setsockopt()"); - goto error; - } - } - - /* bind */ - if( bind(sock, p->ai_addr, p->ai_addrlen) == -1 ) - { - perror("bind()"); - goto error; - } - - /* listen */ - if( listen(sock, UH_LIMIT_CLIENTS) == -1 ) - { - perror("listen()"); - goto error; - } - - /* add listener to global list */ - if( ! (l = uh_listener_add(sock, conf)) ) - { - fprintf(stderr, - "uh_listener_add(): Can not create more than " - "%i listen sockets\n", UH_LIMIT_LISTENERS - ); - - goto error; - } - -#ifdef HAVE_TLS - /* init TLS */ - l->tls = do_tls ? conf->tls : NULL; -#endif - - /* add socket to server fd set */ - FD_SET(sock, serv_fds); - *max_fd = max(*max_fd, sock); - - bound++; - continue; - - error: - if( sock > 0 ) - close(sock); - } - - freeaddrinfo(addrs); - - return bound; -} - -static struct http_request * uh_http_header_parse(struct client *cl, char *buffer, int buflen) -{ - char *method = &buffer[0]; - char *path = NULL; - char *version = NULL; - - char *headers = NULL; - char *hdrname = NULL; - char *hdrdata = NULL; - - int i; - int hdrcount = 0; - - static struct http_request req; - - memset(&req, 0, sizeof(req)); - - - /* terminate initial header line */ - if( (headers = strfind(buffer, buflen, "\r\n", 2)) != NULL ) - { - buffer[buflen-1] = 0; - - *headers++ = 0; - *headers++ = 0; - - /* find request path */ - if( (path = strchr(buffer, ' ')) != NULL ) - *path++ = 0; - - /* find http version */ - if( (path != NULL) && ((version = strchr(path, ' ')) != NULL) ) - *version++ = 0; - - - /* check method */ - if( strcmp(method, "GET") && strcmp(method, "HEAD") && strcmp(method, "POST") ) - { - /* invalid method */ - uh_http_response(cl, 405, "Method Not Allowed"); - return NULL; - } - else - { - switch(method[0]) - { - case 'G': - req.method = UH_HTTP_MSG_GET; - break; - - case 'H': - req.method = UH_HTTP_MSG_HEAD; - break; - - case 'P': - req.method = UH_HTTP_MSG_POST; - break; - } - } - - /* check path */ - if( !path || !strlen(path) ) - { - /* malformed request */ - uh_http_response(cl, 400, "Bad Request"); - return NULL; - } - else - { - req.url = path; - } - - /* check version */ - if( strcmp(version, "HTTP/0.9") && strcmp(version, "HTTP/1.0") && strcmp(version, "HTTP/1.1") ) - { - /* unsupported version */ - uh_http_response(cl, 400, "Bad Request"); - return NULL; - } - else - { - req.version = strtof(&version[5], NULL); - } - - - /* process header fields */ - for( i = (int)(headers - buffer); i < buflen; i++ ) - { - /* found eol and have name + value, push out header tuple */ - if( hdrname && hdrdata && (buffer[i] == '\r' || buffer[i] == '\n') ) - { - buffer[i] = 0; - - /* store */ - if( (hdrcount + 1) < array_size(req.headers) ) - { - req.headers[hdrcount++] = hdrname; - req.headers[hdrcount++] = hdrdata; - - hdrname = hdrdata = NULL; - } - - /* too large */ - else - { - uh_http_response(cl, 413, "Request Entity Too Large"); - return NULL; - } - } - - /* have name but no value and found a colon, start of value */ - else if( hdrname && !hdrdata && ((i+2) < buflen) && - (buffer[i] == ':') && (buffer[i+1] == ' ') - ) { - buffer[i] = 0; - hdrdata = &buffer[i+2]; - } - - /* have no name and found [A-Z], start of name */ - else if( !hdrname && isalpha(buffer[i]) && isupper(buffer[i]) ) - { - hdrname = &buffer[i]; - } - } - - /* valid enough */ - return &req; - } - - /* Malformed request */ - uh_http_response(cl, 400, "Bad Request"); - return NULL; -} - - -static struct http_request * uh_http_header_recv(struct client *cl) -{ - static char buffer[UH_LIMIT_MSGHEAD]; - char *bufptr = &buffer[0]; - char *idxptr = NULL; - - struct timeval timeout; - - fd_set reader; - - ssize_t blen = sizeof(buffer)-1; - ssize_t rlen = 0; - - - memset(buffer, 0, sizeof(buffer)); - - while( blen > 0 ) - { - FD_ZERO(&reader); - FD_SET(cl->socket, &reader); - - /* fail after 0.1s */ - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - - /* check whether fd is readable */ - if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 ) - { - /* receive data */ - rlen = uh_tcp_peek(cl, bufptr, blen); - - if( rlen > 0 ) - { - if( (idxptr = strfind(buffer, sizeof(buffer), "\r\n\r\n", 4)) ) - { - blen -= uh_tcp_recv(cl, bufptr, (int)(idxptr - bufptr) + 4); - - /* header read complete ... */ - return uh_http_header_parse(cl, buffer, sizeof(buffer) - blen - 1); - } - else - { - rlen = uh_tcp_recv(cl, bufptr, rlen); - blen -= rlen; - bufptr += rlen; - } - } - else - { - /* invalid request (unexpected eof/timeout) */ - uh_http_response(cl, 408, "Request Timeout"); - return NULL; - } - } - else - { - /* invalid request (unexpected eof/timeout) */ - uh_http_response(cl, 408, "Request Timeout"); - return NULL; - } - } - - /* request entity too large */ - uh_http_response(cl, 413, "Request Entity Too Large"); - return NULL; -} - -static int uh_path_match(const char *prefix, const char *url) -{ - if( (strstr(url, prefix) == url) && - ((prefix[strlen(prefix)-1] == '/') || - (strlen(url) == strlen(prefix)) || - (url[strlen(prefix)] == '/')) - ) { - return 1; - } - - return 0; -} - - -int main (int argc, char **argv) -{ -#ifdef HAVE_LUA - /* Lua runtime */ - lua_State *L = NULL; -#endif - - /* master file descriptor list */ - fd_set used_fds, serv_fds, read_fds; - - /* working structs */ - struct addrinfo hints; - struct http_request *req; - struct path_info *pin; - struct client *cl; - struct sigaction sa; - struct config conf; - - /* maximum file descriptor number */ - int new_fd, cur_fd, max_fd = 0; - - int tls = 0; - int keys = 0; - int bound = 0; - int nofork = 0; - - /* args */ - char opt; - char bind[128]; - char *port = NULL; - - /* library handles */ - void *tls_lib; - void *lua_lib; - - /* clear the master and temp sets */ - FD_ZERO(&used_fds); - FD_ZERO(&serv_fds); - FD_ZERO(&read_fds); - - /* handle SIGPIPE, SIGCHILD */ - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - - sa.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &sa, NULL); - sigaction(SIGCHLD, &sa, NULL); - - sa.sa_handler = uh_sigterm; - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - - /* prepare addrinfo hints */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - /* parse args */ - memset(&conf, 0, sizeof(conf)); - memset(bind, 0, sizeof(bind)); - -#ifdef HAVE_TLS - /* load TLS plugin */ - if( ! (tls_lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) ) - { - fprintf(stderr, - "Notice: Unable to load TLS plugin - disabling SSL support! " - "(Reason: %s)\n", dlerror() - ); - } - else - { - /* resolve functions */ - if( !(conf.tls_init = dlsym(tls_lib, "uh_tls_ctx_init")) || - !(conf.tls_cert = dlsym(tls_lib, "uh_tls_ctx_cert")) || - !(conf.tls_key = dlsym(tls_lib, "uh_tls_ctx_key")) || - !(conf.tls_free = dlsym(tls_lib, "uh_tls_ctx_free")) || - !(conf.tls_accept = dlsym(tls_lib, "uh_tls_client_accept")) || - !(conf.tls_close = dlsym(tls_lib, "uh_tls_client_close")) || - !(conf.tls_recv = dlsym(tls_lib, "uh_tls_client_recv")) || - !(conf.tls_send = dlsym(tls_lib, "uh_tls_client_send")) - ) { - fprintf(stderr, - "Error: Failed to lookup required symbols " - "in TLS plugin: %s\n", dlerror() - ); - exit(1); - } - - /* init SSL context */ - if( ! (conf.tls = conf.tls_init()) ) - { - fprintf(stderr, "Error: Failed to initalize SSL context\n"); - exit(1); - } - } -#endif - - while( (opt = getopt(argc, argv, "fC:K:p:s:h:c:l:L:d:r:m:x:")) > 0 ) - { - switch(opt) - { - /* [addr:]port */ - case 'p': - case 's': - if( (port = strrchr(optarg, ':')) != NULL ) - { - if( (optarg[0] == '[') && (port > optarg) && (port[-1] == ']') ) - memcpy(bind, optarg + 1, - min(sizeof(bind), (int)(port - optarg) - 2)); - else - memcpy(bind, optarg, - min(sizeof(bind), (int)(port - optarg))); - - port++; - } - else - { - port = optarg; - } - - if( opt == 's' ) - { - if( !conf.tls ) - { - fprintf(stderr, - "Notice: TLS support is disabled, " - "ignoring '-s %s'\n", optarg - ); - continue; - } - - tls = 1; - } - - /* bind sockets */ - bound += uh_socket_bind( - &serv_fds, &max_fd, bind[0] ? bind : NULL, port, - &hints, (opt == 's'), &conf - ); - - break; - -#ifdef HAVE_TLS - /* certificate */ - case 'C': - if( conf.tls ) - { - if( conf.tls_cert(conf.tls, optarg) < 1 ) - { - fprintf(stderr, - "Error: Invalid certificate file given\n"); - exit(1); - } - - keys++; - } - - break; - - /* key */ - case 'K': - if( conf.tls ) - { - if( conf.tls_key(conf.tls, optarg) < 1 ) - { - fprintf(stderr, - "Error: Invalid private key file given\n"); - exit(1); - } - - keys++; - } - - break; -#endif - - /* docroot */ - case 'h': - if( ! realpath(optarg, conf.docroot) ) - { - fprintf(stderr, "Error: Invalid directory %s: %s\n", - optarg, strerror(errno)); - exit(1); - } - break; - -#ifdef HAVE_CGI - /* cgi prefix */ - case 'x': - conf.cgi_prefix = optarg; - break; -#endif - -#ifdef HAVE_LUA - /* lua prefix */ - case 'l': - conf.lua_prefix = optarg; - break; - - /* lua handler */ - case 'L': - conf.lua_handler = optarg; - break; -#endif - - /* no fork */ - case 'f': - nofork = 1; - break; - - /* urldecode */ - case 'd': - if( (port = malloc(strlen(optarg)+1)) != NULL ) - { - memset(port, 0, strlen(optarg)+1); - uh_urldecode(port, strlen(optarg), optarg, strlen(optarg)); - printf("%s", port); - free(port); - exit(0); - } - break; - - /* basic auth realm */ - case 'r': - conf.realm = optarg; - break; - - /* md5 crypt */ - case 'm': - printf("%s\n", crypt(optarg, "$1$")); - exit(0); - break; - - /* config file */ - case 'c': - conf.file = optarg; - break; - - default: - fprintf(stderr, - "Usage: %s -p [addr:]port [-h docroot]\n" - " -f Do not fork to background\n" - " -c file Configuration file, default is '/etc/httpd.conf'\n" - " -p [addr:]port Bind to specified address and port, multiple allowed\n" -#ifdef HAVE_TLS - " -s [addr:]port Like -p but provide HTTPS on this port\n" - " -C file ASN.1 server certificate file\n" - " -K file ASN.1 server private key file\n" -#endif - " -h directory Specify the document root, default is '.'\n" -#ifdef HAVE_LUA - " -l string URL prefix for Lua handler, default is '/lua'\n" - " -L file Lua handler script, omit to disable Lua\n" -#endif -#ifdef HAVE_CGI - " -x string URL prefix for CGI handler, default is '/cgi-bin'\n" -#endif - " -d string URL decode given string\n" - " -r string Specify basic auth realm\n" - " -m string MD5 crypt given string\n" - "\n", argv[0] - ); - - exit(1); - } - } - -#ifdef HAVE_TLS - if( (tls == 1) && (keys < 2) ) - { - fprintf(stderr, "Error: Missing private key or certificate file\n"); - exit(1); - } -#endif - - if( bound < 1 ) - { - fprintf(stderr, "Error: No sockets bound, unable to continue\n"); - exit(1); - } - - /* default docroot */ - if( !conf.docroot[0] && !realpath(".", conf.docroot) ) - { - fprintf(stderr, "Error: Can not determine default document root: %s\n", - strerror(errno)); - exit(1); - } - - /* default realm */ - if( ! conf.realm ) - conf.realm = "Protected Area"; - - /* config file */ - uh_config_parse(conf.file); - -#ifdef HAVE_CGI - /* default cgi prefix */ - if( ! conf.cgi_prefix ) - conf.cgi_prefix = "/cgi-bin"; -#endif - -#ifdef HAVE_LUA - /* load Lua plugin */ - if( ! (lua_lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) ) - { - fprintf(stderr, - "Notice: Unable to load Lua plugin - disabling Lua support! " - "(Reason: %s)\n", dlerror() - ); - } - else - { - /* resolve functions */ - if( !(conf.lua_init = dlsym(lua_lib, "uh_lua_init")) || - !(conf.lua_close = dlsym(lua_lib, "uh_lua_close")) || - !(conf.lua_request = dlsym(lua_lib, "uh_lua_request")) - ) { - fprintf(stderr, - "Error: Failed to lookup required symbols " - "in Lua plugin: %s\n", dlerror() - ); - exit(1); - } - - /* init Lua runtime if handler is specified */ - if( conf.lua_handler ) - { - /* default lua prefix */ - if( ! conf.lua_prefix ) - conf.lua_prefix = "/lua"; - - L = conf.lua_init(conf.lua_handler); - } - } -#endif - - /* fork (if not disabled) */ - if( ! nofork ) - { - switch( fork() ) - { - case -1: - perror("fork()"); - exit(1); - - case 0: - /* daemon setup */ - if( chdir("/") ) - perror("chdir()"); - - if( (cur_fd = open("/dev/null", O_WRONLY)) > -1 ) - dup2(cur_fd, 0); - - if( (cur_fd = open("/dev/null", O_RDONLY)) > -1 ) - dup2(cur_fd, 1); - - if( (cur_fd = open("/dev/null", O_RDONLY)) > -1 ) - dup2(cur_fd, 2); - - break; - - default: - exit(0); - } - } - - /* backup server descriptor set */ - used_fds = serv_fds; - - /* loop */ - while(run) - { - /* create a working copy of the used fd set */ - read_fds = used_fds; - - /* sleep until socket activity */ - if( select(max_fd + 1, &read_fds, NULL, NULL, NULL) == -1 ) - { - perror("select()"); - exit(1); - } - - /* run through the existing connections looking for data to be read */ - for( cur_fd = 0; cur_fd <= max_fd; cur_fd++ ) - { - /* is a socket managed by us */ - if( FD_ISSET(cur_fd, &read_fds) ) - { - /* is one of our listen sockets */ - if( FD_ISSET(cur_fd, &serv_fds) ) - { - /* handle new connections */ - if( (new_fd = accept(cur_fd, NULL, 0)) != -1 ) - { - /* add to global client list */ - if( (cl = uh_client_add(new_fd, uh_listener_lookup(cur_fd))) != NULL ) - { -#ifdef HAVE_TLS - /* setup client tls context */ - if( conf.tls ) - conf.tls_accept(cl); -#endif - - /* add client socket to global fdset */ - FD_SET(new_fd, &used_fds); - max_fd = max(max_fd, new_fd); - } - - /* insufficient resources */ - else - { - fprintf(stderr, - "uh_client_add(): Can not manage more than " - "%i client sockets, connection dropped\n", - UH_LIMIT_CLIENTS - ); - - close(new_fd); - } - } - } - - /* is a client socket */ - else - { - if( ! (cl = uh_client_lookup(cur_fd)) ) - { - /* this should not happen! */ - fprintf(stderr, - "uh_client_lookup(): No entry for fd %i!\n", - cur_fd); - - goto cleanup; - } - - /* parse message header */ - if( (req = uh_http_header_recv(cl)) != NULL ) - { -#ifdef HAVE_LUA - /* Lua request? */ - if( L && uh_path_match(conf.lua_prefix, req->url) ) - { - conf.lua_request(cl, req, L); - } - else -#endif - /* dispatch request */ - if( (pin = uh_path_lookup(cl, req->url)) != NULL ) - { - /* auth ok? */ - if( uh_auth_check(cl, req, pin) ) - { -#ifdef HAVE_CGI - if( uh_path_match(conf.cgi_prefix, pin->name) ) - { - uh_cgi_request(cl, req, pin); - } - else -#endif - { - uh_file_request(cl, req, pin); - } - } - } - - /* 404 */ - else - { - uh_http_sendhf(cl, 404, "Not Found", - "No such file or directory"); - } - } - - /* 400 */ - else - { - uh_http_sendhf(cl, 400, "Bad Request", - "Malformed request received"); - } - -#ifdef HAVE_TLS - /* free client tls context */ - if( conf.tls ) - conf.tls_close(cl); -#endif - - cleanup: - - /* close client socket */ - close(cur_fd); - FD_CLR(cur_fd, &used_fds); - - /* remove from global client list */ - uh_client_remove(cur_fd); - } - } - } - } - -#ifdef HAVE_LUA - /* destroy the Lua state */ - if( L != NULL ) - conf.lua_close(L); -#endif - - return 0; -} - diff --git a/contrib/package/uhttpd/src/uhttpd.h b/contrib/package/uhttpd/src/uhttpd.h deleted file mode 100644 index bb08afa1a..000000000 --- a/contrib/package/uhttpd/src/uhttpd.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * uhttpd - Tiny single-threaded httpd - Main header - * - * Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _UHTTPD_ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/select.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <linux/limits.h> -#include <netdb.h> -#include <ctype.h> - -#include <dlfcn.h> - - -#ifdef HAVE_LUA -#include <lua.h> -#endif - -#ifdef HAVE_TLS -#include <openssl/ssl.h> -#endif - - -#define UH_LIMIT_MSGHEAD 4096 -#define UH_LIMIT_HEADERS 64 - -#define UH_LIMIT_LISTENERS 16 -#define UH_LIMIT_CLIENTS 64 -#define UH_LIMIT_AUTHREALMS 8 - -#define UH_HTTP_MSG_GET 0 -#define UH_HTTP_MSG_HEAD 1 -#define UH_HTTP_MSG_POST 2 - -struct listener; -struct client; -struct http_request; - -struct config { - char docroot[PATH_MAX]; - char *realm; - char *file; -#ifdef HAVE_CGI - char *cgi_prefix; -#endif -#ifdef HAVE_LUA - char *lua_prefix; - char *lua_handler; - lua_State * (*lua_init) (const char *handler); - void (*lua_close) (lua_State *L); - void (*lua_request) (struct client *cl, struct http_request *req, lua_State *L); -#endif -#ifdef HAVE_TLS - char *cert; - char *key; - SSL_CTX *tls; - SSL_CTX * (*tls_init) (void); - int (*tls_cert) (SSL_CTX *c, const char *file); - int (*tls_key) (SSL_CTX *c, const char *file); - void (*tls_free) (struct listener *l); - void (*tls_accept) (struct client *c); - void (*tls_close) (struct client *c); - int (*tls_recv) (struct client *c, void *buf, int len); - int (*tls_send) (struct client *c, void *buf, int len); -#endif -}; - -struct listener { - int socket; - struct sockaddr_in6 addr; - struct config *conf; -#ifdef HAVE_TLS - SSL_CTX *tls; -#endif -}; - -struct client { - int socket; - int peeklen; - char peekbuf[UH_LIMIT_MSGHEAD]; - struct listener *server; - struct sockaddr_in6 servaddr; - struct sockaddr_in6 peeraddr; -#ifdef HAVE_TLS - SSL *tls; -#endif -}; - -struct auth_realm { - char path[PATH_MAX]; - char user[32]; - char pass[128]; -}; - -struct http_request { - int method; - float version; - char *url; - char *headers[UH_LIMIT_HEADERS]; - struct auth_realm *realm; -}; - -struct http_response { - int statuscode; - char *statusmsg; - char *headers[UH_LIMIT_HEADERS]; -}; - -#endif - |