1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

Forked off Anti-Web and made axhttpd

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@51 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich 2006-12-05 06:32:30 +00:00
parent 396d340778
commit 8213b750a1
20 changed files with 2184 additions and 2432 deletions

View File

@ -34,8 +34,7 @@ RELEASE=axTLS-$(VERSION)
# standard version # standard version
target: target:
$(MAKE) -C ssl $(MAKE) -C ssl
ifdef CONFIG_AWHTTPD ifdef CONFIG_AXHTTPD
$(MAKE) -C httpd untar_web_server
$(MAKE) -C httpd $(MAKE) -C httpd
endif endif
ifdef CONFIG_BINDINGS ifdef CONFIG_BINDINGS
@ -72,12 +71,12 @@ install: $(PREFIX) all
chmod 755 $(PREFIX)/lib/libax* chmod 755 $(PREFIX)/lib/libax*
-@install -m 755 $(STAGE)/ax* $(PREFIX)/bin > /dev/null 2>&1 -@install -m 755 $(STAGE)/ax* $(PREFIX)/bin > /dev/null 2>&1
-@install -m 755 $(STAGE)/axtlsp.pm `perl -e 'use Config; print $$Config{installarchlib};'` > /dev/null 2>&1 -@install -m 755 $(STAGE)/axtlsp.pm `perl -e 'use Config; print $$Config{installarchlib};'` > /dev/null 2>&1
-@install -m 755 $(STAGE)/awhttpd* $(PREFIX)/bin > /dev/null 2>&1 -@install -m 755 $(STAGE)/axhttpd* $(PREFIX)/bin > /dev/null 2>&1
installclean: installclean:
-@rm $(PREFIX)/lib/libax* > /dev/null 2>&1 -@rm $(PREFIX)/lib/libax* > /dev/null 2>&1
-@rm $(PREFIX)/bin/ax* > /dev/null 2>&1 -@rm $(PREFIX)/bin/ax* > /dev/null 2>&1
-@rm $(PREFIX)/bin/awhttpd* > /dev/null 2>&1 -@rm $(PREFIX)/bin/axhttpd* > /dev/null 2>&1
-@rm `perl -e 'use Config; print $$Config{installarchlib};'`/axtlsp.pm > /dev/null 2>&1 -@rm `perl -e 'use Config; print $$Config{installarchlib};'`/axtlsp.pm > /dev/null 2>&1
test: test:

11
README
View File

@ -9,7 +9,7 @@ This is a guide to get a small SSL web-server up and running quickly.
######################################################################## ########################################################################
The axTLS project is an SSL client/server library using the TLSv1 protocol. The axTLS project is an SSL client/server library using the TLSv1 protocol.
It is designed to be small and fast, and is suited to embedded projects. A web It is designed to be small and fast, and is suited to embedded projects. A web
server is included (called Anti-Web). server is included.
The web server + SSL library is around 50-60kB and is configurable for The web server + SSL library is around 50-60kB and is configurable for
features or size. features or size.
@ -32,8 +32,8 @@ the extracted directory and typing:
Select your platform type, save the configuration, exit, and then Select your platform type, save the configuration, exit, and then
type "make" again. type "make" again.
If all goes well, you should end up with an executable called "awhttpd" (or If all goes well, you should end up with an executable called "axhttpd" (or
awhttpd.exe) in the _stage directory. axhttpd.exe) in the _stage directory.
To play with all the various axTLS options, type: To play with all the various axTLS options, type:
@ -47,7 +47,7 @@ Save the new configuration and rebuild.
To run it, go to the _stage directory, and type (as superuser): To run it, go to the _stage directory, and type (as superuser):
> awhttpd > axhttpd
And then point your browser at: And then point your browser at:
@ -61,9 +61,6 @@ http://127.0.0.1
to see the same page unencrypted. to see the same page unencrypted.
See the README in the httpd directory from more configuration information on
Anti-Web.
######################################################################## ########################################################################
# The axssl utilities # The axssl utilities
######################################################################## ########################################################################

View File

@ -107,11 +107,11 @@ config CONFIG_EXTRA_LDFLAGS_OPTIONS
endmenu endmenu
source ssl/Config.in source ssl/Config.in
config CONFIG_AWHTTPD config CONFIG_AXHTTPD
bool "Enable HTTP/HTTPS Web Server" bool "Enable HTTP/HTTPS Web Server"
default y default y
help help
Build the AWHTTPD web server Build the AXHTTPD web server
source httpd/Config.in source httpd/Config.in
source bindings/Config.in source bindings/Config.in

View File

@ -1,6 +1,6 @@
<jmeterTestPlan version="1.2" properties="1.8"> <jmeterTestPlan version="1.2" properties="1.8">
<hashTree> <hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="awhttpd Test Plan" enabled="true"> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="axhttpd Test Plan" enabled="true">
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/> <collectionProp name="Arguments.arguments"/>
</elementProp> </elementProp>

View File

@ -37,7 +37,7 @@
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
<ROW Component="New_Folder" ComponentId="{2AD064CD-A20E-40FD-9233-CF8732C8F54D}" Directory_="New_Folder_2_DIR" Attributes="0"/> <ROW Component="New_Folder" ComponentId="{2AD064CD-A20E-40FD-9233-CF8732C8F54D}" Directory_="New_Folder_2_DIR" Attributes="0"/>
<ROW Component="awhttpd.exe" ComponentId="{0AEFFA20-29FA-4304-8227-F9ED0E6B8A0A}" Directory_="APPDIR" Attributes="0" KeyPath="awhttpd.exe" FullKeyPath="APPDIR\awhttpd.exe"/> <ROW Component="axhttpd.exe" ComponentId="{0AEFFA20-29FA-4304-8227-F9ED0E6B8A0A}" Directory_="APPDIR" Attributes="0" KeyPath="axhttpd.exe" FullKeyPath="APPDIR\axhttpd.exe"/>
<ROW Component="axssl.csharp.exe" ComponentId="{B9373428-79F5-4D77-8924-48D23EF3870E}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.csharp.exe" FullKeyPath="APPDIR\axssl.csharp.exe"/> <ROW Component="axssl.csharp.exe" ComponentId="{B9373428-79F5-4D77-8924-48D23EF3870E}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.csharp.exe" FullKeyPath="APPDIR\axssl.csharp.exe"/>
<ROW Component="axssl.exe" ComponentId="{E1E96774-7BFC-45B9-BA33-FC0C631921FD}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.exe" FullKeyPath="APPDIR\axssl.exe"/> <ROW Component="axssl.exe" ComponentId="{E1E96774-7BFC-45B9-BA33-FC0C631921FD}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.exe" FullKeyPath="APPDIR\axssl.exe"/>
<ROW Component="axssl.vbnet.exe" ComponentId="{31F03DA9-E099-4BBD-88B7-4ABBC9F77EFB}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.vbnet.exe" FullKeyPath="APPDIR\axssl.vbnet.exe"/> <ROW Component="axssl.vbnet.exe" ComponentId="{31F03DA9-E099-4BBD-88B7-4ABBC9F77EFB}" Directory_="APPDIR" Attributes="0" KeyPath="axssl.vbnet.exe" FullKeyPath="APPDIR\axssl.vbnet.exe"/>
@ -59,12 +59,12 @@
<ROW Component="wcprops" ComponentId="{4106AB01-565E-4281-97AE-96EC1F865899}" Directory_="wcprops_DIR" Attributes="0"/> <ROW Component="wcprops" ComponentId="{4106AB01-565E-4281-97AE-96EC1F865899}" Directory_="wcprops_DIR" Attributes="0"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="awhttpd.exe axssl.csharp.exe axssl.exe axssl.vbnet.exe axtls.dll axtls.jar axtlsj.dll favicon.ico bigint.h test_cgi.php New_Folder dir_wcprops crypto_2600des.gif.svn_base crypto_2600des.gif.svn_work crypto_2600des.gif.svn_base_1 prop_base props text_base wcprops crypto_2600des.gif.svn_work_1 crypto_2600des.gif"/> <ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0" Components="axhttpd.exe axssl.csharp.exe axssl.exe axssl.vbnet.exe axtls.dll axtls.jar axtlsj.dll favicon.ico bigint.h test_cgi.php New_Folder dir_wcprops crypto_2600des.gif.svn_base crypto_2600des.gif.svn_work crypto_2600des.gif.svn_base_1 prop_base props text_base wcprops crypto_2600des.gif.svn_work_1 crypto_2600des.gif"/>
<ATTRIBUTE name="CurrentFeature" value="MainFeature"/> <ATTRIBUTE name="CurrentFeature" value="MainFeature"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiFilesComponent">
<ROW File="README.txt" Component_="dir_wcprops" FileName="README.txt" Attributes="1" SourcePath="..\www\crypto_files\.svn\README.txt" SelfReg="false" Sequence="43"/> <ROW File="README.txt" Component_="dir_wcprops" FileName="README.txt" Attributes="1" SourcePath="..\www\crypto_files\.svn\README.txt" SelfReg="false" Sequence="43"/>
<ROW File="awhttpd.exe" Component_="awhttpd.exe" FileName="awhttpd.exe" Attributes="0" SourcePath="..\_stage\awhttpd.exe" SelfReg="false" Sequence="1"/> <ROW File="axhttpd.exe" Component_="axhttpd.exe" FileName="axhttpd.exe" Attributes="0" SourcePath="..\_stage\axhttpd.exe" SelfReg="false" Sequence="1"/>
<ROW File="axssl.csharp.exe" Component_="axssl.csharp.exe" FileName="axsslc~1.exe|axssl.csharp.exe" Attributes="0" SourcePath="..\_stage\axssl.csharp.exe" SelfReg="false" Sequence="2"/> <ROW File="axssl.csharp.exe" Component_="axssl.csharp.exe" FileName="axsslc~1.exe|axssl.csharp.exe" Attributes="0" SourcePath="..\_stage\axssl.csharp.exe" SelfReg="false" Sequence="2"/>
<ROW File="axssl.exe" Component_="axssl.exe" FileName="axssl.exe" Attributes="0" SourcePath="..\_stage\axssl.exe" SelfReg="false" Sequence="3"/> <ROW File="axssl.exe" Component_="axssl.exe" FileName="axssl.exe" Attributes="0" SourcePath="..\_stage\axssl.exe" SelfReg="false" Sequence="3"/>
<ROW File="axssl.vbnet.exe" Component_="axssl.vbnet.exe" FileName="axsslv~1.exe|axssl.vbnet.exe" Attributes="0" SourcePath="..\_stage\axssl.vbnet.exe" SelfReg="false" Sequence="4"/> <ROW File="axssl.vbnet.exe" Component_="axssl.vbnet.exe" FileName="axsslv~1.exe|axssl.vbnet.exe" Attributes="0" SourcePath="..\_stage\axssl.vbnet.exe" SelfReg="false" Sequence="4"/>
@ -199,7 +199,7 @@
<ATTRIBUTE name="Package" value="1"/> <ATTRIBUTE name="Package" value="1"/>
</COMPONENT> </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent"> <COMPONENT cid="caphyon.advinst.msicomp.MsiShortsComponent">
<ROW Shortcut="awhttpd.exe" Directory_="SHORTCUTDIR" Name="awhttpd" Component_="awhttpd.exe" Target="[#awhttpd.exe]" Description="awhttpd.exe" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/> <ROW Shortcut="axhttpd.exe" Directory_="SHORTCUTDIR" Name="axhttpd" Component_="axhttpd.exe" Target="[#axhttpd.exe]" Description="axhttpd.exe" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="axssl_client" Directory_="SHORTCUTDIR" Name="axsslc~1|axssl client" Component_="axssl.exe" Target="[#axssl.exe]" Arguments="s_client" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/> <ROW Shortcut="axssl_client" Directory_="SHORTCUTDIR" Name="axsslc~1|axssl client" Component_="axssl.exe" Target="[#axssl.exe]" Arguments="s_client" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
<ROW Shortcut="axssl_server" Directory_="SHORTCUTDIR" Name="axssls~1|axssl server" Component_="axssl.exe" Target="[#axssl.exe]" Arguments="s_server" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/> <ROW Shortcut="axssl_server" Directory_="SHORTCUTDIR" Name="axssls~1|axssl server" Component_="axssl.exe" Target="[#axssl.exe]" Arguments="s_server" Hotkey="0" IconIndex="0" ShowCmd="1" WkDir="APPDIR"/>
</COMPONENT> </COMPONENT>

View File

@ -43,9 +43,8 @@ CONFIG_USE_DEV_URANDOM=y
# CONFIG_WIN32_USE_CRYPTO_LIB is not set # CONFIG_WIN32_USE_CRYPTO_LIB is not set
# CONFIG_PERFORMANCE_TESTING is not set # CONFIG_PERFORMANCE_TESTING is not set
# CONFIG_SSL_TEST is not set # CONFIG_SSL_TEST is not set
# CONFIG_AWHTTPD is not set # CONFIG_AXHTTPD is not set
# CONFIG_HTTP_STATIC_BUILD is not set # CONFIG_HTTP_STATIC_BUILD is not set
# CONFIG_HTTP_HAS_SSL is not set
CONFIG_HTTP_HTTPS_PORT=0 CONFIG_HTTP_HTTPS_PORT=0
CONFIG_HTTP_SESSION_CACHE_SIZE=0 CONFIG_HTTP_SESSION_CACHE_SIZE=0
CONFIG_HTTP_WEBROOT="" CONFIG_HTTP_WEBROOT=""

View File

@ -47,13 +47,12 @@ CONFIG_SSL_MAX_CERTS=2
CONFIG_WIN32_USE_CRYPTO_LIB=y CONFIG_WIN32_USE_CRYPTO_LIB=y
# CONFIG_PERFORMANCE_TESTING is not set # CONFIG_PERFORMANCE_TESTING is not set
# CONFIG_SSL_TEST is not set # CONFIG_SSL_TEST is not set
CONFIG_AWHTTPD=y CONFIG_AXHTTPD=y
# #
# Awhttpd Configuration # Awhttpd Configuration
# #
# CONFIG_HTTP_STATIC_BUILD is not set # CONFIG_HTTP_STATIC_BUILD is not set
CONFIG_HTTP_HAS_SSL=y
CONFIG_HTTP_HTTPS_PORT=443 CONFIG_HTTP_HTTPS_PORT=443
CONFIG_HTTP_WEBROOT="www" CONFIG_HTTP_WEBROOT="www"
CONFIG_HTTP_PORT=80 CONFIG_HTTP_PORT=80

View File

@ -3,26 +3,19 @@
# see scripts/config/Kconfig-language.txt # see scripts/config/Kconfig-language.txt
# #
menu "Awhttpd Configuration" menu "Axhttpd Configuration"
depends on CONFIG_AWHTTPD depends on CONFIG_AXHTTPD
config CONFIG_HTTP_STATIC_BUILD config CONFIG_HTTP_STATIC_BUILD
bool "Static Build" bool "Static Build"
default n default n
help help
Select y if you want awhttp to be a static build (i.e. don't use the Select y if you want axhttp to be a static build (i.e. don't use the
axtls shared library or dll). axtls shared library or dll).
config CONFIG_HTTP_HAS_SSL
bool "Use SSL"
default y
help
Build the HTTP server with SSL capability
config CONFIG_HTTP_HTTPS_PORT config CONFIG_HTTP_HTTPS_PORT
int "HTTPS port" int "HTTPS port"
default 443 default 443
depends on CONFIG_HTTP_HAS_SSL
help help
The port number of the HTTPS server. The port number of the HTTPS server.
@ -31,7 +24,6 @@ config CONFIG_HTTP_HTTPS_PORT
config CONFIG_HTTP_SESSION_CACHE_SIZE config CONFIG_HTTP_SESSION_CACHE_SIZE
int "SSL session cache size" int "SSL session cache size"
default 5 default 5
depends on CONFIG_HTTP_HAS_SSL
help help
The size of the SSL session cache. The size of the SSL session cache.
@ -44,7 +36,7 @@ config CONFIG_HTTP_WEBROOT
default "../www" if !CONFIG_PLATFORM_WIN32 default "../www" if !CONFIG_PLATFORM_WIN32
default "..\\www" if CONFIG_PLATFORM_WIN32 default "..\\www" if CONFIG_PLATFORM_WIN32
help help
The location of the web root in relation to awhttpd. This is The location of the web root in relation to axhttpd. This is
the directory where index.html lives. the directory where index.html lives.
config CONFIG_HTTP_PORT config CONFIG_HTTP_PORT
@ -72,7 +64,7 @@ config CONFIG_HTTP_CGI_EXTENSION
default ".php" default ".php"
depends on CONFIG_HTTP_HAS_CGI depends on CONFIG_HTTP_HAS_CGI
help help
Tell awhhtp what file extension is used for CGI Tell axhhtp what file extension is used for CGI
config CONFIG_HTTP_DIRECTORIES config CONFIG_HTTP_DIRECTORIES
bool "Enable Directory Listing" bool "Enable Directory Listing"
@ -101,14 +93,14 @@ config CONFIG_HTTP_VERBOSE
default y if CONFIG_SSL_FULL_MODE default y if CONFIG_SSL_FULL_MODE
default n if !CONFIG_SSL_FULL_MODE default n if !CONFIG_SSL_FULL_MODE
help help
Enable extra statements used when using awhttpd. Enable extra statements used when using axhttpd.
config CONFIG_HTTP_IS_DAEMON config CONFIG_HTTP_IS_DAEMON
bool "Run as a daemon" bool "Run as a daemon"
default n default n
depends on !CONFIG_PLATFORM_WIN32 depends on !CONFIG_PLATFORM_WIN32
help help
Run awhttpd as a background process. Run axhttpd as a background process.
Does not work under Win32 Does not work under Win32

View File

@ -24,9 +24,9 @@ include ../config/makefile.conf
ifndef CONFIG_PLATFORM_WIN32 ifndef CONFIG_PLATFORM_WIN32
ifdef CONFIG_PLATFORM_CYGWIN ifdef CONFIG_PLATFORM_CYGWIN
TARGET=../$(STAGE)/awhttpd.exe TARGET=../$(STAGE)/axhttpd.exe
else else
TARGET=../$(STAGE)/awhttpd TARGET=../$(STAGE)/axhttpd
endif endif
ifdef CONFIG_HTTP_STATIC_BUILD ifdef CONFIG_HTTP_STATIC_BUILD
@ -38,7 +38,7 @@ endif
CFLAGS += -I../ssl CFLAGS += -I../ssl
else # win32 build else # win32 build
TARGET=../$(STAGE)/awhttpd.exe TARGET=../$(STAGE)/axhttpd.exe
ifdef CONFIG_HTTP_STATIC_BUILD ifdef CONFIG_HTTP_STATIC_BUILD
LIBS=../$(STAGE)/axtls.static.lib ..\\config\\axtls.res LIBS=../$(STAGE)/axtls.static.lib ..\\config\\axtls.res
@ -51,31 +51,16 @@ ifndef CONFIG_AWHTTPD
web_server: web_server:
else else
untar_web_server: awhttpd/Makefile
awhttpd/Makefile:
tar xvf awhttpd-3.0.7.tar
cat awhttpd.patch | patch -p0
web_server : $(TARGET) web_server : $(TARGET)
OBJ= \ OBJ= \
cgi.o \
conn.o \ conn.o \
main.o \ main.o \
net.o \ net.o \
proc.o \ proc.o \
socket.o \ socket.o \
errors.o \
misc.o \ misc.o \
urldecode.o \ mime_types.o
mime_types.o \
index.o \
urlencode.o \
permcheck.o
%.o : awhttpd/%.c ../config/.config
$(CC) -c $(CFLAGS) $<
ifndef CONFIG_PLATFORM_WIN32 ifndef CONFIG_PLATFORM_WIN32
@ -91,10 +76,6 @@ endif
endif endif
else # Win32 else # Win32
OBJ:=$(OBJ:.o=.obj)
%.obj : awhttpd/%.c
$(CC) $(CFLAGS) $<
$(TARGET): $(OBJ) $(TARGET): $(OBJ)
ifdef CONFIG_HTTP_NO_SSL ifdef CONFIG_HTTP_NO_SSL
$(LD) $(LDFLAGS) /out:$@ $(OBJ) $(LD) $(LDFLAGS) /out:$@ $(OBJ)
@ -106,5 +87,4 @@ endif # CONFIG_AWHTTPD
clean:: clean::
-@rm -f $(TARGET)* -@rm -f $(TARGET)*
-@rm -fr awhttpd

6
httpd/README Normal file
View File

@ -0,0 +1,6 @@
axhttpd is a small embedded web server using the axTLS library.
It is based quite closely on the web server written by Doug Currie (original
version is here: http://www.hcsw.org/awhttpd).

Binary file not shown.

File diff suppressed because it is too large Load Diff

164
httpd/axhttp.h Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "os_port.h"
#include "ssl.h"
#define BACKLOG 15
#define VERSION "3.0.7"
#ifdef CONFIG_HTTP_HAS_IPV6
#define HAVE_IPV6
#endif
#define MAXFILEPATH 1024
#define MAXIPLEN 45
#define MAXREQUESTLENGTH 1024
#define MAXCGIARGS 100
#define BLOCKSIZE 4096
#define INITIAL_CONNECTION_SLOTS 10
#define CONFIG_HTTP_DEFAULT_SSL_OPTIONS 0
#define STATE_WANT_TO_READ_HEAD 1
#define STATE_WANT_TO_SEND_HEAD 2
#define STATE_WANT_TO_READ_FILE 3
#define STATE_WANT_TO_SEND_FILE 4
#define STATE_DOING_DIR 5
#define TYPE_GET 0
#define TYPE_HEAD 1
#define TYPE_POST 2
struct connstruct
{
struct connstruct *next;
int state;
int reqtype;
int networkdesc;
int filedesc;
#if defined(CONFIG_HTTP_DIRECTORIES)
#ifdef WIN32
HANDLE dirp;
WIN32_FIND_DATA file_data;
#else
DIR *dirp;
#endif
#endif
time_t timeout;
char ip[MAXIPLEN];
char actualfile[MAXREQUESTLENGTH];
char filereq[MAXREQUESTLENGTH];
#if defined(CONFIG_HTTP_HAS_CGI)
char cgiargs[MAXREQUESTLENGTH];
char cgiscriptinfo[MAXREQUESTLENGTH];
char cgipathinfo[MAXREQUESTLENGTH];
#endif
char virtualhostreq[MAXREQUESTLENGTH];
int numbytes;
char databuf[BLOCKSIZE];
unsigned char is_ssl;
unsigned char close_when_done;
unsigned char modified_since;
};
struct serverstruct
{
struct serverstruct *next;
int sd;
int is_ssl;
SSLCTX *ssl_ctx;
};
struct cgiextstruct
{
struct cgiextstruct *next;
char *ext;
};
struct indexstruct
{
struct indexstruct *next;
char *name;
};
// Global prototypes
extern struct serverstruct *servers;
extern struct connstruct *usedconns;
extern struct connstruct *freeconns;
extern struct cgiextstruct *cgiexts;
extern struct indexstruct *indexlist;
// Conf global prototypes
extern char *webroot;
extern int allowdirectorylisting;
extern int allowcgi;
extern int permcheck;
// conn.c prototypes
void addconnection(int sd, char *ip, int is_ssl);
void removeconnection(struct connstruct *cn);
// proc.c prototypes
int procheadelem(struct connstruct *cn, char *buf);
void procdirlisting(struct connstruct *cn);
void procdodir(struct connstruct *cn);
void procreadhead(struct connstruct *cn);
void procsendhead(struct connstruct *cn);
void procreadfile(struct connstruct *cn);
void procsendfile(struct connstruct *cn);
int special_write(struct connstruct *cn, const uint8_t *buf, size_t count);
// net.c prototypes
void addtoservers(int sd);
void selectloop(void);
// socket.c prototypes
void handlenewconnection(int listenfd, int is_ssl);
int openlistener(int port);
int openlistener6(int port);
// misc.c prototypes
void nada(int sigtype);
void die(int sigtype);
void reaper(int sigtype);
void stripcrlf(char *p);
char *my_strncpy(char *dest, const char *src, size_t n);
#ifndef __HAVE_ARCH_STRNLEN
size_t strnlen ( const char * str, size_t maxlen );
#endif
int iscgi(char *fn);
void split(char *tp, char *sp[], int maxwords, char sc);
int sanitizefile(char *buf);
int sanitizehost(char *buf);
void buildactualfile(struct connstruct *cn);
int issockwriteable(int sd);
int isdir(char *name);
int trycgi_withpathinfo(struct connstruct *cn);
// mime_types.c prototypes
void mime_init(void);
const char *getmimetype(const char *fn);
// main.c prototypes
void initlists(void);

121
httpd/conn.c Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "axhttp.h"
void addconnection(int sd, char *ip, int is_ssl)
{
struct connstruct *tp;
// Get ourselves a connstruct
if (freeconns == NULL)
{
tp = (struct connstruct *) malloc(sizeof(struct connstruct));
}
else
{
tp = freeconns;
freeconns = tp->next;
}
// Attach it to the used list
tp->next = usedconns;
usedconns = tp;
tp->networkdesc = sd;
if (is_ssl)
ssl_server_new(servers->ssl_ctx, sd);
tp->filedesc = -1;
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
tp->dirp = NULL;
#endif
tp->is_ssl = is_ssl;
*(tp->actualfile) = '\0';
*(tp->filereq) = '\0';
#if defined(CONFIG_HTTP_HAS_CGI)
*(tp->cgiargs) = '\0';
#endif
*(tp->virtualhostreq) = '\0';
tp->state = STATE_WANT_TO_READ_HEAD;
tp->reqtype = TYPE_GET;
my_strncpy(tp->ip, ip, MAXIPLEN);
tp->close_when_done = 0;
tp->modified_since = 0;
tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
}
void removeconnection(struct connstruct *cn)
{
struct connstruct *tp;
int shouldret=0;
tp = usedconns;
if (tp == NULL || cn == NULL)
shouldret=1;
else if (tp == cn)
usedconns = tp->next;
else
{
while(tp != NULL)
{
if (tp->next == cn)
{
tp->next = (tp->next)->next;
shouldret=0;
break;
}
tp = tp->next;
shouldret=1;
}
}
if (shouldret)
return;
// If we did, add it to the free list
cn->next = freeconns;
freeconns = cn;
// Close it all down
if (cn->networkdesc != -1)
{
if (cn->is_ssl)
{
ssl_free(ssl_find(servers->ssl_ctx, cn->networkdesc));
}
SOCKET_CLOSE(cn->networkdesc);
}
if (cn->filedesc != -1) close(cn->filedesc);
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
if (cn->dirp != NULL)
#ifdef WIN32
FindClose(cn->dirp);
#else
closedir(cn->dirp);
#endif
#endif
}

323
httpd/main.c Normal file
View File

@ -0,0 +1,323 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include "axhttp.h"
// GLOBALS
struct serverstruct *servers;
struct connstruct *usedconns;
struct connstruct *freeconns;
#if defined(CONFIG_HTTP_HAS_CGI)
struct cgiextstruct *cgiexts;
#endif
struct indexstruct *indexlist;
char *webroot = CONFIG_HTTP_WEBROOT;
static void addindex(char *tp);
#if defined(CONFIG_HTTP_PERM_CHECK)
static void procpermcheck(char *pathtocheck);
#endif
#if defined(CONFIG_HTTP_HAS_CGI)
static void addcgiext(char *tp);
#endif
/* clean up memory for valgrind */
static void sigint_cleanup(int sig)
{
struct serverstruct *sp;
struct connstruct *tp;
int i;
while(servers != NULL)
{
if (servers->is_ssl)
ssl_ctx_free(servers->ssl_ctx);
sp = servers->next;
free(servers);
servers = sp;
}
free(indexlist->name);
free(indexlist);
for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++)
{
if (freeconns == NULL)
break;
tp = freeconns->next;
free(freeconns);
freeconns = tp;
}
exit(0);
}
void initlists()
{
int i;
struct connstruct *tp;
servers = NULL;
usedconns = NULL;
freeconns = NULL;
#if defined(CONFIG_HTTP_HAS_CGI)
cgiexts = NULL;
#endif
indexlist = NULL;
for (i=0; i<INITIAL_CONNECTION_SLOTS; i++)
{
tp = freeconns;
freeconns = (struct connstruct *) calloc(1, sizeof(struct connstruct));
freeconns->next = tp;
}
}
int main(int argc, char *argv[])
{
int tp;
#if defined(CONFIG_HTTP_IS_DAEMON)
int pid;
#endif
#ifdef WIN32
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested,&wsaData);
#endif
mime_init();
initlists();
tp = strlen(webroot);
if (webroot[tp-1] == '/')
webroot[tp-1] = '\0';
if (isdir(webroot) == 0)
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "'%s' is not a directory\n", webroot);
#endif
exit(1);
}
if ((tp=openlistener(CONFIG_HTTP_PORT)) == -1)
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "ERR: Couldn't bind to port %d (IPv4)\n",
CONFIG_HTTP_PORT);
#endif
exit(1);
}
addindex("index.html");
addtoservers(tp);
#ifndef WIN32
if (getuid() == 0)
{
setgid(32767);
setuid(32767);
}
#endif
if ((tp=openlistener(CONFIG_HTTP_HTTPS_PORT)) == -1)
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr, "ERR: Couldn't bind to port %d (IPv4)\n",
CONFIG_HTTP_HTTPS_PORT);
#endif
exit(1);
}
addtoservers(tp);
servers->ssl_ctx = ssl_ctx_new(CONFIG_HTTP_DEFAULT_SSL_OPTIONS,
CONFIG_HTTP_SESSION_CACHE_SIZE);
servers->is_ssl = 1;
#if defined(CONFIG_HTTP_PERM_CHECK)
procpermcheck(webroot);
#endif
#if defined(CONFIG_HTTP_HAS_CGI)
addcgiext(CONFIG_HTTP_CGI_EXTENSION);
#endif
#if defined(CONFIG_HTTP_VERBOSE)
printf("axhttpd: listening on ports http:%d and https:%d\n",
CONFIG_HTTP_PORT, CONFIG_HTTP_HTTPS_PORT);
TTY_FLUSH();
#endif
#if defined(CONFIG_HTTP_IS_DAEMON)
pid = fork();
if (pid > 0)
{
exit(0);
}
else if(pid == -1)
{
#ifdef CONFIG_HTTP_VERBOSE
fprintf(stderr,"axhttpd: Sorry, fork failed... Tough dice.\n");
#endif
exit(1);
}
setsid();
#endif
/* SIGNALS */
signal(SIGINT, sigint_cleanup);
signal(SIGTERM, die);
#if defined(CONFIG_HTTP_HAS_CGI)
#ifndef WIN32
signal(SIGCHLD, reaper);
#endif
#endif
#ifndef WIN32
signal(SIGQUIT, die);
signal(SIGPIPE, SIG_IGN);
#endif
selectloop();
return 0;
}
static void addindex(char *tp)
{
struct indexstruct *ex = (struct indexstruct *)
malloc(sizeof(struct indexstruct));
ex->name = strdup(tp);
ex->next = indexlist;
indexlist = ex;
}
#if defined(CONFIG_HTTP_PERM_CHECK)
static void procpermcheck(char *pathtocheck)
{
char thepath[MAXREQUESTLENGTH];
#ifndef WIN32
DIR *tpdir;
struct dirent *dp;
tpdir = opendir(pathtocheck);
if (tpdir == NULL)
{
printf("WARNING: UID (%d) is unable to read %s\n",
(int)getuid(), pathtocheck);
return;
}
while ((dp=readdir(tpdir)))
{
if (strcmp(dp->d_name, "..")==0)
continue;
if (strcmp(dp->d_name, ".")==0)
continue;
snprintf(thepath, sizeof(thepath), "%s/%s", pathtocheck, dp->d_name);
if (isdir(thepath))
{
procpermcheck(thepath);
continue;
}
if (access(thepath, R_OK) != 0)
printf("WARNING: UID (%d) is unable to read %s\n",
(int)getuid(), thepath);
if (access(thepath, W_OK) == 0)
printf("SECURITY: UID (%d) is ABLE TO WRITE TO %s\n",
(int)getuid(), thepath);
}
closedir(tpdir);
#else /* Win32 */
HANDLE tpdir;
WIN32_FIND_DATA file_data;
struct stat st;
char buf2[1024];
strcpy(buf2, pathtocheck);
strcat(buf2, "\\*");
tpdir = FindFirstFile(buf2, &file_data);
if (tpdir == INVALID_HANDLE_VALUE)
{
printf("WARNING: unable to read %s\n", buf2);
TTY_FLUSH();
return;
}
while (FindNextFile(tpdir, &file_data))
{
if (strcmp(file_data.cFileName, "..") == 0)
continue;
if (strcmp(file_data.cFileName, ".") == 0)
continue;
snprintf(thepath, sizeof(thepath), "%s\\%s",
pathtocheck, file_data.cFileName);
if (isdir(thepath))
{
procpermcheck(thepath);
continue;
}
if (stat(thepath, &st) >= 0)
{
if ((st.st_mode & _S_IREAD) == 0)
{
printf("WARNING: unable to read %s\n", thepath);
TTY_FLUSH();
}
if (st.st_mode & _S_IWRITE)
{
printf("SECURITY: ABLE TO WRITE TO %s\n", thepath);
TTY_FLUSH();
}
}
}
FindClose(tpdir);
#endif
}
#endif /* CONFIG_HTTP_PERM_CHECK */
#if defined(CONFIG_HTTP_HAS_CGI)
static void addcgiext(char *tp)
{
struct cgiextstruct *ex = (struct cgiextstruct *)
malloc(sizeof(struct cgiextstruct));
ex->ext = strdup(tp);
ex->next = cgiexts;
cgiexts = ex;
}
#endif

190
httpd/mime_types.c Normal file
View File

@ -0,0 +1,190 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "os_port.h"
static const char mime_default[] = "text/plain";
typedef struct
{
const char * const ext;
const char * const type;
} mime_table_t;
static mime_table_t mime_table[] =
{
// Fundamentals
{ ".html", "text/html" },
{ ".htm", "text/html" },
{ ".txt", "text/plain" },
// Others
{ ".rtx", "text/richtext" },
{ ".etx", "text/x-setext" },
{ ".tsv", "text/tab-separated-values" },
{ ".css", "text/css" },
{ ".xml", "text/xml" },
{ ".dtd", "text/xml" },
{ ".gif", "image/gif" },
{ ".jpg", "image/jpeg" },
{ ".jpeg", "image/jpeg" },
{ ".jpe", "image/jpeg" },
{ ".jfif", "image/jpeg" },
{ ".tif", "image/tiff" },
{ ".tiff", "image/tiff" },
{ ".pbm", "image/x-portable-bitmap" },
{ ".pgm", "image/x-portable-graymap" },
{ ".ppm", "image/x-portable-pixmap" },
{ ".pnm", "image/x-portable-anymap" },
{ ".xbm", "image/x-xbitmap" },
{ ".xpm", "image/x-xpixmap" },
{ ".xwd", "image/x-xwindowdump" },
{ ".ief", "image/ief" },
{ ".png", "image/png" },
{ ".au", "audio/basic" },
{ ".snd", "audio/basic" },
{ ".aif", "audio/x-aiff" },
{ ".aiff", "audio/x-aiff" },
{ ".aifc", "audio/x-aiff" },
{ ".ra", "audio/x-pn-realaudio" },
{ ".ram", "audio/x-pn-realaudio" },
{ ".rm", "audio/x-pn-realaudio" },
{ ".rpm", "audio/x-pn-realaudio-plugin" },
{ ".wav", "audio/wav" },
{ ".mid", "audio/midi" },
{ ".midi", "audio/midi" },
{ ".kar", "audio/midi" },
{ ".mpga", "audio/mpeg" },
{ ".mp2", "audio/mpeg" },
{ ".mp3", "audio/mpeg" },
{ ".mpeg", "video/mpeg" },
{ ".mpg", "video/mpeg" },
{ ".mpe", "video/mpeg" },
{ ".qt", "video/quicktime" },
{ ".mov", "video/quicktime" },
{ ".avi", "video/x-msvideo" },
{ ".movie", "video/x-sgi-movie" },
{ ".mv", "video/x-sgi-movie" },
{ ".vx", "video/x-rad-screenplay" },
{ ".a", "application/octet-stream" },
{ ".bin", "application/octet-stream" },
{ ".exe", "application/octet-stream" },
{ ".dump", "application/octet-stream" },
{ ".o", "application/octet-stream" },
{ ".class", "application/java" },
{ ".js", "application/x-javascript" },
{ ".ai", "application/postscript" },
{ ".eps", "application/postscript" },
{ ".ps", "application/postscript" },
{ ".dir", "application/x-director" },
{ ".dcr", "application/x-director" },
{ ".dxr", "application/x-director" },
{ ".fgd", "application/x-director" },
{ ".aam", "application/x-authorware-map" },
{ ".aas", "application/x-authorware-seg" },
{ ".aab", "application/x-authorware-bin" },
{ ".fh4", "image/x-freehand" },
{ ".fh7", "image/x-freehand" },
{ ".fh5", "image/x-freehand" },
{ ".fhc", "image/x-freehand" },
{ ".fh", "image/x-freehand" },
{ ".spl", "application/futuresplash" },
{ ".swf", "application/x-shockwave-flash" },
{ ".dvi", "application/x-dvi" },
{ ".gtar", "application/x-gtar" },
{ ".hdf", "application/x-hdf" },
{ ".hqx", "application/mac-binhex40" },
{ ".iv", "application/x-inventor" },
{ ".latex", "application/x-latex" },
{ ".man", "application/x-troff-man" },
{ ".me", "application/x-troff-me" },
{ ".mif", "application/x-mif" },
{ ".ms", "application/x-troff-ms" },
{ ".oda", "application/oda" },
{ ".pdf", "application/pdf" },
{ ".rtf", "application/rtf" },
{ ".bcpio", "application/x-bcpio" },
{ ".cpio", "application/x-cpio" },
{ ".sv4cpio", "application/x-sv4cpio" },
{ ".sv4crc", "application/x-sv4crc" },
{ ".sh", "application/x-shar" },
{ ".shar", "application/x-shar" },
{ ".sit", "application/x-stuffit" },
{ ".tar", "application/x-tar" },
{ ".tex", "application/x-tex" },
{ ".texi", "application/x-texinfo" },
{ ".texinfo", "application/x-texinfo" },
{ ".tr", "application/x-troff" },
{ ".roff", "application/x-troff" },
{ ".man", "application/x-troff-man" },
{ ".me", "application/x-troff-me" },
{ ".ms", "application/x-troff-ms" },
{ ".zip", "application/x-zip-compressed" },
{ ".tsp", "application/dsptype" },
{ ".wsrc", "application/x-wais-source" },
{ ".ustar", "application/x-ustar" },
{ ".cdf", "application/x-netcdf" },
{ ".nc", "application/x-netcdf" },
{ ".doc", "application/msword" },
{ ".ppt", "application/powerpoint" },
{ ".wrl", "model/vrml" },
{ ".vrml", "model/vrml" },
{ ".mime", "message/rfc822" },
{ ".pac", "application/x-ns-proxy-autoconfig" },
{ ".wml", "text/vnd.wap.wml" },
{ ".wmlc", "application/vnd.wap.wmlc" },
{ ".wmls", "text/vnd.wap.wmlscript" },
{ ".wmlsc", "application/vnd.wap.wmlscriptc" },
{ ".wbmp", "image/vnd.wap.wbmp" },
{ ".tgz", "application/x-gzip" },
{ ".tar.gz", "application/x-gzip" },
{ ".bz2", "application/x-bzip2" },
{ ".zip", "application/zip" }
};
static int mime_cmp(const mime_table_t *t1, const mime_table_t *t2)
{
return strcasecmp(t1->ext, t2->ext);
}
void mime_init(void)
{
qsort(mime_table, sizeof(mime_table)/sizeof(mime_table_t),
sizeof(mime_table_t),
(int (*)(const void *, const void *))mime_cmp);
}
const char *getmimetype(const char *name)
{
mime_table_t *mime_type;
if ((name = strrchr(name, '.')) == NULL)
return mime_default;
mime_type = bsearch(&name, mime_table,
sizeof(mime_table)/sizeof(mime_table_t),
sizeof(mime_table_t),
(int (*)(const void *, const void *))mime_cmp);
return mime_type == NULL ? mime_default : mime_type->type;
}

268
httpd/misc.c Normal file
View File

@ -0,0 +1,268 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "axhttp.h"
void nada(int sigtype) { }
void die(int sigtype)
{
exit(0);
}
#if defined(CONFIG_HTTP_HAS_CGI)
#ifndef WIN32
void reaper(int sigtype)
{
wait3(NULL,WNOHANG,NULL);
}
#endif
#endif
void stripcrlf(char *p)
{
while (p && *p)
{
if (*p=='\n' || *p=='\r')
{
*p='\0';
return;
}
p++;
}
}
/* Wrapper function for strncpy() that guarantees
a null-terminated string. This is to avoid any possible
issues due to strncpy()'s behaviour. Thanks to
Werner Almesberger for pointing out this potential
issue. Needless to say, make sure sizeof(dest) > 0
and sizeof(dest) >= n.
*/
char *my_strncpy(char *dest, const char *src, size_t n)
{
strncpy(dest, src, n);
dest[n-1] = '\0';
return dest;
}
/* strnlen is a GNU Extension */
#ifndef __HAVE_ARCH_STRNLEN
size_t strnlen (const char * str, size_t maxlen)
{
const char *p;
for (p=str; maxlen-- && *p!='\0'; ++p);
return (p - str);
}
#endif
int sanitizefile(char *buf)
{
int len, i;
// Don't accept anything not starting with a /
if (*buf != '/')
return 0;
len = strlen(buf);
for (i = 0; i < len; i++)
{
// Check for "/." : In other words, don't send files starting with a .
// Notice, GOBBLES, that this includes ".."
if (buf[i] == '/' && buf[i+1] == '.')
return 0;
}
return 1;
}
int sanitizehost(char *buf)
{
while(*buf != '\0')
{
// Handle the port
if (*buf == ':')
{
*buf = '\0';
return 1;
}
// Enforce some basic URL rules...
if (isalnum(*buf)==0 && *buf != '-' && *buf != '.') return 0;
if (*buf == '.' && *(buf+1) == '.') return 0;
if (*buf == '.' && *(buf+1) == '-') return 0;
if (*buf == '-' && *(buf+1) == '.') return 0;
buf++;
}
return 1;
}
void buildactualfile(struct connstruct *cn)
{
snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s%s",
webroot,
cn->filereq);
/* Add directory slash if not there */
if (isdir(cn->actualfile) &&
cn->actualfile[strlen(cn->actualfile)-1] != '/')
strcat(cn->actualfile, "/");
#ifdef WIN32
/* convert all the forward slashes to back slashes */
{
char *t = cn->actualfile;
while ((t = strchr(t, '/')))
{
*t++ = '\\';
}
}
#endif
}
#if defined(CONFIG_HTTP_DIRECTORIES)
int issockwriteable(int sd)
{
fd_set wfds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&wfds);
FD_SET(sd, &wfds);
select(FD_SETSIZE, NULL, &wfds, NULL, &tv);
return FD_ISSET(sd, &wfds);
}
#endif
int isdir(char *tpbuf)
{
struct stat st;
if (stat(tpbuf, &st) == -1)
return 0;
if ((st.st_mode & S_IFMT) == S_IFDIR)
return 1;
return 0;
}
#if defined(CONFIG_HTTP_HAS_CGI)
int iscgi(char *fn)
{
struct cgiextstruct *tp;
int fnlen, extlen;
fnlen = strlen(fn);
tp = cgiexts;
while (tp != NULL)
{
extlen = strlen(tp->ext);
if (strcasecmp(fn+(fnlen-extlen), tp->ext) == 0)
return 1;
tp = tp->next;
}
return 0;
}
void split(char *tp, char *sp[], int maxwords, char sc)
{
int i = 0;
while(1)
{
/* Skip leading whitespace */
while(*tp == sc) tp++;
if (*tp == '\0')
{
sp[i] = NULL;
break;
}
if (i==maxwords-2)
{
sp[maxwords-2] = NULL;
break;
}
sp[i] = tp;
while(*tp != sc && *tp != '\0')
tp++;
if (*tp == sc)
*tp++ = '\0';
i++;
}
}
int trycgi_withpathinfo(struct connstruct *cn)
{
char tpfile[MAXREQUESTLENGTH];
char fr_str[MAXREQUESTLENGTH];
char *fr_rs[MAXCGIARGS]; // filereq splitted
int i = 0, offset;
my_strncpy(fr_str, cn->filereq, MAXREQUESTLENGTH);
split(fr_str, fr_rs, MAXCGIARGS, '/');
while (fr_rs[i] != NULL)
{
snprintf(tpfile, sizeof(tpfile), "%s/%s%s",
webroot, cn->virtualhostreq, fr_str);
if (iscgi(tpfile) && isdir(tpfile) == 0)
{
/* We've found our CGI file! */
my_strncpy(cn->actualfile, tpfile, MAXREQUESTLENGTH);
my_strncpy(cn->cgiscriptinfo, fr_str, MAXREQUESTLENGTH);
offset = (fr_rs[i] + strlen(fr_rs[i])) - fr_str;
my_strncpy(cn->cgipathinfo, cn->filereq+offset, MAXREQUESTLENGTH);
return 0;
}
*(fr_rs[i]+strlen(fr_rs[i])) = '/';
i++;
}
/* Couldn't find any CGIs :( */
*(cn->cgiscriptinfo) = '\0';
*(cn->cgipathinfo) = '\0';
return -1;
}
#endif

176
httpd/net.c Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include "axhttp.h"
void addtoservers(int sd)
{
struct serverstruct *tp = (struct serverstruct *)
calloc(1, sizeof(struct serverstruct));
tp->next = servers;
tp->sd = sd;
servers = tp;
}
void selectloop()
{
fd_set rfds, wfds;
struct connstruct *tp, *to;
struct serverstruct *sp;
int rnum, wnum, active;
int currtime;
while (1)
{
// MAIN SELECT LOOP
FD_ZERO(&rfds);
FD_ZERO(&wfds);
rnum = wnum = -1;
// Add the listening sockets
sp = servers;
while (sp != NULL)
{
FD_SET(sp->sd, &rfds);
if (sp->sd > rnum) rnum = sp->sd;
sp = sp->next;
}
// Add the established sockets
tp = usedconns;
currtime = time(NULL);
while (tp != NULL)
{
if (currtime > tp->timeout)
{
to = tp;
tp = tp->next;
removeconnection(to);
continue;
}
if (tp->state == STATE_WANT_TO_READ_HEAD)
{
FD_SET(tp->networkdesc, &rfds);
if (tp->networkdesc > rnum)
rnum = tp->networkdesc;
}
if (tp->state == STATE_WANT_TO_SEND_HEAD)
{
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum)
wnum = tp->networkdesc;
}
if (tp->state == STATE_WANT_TO_READ_FILE)
{
FD_SET(tp->filedesc, &rfds);
if (tp->filedesc > rnum)
rnum = tp->filedesc;
}
if (tp->state == STATE_WANT_TO_SEND_FILE)
{
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum)
wnum = tp->networkdesc;
}
#if defined(CONFIG_HTTP_DIRECTORIES)
if (tp->state == STATE_DOING_DIR)
{
FD_SET(tp->networkdesc, &wfds);
if (tp->networkdesc > wnum)
wnum = tp->networkdesc;
}
#endif
tp = tp->next;
}
active = select(wnum > rnum ? wnum+1 : rnum+1,
rnum != -1 ? &rfds : NULL,
wnum != -1 ? &wfds : NULL,
NULL, NULL);
// Handle the listening sockets
sp = servers;
while (active > 0 && sp != NULL)
{
if (FD_ISSET(sp->sd, &rfds))
{
handlenewconnection(sp->sd, sp->is_ssl);
active--;
}
sp = sp->next;
}
// Handle the established sockets
tp = usedconns;
while (active > 0 && tp != NULL)
{
to = tp;
tp = tp->next;
if (to->state == STATE_WANT_TO_READ_HEAD)
if (FD_ISSET(to->networkdesc, &rfds))
{
active--;
procreadhead(to);
}
if (to->state == STATE_WANT_TO_SEND_HEAD)
if (FD_ISSET(to->networkdesc, &wfds))
{
active--;
procsendhead(to);
}
if (to->state == STATE_WANT_TO_READ_FILE)
if (FD_ISSET(to->filedesc, &rfds))
{
active--;
procreadfile(to);
}
if (to->state == STATE_WANT_TO_SEND_FILE)
if (FD_ISSET(to->networkdesc, &wfds))
{
active--;
procsendfile(to);
}
#if defined(CONFIG_HTTP_DIRECTORIES)
if (to->state == STATE_DOING_DIR)
if (FD_ISSET(to->networkdesc, &wfds))
{
active--;
procdodir(to);
}
#endif
}
} // MAIN SELECT LOOP
}

780
httpd/proc.c Normal file
View File

@ -0,0 +1,780 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include "axhttp.h"
static int special_read(struct connstruct *cn, void *buf, size_t count);
static void send301(struct connstruct *cn);
static void send404(struct connstruct *cn);
static int procindex(struct connstruct *cn, struct stat *stp);
static int hexit(char c);
static void urlencode(unsigned char *s, unsigned char *t);
static void urldecode(char *buf);
#if defined(CONFIG_HTTP_HAS_CGI)
static void proccgi(struct connstruct *cn, int has_pathinfo);
#endif
// Returns 1 if elems should continue being read, 0 otherwise
int procheadelem(struct connstruct *cn, char *buf)
{
char *delim, *value;
#if defined(CONFIG_HTTP_HAS_CGI)
char *cgi_delim;
#endif
if ((delim = strchr(buf, ' ')) == NULL)
return 0;
*delim = 0;
value = delim+1;
if (strcmp(buf, "GET")==0 ||
strcmp(buf, "HEAD")==0 ||
strcmp(buf, "POST")==0)
{
if (buf[0] == 'H')
cn->reqtype = TYPE_HEAD;
else if (buf[0] == 'P')
cn->reqtype = TYPE_POST;
if ((delim = strchr(value, ' ')) == NULL) /* expect HTTP type */
return 0;
*delim = 0;
urldecode(value);
if (sanitizefile(value) == 0)
{
send404(cn);
removeconnection(cn);
return 0;
}
my_strncpy(cn->filereq, value, MAXREQUESTLENGTH);
#if defined(CONFIG_HTTP_HAS_CGI)
if ((cgi_delim = strchr(value, '?')))
{
*cgi_delim = 0;
my_strncpy(cn->cgiargs, value+1, MAXREQUESTLENGTH);
}
#endif
}
else if (strcmp(buf, "Host:")==0)
{
if (sanitizehost(value) == 0)
{
send404(cn);
removeconnection(cn);
return 0;
}
my_strncpy(cn->virtualhostreq, value, MAXREQUESTLENGTH);
}
else if (strcmp(buf, "Connection:")==0 &&
strcmp(value, "close")==0) {
cn->close_when_done = 1;
}
else if (strcmp(buf, "If-Modified-Since:") ==0 )
{
/* TODO: parse this date properly with getdate() or similar */
cn->modified_since = 1;
}
return 1;
}
#if defined(CONFIG_HTTP_DIRECTORIES)
void procdirlisting(struct connstruct *cn)
{
char buf[MAXREQUESTLENGTH];
char actualfile[1024];
#ifndef CONFIG_HTTP_DIRECTORIES
if (allowdirectorylisting == 0)
{
send404(cn);
removeconnection(cn);
return;
}
#endif
if (cn->reqtype == TYPE_HEAD)
{
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
write(cn->networkdesc, buf, strlen(buf));
removeconnection(cn);
return;
}
strcpy(actualfile, cn->actualfile);
#ifdef WIN32
strcat(actualfile, "*");
cn->dirp = FindFirstFile(actualfile, &cn->file_data);
if (cn->dirp == INVALID_HANDLE_VALUE)
{
send404(cn);
removeconnection(cn);
return;
}
#else
cn->dirp = opendir(actualfile);
if (cn->dirp == NULL)
{
send404(cn);
removeconnection(cn);
return;
}
// Get rid of the "."
readdir(cn->dirp);
#endif
sprintf(buf, "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>Directory Listing</TITLE>\n<H2>Directory listing of %s://%s%s</H2><BR>\n", cn->is_ssl ? "https" : "http", cn->virtualhostreq, cn->filereq);
special_write(cn, buf, strlen(buf));
cn->state = STATE_DOING_DIR;
}
void procdodir(struct connstruct *cn)
{
#ifndef WIN32
struct dirent *dp;
#endif
char buf[MAXREQUESTLENGTH];
char encbuf[1024];
int putslash;
char *file;
do
{
#ifdef WIN32
if (!FindNextFile(cn->dirp, &cn->file_data))
#else
if ((dp = readdir(cn->dirp)) == NULL)
#endif
{
snprintf(buf, sizeof(buf), "</BODY></HTML>\n");
special_write(cn, buf, strlen(buf));
removeconnection(cn);
return;
}
#ifdef WIN32
file = cn->file_data.cFileName;
#else
file = dp->d_name;
#endif
if (cn->filereq[0] == '/' && cn->filereq[1] == '\0' &&
strcmp(file, "..") == 0) continue;
snprintf(buf, sizeof(buf), "%s%s", cn->actualfile, file);
putslash = isdir(buf);
urlencode(file, encbuf);
snprintf(buf, sizeof(buf), "<A HREF=\"%s%s\">%s%s</A><BR>\n",
encbuf, putslash ? "/" : "", file, putslash ? "/" : "");
special_write(cn, buf, strlen(buf));
}
while (issockwriteable(cn->networkdesc));
}
#endif
void procreadhead(struct connstruct *cn)
{
char buf[MAXREQUESTLENGTH*4], *tp, *next;
int rv;
rv = special_read(cn, buf, sizeof(buf)-1);
if (rv <= 0) {
if (rv < 0)
removeconnection(cn);
return;
}
buf[rv] = '\0';
next = tp = buf;
// Split up lines and send to procheadelem()
while(*next != '\0')
{
// If we have a blank line, advance to next stage!
if (*next == '\r' || *next == '\n')
{
buildactualfile(cn);
cn->state = STATE_WANT_TO_SEND_HEAD;
return;
}
while(*next != '\r' && *next != '\n' && *next != '\0')
next++;
if (*next == '\r')
{
*next = '\0';
next+=2;
}
else if (*next == '\n')
*next++ = '\0';
if (procheadelem(cn, tp) == 0)
return;
tp = next;
}
}
/* In this function we assume that the file has been checked for
* maliciousness (".."s, etc) and has been decoded
*/
void procsendhead(struct connstruct *cn)
{
char buf[1024];
char actualfile[1024];
struct stat stbuf;
time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT;
char date[32];
strcpy(date, ctime(&now));
strcpy(actualfile, cn->actualfile);
#ifdef WIN32
/* stat() under win32 can't deal with trail slash */
if (actualfile[strlen(actualfile)-1] == '\\')
actualfile[strlen(actualfile)-1] = 0;
#endif
if (stat(actualfile, &stbuf) == -1)
{
#if defined(CONFIG_HTTP_HAS_CGI)
if (trycgi_withpathinfo(cn) == 0)
{ // We Try To Find A CGI
proccgi(cn,1);
return;
}
#endif
send404(cn);
removeconnection(cn);
return;
}
#if defined(CONFIG_HTTP_HAS_CGI)
if (iscgi(cn->actualfile))
{
#ifndef WIN32
// Set up CGI script
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
{
send404(cn);
removeconnection(cn);
return;
}
#endif
proccgi(cn,0);
return;
}
#endif
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
{
if (cn->filereq[strlen(cn->filereq)-1] != '/')
{
send301(cn);
removeconnection(cn);
return;
}
// Check to see if this dir has an index file
if (procindex(cn, &stbuf) == 0)
{
#if defined(CONFIG_HTTP_DIRECTORIES)
// If not, we do a directory listing of it
procdirlisting(cn);
#else
send404(cn);
removeconnection(cn);
#endif
return;
}
#if defined(CONFIG_HTTP_HAS_CGI)
// If the index is a CGI file, handle it like any other CGI
if (iscgi(cn->actualfile))
{
// Set up CGI script
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
{
send404(cn);
removeconnection(cn);
return;
}
proccgi(cn,0);
return;
}
#endif
// If the index isn't a CGI, we continue on with the index file
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
{
if (cn->filereq[strlen(cn->filereq)-1] != '/')
{
send301(cn);
removeconnection(cn);
return;
}
// Check to see if this dir has an index file
if (procindex(cn, &stbuf) == 0)
{
#if defined(CONFIG_HTTP_DIRECTORIES)
// If not, we do a directory listing of it
procdirlisting(cn);
#endif
return;
}
#if defined(CONFIG_HTTP_HAS_CGI)
// If the index is a CGI file, handle it like any other CGI
if (iscgi(cn->actualfile))
{
// Set up CGI script
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
{
send404(cn);
removeconnection(cn);
return;
}
proccgi(cn,0);
return;
}
#endif
// If the index isn't a CGI, we continue on with the index file
}
if (cn->modified_since)
{
snprintf(buf, sizeof(buf), "HTTP/1.1 304 Not Modified\nServer: axhttpd V%s\nDate: %s\n", VERSION, date);
special_write(cn, buf, strlen(buf));
cn->modified_since = 0;
cn->state = STATE_WANT_TO_READ_HEAD;
return;
}
else
{
#ifdef CONFIG_HTTP_VERBOSE
printf("axhttpd: %s send %s\n",
cn->is_ssl ? "https" : "http", cn->actualfile);
TTY_FLUSH();
#endif
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: axhttpd V%s\nContent-Type: %s\nContent-Length: %ld\nDate: %sLast-Modified: %s\n",
VERSION,
getmimetype(cn->actualfile),
(long) stbuf.st_size,
date,
ctime(&(stbuf.st_mtime))); // ctime() has a \n on the end
}
special_write(cn, buf, strlen(buf));
if (cn->reqtype == TYPE_HEAD)
{
removeconnection(cn);
return;
}
else
{
int flags = O_RDONLY;
#if defined(WIN32) || defined(CYGWIN)
flags |= O_BINARY;
#endif
cn->filedesc = open(cn->actualfile, flags);
if (cn->filedesc == -1)
{
send404(cn);
removeconnection(cn);
return;
}
#ifdef WIN32
for (;;)
{
procreadfile(cn);
if (cn->filedesc == -1)
break;
do
{
procsendfile(cn);
} while (cn->state != STATE_WANT_TO_READ_FILE);
}
#else
cn->state = STATE_WANT_TO_READ_FILE;
#endif
return;
}
}
void procreadfile(struct connstruct *cn)
{
int rv = read(cn->filedesc, cn->databuf, BLOCKSIZE);
if (rv == 0 || rv == -1)
{
close(cn->filedesc);
cn->filedesc = -1;
if (cn->close_when_done) /* close immediately */
removeconnection(cn);
else
{ /* keep socket open - HTTP 1.1 */
cn->state = STATE_WANT_TO_READ_HEAD;
cn->numbytes = 0;
}
return;
}
cn->numbytes = rv;
cn->state = STATE_WANT_TO_SEND_FILE;
}
void procsendfile(struct connstruct *cn)
{
int rv = special_write(cn, cn->databuf, cn->numbytes);
if (rv < 0)
removeconnection(cn);
else if (rv == cn->numbytes)
cn->state = STATE_WANT_TO_READ_FILE;
else if (rv == 0)
{ /* Do nothing */ }
else
{
memmove(cn->databuf, cn->databuf + rv, cn->numbytes - rv);
cn->numbytes -= rv;
}
}
int special_write(struct connstruct *cn, const uint8_t *buf, size_t count)
{
int res;
if (cn->is_ssl)
{
SSL *ssl = ssl_find(servers->ssl_ctx, cn->networkdesc);
if (ssl)
{
res = ssl_write(ssl, (unsigned char *)buf, count);
}
else
return -1;
}
else
res = SOCKET_WRITE(cn->networkdesc, buf, count);
return res;
}
static int special_read(struct connstruct *cn, void *buf, size_t count)
{
int res;
if (cn->is_ssl)
{
SSL *ssl = ssl_find(servers->ssl_ctx, cn->networkdesc);
unsigned char *read_buf;
if ((res = ssl_read(ssl, &read_buf)) > SSL_OK)
memcpy(buf, read_buf, res > (int)count ? count : res);
}
else
res = SOCKET_READ(cn->networkdesc, buf, count);
return res;
}
static void send301(struct connstruct *cn)
{
char buf[2048];
sprintf(buf, "HTTP/1.1 301 Moved Permanently\nLocation: %s/\n\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>301 Moved Permanently</TITLE>\n</HEAD><BODY>\n<H1>Moved Permanently</H1>\nThe document has moved <A HREF=\"%s/\">here</A>.<P>\n<HR>\n</BODY></HTML>\n", cn->filereq, cn->filereq);
special_write(cn, buf, strlen(buf));
}
static void send404(struct connstruct *cn)
{
char buf[1024];
sprintf(buf, "HTTP/1.0 404 Not Found\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>404 Not Found</TITLE><H1>It ain't there my friend. (404 Not Found)</H1>\n</BODY></HTML>\n");
special_write(cn, buf, strlen(buf));
}
// Returns 0 if no index was found and doesn't modify cn->actualfile
// Returns 1 if an index was found and puts the index in cn->actualfile
// and puts its stat info into stp
static int procindex(struct connstruct *cn, struct stat *stp)
{
char tbuf[MAXREQUESTLENGTH];
struct indexstruct *tp;
tp = indexlist;
while(tp != NULL) {
sprintf(tbuf, "%s%s%s", cn->actualfile,
#ifdef WIN32
"\\",
#else
"/",
#endif
tp->name);
if (stat(tbuf, stp) != -1)
{
my_strncpy(cn->actualfile, tbuf, MAXREQUESTLENGTH);
return 1;
}
tp = tp->next;
}
return 0;
}
#if defined(CONFIG_HTTP_HAS_CGI)
static void proccgi(struct connstruct *cn, int has_pathinfo)
{
int tpipe[2];
char *myargs[5];
char buf[MAXREQUESTLENGTH];
#ifdef WIN32
int tmp_stdout;
#else
int fv;
#endif
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: axhttpd V%s\n%s",
VERSION, (cn->reqtype == TYPE_HEAD) ? "\n" : "");
special_write(cn, buf, strlen(buf));
if (cn->reqtype == TYPE_HEAD)
{
removeconnection(cn);
return;
}
#ifndef WIN32
if (pipe(tpipe) == -1)
{
removeconnection(cn);
return;
}
fv = fork();
if (fv == -1)
{
close(tpipe[0]);
close(tpipe[1]);
removeconnection(cn);
return;
}
if (fv != 0)
{
// Close the write descriptor
close(tpipe[1]);
cn->filedesc = tpipe[0];
cn->state = STATE_WANT_TO_READ_FILE;
return;
}
// The problem child...
// Our stdout/stderr goes to the socket
dup2(tpipe[1], 1);
dup2(tpipe[1], 2);
// If it was a POST request, send the socket data to our stdin
if (cn->reqtype == TYPE_POST)
dup2(cn->networkdesc, 0);
else // Otherwise we can shutdown the read side of the sock
shutdown(cn->networkdesc, 0);
close(tpipe[0]);
close(tpipe[1]);
myargs[0] = cn->actualfile;
myargs[1] = cn->cgiargs;
myargs[2] = NULL;
if (!has_pathinfo)
{
my_strncpy(cn->cgipathinfo, "/", MAXREQUESTLENGTH);
my_strncpy(cn->cgiscriptinfo, cn->filereq, MAXREQUESTLENGTH);
}
execv(cn->actualfile, myargs);
#else /* WIN32 */
if (_pipe(tpipe, 4096, O_BINARY| O_NOINHERIT) == -1)
{
removeconnection(cn);
return;
}
myargs[0] = "sh";
myargs[1] = "-c";
myargs[2] = cn->actualfile;
myargs[3] = cn->cgiargs;
myargs[4] = NULL;
/* convert all the forward slashes to back slashes */
{
char *t = myargs[2];
while ((t = strchr(t, '\\')))
{
*t++ = '/';
}
}
tmp_stdout = _dup(_fileno(stdout));
_dup2(tpipe[1], _fileno(stdout));
close(tpipe[1]);
/* change to suit execution method */
if (spawnl(P_NOWAIT, "c:\\Program Files\\cygwin\\bin\\sh.exe",
myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]) == -1)
{
removeconnection(cn);
return;
}
_dup2(tmp_stdout, _fileno(stdout));
close(tmp_stdout);
cn->filedesc = tpipe[0];
cn->state = STATE_WANT_TO_READ_FILE;
for (;;)
{
procreadfile(cn);
if (cn->filedesc == -1)
break;
procsendfile(cn);
usleep(200000); /* don't know why this delay makes it work (yet) */
}
#endif
}
#endif /* CONFIG_HTTP_HAS_CGI */
/* Encode funny chars -> %xx in newly allocated storage */
/* (preserves '/' !) */
static void urlencode(unsigned char *s, unsigned char *t)
{
uint8_t *p, *tp;
tp =t ;
for (p=s; *p; p++)
{
if ((*p > 0x00 && *p < ',') ||
(*p > '9' && *p < 'A') ||
(*p > 'Z' && *p < '_') ||
(*p > '_' && *p < 'a') ||
(*p > 'z' && *p < 0xA1)) {
sprintf((char *)tp, "%%%02X", *p);
tp += 3;
}
else
{
*tp = *p;
tp++;
}
}
*tp='\0';
}
/* Decode string %xx -> char (in place) */
static void urldecode(char *buf)
{
int v;
char *p, *s, *w;
w = p = buf;
while (*p)
{
v = 0;
if (*p=='%')
{
s = p;
s++;
if (isxdigit((int) s[0]) && isxdigit((int) s[1]))
{
v = hexit(s[0])*16+hexit(s[1]);
if (v)
{ /* do not decode %00 to null char */
*w=(char)v;
p=&s[1];
}
}
}
if (!v)
*w=*p;
p++; w++;
}
*w='\0';
}
static int hexit(char c)
{
if ( c >= '0' && c <= '9' )
return c - '0';
if ( c >= 'a' && c <= 'f' )
return c - 'a' + 10;
if ( c >= 'A' && c <= 'F' )
return c - 'A' + 10;
return 0;
}

129
httpd/socket.c Normal file
View File

@ -0,0 +1,129 @@
/*
* Copyright(C) 2006 Cameron Rich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include "axhttp.h"
#ifdef HAVE_IPV6
void handlenewconnection(int listenfd, int is_ssl)
{
struct sockaddr_in6 their_addr;
int tp = sizeof(their_addr);
char ipbuf[100];
int connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
if (connfd == -1)
return;
if (tp == sizeof(struct sockaddr_in6))
{
inet_ntop(AF_INET6, &their_addr.sin6_addr, ipbuf, sizeof(ipbuf));
}
else if (tp == sizeof(struct sockaddr_in))
{
inet_ntop(AF_INET, &(((struct sockaddr_in *)&their_addr)->sin_addr),
ipbuf, sizeof(ipbuf));
}
else
{
*ipbuf = '\0';
}
addconnection(connfd, ipbuf, is_ssl);
}
#else
void handlenewconnection(int listenfd, int is_ssl)
{
struct sockaddr_in their_addr;
int tp = sizeof(struct sockaddr_in);
int connfd = accept(listenfd, (struct sockaddr *)&their_addr, &tp);
if (connfd == -1)
return;
addconnection(connfd, inet_ntoa(their_addr.sin_addr), is_ssl);
}
#endif
int openlistener(int port)
{
int sd;
#ifdef WIN32
char tp=1;
#else
int tp=1;
#endif
struct sockaddr_in my_addr;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return -1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &tp, sizeof(tp));
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons((short)port); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), 0, 8); // zero the rest of the struct
if (bind(sd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
close(sd);
return -1;
}
if (listen(sd, BACKLOG) == -1)
{
close(sd);
return -1;
}
return sd;
}
#ifdef HAVE_IPV6
int openlistener6(int port)
{
int sd,tp;
struct sockaddr_in6 my_addr;
if ((sd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
return -1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &tp, sizeof(tp));
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin6_family = AF_INET6;
my_addr.sin6_port = htons(port);
if (bind(sd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
{
close(sd);
return -1;
}
if (listen(sd, BACKLOG) == -1)
{
close(sd);
return -1;
}
return sd;
}
#endif